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