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