WinCOFFObjectWriter.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. //===-- llvm/MC/WinCOFFObjectWriter.cpp -------------------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file contains an implementation of a Win32 COFF object file writer.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/MC/MCWinCOFFObjectWriter.h"
  14. #include "llvm/ADT/DenseMap.h"
  15. #include "llvm/ADT/StringMap.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include "llvm/ADT/STLExtras.h"
  18. #include "llvm/ADT/Twine.h"
  19. #include "llvm/MC/MCAsmLayout.h"
  20. #include "llvm/MC/MCAssembler.h"
  21. #include "llvm/MC/MCContext.h"
  22. #include "llvm/MC/MCExpr.h"
  23. #include "llvm/MC/MCObjectWriter.h"
  24. #include "llvm/MC/MCSection.h"
  25. #include "llvm/MC/MCSectionCOFF.h"
  26. #include "llvm/MC/MCSymbol.h"
  27. #include "llvm/MC/MCValue.h"
  28. #include "llvm/Support/COFF.h"
  29. #include "llvm/Support/Debug.h"
  30. #include "llvm/Support/ErrorHandling.h"
  31. #include "llvm/Support/TimeValue.h"
  32. #include <cstdio>
  33. using namespace llvm;
  34. #define DEBUG_TYPE "WinCOFFObjectWriter"
  35. namespace {
  36. typedef SmallString<COFF::NameSize> name;
  37. enum AuxiliaryType {
  38. ATFunctionDefinition,
  39. ATbfAndefSymbol,
  40. ATWeakExternal,
  41. ATFile,
  42. ATSectionDefinition
  43. };
  44. struct AuxSymbol {
  45. AuxiliaryType AuxType;
  46. COFF::Auxiliary Aux;
  47. };
  48. class COFFSymbol;
  49. class COFFSection;
  50. class COFFSymbol {
  51. public:
  52. COFF::symbol Data;
  53. typedef SmallVector<AuxSymbol, 1> AuxiliarySymbols;
  54. name Name;
  55. int Index;
  56. AuxiliarySymbols Aux;
  57. COFFSymbol *Other;
  58. COFFSection *Section;
  59. int Relocations;
  60. MCSymbolData const *MCData;
  61. COFFSymbol(StringRef name);
  62. size_t size() const;
  63. void set_name_offset(uint32_t Offset);
  64. bool should_keep() const;
  65. };
  66. // This class contains staging data for a COFF relocation entry.
  67. struct COFFRelocation {
  68. COFF::relocation Data;
  69. COFFSymbol *Symb;
  70. COFFRelocation() : Symb(nullptr) {}
  71. static size_t size() { return COFF::RelocationSize; }
  72. };
  73. typedef std::vector<COFFRelocation> relocations;
  74. class COFFSection {
  75. public:
  76. COFF::section Header;
  77. std::string Name;
  78. int Number;
  79. MCSectionData const *MCData;
  80. COFFSymbol *Symbol;
  81. relocations Relocations;
  82. COFFSection(StringRef name);
  83. static size_t size();
  84. };
  85. // This class holds the COFF string table.
  86. class StringTable {
  87. typedef StringMap<size_t> map;
  88. map Map;
  89. void update_length();
  90. public:
  91. std::vector<char> Data;
  92. StringTable();
  93. size_t size() const;
  94. size_t insert(StringRef String);
  95. };
  96. class WinCOFFObjectWriter : public MCObjectWriter {
  97. public:
  98. typedef std::vector<std::unique_ptr<COFFSymbol>> symbols;
  99. typedef std::vector<std::unique_ptr<COFFSection>> sections;
  100. typedef DenseMap<MCSymbol const *, COFFSymbol *> symbol_map;
  101. typedef DenseMap<MCSection const *, COFFSection *> section_map;
  102. std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
  103. // Root level file contents.
  104. COFF::header Header;
  105. sections Sections;
  106. symbols Symbols;
  107. StringTable Strings;
  108. // Maps used during object file creation.
  109. section_map SectionMap;
  110. symbol_map SymbolMap;
  111. WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS);
  112. COFFSymbol *createSymbol(StringRef Name);
  113. COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol);
  114. COFFSection *createSection(StringRef Name);
  115. template <typename object_t, typename list_t>
  116. object_t *createCOFFEntity(StringRef Name, list_t &List);
  117. void DefineSection(MCSectionData const &SectionData);
  118. void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler,
  119. const MCAsmLayout &Layout);
  120. void MakeSymbolReal(COFFSymbol &S, size_t Index);
  121. void MakeSectionReal(COFFSection &S, size_t Number);
  122. bool ExportSymbol(MCSymbolData const &SymbolData, MCAssembler &Asm);
  123. bool IsPhysicalSection(COFFSection *S);
  124. // Entity writing methods.
  125. void WriteFileHeader(const COFF::header &Header);
  126. void WriteSymbol(const COFFSymbol &S);
  127. void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S);
  128. void WriteSectionHeader(const COFF::section &S);
  129. void WriteRelocation(const COFF::relocation &R);
  130. // MCObjectWriter interface implementation.
  131. void ExecutePostLayoutBinding(MCAssembler &Asm,
  132. const MCAsmLayout &Layout) override;
  133. void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
  134. const MCFragment *Fragment, const MCFixup &Fixup,
  135. MCValue Target, bool &IsPCRel,
  136. uint64_t &FixedValue) override;
  137. void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
  138. };
  139. }
  140. static inline void write_uint32_le(void *Data, uint32_t const &Value) {
  141. uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data);
  142. Ptr[0] = (Value & 0x000000FF) >> 0;
  143. Ptr[1] = (Value & 0x0000FF00) >> 8;
  144. Ptr[2] = (Value & 0x00FF0000) >> 16;
  145. Ptr[3] = (Value & 0xFF000000) >> 24;
  146. }
  147. //------------------------------------------------------------------------------
  148. // Symbol class implementation
  149. COFFSymbol::COFFSymbol(StringRef name)
  150. : Name(name.begin(), name.end())
  151. , Other(nullptr)
  152. , Section(nullptr)
  153. , Relocations(0)
  154. , MCData(nullptr) {
  155. memset(&Data, 0, sizeof(Data));
  156. }
  157. size_t COFFSymbol::size() const {
  158. return COFF::SymbolSize + (Data.NumberOfAuxSymbols * COFF::SymbolSize);
  159. }
  160. // In the case that the name does not fit within 8 bytes, the offset
  161. // into the string table is stored in the last 4 bytes instead, leaving
  162. // the first 4 bytes as 0.
  163. void COFFSymbol::set_name_offset(uint32_t Offset) {
  164. write_uint32_le(Data.Name + 0, 0);
  165. write_uint32_le(Data.Name + 4, Offset);
  166. }
  167. /// logic to decide if the symbol should be reported in the symbol table
  168. bool COFFSymbol::should_keep() const {
  169. // no section means its external, keep it
  170. if (!Section)
  171. return true;
  172. // if it has relocations pointing at it, keep it
  173. if (Relocations > 0) {
  174. assert(Section->Number != -1 && "Sections with relocations must be real!");
  175. return true;
  176. }
  177. // if the section its in is being droped, drop it
  178. if (Section->Number == -1)
  179. return false;
  180. // if it is the section symbol, keep it
  181. if (Section->Symbol == this)
  182. return true;
  183. // if its temporary, drop it
  184. if (MCData && MCData->getSymbol().isTemporary())
  185. return false;
  186. // otherwise, keep it
  187. return true;
  188. }
  189. //------------------------------------------------------------------------------
  190. // Section class implementation
  191. COFFSection::COFFSection(StringRef name)
  192. : Name(name)
  193. , MCData(nullptr)
  194. , Symbol(nullptr) {
  195. memset(&Header, 0, sizeof(Header));
  196. }
  197. size_t COFFSection::size() {
  198. return COFF::SectionSize;
  199. }
  200. //------------------------------------------------------------------------------
  201. // StringTable class implementation
  202. /// Write the length of the string table into Data.
  203. /// The length of the string table includes uint32 length header.
  204. void StringTable::update_length() {
  205. write_uint32_le(&Data.front(), Data.size());
  206. }
  207. StringTable::StringTable() {
  208. // The string table data begins with the length of the entire string table
  209. // including the length header. Allocate space for this header.
  210. Data.resize(4);
  211. update_length();
  212. }
  213. size_t StringTable::size() const {
  214. return Data.size();
  215. }
  216. /// Add String to the table iff it is not already there.
  217. /// @returns the index into the string table where the string is now located.
  218. size_t StringTable::insert(StringRef String) {
  219. map::iterator i = Map.find(String);
  220. if (i != Map.end())
  221. return i->second;
  222. size_t Offset = Data.size();
  223. // Insert string data into string table.
  224. Data.insert(Data.end(), String.begin(), String.end());
  225. Data.push_back('\0');
  226. // Put a reference to it in the map.
  227. Map[String] = Offset;
  228. // Update the internal length field.
  229. update_length();
  230. return Offset;
  231. }
  232. //------------------------------------------------------------------------------
  233. // WinCOFFObjectWriter class implementation
  234. WinCOFFObjectWriter::WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
  235. raw_ostream &OS)
  236. : MCObjectWriter(OS, true)
  237. , TargetObjectWriter(MOTW) {
  238. memset(&Header, 0, sizeof(Header));
  239. Header.Machine = TargetObjectWriter->getMachine();
  240. }
  241. COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) {
  242. return createCOFFEntity<COFFSymbol>(Name, Symbols);
  243. }
  244. COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol * Symbol){
  245. symbol_map::iterator i = SymbolMap.find(Symbol);
  246. if (i != SymbolMap.end())
  247. return i->second;
  248. COFFSymbol *RetSymbol
  249. = createCOFFEntity<COFFSymbol>(Symbol->getName(), Symbols);
  250. SymbolMap[Symbol] = RetSymbol;
  251. return RetSymbol;
  252. }
  253. COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) {
  254. return createCOFFEntity<COFFSection>(Name, Sections);
  255. }
  256. /// A template used to lookup or create a symbol/section, and initialize it if
  257. /// needed.
  258. template <typename object_t, typename list_t>
  259. object_t *WinCOFFObjectWriter::createCOFFEntity(StringRef Name,
  260. list_t &List) {
  261. List.push_back(make_unique<object_t>(Name));
  262. return List.back().get();
  263. }
  264. /// This function takes a section data object from the assembler
  265. /// and creates the associated COFF section staging object.
  266. void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
  267. assert(SectionData.getSection().getVariant() == MCSection::SV_COFF
  268. && "Got non-COFF section in the COFF backend!");
  269. // FIXME: Not sure how to verify this (at least in a debug build).
  270. MCSectionCOFF const &Sec =
  271. static_cast<MCSectionCOFF const &>(SectionData.getSection());
  272. COFFSection *coff_section = createSection(Sec.getSectionName());
  273. COFFSymbol *coff_symbol = createSymbol(Sec.getSectionName());
  274. coff_section->Symbol = coff_symbol;
  275. coff_symbol->Section = coff_section;
  276. coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
  277. // In this case the auxiliary symbol is a Section Definition.
  278. coff_symbol->Aux.resize(1);
  279. memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
  280. coff_symbol->Aux[0].AuxType = ATSectionDefinition;
  281. coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.getSelection();
  282. coff_section->Header.Characteristics = Sec.getCharacteristics();
  283. uint32_t &Characteristics = coff_section->Header.Characteristics;
  284. switch (SectionData.getAlignment()) {
  285. case 1: Characteristics |= COFF::IMAGE_SCN_ALIGN_1BYTES; break;
  286. case 2: Characteristics |= COFF::IMAGE_SCN_ALIGN_2BYTES; break;
  287. case 4: Characteristics |= COFF::IMAGE_SCN_ALIGN_4BYTES; break;
  288. case 8: Characteristics |= COFF::IMAGE_SCN_ALIGN_8BYTES; break;
  289. case 16: Characteristics |= COFF::IMAGE_SCN_ALIGN_16BYTES; break;
  290. case 32: Characteristics |= COFF::IMAGE_SCN_ALIGN_32BYTES; break;
  291. case 64: Characteristics |= COFF::IMAGE_SCN_ALIGN_64BYTES; break;
  292. case 128: Characteristics |= COFF::IMAGE_SCN_ALIGN_128BYTES; break;
  293. case 256: Characteristics |= COFF::IMAGE_SCN_ALIGN_256BYTES; break;
  294. case 512: Characteristics |= COFF::IMAGE_SCN_ALIGN_512BYTES; break;
  295. case 1024: Characteristics |= COFF::IMAGE_SCN_ALIGN_1024BYTES; break;
  296. case 2048: Characteristics |= COFF::IMAGE_SCN_ALIGN_2048BYTES; break;
  297. case 4096: Characteristics |= COFF::IMAGE_SCN_ALIGN_4096BYTES; break;
  298. case 8192: Characteristics |= COFF::IMAGE_SCN_ALIGN_8192BYTES; break;
  299. default:
  300. llvm_unreachable("unsupported section alignment");
  301. }
  302. // Bind internal COFF section to MC section.
  303. coff_section->MCData = &SectionData;
  304. SectionMap[&SectionData.getSection()] = coff_section;
  305. }
  306. /// This function takes a symbol data object from the assembler
  307. /// and creates the associated COFF symbol staging object.
  308. void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
  309. MCAssembler &Assembler,
  310. const MCAsmLayout &Layout) {
  311. MCSymbol const &Symbol = SymbolData.getSymbol();
  312. COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
  313. SymbolMap[&Symbol] = coff_symbol;
  314. if (SymbolData.getFlags() & COFF::SF_WeakExternal) {
  315. coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
  316. if (Symbol.isVariable()) {
  317. const MCSymbolRefExpr *SymRef =
  318. dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
  319. if (!SymRef)
  320. report_fatal_error("Weak externals may only alias symbols");
  321. coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol());
  322. } else {
  323. std::string WeakName = std::string(".weak.")
  324. + Symbol.getName().str()
  325. + ".default";
  326. COFFSymbol *WeakDefault = createSymbol(WeakName);
  327. WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
  328. WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL;
  329. WeakDefault->Data.Type = 0;
  330. WeakDefault->Data.Value = 0;
  331. coff_symbol->Other = WeakDefault;
  332. }
  333. // Setup the Weak External auxiliary symbol.
  334. coff_symbol->Aux.resize(1);
  335. memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
  336. coff_symbol->Aux[0].AuxType = ATWeakExternal;
  337. coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
  338. coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
  339. COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
  340. coff_symbol->MCData = &SymbolData;
  341. } else {
  342. const MCSymbolData &ResSymData =
  343. Assembler.getSymbolData(Symbol.AliasedSymbol());
  344. if (Symbol.isVariable()) {
  345. int64_t Addr;
  346. if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout))
  347. coff_symbol->Data.Value = Addr;
  348. } else if (SymbolData.isExternal() && SymbolData.isCommon()) {
  349. coff_symbol->Data.Value = SymbolData.getCommonSize();
  350. }
  351. coff_symbol->Data.Type = (ResSymData.getFlags() & 0x0000FFFF) >> 0;
  352. coff_symbol->Data.StorageClass = (ResSymData.getFlags() & 0x00FF0000) >> 16;
  353. // If no storage class was specified in the streamer, define it here.
  354. if (coff_symbol->Data.StorageClass == 0) {
  355. bool external = ResSymData.isExternal() || !ResSymData.Fragment;
  356. coff_symbol->Data.StorageClass =
  357. external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC;
  358. }
  359. if (Symbol.isAbsolute() || Symbol.AliasedSymbol().isVariable())
  360. coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
  361. else if (ResSymData.Fragment)
  362. coff_symbol->Section =
  363. SectionMap[&ResSymData.Fragment->getParent()->getSection()];
  364. coff_symbol->MCData = &ResSymData;
  365. }
  366. }
  367. // Maximum offsets for different string table entry encodings.
  368. static const unsigned Max6DecimalOffset = 999999;
  369. static const unsigned Max7DecimalOffset = 9999999;
  370. static const uint64_t MaxBase64Offset = 0xFFFFFFFFFULL; // 64^6, including 0
  371. // Encode a string table entry offset in base 64, padded to 6 chars, and
  372. // prefixed with a double slash: '//AAAAAA', '//AAAAAB', ...
  373. // Buffer must be at least 8 bytes large. No terminating null appended.
  374. static void encodeBase64StringEntry(char* Buffer, uint64_t Value) {
  375. assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset &&
  376. "Illegal section name encoding for value");
  377. static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  378. "abcdefghijklmnopqrstuvwxyz"
  379. "0123456789+/";
  380. Buffer[0] = '/';
  381. Buffer[1] = '/';
  382. char* Ptr = Buffer + 7;
  383. for (unsigned i = 0; i < 6; ++i) {
  384. unsigned Rem = Value % 64;
  385. Value /= 64;
  386. *(Ptr--) = Alphabet[Rem];
  387. }
  388. }
  389. /// making a section real involves assigned it a number and putting
  390. /// name into the string table if needed
  391. void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) {
  392. if (S.Name.size() > COFF::NameSize) {
  393. uint64_t StringTableEntry = Strings.insert(S.Name.c_str());
  394. if (StringTableEntry <= Max6DecimalOffset) {
  395. std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry));
  396. } else if (StringTableEntry <= Max7DecimalOffset) {
  397. // With seven digits, we have to skip the terminating null. Because
  398. // sprintf always appends it, we use a larger temporary buffer.
  399. char buffer[9] = { };
  400. std::sprintf(buffer, "/%d", unsigned(StringTableEntry));
  401. std::memcpy(S.Header.Name, buffer, 8);
  402. } else if (StringTableEntry <= MaxBase64Offset) {
  403. // Starting with 10,000,000, offsets are encoded as base64.
  404. encodeBase64StringEntry(S.Header.Name, StringTableEntry);
  405. } else {
  406. report_fatal_error("COFF string table is greater than 64 GB.");
  407. }
  408. } else
  409. std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
  410. S.Number = Number;
  411. S.Symbol->Data.SectionNumber = S.Number;
  412. S.Symbol->Aux[0].Aux.SectionDefinition.Number = S.Number;
  413. }
  414. void WinCOFFObjectWriter::MakeSymbolReal(COFFSymbol &S, size_t Index) {
  415. if (S.Name.size() > COFF::NameSize) {
  416. size_t StringTableEntry = Strings.insert(S.Name.c_str());
  417. S.set_name_offset(StringTableEntry);
  418. } else
  419. std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
  420. S.Index = Index;
  421. }
  422. bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData,
  423. MCAssembler &Asm) {
  424. // This doesn't seem to be right. Strings referred to from the .data section
  425. // need symbols so they can be linked to code in the .text section right?
  426. // return Asm.isSymbolLinkerVisible (&SymbolData);
  427. // For now, all non-variable symbols are exported,
  428. // the linker will sort the rest out for us.
  429. return SymbolData.isExternal() || !SymbolData.getSymbol().isVariable();
  430. }
  431. bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
  432. return (S->Header.Characteristics
  433. & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0;
  434. }
  435. //------------------------------------------------------------------------------
  436. // entity writing methods
  437. void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
  438. WriteLE16(Header.Machine);
  439. WriteLE16(Header.NumberOfSections);
  440. WriteLE32(Header.TimeDateStamp);
  441. WriteLE32(Header.PointerToSymbolTable);
  442. WriteLE32(Header.NumberOfSymbols);
  443. WriteLE16(Header.SizeOfOptionalHeader);
  444. WriteLE16(Header.Characteristics);
  445. }
  446. void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
  447. WriteBytes(StringRef(S.Data.Name, COFF::NameSize));
  448. WriteLE32(S.Data.Value);
  449. WriteLE16(S.Data.SectionNumber);
  450. WriteLE16(S.Data.Type);
  451. Write8(S.Data.StorageClass);
  452. Write8(S.Data.NumberOfAuxSymbols);
  453. WriteAuxiliarySymbols(S.Aux);
  454. }
  455. void WinCOFFObjectWriter::WriteAuxiliarySymbols(
  456. const COFFSymbol::AuxiliarySymbols &S) {
  457. for(COFFSymbol::AuxiliarySymbols::const_iterator i = S.begin(), e = S.end();
  458. i != e; ++i) {
  459. switch(i->AuxType) {
  460. case ATFunctionDefinition:
  461. WriteLE32(i->Aux.FunctionDefinition.TagIndex);
  462. WriteLE32(i->Aux.FunctionDefinition.TotalSize);
  463. WriteLE32(i->Aux.FunctionDefinition.PointerToLinenumber);
  464. WriteLE32(i->Aux.FunctionDefinition.PointerToNextFunction);
  465. WriteZeros(sizeof(i->Aux.FunctionDefinition.unused));
  466. break;
  467. case ATbfAndefSymbol:
  468. WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused1));
  469. WriteLE16(i->Aux.bfAndefSymbol.Linenumber);
  470. WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused2));
  471. WriteLE32(i->Aux.bfAndefSymbol.PointerToNextFunction);
  472. WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused3));
  473. break;
  474. case ATWeakExternal:
  475. WriteLE32(i->Aux.WeakExternal.TagIndex);
  476. WriteLE32(i->Aux.WeakExternal.Characteristics);
  477. WriteZeros(sizeof(i->Aux.WeakExternal.unused));
  478. break;
  479. case ATFile:
  480. WriteBytes(StringRef(reinterpret_cast<const char *>(i->Aux.File.FileName),
  481. sizeof(i->Aux.File.FileName)));
  482. break;
  483. case ATSectionDefinition:
  484. WriteLE32(i->Aux.SectionDefinition.Length);
  485. WriteLE16(i->Aux.SectionDefinition.NumberOfRelocations);
  486. WriteLE16(i->Aux.SectionDefinition.NumberOfLinenumbers);
  487. WriteLE32(i->Aux.SectionDefinition.CheckSum);
  488. WriteLE16(i->Aux.SectionDefinition.Number);
  489. Write8(i->Aux.SectionDefinition.Selection);
  490. WriteZeros(sizeof(i->Aux.SectionDefinition.unused));
  491. break;
  492. }
  493. }
  494. }
  495. void WinCOFFObjectWriter::WriteSectionHeader(const COFF::section &S) {
  496. WriteBytes(StringRef(S.Name, COFF::NameSize));
  497. WriteLE32(S.VirtualSize);
  498. WriteLE32(S.VirtualAddress);
  499. WriteLE32(S.SizeOfRawData);
  500. WriteLE32(S.PointerToRawData);
  501. WriteLE32(S.PointerToRelocations);
  502. WriteLE32(S.PointerToLineNumbers);
  503. WriteLE16(S.NumberOfRelocations);
  504. WriteLE16(S.NumberOfLineNumbers);
  505. WriteLE32(S.Characteristics);
  506. }
  507. void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
  508. WriteLE32(R.VirtualAddress);
  509. WriteLE32(R.SymbolTableIndex);
  510. WriteLE16(R.Type);
  511. }
  512. ////////////////////////////////////////////////////////////////////////////////
  513. // MCObjectWriter interface implementations
  514. void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
  515. const MCAsmLayout &Layout) {
  516. // "Define" each section & symbol. This creates section & symbol
  517. // entries in the staging area.
  518. static_assert(sizeof(((COFF::AuxiliaryFile *)0)->FileName) == COFF::SymbolSize,
  519. "size mismatch for COFF::AuxiliaryFile::FileName");
  520. for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end();
  521. FI != FE; ++FI) {
  522. // round up to calculate the number of auxiliary symbols required
  523. unsigned Count = (FI->size() + COFF::SymbolSize - 1) / COFF::SymbolSize;
  524. COFFSymbol *file = createSymbol(".file");
  525. file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE;
  526. file->Aux.resize(Count);
  527. unsigned Offset = 0;
  528. unsigned Length = FI->size();
  529. for (auto & Aux : file->Aux) {
  530. Aux.AuxType = ATFile;
  531. if (Length > COFF::SymbolSize) {
  532. memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, COFF::SymbolSize);
  533. Length = Length - COFF::SymbolSize;
  534. } else {
  535. memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, Length);
  536. memset(&Aux.Aux.File.FileName[Length], 0, COFF::SymbolSize - Length);
  537. Length = 0;
  538. }
  539. Offset = Offset + COFF::SymbolSize;
  540. }
  541. }
  542. for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++)
  543. DefineSection(*i);
  544. for (MCSymbolData &SD : Asm.symbols())
  545. if (ExportSymbol(SD, Asm))
  546. DefineSymbol(SD, Asm, Layout);
  547. }
  548. void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
  549. const MCAsmLayout &Layout,
  550. const MCFragment *Fragment,
  551. const MCFixup &Fixup,
  552. MCValue Target,
  553. bool &IsPCRel,
  554. uint64_t &FixedValue) {
  555. assert(Target.getSymA() && "Relocation must reference a symbol!");
  556. const MCSymbol &Symbol = Target.getSymA()->getSymbol();
  557. const MCSymbol &A = Symbol.AliasedSymbol();
  558. if (!Asm.hasSymbolData(A))
  559. Asm.getContext().FatalError(
  560. Fixup.getLoc(),
  561. Twine("symbol '") + A.getName() + "' can not be undefined");
  562. MCSymbolData &A_SD = Asm.getSymbolData(A);
  563. MCSectionData const *SectionData = Fragment->getParent();
  564. // Mark this symbol as requiring an entry in the symbol table.
  565. assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() &&
  566. "Section must already have been defined in ExecutePostLayoutBinding!");
  567. assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() &&
  568. "Symbol must already have been defined in ExecutePostLayoutBinding!");
  569. COFFSection *coff_section = SectionMap[&SectionData->getSection()];
  570. COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()];
  571. const MCSymbolRefExpr *SymB = Target.getSymB();
  572. bool CrossSection = false;
  573. if (SymB) {
  574. const MCSymbol *B = &SymB->getSymbol();
  575. MCSymbolData &B_SD = Asm.getSymbolData(*B);
  576. if (!B_SD.getFragment())
  577. Asm.getContext().FatalError(
  578. Fixup.getLoc(),
  579. Twine("symbol '") + B->getName() +
  580. "' can not be undefined in a subtraction expression");
  581. if (!A_SD.getFragment())
  582. Asm.getContext().FatalError(
  583. Fixup.getLoc(),
  584. Twine("symbol '") + Symbol.getName() +
  585. "' can not be undefined in a subtraction expression");
  586. CrossSection = &Symbol.getSection() != &B->getSection();
  587. // Offset of the symbol in the section
  588. int64_t a = Layout.getSymbolOffset(&B_SD);
  589. // Ofeset of the relocation in the section
  590. int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  591. FixedValue = b - a;
  592. // In the case where we have SymbA and SymB, we just need to store the delta
  593. // between the two symbols. Update FixedValue to account for the delta, and
  594. // skip recording the relocation.
  595. if (!CrossSection)
  596. return;
  597. } else {
  598. FixedValue = Target.getConstant();
  599. }
  600. COFFRelocation Reloc;
  601. Reloc.Data.SymbolTableIndex = 0;
  602. Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);
  603. // Turn relocations for temporary symbols into section relocations.
  604. if (coff_symbol->MCData->getSymbol().isTemporary() || CrossSection) {
  605. Reloc.Symb = coff_symbol->Section->Symbol;
  606. FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment)
  607. + coff_symbol->MCData->getOffset();
  608. } else
  609. Reloc.Symb = coff_symbol;
  610. ++Reloc.Symb->Relocations;
  611. Reloc.Data.VirtualAddress += Fixup.getOffset();
  612. Reloc.Data.Type = TargetObjectWriter->getRelocType(Target, Fixup,
  613. CrossSection);
  614. // FIXME: Can anyone explain what this does other than adjust for the size
  615. // of the offset?
  616. if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 &&
  617. Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) ||
  618. (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 &&
  619. Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32))
  620. FixedValue += 4;
  621. coff_section->Relocations.push_back(Reloc);
  622. }
  623. void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
  624. const MCAsmLayout &Layout) {
  625. // Assign symbol and section indexes and offsets.
  626. Header.NumberOfSections = 0;
  627. DenseMap<COFFSection *, uint16_t> SectionIndices;
  628. for (sections::iterator i = Sections.begin(),
  629. e = Sections.end(); i != e; i++) {
  630. if (Layout.getSectionAddressSize((*i)->MCData) > 0) {
  631. size_t Number = ++Header.NumberOfSections;
  632. SectionIndices[i->get()] = Number;
  633. MakeSectionReal(**i, Number);
  634. } else {
  635. (*i)->Number = -1;
  636. }
  637. }
  638. Header.NumberOfSymbols = 0;
  639. for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) {
  640. COFFSymbol &coff_symbol = **i;
  641. MCSymbolData const *SymbolData = coff_symbol.MCData;
  642. // Update section number & offset for symbols that have them.
  643. if (SymbolData && SymbolData->Fragment) {
  644. assert(coff_symbol.Section != nullptr);
  645. coff_symbol.Data.SectionNumber = coff_symbol.Section->Number;
  646. coff_symbol.Data.Value = Layout.getFragmentOffset(SymbolData->Fragment)
  647. + SymbolData->Offset;
  648. }
  649. if (coff_symbol.should_keep()) {
  650. MakeSymbolReal(coff_symbol, Header.NumberOfSymbols++);
  651. // Update auxiliary symbol info.
  652. coff_symbol.Data.NumberOfAuxSymbols = coff_symbol.Aux.size();
  653. Header.NumberOfSymbols += coff_symbol.Data.NumberOfAuxSymbols;
  654. } else
  655. coff_symbol.Index = -1;
  656. }
  657. // Fixup weak external references.
  658. for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) {
  659. COFFSymbol &coff_symbol = **i;
  660. if (coff_symbol.Other) {
  661. assert(coff_symbol.Index != -1);
  662. assert(coff_symbol.Aux.size() == 1 &&
  663. "Symbol must contain one aux symbol!");
  664. assert(coff_symbol.Aux[0].AuxType == ATWeakExternal &&
  665. "Symbol's aux symbol must be a Weak External!");
  666. coff_symbol.Aux[0].Aux.WeakExternal.TagIndex = coff_symbol.Other->Index;
  667. }
  668. }
  669. // Fixup associative COMDAT sections.
  670. for (sections::iterator i = Sections.begin(),
  671. e = Sections.end(); i != e; i++) {
  672. if ((*i)->Symbol->Aux[0].Aux.SectionDefinition.Selection !=
  673. COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
  674. continue;
  675. const MCSectionCOFF &MCSec = static_cast<const MCSectionCOFF &>(
  676. (*i)->MCData->getSection());
  677. COFFSection *Assoc = SectionMap.lookup(MCSec.getAssocSection());
  678. if (!Assoc) {
  679. report_fatal_error(Twine("Missing associated COMDAT section ") +
  680. MCSec.getAssocSection()->getSectionName() +
  681. " for section " + MCSec.getSectionName());
  682. }
  683. // Skip this section if the associated section is unused.
  684. if (Assoc->Number == -1)
  685. continue;
  686. (*i)->Symbol->Aux[0].Aux.SectionDefinition.Number = SectionIndices[Assoc];
  687. }
  688. // Assign file offsets to COFF object file structures.
  689. unsigned offset = 0;
  690. offset += COFF::HeaderSize;
  691. offset += COFF::SectionSize * Header.NumberOfSections;
  692. for (MCAssembler::const_iterator i = Asm.begin(),
  693. e = Asm.end();
  694. i != e; i++) {
  695. COFFSection *Sec = SectionMap[&i->getSection()];
  696. if (Sec->Number == -1)
  697. continue;
  698. Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(i);
  699. if (IsPhysicalSection(Sec)) {
  700. Sec->Header.PointerToRawData = offset;
  701. offset += Sec->Header.SizeOfRawData;
  702. }
  703. if (Sec->Relocations.size() > 0) {
  704. bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;
  705. if (RelocationsOverflow) {
  706. // Signal overflow by setting NumberOfSections to max value. Actual
  707. // size is found in reloc #0. Microsoft tools understand this.
  708. Sec->Header.NumberOfRelocations = 0xffff;
  709. } else {
  710. Sec->Header.NumberOfRelocations = Sec->Relocations.size();
  711. }
  712. Sec->Header.PointerToRelocations = offset;
  713. if (RelocationsOverflow) {
  714. // Reloc #0 will contain actual count, so make room for it.
  715. offset += COFF::RelocationSize;
  716. }
  717. offset += COFF::RelocationSize * Sec->Relocations.size();
  718. for (relocations::iterator cr = Sec->Relocations.begin(),
  719. er = Sec->Relocations.end();
  720. cr != er; ++cr) {
  721. assert((*cr).Symb->Index != -1);
  722. (*cr).Data.SymbolTableIndex = (*cr).Symb->Index;
  723. }
  724. }
  725. assert(Sec->Symbol->Aux.size() == 1
  726. && "Section's symbol must have one aux!");
  727. AuxSymbol &Aux = Sec->Symbol->Aux[0];
  728. assert(Aux.AuxType == ATSectionDefinition &&
  729. "Section's symbol's aux symbol must be a Section Definition!");
  730. Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
  731. Aux.Aux.SectionDefinition.NumberOfRelocations =
  732. Sec->Header.NumberOfRelocations;
  733. Aux.Aux.SectionDefinition.NumberOfLinenumbers =
  734. Sec->Header.NumberOfLineNumbers;
  735. }
  736. Header.PointerToSymbolTable = offset;
  737. // We want a deterministic output. It looks like GNU as also writes 0 in here.
  738. Header.TimeDateStamp = 0;
  739. // Write it all to disk...
  740. WriteFileHeader(Header);
  741. {
  742. sections::iterator i, ie;
  743. MCAssembler::const_iterator j, je;
  744. for (i = Sections.begin(), ie = Sections.end(); i != ie; i++)
  745. if ((*i)->Number != -1) {
  746. if ((*i)->Relocations.size() >= 0xffff) {
  747. (*i)->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
  748. }
  749. WriteSectionHeader((*i)->Header);
  750. }
  751. for (i = Sections.begin(), ie = Sections.end(),
  752. j = Asm.begin(), je = Asm.end();
  753. (i != ie) && (j != je); ++i, ++j) {
  754. if ((*i)->Number == -1)
  755. continue;
  756. if ((*i)->Header.PointerToRawData != 0) {
  757. assert(OS.tell() == (*i)->Header.PointerToRawData &&
  758. "Section::PointerToRawData is insane!");
  759. Asm.writeSectionData(j, Layout);
  760. }
  761. if ((*i)->Relocations.size() > 0) {
  762. assert(OS.tell() == (*i)->Header.PointerToRelocations &&
  763. "Section::PointerToRelocations is insane!");
  764. if ((*i)->Relocations.size() >= 0xffff) {
  765. // In case of overflow, write actual relocation count as first
  766. // relocation. Including the synthetic reloc itself (+ 1).
  767. COFF::relocation r;
  768. r.VirtualAddress = (*i)->Relocations.size() + 1;
  769. r.SymbolTableIndex = 0;
  770. r.Type = 0;
  771. WriteRelocation(r);
  772. }
  773. for (relocations::const_iterator k = (*i)->Relocations.begin(),
  774. ke = (*i)->Relocations.end();
  775. k != ke; k++) {
  776. WriteRelocation(k->Data);
  777. }
  778. } else
  779. assert((*i)->Header.PointerToRelocations == 0 &&
  780. "Section::PointerToRelocations is insane!");
  781. }
  782. }
  783. assert(OS.tell() == Header.PointerToSymbolTable &&
  784. "Header::PointerToSymbolTable is insane!");
  785. for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++)
  786. if ((*i)->Index != -1)
  787. WriteSymbol(**i);
  788. OS.write((char const *)&Strings.Data.front(), Strings.Data.size());
  789. }
  790. MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) :
  791. Machine(Machine_) {
  792. }
  793. // Pin the vtable to this file.
  794. void MCWinCOFFObjectTargetWriter::anchor() {}
  795. //------------------------------------------------------------------------------
  796. // WinCOFFObjectWriter factory function
  797. namespace llvm {
  798. MCObjectWriter *createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
  799. raw_ostream &OS) {
  800. return new WinCOFFObjectWriter(MOTW, OS);
  801. }
  802. }