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