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