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