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