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