XCOFFObjectWriter.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements XCOFF object file writer information.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/BinaryFormat/XCOFF.h"
  13. #include "llvm/MC/MCAsmBackend.h"
  14. #include "llvm/MC/MCAsmLayout.h"
  15. #include "llvm/MC/MCAssembler.h"
  16. #include "llvm/MC/MCFixup.h"
  17. #include "llvm/MC/MCFixupKindInfo.h"
  18. #include "llvm/MC/MCObjectWriter.h"
  19. #include "llvm/MC/MCSectionXCOFF.h"
  20. #include "llvm/MC/MCSymbolXCOFF.h"
  21. #include "llvm/MC/MCValue.h"
  22. #include "llvm/MC/MCXCOFFObjectWriter.h"
  23. #include "llvm/MC/StringTableBuilder.h"
  24. #include "llvm/Support/EndianStream.h"
  25. #include "llvm/Support/Error.h"
  26. #include "llvm/Support/MathExtras.h"
  27. #include <deque>
  28. using namespace llvm;
  29. // An XCOFF object file has a limited set of predefined sections. The most
  30. // important ones for us (right now) are:
  31. // .text --> contains program code and read-only data.
  32. // .data --> contains initialized data, function descriptors, and the TOC.
  33. // .bss --> contains uninitialized data.
  34. // Each of these sections is composed of 'Control Sections'. A Control Section
  35. // is more commonly referred to as a csect. A csect is an indivisible unit of
  36. // code or data, and acts as a container for symbols. A csect is mapped
  37. // into a section based on its storage-mapping class, with the exception of
  38. // XMC_RW which gets mapped to either .data or .bss based on whether it's
  39. // explicitly initialized or not.
  40. //
  41. // We don't represent the sections in the MC layer as there is nothing
  42. // interesting about them at at that level: they carry information that is
  43. // only relevant to the ObjectWriter, so we materialize them in this class.
  44. namespace {
  45. constexpr unsigned DefaultSectionAlign = 4;
  46. constexpr int16_t MaxSectionIndex = INT16_MAX;
  47. // Packs the csect's alignment and type into a byte.
  48. uint8_t getEncodedType(const MCSectionXCOFF *);
  49. struct XCOFFRelocation {
  50. uint32_t SymbolTableIndex;
  51. uint32_t FixupOffsetInCsect;
  52. uint8_t SignAndSize;
  53. uint8_t Type;
  54. };
  55. // Wrapper around an MCSymbolXCOFF.
  56. struct Symbol {
  57. const MCSymbolXCOFF *const MCSym;
  58. uint32_t SymbolTableIndex;
  59. XCOFF::StorageClass getStorageClass() const {
  60. return MCSym->getStorageClass();
  61. }
  62. StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
  63. Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
  64. };
  65. // Wrapper for an MCSectionXCOFF.
  66. struct ControlSection {
  67. const MCSectionXCOFF *const MCCsect;
  68. uint32_t SymbolTableIndex;
  69. uint32_t Address;
  70. uint32_t Size;
  71. SmallVector<Symbol, 1> Syms;
  72. SmallVector<XCOFFRelocation, 1> Relocations;
  73. StringRef getSymbolTableName() const { return MCCsect->getSymbolTableName(); }
  74. ControlSection(const MCSectionXCOFF *MCSec)
  75. : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
  76. };
  77. // Type to be used for a container representing a set of csects with
  78. // (approximately) the same storage mapping class. For example all the csects
  79. // with a storage mapping class of `xmc_pr` will get placed into the same
  80. // container.
  81. using CsectGroup = std::deque<ControlSection>;
  82. using CsectGroups = std::deque<CsectGroup *>;
  83. // Represents the data related to a section excluding the csects that make up
  84. // the raw data of the section. The csects are stored separately as not all
  85. // sections contain csects, and some sections contain csects which are better
  86. // stored separately, e.g. the .data section containing read-write, descriptor,
  87. // TOCBase and TOC-entry csects.
  88. struct Section {
  89. char Name[XCOFF::NameSize];
  90. // The physical/virtual address of the section. For an object file
  91. // these values are equivalent.
  92. uint32_t Address;
  93. uint32_t Size;
  94. uint32_t FileOffsetToData;
  95. uint32_t FileOffsetToRelocations;
  96. uint32_t RelocationCount;
  97. int32_t Flags;
  98. int16_t Index;
  99. // Virtual sections do not need storage allocated in the object file.
  100. const bool IsVirtual;
  101. // XCOFF has special section numbers for symbols:
  102. // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
  103. // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
  104. // relocatable.
  105. // 0 Specifies N_UNDEF, an undefined external symbol.
  106. // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
  107. // hasn't been initialized.
  108. static constexpr int16_t UninitializedIndex =
  109. XCOFF::ReservedSectionNum::N_DEBUG - 1;
  110. CsectGroups Groups;
  111. void reset() {
  112. Address = 0;
  113. Size = 0;
  114. FileOffsetToData = 0;
  115. FileOffsetToRelocations = 0;
  116. RelocationCount = 0;
  117. Index = UninitializedIndex;
  118. // Clear any csects we have stored.
  119. for (auto *Group : Groups)
  120. Group->clear();
  121. }
  122. Section(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
  123. CsectGroups Groups)
  124. : Name(), Address(0), Size(0), FileOffsetToData(0),
  125. FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
  126. Index(UninitializedIndex), IsVirtual(IsVirtual), Groups(Groups) {
  127. assert(N.size() <= XCOFF::NameSize && "section name too long");
  128. memcpy(Name, N.data(), N.size());
  129. }
  130. };
  131. class XCOFFObjectWriter : public MCObjectWriter {
  132. uint32_t SymbolTableEntryCount = 0;
  133. uint32_t SymbolTableOffset = 0;
  134. uint16_t SectionCount = 0;
  135. uint32_t RelocationEntryOffset = 0;
  136. support::endian::Writer W;
  137. std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
  138. StringTableBuilder Strings;
  139. // Maps the MCSection representation to its corresponding ControlSection
  140. // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
  141. // from its containing MCSectionXCOFF.
  142. DenseMap<const MCSectionXCOFF *, ControlSection *> SectionMap;
  143. // Maps the MCSymbol representation to its corrresponding symbol table index.
  144. // Needed for relocation.
  145. DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
  146. // CsectGroups. These store the csects which make up different parts of
  147. // the sections. Should have one for each set of csects that get mapped into
  148. // the same section and get handled in a 'similar' way.
  149. CsectGroup UndefinedCsects;
  150. CsectGroup ProgramCodeCsects;
  151. CsectGroup ReadOnlyCsects;
  152. CsectGroup DataCsects;
  153. CsectGroup FuncDSCsects;
  154. CsectGroup TOCCsects;
  155. CsectGroup BSSCsects;
  156. // The Predefined sections.
  157. Section Text;
  158. Section Data;
  159. Section BSS;
  160. // All the XCOFF sections, in the order they will appear in the section header
  161. // table.
  162. std::array<Section *const, 3> Sections{{&Text, &Data, &BSS}};
  163. CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
  164. virtual void reset() override;
  165. void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
  166. void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
  167. const MCFixup &, MCValue, uint64_t &) override;
  168. uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
  169. static bool nameShouldBeInStringTable(const StringRef &);
  170. void writeSymbolName(const StringRef &);
  171. void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
  172. const ControlSection &, int16_t,
  173. uint64_t);
  174. void writeSymbolTableEntryForControlSection(const ControlSection &, int16_t,
  175. XCOFF::StorageClass);
  176. void writeFileHeader();
  177. void writeSectionHeaderTable();
  178. void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
  179. void writeSymbolTable(const MCAsmLayout &Layout);
  180. void writeRelocations();
  181. void writeRelocation(XCOFFRelocation Reloc, const ControlSection &CSection);
  182. // Called after all the csects and symbols have been processed by
  183. // `executePostLayoutBinding`, this function handles building up the majority
  184. // of the structures in the object file representation. Namely:
  185. // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
  186. // sizes.
  187. // *) Assigns symbol table indices.
  188. // *) Builds up the section header table by adding any non-empty sections to
  189. // `Sections`.
  190. void assignAddressesAndIndices(const MCAsmLayout &);
  191. void finalizeSectionInfo();
  192. bool
  193. needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
  194. return false;
  195. }
  196. // Returns the size of the auxiliary header to be written to the object file.
  197. size_t auxiliaryHeaderSize() const {
  198. assert(!needsAuxiliaryHeader() &&
  199. "Auxiliary header support not implemented.");
  200. return 0;
  201. }
  202. public:
  203. XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
  204. raw_pwrite_stream &OS);
  205. };
  206. XCOFFObjectWriter::XCOFFObjectWriter(
  207. std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
  208. : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
  209. Strings(StringTableBuilder::XCOFF),
  210. Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
  211. CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
  212. Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
  213. CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
  214. BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
  215. CsectGroups{&BSSCsects}) {}
  216. void XCOFFObjectWriter::reset() {
  217. // Clear the mappings we created.
  218. SymbolIndexMap.clear();
  219. SectionMap.clear();
  220. UndefinedCsects.clear();
  221. // Reset any sections we have written to, and empty the section header table.
  222. for (auto *Sec : Sections)
  223. Sec->reset();
  224. // Reset states in XCOFFObjectWriter.
  225. SymbolTableEntryCount = 0;
  226. SymbolTableOffset = 0;
  227. SectionCount = 0;
  228. RelocationEntryOffset = 0;
  229. Strings.clear();
  230. MCObjectWriter::reset();
  231. }
  232. CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
  233. switch (MCSec->getMappingClass()) {
  234. case XCOFF::XMC_PR:
  235. assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
  236. "Only an initialized csect can contain program code.");
  237. return ProgramCodeCsects;
  238. case XCOFF::XMC_RO:
  239. assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
  240. "Only an initialized csect can contain read only data.");
  241. return ReadOnlyCsects;
  242. case XCOFF::XMC_RW:
  243. if (XCOFF::XTY_CM == MCSec->getCSectType())
  244. return BSSCsects;
  245. if (XCOFF::XTY_SD == MCSec->getCSectType())
  246. return DataCsects;
  247. report_fatal_error("Unhandled mapping of read-write csect to section.");
  248. case XCOFF::XMC_DS:
  249. return FuncDSCsects;
  250. case XCOFF::XMC_BS:
  251. assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
  252. "Mapping invalid csect. CSECT with bss storage class must be "
  253. "common type.");
  254. return BSSCsects;
  255. case XCOFF::XMC_TC0:
  256. assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
  257. "Only an initialized csect can contain TOC-base.");
  258. assert(TOCCsects.empty() &&
  259. "We should have only one TOC-base, and it should be the first csect "
  260. "in this CsectGroup.");
  261. return TOCCsects;
  262. case XCOFF::XMC_TC:
  263. case XCOFF::XMC_TE:
  264. assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
  265. "Only an initialized csect can contain TC entry.");
  266. assert(!TOCCsects.empty() &&
  267. "We should at least have a TOC-base in this CsectGroup.");
  268. return TOCCsects;
  269. default:
  270. report_fatal_error("Unhandled mapping of csect to section.");
  271. }
  272. }
  273. static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
  274. if (XSym->isDefined())
  275. return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
  276. return XSym->getRepresentedCsect();
  277. }
  278. void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
  279. const MCAsmLayout &Layout) {
  280. if (TargetObjectWriter->is64Bit())
  281. report_fatal_error("64-bit XCOFF object files are not supported yet.");
  282. for (const auto &S : Asm) {
  283. const auto *MCSec = cast<const MCSectionXCOFF>(&S);
  284. assert(SectionMap.find(MCSec) == SectionMap.end() &&
  285. "Cannot add a csect twice.");
  286. assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
  287. "An undefined csect should not get registered.");
  288. // If the name does not fit in the storage provided in the symbol table
  289. // entry, add it to the string table.
  290. if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
  291. Strings.add(MCSec->getSymbolTableName());
  292. CsectGroup &Group = getCsectGroup(MCSec);
  293. Group.emplace_back(MCSec);
  294. SectionMap[MCSec] = &Group.back();
  295. }
  296. for (const MCSymbol &S : Asm.symbols()) {
  297. // Nothing to do for temporary symbols.
  298. if (S.isTemporary())
  299. continue;
  300. const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
  301. const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
  302. if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
  303. // Handle undefined symbol.
  304. UndefinedCsects.emplace_back(ContainingCsect);
  305. SectionMap[ContainingCsect] = &UndefinedCsects.back();
  306. if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
  307. Strings.add(ContainingCsect->getSymbolTableName());
  308. continue;
  309. }
  310. // If the symbol is the csect itself, we don't need to put the symbol
  311. // into csect's Syms.
  312. if (XSym == ContainingCsect->getQualNameSymbol())
  313. continue;
  314. // Only put a label into the symbol table when it is an external label.
  315. if (!XSym->isExternal())
  316. continue;
  317. assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
  318. "Expected containing csect to exist in map");
  319. // Lookup the containing csect and add the symbol to it.
  320. SectionMap[ContainingCsect]->Syms.emplace_back(XSym);
  321. // If the name does not fit in the storage provided in the symbol table
  322. // entry, add it to the string table.
  323. if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
  324. Strings.add(XSym->getSymbolTableName());
  325. }
  326. Strings.finalize();
  327. assignAddressesAndIndices(Layout);
  328. }
  329. void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
  330. const MCAsmLayout &Layout,
  331. const MCFragment *Fragment,
  332. const MCFixup &Fixup, MCValue Target,
  333. uint64_t &FixedValue) {
  334. auto getIndex = [this](const MCSymbol *Sym,
  335. const MCSectionXCOFF *ContainingCsect) {
  336. // If we could not find the symbol directly in SymbolIndexMap, this symbol
  337. // could either be a temporary symbol or an undefined symbol. In this case,
  338. // we would need to have the relocation reference its csect instead.
  339. return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
  340. ? SymbolIndexMap[Sym]
  341. : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
  342. };
  343. auto getVirtualAddress = [this,
  344. &Layout](const MCSymbol *Sym,
  345. const MCSectionXCOFF *ContainingCsect) {
  346. // If Sym is a csect, return csect's address.
  347. // If Sym is a label, return csect's address + label's offset from the csect.
  348. return SectionMap[ContainingCsect]->Address +
  349. (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0);
  350. };
  351. const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
  352. MCAsmBackend &Backend = Asm.getBackend();
  353. bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
  354. MCFixupKindInfo::FKF_IsPCRel;
  355. uint8_t Type;
  356. uint8_t SignAndSize;
  357. std::tie(Type, SignAndSize) =
  358. TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
  359. const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
  360. assert(SectionMap.find(SymASec) != SectionMap.end() &&
  361. "Expected containing csect to exist in map.");
  362. const uint32_t Index = getIndex(SymA, SymASec);
  363. if (Type == XCOFF::RelocationType::R_POS)
  364. // The FixedValue should be symbol's virtual address in this object file
  365. // plus any constant value that we might get.
  366. FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
  367. else if (Type == XCOFF::RelocationType::R_TOC ||
  368. Type == XCOFF::RelocationType::R_TOCL) {
  369. // The FixedValue should be the TOC entry offset from the TOC-base plus any
  370. // constant offset value.
  371. const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
  372. TOCCsects.front().Address +
  373. Target.getConstant();
  374. if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
  375. report_fatal_error("TOCEntryOffset overflows in small code model mode");
  376. FixedValue = TOCEntryOffset;
  377. }
  378. assert(
  379. (TargetObjectWriter->is64Bit() ||
  380. Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
  381. "Fragment offset + fixup offset is overflowed in 32-bit mode.");
  382. uint32_t FixupOffsetInCsect =
  383. Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  384. XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
  385. MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
  386. assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
  387. "Expected containing csect to exist in map.");
  388. SectionMap[RelocationSec]->Relocations.push_back(Reloc);
  389. if (!Target.getSymB())
  390. return;
  391. const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
  392. if (SymA == SymB)
  393. report_fatal_error("relocation for opposite term is not yet supported");
  394. const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
  395. assert(SectionMap.find(SymBSec) != SectionMap.end() &&
  396. "Expected containing csect to exist in map.");
  397. if (SymASec == SymBSec)
  398. report_fatal_error(
  399. "relocation for paired relocatable term is not yet supported");
  400. assert(Type == XCOFF::RelocationType::R_POS &&
  401. "SymA must be R_POS here if it's not opposite term or paired "
  402. "relocatable term.");
  403. const uint32_t IndexB = getIndex(SymB, SymBSec);
  404. // SymB must be R_NEG here, given the general form of Target(MCValue) is
  405. // "SymbolA - SymbolB + imm64".
  406. const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
  407. XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
  408. SectionMap[RelocationSec]->Relocations.push_back(RelocB);
  409. // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
  410. // now we just need to fold "- SymbolB" here.
  411. FixedValue -= getVirtualAddress(SymB, SymBSec);
  412. }
  413. void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
  414. const MCAsmLayout &Layout) {
  415. uint32_t CurrentAddressLocation = 0;
  416. for (const auto *Section : Sections) {
  417. // Nothing to write for this Section.
  418. if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
  419. continue;
  420. // There could be a gap (without corresponding zero padding) between
  421. // sections.
  422. assert(CurrentAddressLocation <= Section->Address &&
  423. "CurrentAddressLocation should be less than or equal to section "
  424. "address.");
  425. CurrentAddressLocation = Section->Address;
  426. for (const auto *Group : Section->Groups) {
  427. for (const auto &Csect : *Group) {
  428. if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
  429. W.OS.write_zeros(PaddingSize);
  430. if (Csect.Size)
  431. Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
  432. CurrentAddressLocation = Csect.Address + Csect.Size;
  433. }
  434. }
  435. // The size of the tail padding in a section is the end virtual address of
  436. // the current section minus the the end virtual address of the last csect
  437. // in that section.
  438. if (uint32_t PaddingSize =
  439. Section->Address + Section->Size - CurrentAddressLocation) {
  440. W.OS.write_zeros(PaddingSize);
  441. CurrentAddressLocation += PaddingSize;
  442. }
  443. }
  444. }
  445. uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
  446. const MCAsmLayout &Layout) {
  447. // We always emit a timestamp of 0 for reproducibility, so ensure incremental
  448. // linking is not enabled, in case, like with Windows COFF, such a timestamp
  449. // is incompatible with incremental linking of XCOFF.
  450. if (Asm.isIncrementalLinkerCompatible())
  451. report_fatal_error("Incremental linking not supported for XCOFF.");
  452. if (TargetObjectWriter->is64Bit())
  453. report_fatal_error("64-bit XCOFF object files are not supported yet.");
  454. finalizeSectionInfo();
  455. uint64_t StartOffset = W.OS.tell();
  456. writeFileHeader();
  457. writeSectionHeaderTable();
  458. writeSections(Asm, Layout);
  459. writeRelocations();
  460. writeSymbolTable(Layout);
  461. // Write the string table.
  462. Strings.write(W.OS);
  463. return W.OS.tell() - StartOffset;
  464. }
  465. bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
  466. return SymbolName.size() > XCOFF::NameSize;
  467. }
  468. void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
  469. if (nameShouldBeInStringTable(SymbolName)) {
  470. W.write<int32_t>(0);
  471. W.write<uint32_t>(Strings.getOffset(SymbolName));
  472. } else {
  473. char Name[XCOFF::NameSize+1];
  474. std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
  475. ArrayRef<char> NameRef(Name, XCOFF::NameSize);
  476. W.write(NameRef);
  477. }
  478. }
  479. void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
  480. const Symbol &SymbolRef, const ControlSection &CSectionRef,
  481. int16_t SectionIndex, uint64_t SymbolOffset) {
  482. // Name or Zeros and string table offset
  483. writeSymbolName(SymbolRef.getSymbolTableName());
  484. assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
  485. "Symbol address overflows.");
  486. W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
  487. W.write<int16_t>(SectionIndex);
  488. // Basic/Derived type. See the description of the n_type field for symbol
  489. // table entries for a detailed description. Since we don't yet support
  490. // visibility, and all other bits are either optionally set or reserved, this
  491. // is always zero.
  492. // TODO FIXME How to assert a symbol's visibilty is default?
  493. // TODO Set the function indicator (bit 10, 0x0020) for functions
  494. // when debugging is enabled.
  495. W.write<uint16_t>(0);
  496. W.write<uint8_t>(SymbolRef.getStorageClass());
  497. // Always 1 aux entry for now.
  498. W.write<uint8_t>(1);
  499. // Now output the auxiliary entry.
  500. W.write<uint32_t>(CSectionRef.SymbolTableIndex);
  501. // Parameter typecheck hash. Not supported.
  502. W.write<uint32_t>(0);
  503. // Typecheck section number. Not supported.
  504. W.write<uint16_t>(0);
  505. // Symbol type: Label
  506. W.write<uint8_t>(XCOFF::XTY_LD);
  507. // Storage mapping class.
  508. W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
  509. // Reserved (x_stab).
  510. W.write<uint32_t>(0);
  511. // Reserved (x_snstab).
  512. W.write<uint16_t>(0);
  513. }
  514. void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
  515. const ControlSection &CSectionRef, int16_t SectionIndex,
  516. XCOFF::StorageClass StorageClass) {
  517. // n_name, n_zeros, n_offset
  518. writeSymbolName(CSectionRef.getSymbolTableName());
  519. // n_value
  520. W.write<uint32_t>(CSectionRef.Address);
  521. // n_scnum
  522. W.write<int16_t>(SectionIndex);
  523. // Basic/Derived type. See the description of the n_type field for symbol
  524. // table entries for a detailed description. Since we don't yet support
  525. // visibility, and all other bits are either optionally set or reserved, this
  526. // is always zero.
  527. // TODO FIXME How to assert a symbol's visibilty is default?
  528. // TODO Set the function indicator (bit 10, 0x0020) for functions
  529. // when debugging is enabled.
  530. W.write<uint16_t>(0);
  531. // n_sclass
  532. W.write<uint8_t>(StorageClass);
  533. // Always 1 aux entry for now.
  534. W.write<uint8_t>(1);
  535. // Now output the auxiliary entry.
  536. W.write<uint32_t>(CSectionRef.Size);
  537. // Parameter typecheck hash. Not supported.
  538. W.write<uint32_t>(0);
  539. // Typecheck section number. Not supported.
  540. W.write<uint16_t>(0);
  541. // Symbol type.
  542. W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect));
  543. // Storage mapping class.
  544. W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
  545. // Reserved (x_stab).
  546. W.write<uint32_t>(0);
  547. // Reserved (x_snstab).
  548. W.write<uint16_t>(0);
  549. }
  550. void XCOFFObjectWriter::writeFileHeader() {
  551. // Magic.
  552. W.write<uint16_t>(0x01df);
  553. // Number of sections.
  554. W.write<uint16_t>(SectionCount);
  555. // Timestamp field. For reproducible output we write a 0, which represents no
  556. // timestamp.
  557. W.write<int32_t>(0);
  558. // Byte Offset to the start of the symbol table.
  559. W.write<uint32_t>(SymbolTableOffset);
  560. // Number of entries in the symbol table.
  561. W.write<int32_t>(SymbolTableEntryCount);
  562. // Size of the optional header.
  563. W.write<uint16_t>(0);
  564. // Flags.
  565. W.write<uint16_t>(0);
  566. }
  567. void XCOFFObjectWriter::writeSectionHeaderTable() {
  568. for (const auto *Sec : Sections) {
  569. // Nothing to write for this Section.
  570. if (Sec->Index == Section::UninitializedIndex)
  571. continue;
  572. // Write Name.
  573. ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
  574. W.write(NameRef);
  575. // Write the Physical Address and Virtual Address. In an object file these
  576. // are the same.
  577. W.write<uint32_t>(Sec->Address);
  578. W.write<uint32_t>(Sec->Address);
  579. W.write<uint32_t>(Sec->Size);
  580. W.write<uint32_t>(Sec->FileOffsetToData);
  581. W.write<uint32_t>(Sec->FileOffsetToRelocations);
  582. // Line number pointer. Not supported yet.
  583. W.write<uint32_t>(0);
  584. W.write<uint16_t>(Sec->RelocationCount);
  585. // Line number counts. Not supported yet.
  586. W.write<uint16_t>(0);
  587. W.write<int32_t>(Sec->Flags);
  588. }
  589. }
  590. void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
  591. const ControlSection &CSection) {
  592. W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
  593. W.write<uint32_t>(Reloc.SymbolTableIndex);
  594. W.write<uint8_t>(Reloc.SignAndSize);
  595. W.write<uint8_t>(Reloc.Type);
  596. }
  597. void XCOFFObjectWriter::writeRelocations() {
  598. for (const auto *Section : Sections) {
  599. if (Section->Index == Section::UninitializedIndex)
  600. // Nothing to write for this Section.
  601. continue;
  602. for (const auto *Group : Section->Groups) {
  603. if (Group->empty())
  604. continue;
  605. for (const auto &Csect : *Group) {
  606. for (const auto Reloc : Csect.Relocations)
  607. writeRelocation(Reloc, Csect);
  608. }
  609. }
  610. }
  611. }
  612. void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
  613. for (const auto &Csect : UndefinedCsects) {
  614. writeSymbolTableEntryForControlSection(
  615. Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass());
  616. }
  617. for (const auto *Section : Sections) {
  618. if (Section->Index == Section::UninitializedIndex)
  619. // Nothing to write for this Section.
  620. continue;
  621. for (const auto *Group : Section->Groups) {
  622. if (Group->empty())
  623. continue;
  624. const int16_t SectionIndex = Section->Index;
  625. for (const auto &Csect : *Group) {
  626. // Write out the control section first and then each symbol in it.
  627. writeSymbolTableEntryForControlSection(
  628. Csect, SectionIndex, Csect.MCCsect->getStorageClass());
  629. for (const auto &Sym : Csect.Syms)
  630. writeSymbolTableEntryForCsectMemberLabel(
  631. Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
  632. }
  633. }
  634. }
  635. }
  636. void XCOFFObjectWriter::finalizeSectionInfo() {
  637. for (auto *Section : Sections) {
  638. if (Section->Index == Section::UninitializedIndex)
  639. // Nothing to record for this Section.
  640. continue;
  641. for (const auto *Group : Section->Groups) {
  642. if (Group->empty())
  643. continue;
  644. for (auto &Csect : *Group) {
  645. const size_t CsectRelocCount = Csect.Relocations.size();
  646. if (CsectRelocCount >= XCOFF::RelocOverflow ||
  647. Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
  648. report_fatal_error(
  649. "relocation entries overflowed; overflow section is "
  650. "not implemented yet");
  651. Section->RelocationCount += CsectRelocCount;
  652. }
  653. }
  654. }
  655. // Calculate the file offset to the relocation entries.
  656. uint64_t RawPointer = RelocationEntryOffset;
  657. for (auto Sec : Sections) {
  658. if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount)
  659. continue;
  660. Sec->FileOffsetToRelocations = RawPointer;
  661. const uint32_t RelocationSizeInSec =
  662. Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
  663. RawPointer += RelocationSizeInSec;
  664. if (RawPointer > UINT32_MAX)
  665. report_fatal_error("Relocation data overflowed this object file.");
  666. }
  667. // TODO Error check that the number of symbol table entries fits in 32-bits
  668. // signed ...
  669. if (SymbolTableEntryCount)
  670. SymbolTableOffset = RawPointer;
  671. }
  672. void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
  673. // The first symbol table entry is for the file name. We are not emitting it
  674. // yet, so start at index 0.
  675. uint32_t SymbolTableIndex = 0;
  676. // Calculate indices for undefined symbols.
  677. for (auto &Csect : UndefinedCsects) {
  678. Csect.Size = 0;
  679. Csect.Address = 0;
  680. Csect.SymbolTableIndex = SymbolTableIndex;
  681. SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex;
  682. // 1 main and 1 auxiliary symbol table entry for each contained symbol.
  683. SymbolTableIndex += 2;
  684. }
  685. // The address corrresponds to the address of sections and symbols in the
  686. // object file. We place the shared address 0 immediately after the
  687. // section header table.
  688. uint32_t Address = 0;
  689. // Section indices are 1-based in XCOFF.
  690. int32_t SectionIndex = 1;
  691. for (auto *Section : Sections) {
  692. const bool IsEmpty =
  693. llvm::all_of(Section->Groups,
  694. [](const CsectGroup *Group) { return Group->empty(); });
  695. if (IsEmpty)
  696. continue;
  697. if (SectionIndex > MaxSectionIndex)
  698. report_fatal_error("Section index overflow!");
  699. Section->Index = SectionIndex++;
  700. SectionCount++;
  701. bool SectionAddressSet = false;
  702. for (auto *Group : Section->Groups) {
  703. if (Group->empty())
  704. continue;
  705. for (auto &Csect : *Group) {
  706. const MCSectionXCOFF *MCSec = Csect.MCCsect;
  707. Csect.Address = alignTo(Address, MCSec->getAlignment());
  708. Csect.Size = Layout.getSectionAddressSize(MCSec);
  709. Address = Csect.Address + Csect.Size;
  710. Csect.SymbolTableIndex = SymbolTableIndex;
  711. SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
  712. // 1 main and 1 auxiliary symbol table entry for the csect.
  713. SymbolTableIndex += 2;
  714. for (auto &Sym : Csect.Syms) {
  715. Sym.SymbolTableIndex = SymbolTableIndex;
  716. SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
  717. // 1 main and 1 auxiliary symbol table entry for each contained
  718. // symbol.
  719. SymbolTableIndex += 2;
  720. }
  721. }
  722. if (!SectionAddressSet) {
  723. Section->Address = Group->front().Address;
  724. SectionAddressSet = true;
  725. }
  726. }
  727. // Make sure the address of the next section aligned to
  728. // DefaultSectionAlign.
  729. Address = alignTo(Address, DefaultSectionAlign);
  730. Section->Size = Address - Section->Address;
  731. }
  732. SymbolTableEntryCount = SymbolTableIndex;
  733. // Calculate the RawPointer value for each section.
  734. uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() +
  735. SectionCount * sizeof(XCOFF::SectionHeader32);
  736. for (auto *Sec : Sections) {
  737. if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual)
  738. continue;
  739. Sec->FileOffsetToData = RawPointer;
  740. RawPointer += Sec->Size;
  741. if (RawPointer > UINT32_MAX)
  742. report_fatal_error("Section raw data overflowed this object file.");
  743. }
  744. RelocationEntryOffset = RawPointer;
  745. }
  746. // Takes the log base 2 of the alignment and shifts the result into the 5 most
  747. // significant bits of a byte, then or's in the csect type into the least
  748. // significant 3 bits.
  749. uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
  750. unsigned Align = Sec->getAlignment();
  751. assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
  752. unsigned Log2Align = Log2_32(Align);
  753. // Result is a number in the range [0, 31] which fits in the 5 least
  754. // significant bits. Shift this value into the 5 most significant bits, and
  755. // bitwise-or in the csect type.
  756. uint8_t EncodedAlign = Log2Align << 3;
  757. return EncodedAlign | Sec->getCSectType();
  758. }
  759. } // end anonymous namespace
  760. std::unique_ptr<MCObjectWriter>
  761. llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
  762. raw_pwrite_stream &OS) {
  763. return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
  764. }