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