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 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, 317 const MCAsmLayout &Layout) { 318 if (TargetObjectWriter->is64Bit()) 319 report_fatal_error("64-bit XCOFF object files are not supported yet."); 320 321 for (const auto &S : Asm) { 322 const auto *MCSec = cast<const MCSectionXCOFF>(&S); 323 assert(SectionMap.find(MCSec) == SectionMap.end() && 324 "Cannot add a csect twice."); 325 assert(XCOFF::XTY_ER != MCSec->getCSectType() && 326 "An undefined csect should not get registered."); 327 328 // If the name does not fit in the storage provided in the symbol table 329 // entry, add it to the string table. 330 if (nameShouldBeInStringTable(MCSec->getSectionName())) 331 Strings.add(MCSec->getSectionName()); 332 333 CsectGroup &Group = getCsectGroup(MCSec); 334 Group.emplace_back(MCSec); 335 SectionMap[MCSec] = &Group.back(); 336 } 337 338 for (const MCSymbol &S : Asm.symbols()) { 339 // Nothing to do for temporary symbols. 340 if (S.isTemporary()) 341 continue; 342 343 const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S); 344 const MCSectionXCOFF *ContainingCsect = XSym->getContainingCsect(); 345 346 // Handle undefined symbol. 347 if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) { 348 UndefinedCsects.emplace_back(ContainingCsect); 349 SectionMap[ContainingCsect] = &UndefinedCsects.back(); 350 continue; 351 } 352 353 // If the symbol is the csect itself, we don't need to put the symbol 354 // into csect's Syms. 355 if (XSym == ContainingCsect->getQualNameSymbol()) 356 continue; 357 358 assert(SectionMap.find(ContainingCsect) != SectionMap.end() && 359 "Expected containing csect to exist in map"); 360 361 // Lookup the containing csect and add the symbol to it. 362 SectionMap[ContainingCsect]->Syms.emplace_back(XSym); 363 364 // If the name does not fit in the storage provided in the symbol table 365 // entry, add it to the string table. 366 if (nameShouldBeInStringTable(XSym->getName())) 367 Strings.add(XSym->getName()); 368 } 369 370 Strings.finalize(); 371 assignAddressesAndIndices(Layout); 372 } 373 374 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm, 375 const MCAsmLayout &Layout, 376 const MCFragment *Fragment, 377 const MCFixup &Fixup, MCValue Target, 378 uint64_t &FixedValue) { 379 380 if (Target.getSymB()) 381 report_fatal_error("Handling Target.SymB for relocation is unimplemented."); 382 383 const MCSymbol &SymA = Target.getSymA()->getSymbol(); 384 385 MCAsmBackend &Backend = Asm.getBackend(); 386 bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & 387 MCFixupKindInfo::FKF_IsPCRel; 388 389 uint8_t Type; 390 uint8_t SignAndSize; 391 std::tie(Type, SignAndSize) = 392 TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel); 393 394 const MCSectionXCOFF *SymASec = 395 cast<MCSymbolXCOFF>(SymA).getContainingCsect(); 396 assert(SectionMap.find(SymASec) != SectionMap.end() && 397 "Expected containing csect to exist in map."); 398 399 // If we could not find SymA directly in SymbolIndexMap, this symbol could 400 // either be a temporary symbol or an undefined symbol. In this case, we 401 // would need to have the relocation reference its csect instead. 402 uint32_t Index = SymbolIndexMap.find(&SymA) != SymbolIndexMap.end() 403 ? SymbolIndexMap[&SymA] 404 : SymbolIndexMap[SymASec->getQualNameSymbol()]; 405 406 if (Type == XCOFF::RelocationType::R_POS) 407 // The FixedValue should be symbol's virtual address in this object file 408 // plus any constant value that we might get. 409 // Notice that SymA.isDefined() could return false, but SymASec could still 410 // be a defined csect. One of the example is the TOC-base symbol. 411 FixedValue = SectionMap[SymASec]->Address + 412 (SymA.isDefined() ? Layout.getSymbolOffset(SymA) : 0) + 413 Target.getConstant(); 414 else if (Type == XCOFF::RelocationType::R_TOC) 415 // The FixedValue should be the TC entry offset from TOC-base. 416 FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address; 417 418 assert( 419 (TargetObjectWriter->is64Bit() || 420 Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) && 421 "Fragment offset + fixup offset is overflowed in 32-bit mode."); 422 uint32_t FixupOffsetInCsect = 423 Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); 424 425 XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type}; 426 MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent()); 427 assert(SectionMap.find(RelocationSec) != SectionMap.end() && 428 "Expected containing csect to exist in map."); 429 SectionMap[RelocationSec]->Relocations.push_back(Reloc); 430 } 431 432 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm, 433 const MCAsmLayout &Layout) { 434 uint32_t CurrentAddressLocation = 0; 435 for (const auto *Section : Sections) { 436 // Nothing to write for this Section. 437 if (Section->Index == Section::UninitializedIndex || Section->IsVirtual) 438 continue; 439 440 assert(CurrentAddressLocation == Section->Address && 441 "Sections should be written consecutively."); 442 for (const auto *Group : Section->Groups) { 443 for (const auto &Csect : *Group) { 444 if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation) 445 W.OS.write_zeros(PaddingSize); 446 if (Csect.Size) 447 Asm.writeSectionData(W.OS, Csect.MCCsect, Layout); 448 CurrentAddressLocation = Csect.Address + Csect.Size; 449 } 450 } 451 452 // The size of the tail padding in a section is the end virtual address of 453 // the current section minus the the end virtual address of the last csect 454 // in that section. 455 if (uint32_t PaddingSize = 456 Section->Address + Section->Size - CurrentAddressLocation) { 457 W.OS.write_zeros(PaddingSize); 458 CurrentAddressLocation += PaddingSize; 459 } 460 } 461 } 462 463 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, 464 const MCAsmLayout &Layout) { 465 // We always emit a timestamp of 0 for reproducibility, so ensure incremental 466 // linking is not enabled, in case, like with Windows COFF, such a timestamp 467 // is incompatible with incremental linking of XCOFF. 468 if (Asm.isIncrementalLinkerCompatible()) 469 report_fatal_error("Incremental linking not supported for XCOFF."); 470 471 if (TargetObjectWriter->is64Bit()) 472 report_fatal_error("64-bit XCOFF object files are not supported yet."); 473 474 finalizeSectionInfo(); 475 uint64_t StartOffset = W.OS.tell(); 476 477 writeFileHeader(); 478 writeSectionHeaderTable(); 479 writeSections(Asm, Layout); 480 writeRelocations(); 481 482 writeSymbolTable(Layout); 483 // Write the string table. 484 Strings.write(W.OS); 485 486 return W.OS.tell() - StartOffset; 487 } 488 489 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) { 490 return SymbolName.size() > XCOFF::NameSize; 491 } 492 493 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) { 494 if (nameShouldBeInStringTable(SymbolName)) { 495 W.write<int32_t>(0); 496 W.write<uint32_t>(Strings.getOffset(SymbolName)); 497 } else { 498 char Name[XCOFF::NameSize+1]; 499 std::strncpy(Name, SymbolName.data(), XCOFF::NameSize); 500 ArrayRef<char> NameRef(Name, XCOFF::NameSize); 501 W.write(NameRef); 502 } 503 } 504 505 void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel( 506 const Symbol &SymbolRef, const ControlSection &CSectionRef, 507 int16_t SectionIndex, uint64_t SymbolOffset) { 508 // Name or Zeros and string table offset 509 writeSymbolName(SymbolRef.getName()); 510 assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address && 511 "Symbol address overflows."); 512 W.write<uint32_t>(CSectionRef.Address + SymbolOffset); 513 W.write<int16_t>(SectionIndex); 514 // Basic/Derived type. See the description of the n_type field for symbol 515 // table entries for a detailed description. Since we don't yet support 516 // visibility, and all other bits are either optionally set or reserved, this 517 // is always zero. 518 // TODO FIXME How to assert a symbol's visibilty is default? 519 // TODO Set the function indicator (bit 10, 0x0020) for functions 520 // when debugging is enabled. 521 W.write<uint16_t>(0); 522 W.write<uint8_t>(SymbolRef.getStorageClass()); 523 // Always 1 aux entry for now. 524 W.write<uint8_t>(1); 525 526 // Now output the auxiliary entry. 527 W.write<uint32_t>(CSectionRef.SymbolTableIndex); 528 // Parameter typecheck hash. Not supported. 529 W.write<uint32_t>(0); 530 // Typecheck section number. Not supported. 531 W.write<uint16_t>(0); 532 // Symbol type: Label 533 W.write<uint8_t>(XCOFF::XTY_LD); 534 // Storage mapping class. 535 W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass()); 536 // Reserved (x_stab). 537 W.write<uint32_t>(0); 538 // Reserved (x_snstab). 539 W.write<uint16_t>(0); 540 } 541 542 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection( 543 const ControlSection &CSectionRef, int16_t SectionIndex, 544 XCOFF::StorageClass StorageClass) { 545 // n_name, n_zeros, n_offset 546 writeSymbolName(CSectionRef.getName()); 547 // n_value 548 W.write<uint32_t>(CSectionRef.Address); 549 // n_scnum 550 W.write<int16_t>(SectionIndex); 551 // Basic/Derived type. See the description of the n_type field for symbol 552 // table entries for a detailed description. Since we don't yet support 553 // visibility, and all other bits are either optionally set or reserved, this 554 // is always zero. 555 // TODO FIXME How to assert a symbol's visibilty is default? 556 // TODO Set the function indicator (bit 10, 0x0020) for functions 557 // when debugging is enabled. 558 W.write<uint16_t>(0); 559 // n_sclass 560 W.write<uint8_t>(StorageClass); 561 // Always 1 aux entry for now. 562 W.write<uint8_t>(1); 563 564 // Now output the auxiliary entry. 565 W.write<uint32_t>(CSectionRef.Size); 566 // Parameter typecheck hash. Not supported. 567 W.write<uint32_t>(0); 568 // Typecheck section number. Not supported. 569 W.write<uint16_t>(0); 570 // Symbol type. 571 W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect)); 572 // Storage mapping class. 573 W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass()); 574 // Reserved (x_stab). 575 W.write<uint32_t>(0); 576 // Reserved (x_snstab). 577 W.write<uint16_t>(0); 578 } 579 580 void XCOFFObjectWriter::writeFileHeader() { 581 // Magic. 582 W.write<uint16_t>(0x01df); 583 // Number of sections. 584 W.write<uint16_t>(SectionCount); 585 // Timestamp field. For reproducible output we write a 0, which represents no 586 // timestamp. 587 W.write<int32_t>(0); 588 // Byte Offset to the start of the symbol table. 589 W.write<uint32_t>(SymbolTableOffset); 590 // Number of entries in the symbol table. 591 W.write<int32_t>(SymbolTableEntryCount); 592 // Size of the optional header. 593 W.write<uint16_t>(0); 594 // Flags. 595 W.write<uint16_t>(0); 596 } 597 598 void XCOFFObjectWriter::writeSectionHeaderTable() { 599 for (const auto *Sec : Sections) { 600 // Nothing to write for this Section. 601 if (Sec->Index == Section::UninitializedIndex) 602 continue; 603 604 // Write Name. 605 ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize); 606 W.write(NameRef); 607 608 // Write the Physical Address and Virtual Address. In an object file these 609 // are the same. 610 W.write<uint32_t>(Sec->Address); 611 W.write<uint32_t>(Sec->Address); 612 613 W.write<uint32_t>(Sec->Size); 614 W.write<uint32_t>(Sec->FileOffsetToData); 615 W.write<uint32_t>(Sec->FileOffsetToRelocations); 616 617 // Line number pointer. Not supported yet. 618 W.write<uint32_t>(0); 619 620 W.write<uint16_t>(Sec->RelocationCount); 621 622 // Line number counts. Not supported yet. 623 W.write<uint16_t>(0); 624 625 W.write<int32_t>(Sec->Flags); 626 } 627 } 628 629 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc, 630 const ControlSection &CSection) { 631 W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect); 632 W.write<uint32_t>(Reloc.SymbolTableIndex); 633 W.write<uint8_t>(Reloc.SignAndSize); 634 W.write<uint8_t>(Reloc.Type); 635 } 636 637 void XCOFFObjectWriter::writeRelocations() { 638 for (const auto *Section : Sections) { 639 if (Section->Index == Section::UninitializedIndex) 640 // Nothing to write for this Section. 641 continue; 642 643 for (const auto *Group : Section->Groups) { 644 if (Group->empty()) 645 continue; 646 647 for (const auto &Csect : *Group) { 648 for (const auto Reloc : Csect.Relocations) 649 writeRelocation(Reloc, Csect); 650 } 651 } 652 } 653 } 654 655 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) { 656 for (const auto &Csect : UndefinedCsects) { 657 writeSymbolTableEntryForControlSection( 658 Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass()); 659 } 660 661 for (const auto *Section : Sections) { 662 if (Section->Index == Section::UninitializedIndex) 663 // Nothing to write for this Section. 664 continue; 665 666 for (const auto *Group : Section->Groups) { 667 if (Group->empty()) 668 continue; 669 670 const int16_t SectionIndex = Section->Index; 671 for (const auto &Csect : *Group) { 672 // Write out the control section first and then each symbol in it. 673 writeSymbolTableEntryForControlSection( 674 Csect, SectionIndex, Csect.MCCsect->getStorageClass()); 675 676 for (const auto &Sym : Csect.Syms) 677 writeSymbolTableEntryForCsectMemberLabel( 678 Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym))); 679 } 680 } 681 } 682 } 683 684 void XCOFFObjectWriter::finalizeSectionInfo() { 685 for (auto *Section : Sections) { 686 if (Section->Index == Section::UninitializedIndex) 687 // Nothing to record for this Section. 688 continue; 689 690 for (const auto *Group : Section->Groups) { 691 if (Group->empty()) 692 continue; 693 694 for (auto &Csect : *Group) 695 Section->RelocationCount += Csect.Relocations.size(); 696 } 697 } 698 699 // Calculate the file offset to the relocation entries. 700 uint64_t RawPointer = RelocationEntryOffset; 701 for (auto Sec : Sections) { 702 if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount) 703 continue; 704 705 Sec->FileOffsetToRelocations = RawPointer; 706 const uint32_t RelocationSizeInSec = 707 Sec->RelocationCount * XCOFF::RelocationSerializationSize32; 708 RawPointer += RelocationSizeInSec; 709 if (RawPointer > UINT32_MAX) 710 report_fatal_error("Relocation data overflowed this object file."); 711 } 712 713 // TODO Error check that the number of symbol table entries fits in 32-bits 714 // signed ... 715 if (SymbolTableEntryCount) 716 SymbolTableOffset = RawPointer; 717 } 718 719 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) { 720 // The first symbol table entry is for the file name. We are not emitting it 721 // yet, so start at index 0. 722 uint32_t SymbolTableIndex = 0; 723 724 // Calculate indices for undefined symbols. 725 for (auto &Csect : UndefinedCsects) { 726 Csect.Size = 0; 727 Csect.Address = 0; 728 Csect.SymbolTableIndex = SymbolTableIndex; 729 SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex; 730 // 1 main and 1 auxiliary symbol table entry for each contained symbol. 731 SymbolTableIndex += 2; 732 } 733 734 // The address corrresponds to the address of sections and symbols in the 735 // object file. We place the shared address 0 immediately after the 736 // section header table. 737 uint32_t Address = 0; 738 // Section indices are 1-based in XCOFF. 739 int32_t SectionIndex = 1; 740 741 for (auto *Section : Sections) { 742 const bool IsEmpty = 743 llvm::all_of(Section->Groups, 744 [](const CsectGroup *Group) { return Group->empty(); }); 745 if (IsEmpty) 746 continue; 747 748 if (SectionIndex > MaxSectionIndex) 749 report_fatal_error("Section index overflow!"); 750 Section->Index = SectionIndex++; 751 SectionCount++; 752 753 bool SectionAddressSet = false; 754 for (auto *Group : Section->Groups) { 755 if (Group->empty()) 756 continue; 757 758 for (auto &Csect : *Group) { 759 const MCSectionXCOFF *MCSec = Csect.MCCsect; 760 Csect.Address = alignTo(Address, MCSec->getAlignment()); 761 Csect.Size = Layout.getSectionAddressSize(MCSec); 762 Address = Csect.Address + Csect.Size; 763 Csect.SymbolTableIndex = SymbolTableIndex; 764 SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 765 // 1 main and 1 auxiliary symbol table entry for the csect. 766 SymbolTableIndex += 2; 767 768 for (auto &Sym : Csect.Syms) { 769 Sym.SymbolTableIndex = SymbolTableIndex; 770 SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex; 771 // 1 main and 1 auxiliary symbol table entry for each contained 772 // symbol. 773 SymbolTableIndex += 2; 774 } 775 } 776 777 if (!SectionAddressSet) { 778 Section->Address = Group->front().Address; 779 SectionAddressSet = true; 780 } 781 } 782 783 // Make sure the address of the next section aligned to 784 // DefaultSectionAlign. 785 Address = alignTo(Address, DefaultSectionAlign); 786 Section->Size = Address - Section->Address; 787 } 788 789 SymbolTableEntryCount = SymbolTableIndex; 790 791 // Calculate the RawPointer value for each section. 792 uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() + 793 SectionCount * sizeof(XCOFF::SectionHeader32); 794 for (auto *Sec : Sections) { 795 if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual) 796 continue; 797 798 Sec->FileOffsetToData = RawPointer; 799 RawPointer += Sec->Size; 800 if (RawPointer > UINT32_MAX) 801 report_fatal_error("Section raw data overflowed this object file."); 802 } 803 804 RelocationEntryOffset = RawPointer; 805 } 806 807 // Takes the log base 2 of the alignment and shifts the result into the 5 most 808 // significant bits of a byte, then or's in the csect type into the least 809 // significant 3 bits. 810 uint8_t getEncodedType(const MCSectionXCOFF *Sec) { 811 unsigned Align = Sec->getAlignment(); 812 assert(isPowerOf2_32(Align) && "Alignment must be a power of 2."); 813 unsigned Log2Align = Log2_32(Align); 814 // Result is a number in the range [0, 31] which fits in the 5 least 815 // significant bits. Shift this value into the 5 most significant bits, and 816 // bitwise-or in the csect type. 817 uint8_t EncodedAlign = Log2Align << 3; 818 return EncodedAlign | Sec->getCSectType(); 819 } 820 821 } // end anonymous namespace 822 823 std::unique_ptr<MCObjectWriter> 824 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 825 raw_pwrite_stream &OS) { 826 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS); 827 } 828