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/Casting.h" 26 #include "llvm/Support/EndianStream.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/MathExtras.h" 29 30 #include <deque> 31 32 using namespace llvm; 33 34 // An XCOFF object file has a limited set of predefined sections. The most 35 // important ones for us (right now) are: 36 // .text --> contains program code and read-only data. 37 // .data --> contains initialized data, function descriptors, and the TOC. 38 // .bss --> contains uninitialized data. 39 // Each of these sections is composed of 'Control Sections'. A Control Section 40 // is more commonly referred to as a csect. A csect is an indivisible unit of 41 // code or data, and acts as a container for symbols. A csect is mapped 42 // into a section based on its storage-mapping class, with the exception of 43 // XMC_RW which gets mapped to either .data or .bss based on whether it's 44 // explicitly initialized or not. 45 // 46 // We don't represent the sections in the MC layer as there is nothing 47 // interesting about them at at that level: they carry information that is 48 // only relevant to the ObjectWriter, so we materialize them in this class. 49 namespace { 50 51 constexpr unsigned DefaultSectionAlign = 4; 52 constexpr int16_t MaxSectionIndex = INT16_MAX; 53 54 // Packs the csect's alignment and type into a byte. 55 uint8_t getEncodedType(const MCSectionXCOFF *); 56 57 struct XCOFFRelocation { 58 uint32_t SymbolTableIndex; 59 uint32_t FixupOffsetInCsect; 60 uint8_t SignAndSize; 61 uint8_t Type; 62 }; 63 64 // Wrapper around an MCSymbolXCOFF. 65 struct Symbol { 66 const MCSymbolXCOFF *const MCSym; 67 uint32_t SymbolTableIndex; 68 69 XCOFF::VisibilityType getVisibilityType() const { 70 return MCSym->getVisibilityType(); 71 } 72 73 XCOFF::StorageClass getStorageClass() const { 74 return MCSym->getStorageClass(); 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 // It can be a Csect or debug section or DWARF section and so on. 82 struct XCOFFSection { 83 const MCSectionXCOFF *const MCSec; 84 uint32_t SymbolTableIndex; 85 uint64_t Address; 86 uint64_t Size; 87 88 SmallVector<Symbol, 1> Syms; 89 SmallVector<XCOFFRelocation, 1> Relocations; 90 StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); } 91 XCOFF::VisibilityType getVisibilityType() const { 92 return MCSec->getVisibilityType(); 93 } 94 XCOFFSection(const MCSectionXCOFF *MCSec) 95 : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {} 96 }; 97 98 // Type to be used for a container representing a set of csects with 99 // (approximately) the same storage mapping class. For example all the csects 100 // with a storage mapping class of `xmc_pr` will get placed into the same 101 // container. 102 using CsectGroup = std::deque<XCOFFSection>; 103 using CsectGroups = std::deque<CsectGroup *>; 104 105 // The basic section entry defination. This Section represents a section entry 106 // in XCOFF section header table. 107 struct SectionEntry { 108 char Name[XCOFF::NameSize]; 109 // The physical/virtual address of the section. For an object file 110 // these values are equivalent. 111 uint64_t Address; 112 uint64_t Size; 113 uint64_t FileOffsetToData; 114 uint64_t FileOffsetToRelocations; 115 uint32_t RelocationCount; 116 int32_t Flags; 117 118 int16_t Index; 119 120 // XCOFF has special section numbers for symbols: 121 // -2 Specifies N_DEBUG, a special symbolic debugging symbol. 122 // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not 123 // relocatable. 124 // 0 Specifies N_UNDEF, an undefined external symbol. 125 // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that 126 // hasn't been initialized. 127 static constexpr int16_t UninitializedIndex = 128 XCOFF::ReservedSectionNum::N_DEBUG - 1; 129 130 SectionEntry(StringRef N, int32_t Flags) 131 : Name(), Address(0), Size(0), FileOffsetToData(0), 132 FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags), 133 Index(UninitializedIndex) { 134 assert(N.size() <= XCOFF::NameSize && "section name too long"); 135 memcpy(Name, N.data(), N.size()); 136 } 137 138 virtual void reset() { 139 Address = 0; 140 Size = 0; 141 FileOffsetToData = 0; 142 FileOffsetToRelocations = 0; 143 RelocationCount = 0; 144 Index = UninitializedIndex; 145 } 146 147 virtual ~SectionEntry() = default; 148 }; 149 150 // Represents the data related to a section excluding the csects that make up 151 // the raw data of the section. The csects are stored separately as not all 152 // sections contain csects, and some sections contain csects which are better 153 // stored separately, e.g. the .data section containing read-write, descriptor, 154 // TOCBase and TOC-entry csects. 155 struct CsectSectionEntry : public SectionEntry { 156 // Virtual sections do not need storage allocated in the object file. 157 const bool IsVirtual; 158 159 // This is a section containing csect groups. 160 CsectGroups Groups; 161 162 CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual, 163 CsectGroups Groups) 164 : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) { 165 assert(N.size() <= XCOFF::NameSize && "section name too long"); 166 memcpy(Name, N.data(), N.size()); 167 } 168 169 void reset() override { 170 SectionEntry::reset(); 171 // Clear any csects we have stored. 172 for (auto *Group : Groups) 173 Group->clear(); 174 } 175 176 virtual ~CsectSectionEntry() = default; 177 }; 178 179 struct DwarfSectionEntry : public SectionEntry { 180 // For DWARF section entry. 181 std::unique_ptr<XCOFFSection> DwarfSect; 182 183 // For DWARF section, we must use real size in the section header. MemorySize 184 // is for the size the DWARF section occupies including paddings. 185 uint32_t MemorySize; 186 187 DwarfSectionEntry(StringRef N, int32_t Flags, 188 std::unique_ptr<XCOFFSection> Sect) 189 : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)), 190 MemorySize(0) { 191 assert(DwarfSect->MCSec->isDwarfSect() && 192 "This should be a DWARF section!"); 193 assert(N.size() <= XCOFF::NameSize && "section name too long"); 194 memcpy(Name, N.data(), N.size()); 195 } 196 197 DwarfSectionEntry(DwarfSectionEntry &&s) = default; 198 199 virtual ~DwarfSectionEntry() = default; 200 }; 201 202 class XCOFFObjectWriter : public MCObjectWriter { 203 204 uint32_t SymbolTableEntryCount = 0; 205 uint64_t SymbolTableOffset = 0; 206 uint16_t SectionCount = 0; 207 uint64_t RelocationEntryOffset = 0; 208 std::vector<std::pair<std::string, size_t>> FileNames; 209 bool HasVisibility = false; 210 211 support::endian::Writer W; 212 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter; 213 StringTableBuilder Strings; 214 215 const uint64_t MaxRawDataSize = 216 TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX; 217 218 // Maps the MCSection representation to its corresponding XCOFFSection 219 // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into 220 // from its containing MCSectionXCOFF. 221 DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap; 222 223 // Maps the MCSymbol representation to its corrresponding symbol table index. 224 // Needed for relocation. 225 DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap; 226 227 // CsectGroups. These store the csects which make up different parts of 228 // the sections. Should have one for each set of csects that get mapped into 229 // the same section and get handled in a 'similar' way. 230 CsectGroup UndefinedCsects; 231 CsectGroup ProgramCodeCsects; 232 CsectGroup ReadOnlyCsects; 233 CsectGroup DataCsects; 234 CsectGroup FuncDSCsects; 235 CsectGroup TOCCsects; 236 CsectGroup BSSCsects; 237 CsectGroup TDataCsects; 238 CsectGroup TBSSCsects; 239 240 // The Predefined sections. 241 CsectSectionEntry Text; 242 CsectSectionEntry Data; 243 CsectSectionEntry BSS; 244 CsectSectionEntry TData; 245 CsectSectionEntry TBSS; 246 247 // All the XCOFF sections, in the order they will appear in the section header 248 // table. 249 std::array<CsectSectionEntry *const, 5> Sections{ 250 {&Text, &Data, &BSS, &TData, &TBSS}}; 251 252 std::vector<DwarfSectionEntry> DwarfSections; 253 254 CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); 255 256 void reset() override; 257 258 void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override; 259 260 void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *, 261 const MCFixup &, MCValue, uint64_t &) override; 262 263 uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override; 264 265 bool is64Bit() const { return TargetObjectWriter->is64Bit(); } 266 bool nameShouldBeInStringTable(const StringRef &); 267 void writeSymbolName(const StringRef &); 268 269 void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef, 270 const XCOFFSection &CSectionRef, 271 int16_t SectionIndex, 272 uint64_t SymbolOffset); 273 void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef, 274 int16_t SectionIndex, 275 XCOFF::StorageClass StorageClass); 276 void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef, 277 int16_t SectionIndex); 278 void writeFileHeader(); 279 void writeAuxFileHeader(); 280 void writeSectionHeaderTable(); 281 void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout); 282 void writeSectionForControlSectionEntry(const MCAssembler &Asm, 283 const MCAsmLayout &Layout, 284 const CsectSectionEntry &CsectEntry, 285 uint64_t &CurrentAddressLocation); 286 void writeSectionForDwarfSectionEntry(const MCAssembler &Asm, 287 const MCAsmLayout &Layout, 288 const DwarfSectionEntry &DwarfEntry, 289 uint64_t &CurrentAddressLocation); 290 void writeSymbolTable(const MCAsmLayout &Layout); 291 void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion, 292 uint64_t NumberOfRelocEnt = 0); 293 void writeSymbolAuxCsectEntry(uint64_t SectionOrLength, 294 uint8_t SymbolAlignmentAndType, 295 uint8_t StorageMappingClass); 296 void writeSymbolEntry(StringRef SymbolName, uint64_t Value, 297 int16_t SectionNumber, uint16_t SymbolType, 298 uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1); 299 void writeRelocations(); 300 void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section); 301 302 // Called after all the csects and symbols have been processed by 303 // `executePostLayoutBinding`, this function handles building up the majority 304 // of the structures in the object file representation. Namely: 305 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section 306 // sizes. 307 // *) Assigns symbol table indices. 308 // *) Builds up the section header table by adding any non-empty sections to 309 // `Sections`. 310 void assignAddressesAndIndices(const MCAsmLayout &); 311 void finalizeSectionInfo(); 312 313 size_t auxiliaryHeaderSize() const { 314 // 64-bit object files have no auxiliary header. 315 return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0; 316 } 317 318 public: 319 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 320 raw_pwrite_stream &OS); 321 322 void writeWord(uint64_t Word) { 323 is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word); 324 } 325 }; 326 327 XCOFFObjectWriter::XCOFFObjectWriter( 328 std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) 329 : W(OS, support::big), TargetObjectWriter(std::move(MOTW)), 330 Strings(StringTableBuilder::XCOFF), 331 Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false, 332 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}), 333 Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false, 334 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}), 335 BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true, 336 CsectGroups{&BSSCsects}), 337 TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false, 338 CsectGroups{&TDataCsects}), 339 TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true, 340 CsectGroups{&TBSSCsects}) {} 341 342 void XCOFFObjectWriter::reset() { 343 // Clear the mappings we created. 344 SymbolIndexMap.clear(); 345 SectionMap.clear(); 346 347 UndefinedCsects.clear(); 348 // Reset any sections we have written to, and empty the section header table. 349 for (auto *Sec : Sections) 350 Sec->reset(); 351 for (auto &DwarfSec : DwarfSections) 352 DwarfSec.reset(); 353 354 // Reset states in XCOFFObjectWriter. 355 SymbolTableEntryCount = 0; 356 SymbolTableOffset = 0; 357 SectionCount = 0; 358 RelocationEntryOffset = 0; 359 Strings.clear(); 360 361 MCObjectWriter::reset(); 362 } 363 364 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) { 365 switch (MCSec->getMappingClass()) { 366 case XCOFF::XMC_PR: 367 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 368 "Only an initialized csect can contain program code."); 369 return ProgramCodeCsects; 370 case XCOFF::XMC_RO: 371 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 372 "Only an initialized csect can contain read only data."); 373 return ReadOnlyCsects; 374 case XCOFF::XMC_RW: 375 if (XCOFF::XTY_CM == MCSec->getCSectType()) 376 return BSSCsects; 377 378 if (XCOFF::XTY_SD == MCSec->getCSectType()) 379 return DataCsects; 380 381 report_fatal_error("Unhandled mapping of read-write csect to section."); 382 case XCOFF::XMC_DS: 383 return FuncDSCsects; 384 case XCOFF::XMC_BS: 385 assert(XCOFF::XTY_CM == MCSec->getCSectType() && 386 "Mapping invalid csect. CSECT with bss storage class must be " 387 "common type."); 388 return BSSCsects; 389 case XCOFF::XMC_TL: 390 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 391 "Mapping invalid csect. CSECT with tdata storage class must be " 392 "an initialized csect."); 393 return TDataCsects; 394 case XCOFF::XMC_UL: 395 assert(XCOFF::XTY_CM == MCSec->getCSectType() && 396 "Mapping invalid csect. CSECT with tbss storage class must be " 397 "an uninitialized csect."); 398 return TBSSCsects; 399 case XCOFF::XMC_TC0: 400 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 401 "Only an initialized csect can contain TOC-base."); 402 assert(TOCCsects.empty() && 403 "We should have only one TOC-base, and it should be the first csect " 404 "in this CsectGroup."); 405 return TOCCsects; 406 case XCOFF::XMC_TC: 407 case XCOFF::XMC_TE: 408 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 409 "Only an initialized csect can contain TC entry."); 410 assert(!TOCCsects.empty() && 411 "We should at least have a TOC-base in this CsectGroup."); 412 return TOCCsects; 413 case XCOFF::XMC_TD: 414 report_fatal_error("toc-data not yet supported when writing object files."); 415 default: 416 report_fatal_error("Unhandled mapping of csect to section."); 417 } 418 } 419 420 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) { 421 if (XSym->isDefined()) 422 return cast<MCSectionXCOFF>(XSym->getFragment()->getParent()); 423 return XSym->getRepresentedCsect(); 424 } 425 426 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, 427 const MCAsmLayout &Layout) { 428 for (const auto &S : Asm) { 429 const auto *MCSec = cast<const MCSectionXCOFF>(&S); 430 assert(SectionMap.find(MCSec) == SectionMap.end() && 431 "Cannot add a section twice."); 432 433 // If the name does not fit in the storage provided in the symbol table 434 // entry, add it to the string table. 435 if (nameShouldBeInStringTable(MCSec->getSymbolTableName())) 436 Strings.add(MCSec->getSymbolTableName()); 437 if (MCSec->isCsect()) { 438 // A new control section. Its CsectSectionEntry should already be staticly 439 // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of 440 // the CsectSectionEntry. 441 assert(XCOFF::XTY_ER != MCSec->getCSectType() && 442 "An undefined csect should not get registered."); 443 CsectGroup &Group = getCsectGroup(MCSec); 444 Group.emplace_back(MCSec); 445 SectionMap[MCSec] = &Group.back(); 446 } else if (MCSec->isDwarfSect()) { 447 // A new DwarfSectionEntry. 448 std::unique_ptr<XCOFFSection> DwarfSec = 449 std::make_unique<XCOFFSection>(MCSec); 450 SectionMap[MCSec] = DwarfSec.get(); 451 452 DwarfSectionEntry SecEntry(MCSec->getName(), 453 *MCSec->getDwarfSubtypeFlags(), 454 std::move(DwarfSec)); 455 DwarfSections.push_back(std::move(SecEntry)); 456 } else 457 llvm_unreachable("unsupport section type!"); 458 } 459 460 for (const MCSymbol &S : Asm.symbols()) { 461 // Nothing to do for temporary symbols. 462 if (S.isTemporary()) 463 continue; 464 465 const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S); 466 const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym); 467 468 if (XSym->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED) 469 HasVisibility = true; 470 471 if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) { 472 // Handle undefined symbol. 473 UndefinedCsects.emplace_back(ContainingCsect); 474 SectionMap[ContainingCsect] = &UndefinedCsects.back(); 475 if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName())) 476 Strings.add(ContainingCsect->getSymbolTableName()); 477 continue; 478 } 479 480 // If the symbol is the csect itself, we don't need to put the symbol 481 // into csect's Syms. 482 if (XSym == ContainingCsect->getQualNameSymbol()) 483 continue; 484 485 // Only put a label into the symbol table when it is an external label. 486 if (!XSym->isExternal()) 487 continue; 488 489 assert(SectionMap.find(ContainingCsect) != SectionMap.end() && 490 "Expected containing csect to exist in map"); 491 XCOFFSection *Csect = SectionMap[ContainingCsect]; 492 // Lookup the containing csect and add the symbol to it. 493 assert(Csect->MCSec->isCsect() && "only csect is supported now!"); 494 Csect->Syms.emplace_back(XSym); 495 496 // If the name does not fit in the storage provided in the symbol table 497 // entry, add it to the string table. 498 if (nameShouldBeInStringTable(XSym->getSymbolTableName())) 499 Strings.add(XSym->getSymbolTableName()); 500 } 501 502 FileNames = Asm.getFileNames(); 503 // Emit ".file" as the source file name when there is no file name. 504 if (FileNames.empty()) 505 FileNames.emplace_back(".file", 0); 506 for (const std::pair<std::string, size_t> &F : FileNames) { 507 if (nameShouldBeInStringTable(F.first)) 508 Strings.add(F.first); 509 } 510 511 Strings.finalize(); 512 assignAddressesAndIndices(Layout); 513 } 514 515 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm, 516 const MCAsmLayout &Layout, 517 const MCFragment *Fragment, 518 const MCFixup &Fixup, MCValue Target, 519 uint64_t &FixedValue) { 520 auto getIndex = [this](const MCSymbol *Sym, 521 const MCSectionXCOFF *ContainingCsect) { 522 // If we could not find the symbol directly in SymbolIndexMap, this symbol 523 // could either be a temporary symbol or an undefined symbol. In this case, 524 // we would need to have the relocation reference its csect instead. 525 return SymbolIndexMap.find(Sym) != SymbolIndexMap.end() 526 ? SymbolIndexMap[Sym] 527 : SymbolIndexMap[ContainingCsect->getQualNameSymbol()]; 528 }; 529 530 auto getVirtualAddress = 531 [this, &Layout](const MCSymbol *Sym, 532 const MCSectionXCOFF *ContainingSect) -> uint64_t { 533 // A DWARF section. 534 if (ContainingSect->isDwarfSect()) 535 return Layout.getSymbolOffset(*Sym); 536 537 // A csect. 538 if (!Sym->isDefined()) 539 return SectionMap[ContainingSect]->Address; 540 541 // A label. 542 assert(Sym->isDefined() && "not a valid object that has address!"); 543 return SectionMap[ContainingSect]->Address + Layout.getSymbolOffset(*Sym); 544 }; 545 546 const MCSymbol *const SymA = &Target.getSymA()->getSymbol(); 547 548 MCAsmBackend &Backend = Asm.getBackend(); 549 bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & 550 MCFixupKindInfo::FKF_IsPCRel; 551 552 uint8_t Type; 553 uint8_t SignAndSize; 554 std::tie(Type, SignAndSize) = 555 TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel); 556 557 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA)); 558 559 if (SymASec->isCsect() && SymASec->getMappingClass() == XCOFF::XMC_TD) 560 report_fatal_error("toc-data not yet supported when writing object files."); 561 562 assert(SectionMap.find(SymASec) != SectionMap.end() && 563 "Expected containing csect to exist in map."); 564 565 const uint32_t Index = getIndex(SymA, SymASec); 566 if (Type == XCOFF::RelocationType::R_POS || 567 Type == XCOFF::RelocationType::R_TLS) 568 // The FixedValue should be symbol's virtual address in this object file 569 // plus any constant value that we might get. 570 FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant(); 571 else if (Type == XCOFF::RelocationType::R_TLSM) 572 // The FixedValue should always be zero since the region handle is only 573 // known at load time. 574 FixedValue = 0; 575 else if (Type == XCOFF::RelocationType::R_TOC || 576 Type == XCOFF::RelocationType::R_TOCL) { 577 // The FixedValue should be the TOC entry offset from the TOC-base plus any 578 // constant offset value. 579 const int64_t TOCEntryOffset = SectionMap[SymASec]->Address - 580 TOCCsects.front().Address + 581 Target.getConstant(); 582 if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset)) 583 report_fatal_error("TOCEntryOffset overflows in small code model mode"); 584 585 FixedValue = TOCEntryOffset; 586 } 587 588 assert((Fixup.getOffset() <= 589 MaxRawDataSize - Layout.getFragmentOffset(Fragment)) && 590 "Fragment offset + fixup offset is overflowed."); 591 uint32_t FixupOffsetInCsect = 592 Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); 593 594 XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type}; 595 MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent()); 596 assert(SectionMap.find(RelocationSec) != SectionMap.end() && 597 "Expected containing csect to exist in map."); 598 SectionMap[RelocationSec]->Relocations.push_back(Reloc); 599 600 if (!Target.getSymB()) 601 return; 602 603 const MCSymbol *const SymB = &Target.getSymB()->getSymbol(); 604 if (SymA == SymB) 605 report_fatal_error("relocation for opposite term is not yet supported"); 606 607 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB)); 608 assert(SectionMap.find(SymBSec) != SectionMap.end() && 609 "Expected containing csect to exist in map."); 610 if (SymASec == SymBSec) 611 report_fatal_error( 612 "relocation for paired relocatable term is not yet supported"); 613 614 assert(Type == XCOFF::RelocationType::R_POS && 615 "SymA must be R_POS here if it's not opposite term or paired " 616 "relocatable term."); 617 const uint32_t IndexB = getIndex(SymB, SymBSec); 618 // SymB must be R_NEG here, given the general form of Target(MCValue) is 619 // "SymbolA - SymbolB + imm64". 620 const uint8_t TypeB = XCOFF::RelocationType::R_NEG; 621 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB}; 622 SectionMap[RelocationSec]->Relocations.push_back(RelocB); 623 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA, 624 // now we just need to fold "- SymbolB" here. 625 FixedValue -= getVirtualAddress(SymB, SymBSec); 626 } 627 628 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm, 629 const MCAsmLayout &Layout) { 630 uint64_t CurrentAddressLocation = 0; 631 for (const auto *Section : Sections) 632 writeSectionForControlSectionEntry(Asm, Layout, *Section, 633 CurrentAddressLocation); 634 for (const auto &DwarfSection : DwarfSections) 635 writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection, 636 CurrentAddressLocation); 637 } 638 639 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, 640 const MCAsmLayout &Layout) { 641 // We always emit a timestamp of 0 for reproducibility, so ensure incremental 642 // linking is not enabled, in case, like with Windows COFF, such a timestamp 643 // is incompatible with incremental linking of XCOFF. 644 if (Asm.isIncrementalLinkerCompatible()) 645 report_fatal_error("Incremental linking not supported for XCOFF."); 646 647 finalizeSectionInfo(); 648 uint64_t StartOffset = W.OS.tell(); 649 650 writeFileHeader(); 651 writeAuxFileHeader(); 652 writeSectionHeaderTable(); 653 writeSections(Asm, Layout); 654 writeRelocations(); 655 writeSymbolTable(Layout); 656 // Write the string table. 657 Strings.write(W.OS); 658 659 return W.OS.tell() - StartOffset; 660 } 661 662 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) { 663 return SymbolName.size() > XCOFF::NameSize || is64Bit(); 664 } 665 666 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) { 667 // Magic, Offset or SymbolName. 668 if (nameShouldBeInStringTable(SymbolName)) { 669 W.write<int32_t>(0); 670 W.write<uint32_t>(Strings.getOffset(SymbolName)); 671 } else { 672 char Name[XCOFF::NameSize + 1]; 673 std::strncpy(Name, SymbolName.data(), XCOFF::NameSize); 674 ArrayRef<char> NameRef(Name, XCOFF::NameSize); 675 W.write(NameRef); 676 } 677 } 678 679 void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value, 680 int16_t SectionNumber, 681 uint16_t SymbolType, 682 uint8_t StorageClass, 683 uint8_t NumberOfAuxEntries) { 684 if (is64Bit()) { 685 W.write<uint64_t>(Value); 686 W.write<uint32_t>(Strings.getOffset(SymbolName)); 687 } else { 688 writeSymbolName(SymbolName); 689 W.write<uint32_t>(Value); 690 } 691 W.write<int16_t>(SectionNumber); 692 // TODO Set the function indicator (bit 10, 0x0020) for functions 693 // when debugging is enabled. 694 W.write<uint16_t>(SymbolType); 695 W.write<uint8_t>(StorageClass); 696 W.write<uint8_t>(NumberOfAuxEntries); 697 } 698 699 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength, 700 uint8_t SymbolAlignmentAndType, 701 uint8_t StorageMappingClass) { 702 W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength); 703 W.write<uint32_t>(0); // ParameterHashIndex 704 W.write<uint16_t>(0); // TypeChkSectNum 705 W.write<uint8_t>(SymbolAlignmentAndType); 706 W.write<uint8_t>(StorageMappingClass); 707 if (is64Bit()) { 708 W.write<uint32_t>(Hi_32(SectionOrLength)); 709 W.OS.write_zeros(1); // Reserved 710 W.write<uint8_t>(XCOFF::AUX_CSECT); 711 } else { 712 W.write<uint32_t>(0); // StabInfoIndex 713 W.write<uint16_t>(0); // StabSectNum 714 } 715 } 716 717 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry( 718 uint64_t LengthOfSectionPortion, uint64_t NumberOfRelocEnt) { 719 writeWord(LengthOfSectionPortion); 720 if (!is64Bit()) 721 W.OS.write_zeros(4); // Reserved 722 writeWord(NumberOfRelocEnt); 723 if (is64Bit()) { 724 W.OS.write_zeros(1); // Reserved 725 W.write<uint8_t>(XCOFF::AUX_SECT); 726 } else { 727 W.OS.write_zeros(6); // Reserved 728 } 729 } 730 731 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel( 732 const Symbol &SymbolRef, const XCOFFSection &CSectionRef, 733 int16_t SectionIndex, uint64_t SymbolOffset) { 734 assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address && 735 "Symbol address overflowed."); 736 737 writeSymbolEntry(SymbolRef.getSymbolTableName(), 738 CSectionRef.Address + SymbolOffset, SectionIndex, 739 SymbolRef.getVisibilityType(), SymbolRef.getStorageClass()); 740 741 writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD, 742 CSectionRef.MCSec->getMappingClass()); 743 } 744 745 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection( 746 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) { 747 assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!"); 748 749 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0, 750 SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF); 751 752 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size); 753 } 754 755 void XCOFFObjectWriter::writeSymbolEntryForControlSection( 756 const XCOFFSection &CSectionRef, int16_t SectionIndex, 757 XCOFF::StorageClass StorageClass) { 758 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address, 759 SectionIndex, CSectionRef.getVisibilityType(), StorageClass); 760 761 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec), 762 CSectionRef.MCSec->getMappingClass()); 763 } 764 765 void XCOFFObjectWriter::writeFileHeader() { 766 W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32); 767 W.write<uint16_t>(SectionCount); 768 W.write<int32_t>(0); // TimeStamp 769 writeWord(SymbolTableOffset); 770 if (is64Bit()) { 771 W.write<uint16_t>(auxiliaryHeaderSize()); 772 W.write<uint16_t>(0); // Flags 773 W.write<int32_t>(SymbolTableEntryCount); 774 } else { 775 W.write<int32_t>(SymbolTableEntryCount); 776 W.write<uint16_t>(auxiliaryHeaderSize()); 777 W.write<uint16_t>(0); // Flags 778 } 779 } 780 781 void XCOFFObjectWriter::writeAuxFileHeader() { 782 if (!auxiliaryHeaderSize()) 783 return; 784 W.write<uint16_t>(0); // Magic 785 W.write<uint16_t>( 786 XCOFF::NEW_XCOFF_INTERPRET); // Version. The new interpretation of the 787 // n_type field in the symbol table entry is 788 // used in XCOFF32. 789 W.write<uint32_t>(Sections[0]->Size); // TextSize 790 W.write<uint32_t>(Sections[1]->Size); // InitDataSize 791 W.write<uint32_t>(Sections[2]->Size); // BssDataSize 792 W.write<uint32_t>(0); // EntryPointAddr 793 W.write<uint32_t>(Sections[0]->Address); // TextStartAddr 794 W.write<uint32_t>(Sections[1]->Address); // DataStartAddr 795 } 796 797 void XCOFFObjectWriter::writeSectionHeaderTable() { 798 auto writeSectionHeader = [&](const SectionEntry *Sec, bool IsDwarf) { 799 // Nothing to write for this Section. 800 if (Sec->Index == SectionEntry::UninitializedIndex) 801 return false; 802 803 // Write Name. 804 ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize); 805 W.write(NameRef); 806 807 // Write the Physical Address and Virtual Address. In an object file these 808 // are the same. 809 // We use 0 for DWARF sections' Physical and Virtual Addresses. 810 writeWord(IsDwarf ? 0 : Sec->Address); 811 writeWord(IsDwarf ? 0 : Sec->Address); 812 813 writeWord(Sec->Size); 814 writeWord(Sec->FileOffsetToData); 815 writeWord(Sec->FileOffsetToRelocations); 816 writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet. 817 818 if (is64Bit()) { 819 W.write<uint32_t>(Sec->RelocationCount); 820 W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet. 821 W.write<int32_t>(Sec->Flags); 822 W.OS.write_zeros(4); 823 } else { 824 W.write<uint16_t>(Sec->RelocationCount); 825 W.write<uint16_t>(0); // NumberOfLineNumbers. Not supported yet. 826 W.write<int32_t>(Sec->Flags); 827 } 828 829 return true; 830 }; 831 832 for (const auto *CsectSec : Sections) 833 writeSectionHeader(CsectSec, /* IsDwarf */ false); 834 for (const auto &DwarfSec : DwarfSections) 835 writeSectionHeader(&DwarfSec, /* IsDwarf */ true); 836 } 837 838 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc, 839 const XCOFFSection &Section) { 840 if (Section.MCSec->isCsect()) 841 writeWord(Section.Address + Reloc.FixupOffsetInCsect); 842 else { 843 // DWARF sections' address is set to 0. 844 assert(Section.MCSec->isDwarfSect() && "unsupport section type!"); 845 writeWord(Reloc.FixupOffsetInCsect); 846 } 847 W.write<uint32_t>(Reloc.SymbolTableIndex); 848 W.write<uint8_t>(Reloc.SignAndSize); 849 W.write<uint8_t>(Reloc.Type); 850 } 851 852 void XCOFFObjectWriter::writeRelocations() { 853 for (const auto *Section : Sections) { 854 if (Section->Index == SectionEntry::UninitializedIndex) 855 // Nothing to write for this Section. 856 continue; 857 858 for (const auto *Group : Section->Groups) { 859 if (Group->empty()) 860 continue; 861 862 for (const auto &Csect : *Group) { 863 for (const auto Reloc : Csect.Relocations) 864 writeRelocation(Reloc, Csect); 865 } 866 } 867 } 868 869 for (const auto &DwarfSection : DwarfSections) 870 for (const auto &Reloc : DwarfSection.DwarfSect->Relocations) 871 writeRelocation(Reloc, *DwarfSection.DwarfSect); 872 } 873 874 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) { 875 // Write C_FILE symbols. 876 // The n_name of a C_FILE symbol is the source file's name when no auxiliary 877 // entries are present. 878 for (const std::pair<std::string, size_t> &F : FileNames) { 879 writeSymbolEntry(F.first, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG, 880 /*SymbolType=*/0, XCOFF::C_FILE, 881 /*NumberOfAuxEntries=*/0); 882 } 883 884 for (const auto &Csect : UndefinedCsects) { 885 writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF, 886 Csect.MCSec->getStorageClass()); 887 } 888 889 for (const auto *Section : Sections) { 890 if (Section->Index == SectionEntry::UninitializedIndex) 891 // Nothing to write for this Section. 892 continue; 893 894 for (const auto *Group : Section->Groups) { 895 if (Group->empty()) 896 continue; 897 898 const int16_t SectionIndex = Section->Index; 899 for (const auto &Csect : *Group) { 900 // Write out the control section first and then each symbol in it. 901 writeSymbolEntryForControlSection(Csect, SectionIndex, 902 Csect.MCSec->getStorageClass()); 903 904 for (const auto &Sym : Csect.Syms) 905 writeSymbolEntryForCsectMemberLabel( 906 Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym))); 907 } 908 } 909 } 910 911 for (const auto &DwarfSection : DwarfSections) 912 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect, 913 DwarfSection.Index); 914 } 915 916 void XCOFFObjectWriter::finalizeSectionInfo() { 917 for (auto *Section : Sections) { 918 if (Section->Index == SectionEntry::UninitializedIndex) 919 // Nothing to record for this Section. 920 continue; 921 922 for (const auto *Group : Section->Groups) { 923 if (Group->empty()) 924 continue; 925 926 for (auto &Csect : *Group) { 927 const size_t CsectRelocCount = Csect.Relocations.size(); 928 // An XCOFF64 file may not contain an overflow section header. 929 if (!is64Bit() && (CsectRelocCount >= XCOFF::RelocOverflow || 930 Section->RelocationCount >= 931 XCOFF::RelocOverflow - CsectRelocCount)) 932 report_fatal_error( 933 "relocation entries overflowed; overflow section is " 934 "not implemented yet"); 935 936 Section->RelocationCount += CsectRelocCount; 937 } 938 } 939 } 940 941 for (auto &DwarfSection : DwarfSections) 942 DwarfSection.RelocationCount = DwarfSection.DwarfSect->Relocations.size(); 943 944 // Calculate the file offset to the relocation entries. 945 uint64_t RawPointer = RelocationEntryOffset; 946 auto calcOffsetToRelocations = [&](SectionEntry *Sec, bool IsDwarf) { 947 if (!IsDwarf && Sec->Index == SectionEntry::UninitializedIndex) 948 return false; 949 950 if (!Sec->RelocationCount) 951 return false; 952 953 Sec->FileOffsetToRelocations = RawPointer; 954 const uint64_t RelocationSizeInSec = 955 Sec->RelocationCount * (is64Bit() 956 ? XCOFF::RelocationSerializationSize64 957 : XCOFF::RelocationSerializationSize32); 958 RawPointer += RelocationSizeInSec; 959 if (RawPointer > MaxRawDataSize) 960 report_fatal_error("Relocation data overflowed this object file."); 961 962 return true; 963 }; 964 965 for (auto *Sec : Sections) 966 calcOffsetToRelocations(Sec, /* IsDwarf */ false); 967 968 for (auto &DwarfSec : DwarfSections) 969 calcOffsetToRelocations(&DwarfSec, /* IsDwarf */ true); 970 971 // TODO Error check that the number of symbol table entries fits in 32-bits 972 // signed ... 973 if (SymbolTableEntryCount) 974 SymbolTableOffset = RawPointer; 975 } 976 977 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) { 978 // The symbol table starts with all the C_FILE symbols. 979 uint32_t SymbolTableIndex = FileNames.size(); 980 981 // Calculate indices for undefined symbols. 982 for (auto &Csect : UndefinedCsects) { 983 Csect.Size = 0; 984 Csect.Address = 0; 985 Csect.SymbolTableIndex = SymbolTableIndex; 986 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 987 // 1 main and 1 auxiliary symbol table entry for each contained symbol. 988 SymbolTableIndex += 2; 989 } 990 991 // The address corrresponds to the address of sections and symbols in the 992 // object file. We place the shared address 0 immediately after the 993 // section header table. 994 uint64_t Address = 0; 995 // Section indices are 1-based in XCOFF. 996 int32_t SectionIndex = 1; 997 bool HasTDataSection = false; 998 uint32_t PaddingsBeforeDwarf = 0; 999 1000 for (auto *Section : Sections) { 1001 const bool IsEmpty = 1002 llvm::all_of(Section->Groups, 1003 [](const CsectGroup *Group) { return Group->empty(); }); 1004 if (IsEmpty) 1005 continue; 1006 1007 if (SectionIndex > MaxSectionIndex) 1008 report_fatal_error("Section index overflow!"); 1009 Section->Index = SectionIndex++; 1010 SectionCount++; 1011 1012 bool SectionAddressSet = false; 1013 // Reset the starting address to 0 for TData section. 1014 if (Section->Flags == XCOFF::STYP_TDATA) { 1015 Address = 0; 1016 HasTDataSection = true; 1017 } 1018 // Reset the starting address to 0 for TBSS section if the object file does 1019 // not contain TData Section. 1020 if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection) 1021 Address = 0; 1022 1023 for (auto *Group : Section->Groups) { 1024 if (Group->empty()) 1025 continue; 1026 1027 for (auto &Csect : *Group) { 1028 const MCSectionXCOFF *MCSec = Csect.MCSec; 1029 Csect.Address = alignTo(Address, MCSec->getAlignment()); 1030 Csect.Size = Layout.getSectionAddressSize(MCSec); 1031 Address = Csect.Address + Csect.Size; 1032 Csect.SymbolTableIndex = SymbolTableIndex; 1033 SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 1034 // 1 main and 1 auxiliary symbol table entry for the csect. 1035 SymbolTableIndex += 2; 1036 1037 for (auto &Sym : Csect.Syms) { 1038 Sym.SymbolTableIndex = SymbolTableIndex; 1039 SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex; 1040 // 1 main and 1 auxiliary symbol table entry for each contained 1041 // symbol. 1042 SymbolTableIndex += 2; 1043 } 1044 } 1045 1046 if (!SectionAddressSet) { 1047 Section->Address = Group->front().Address; 1048 SectionAddressSet = true; 1049 } 1050 } 1051 1052 // Make sure the address of the next section aligned to 1053 // DefaultSectionAlign. 1054 Address = alignTo(Address, DefaultSectionAlign); 1055 Section->Size = Address - Section->Address; 1056 } 1057 1058 // Start to generate DWARF sections. Sections other than DWARF section use 1059 // DefaultSectionAlign as the default alignment, while DWARF sections have 1060 // their own alignments. If these two alignments are not the same, we need 1061 // some paddings here and record the paddings bytes for FileOffsetToData 1062 // calculation. 1063 if (!DwarfSections.empty()) 1064 PaddingsBeforeDwarf = 1065 alignTo(Address, 1066 (*DwarfSections.begin()).DwarfSect->MCSec->getAlignment()) - 1067 Address; 1068 1069 DwarfSectionEntry *LastDwarfSection = nullptr; 1070 1071 for (auto &DwarfSection : DwarfSections) { 1072 assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!"); 1073 1074 XCOFFSection &DwarfSect = *DwarfSection.DwarfSect; 1075 const MCSectionXCOFF *MCSec = DwarfSect.MCSec; 1076 1077 // Section index. 1078 DwarfSection.Index = SectionIndex++; 1079 SectionCount++; 1080 1081 // Symbol index. 1082 DwarfSect.SymbolTableIndex = SymbolTableIndex; 1083 SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex; 1084 // 1 main and 1 auxiliary symbol table entry for the csect. 1085 SymbolTableIndex += 2; 1086 1087 // Section address. Make it align to section alignment. 1088 // We use address 0 for DWARF sections' Physical and Virtual Addresses. 1089 // This address is used to tell where is the section in the final object. 1090 // See writeSectionForDwarfSectionEntry(). 1091 DwarfSection.Address = DwarfSect.Address = 1092 alignTo(Address, MCSec->getAlignment()); 1093 1094 // Section size. 1095 // For DWARF section, we must use the real size which may be not aligned. 1096 DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec); 1097 1098 Address = DwarfSection.Address + DwarfSection.Size; 1099 1100 if (LastDwarfSection) 1101 LastDwarfSection->MemorySize = 1102 DwarfSection.Address - LastDwarfSection->Address; 1103 LastDwarfSection = &DwarfSection; 1104 } 1105 if (LastDwarfSection) { 1106 // Make the final DWARF section address align to the default section 1107 // alignment for follow contents. 1108 Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size, 1109 DefaultSectionAlign); 1110 LastDwarfSection->MemorySize = Address - LastDwarfSection->Address; 1111 } 1112 1113 SymbolTableEntryCount = SymbolTableIndex; 1114 1115 // Calculate the RawPointer value for each section. 1116 uint64_t RawPointer = 1117 (is64Bit() ? (XCOFF::FileHeaderSize64 + 1118 SectionCount * XCOFF::SectionHeaderSize64) 1119 : (XCOFF::FileHeaderSize32 + 1120 SectionCount * XCOFF::SectionHeaderSize32)) + 1121 auxiliaryHeaderSize(); 1122 1123 for (auto *Sec : Sections) { 1124 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual) 1125 continue; 1126 1127 Sec->FileOffsetToData = RawPointer; 1128 RawPointer += Sec->Size; 1129 if (RawPointer > MaxRawDataSize) 1130 report_fatal_error("Section raw data overflowed this object file."); 1131 } 1132 1133 // Increase the raw pointer for the padding bytes between csect sections and 1134 // DWARF sections. 1135 if (!DwarfSections.empty()) 1136 RawPointer += PaddingsBeforeDwarf; 1137 1138 for (auto &DwarfSection : DwarfSections) { 1139 DwarfSection.FileOffsetToData = RawPointer; 1140 1141 RawPointer += DwarfSection.MemorySize; 1142 1143 assert(RawPointer <= MaxRawDataSize && 1144 "Section raw data overflowed this object file."); 1145 } 1146 1147 RelocationEntryOffset = RawPointer; 1148 } 1149 1150 void XCOFFObjectWriter::writeSectionForControlSectionEntry( 1151 const MCAssembler &Asm, const MCAsmLayout &Layout, 1152 const CsectSectionEntry &CsectEntry, uint64_t &CurrentAddressLocation) { 1153 // Nothing to write for this Section. 1154 if (CsectEntry.Index == SectionEntry::UninitializedIndex) 1155 return; 1156 1157 // There could be a gap (without corresponding zero padding) between 1158 // sections. 1159 // There could be a gap (without corresponding zero padding) between 1160 // sections. 1161 assert(((CurrentAddressLocation <= CsectEntry.Address) || 1162 (CsectEntry.Flags == XCOFF::STYP_TDATA) || 1163 (CsectEntry.Flags == XCOFF::STYP_TBSS)) && 1164 "CurrentAddressLocation should be less than or equal to section " 1165 "address if the section is not TData or TBSS."); 1166 1167 CurrentAddressLocation = CsectEntry.Address; 1168 1169 // For virtual sections, nothing to write. But need to increase 1170 // CurrentAddressLocation for later sections like DWARF section has a correct 1171 // writing location. 1172 if (CsectEntry.IsVirtual) { 1173 CurrentAddressLocation += CsectEntry.Size; 1174 return; 1175 } 1176 1177 for (const auto &Group : CsectEntry.Groups) { 1178 for (const auto &Csect : *Group) { 1179 if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation) 1180 W.OS.write_zeros(PaddingSize); 1181 if (Csect.Size) 1182 Asm.writeSectionData(W.OS, Csect.MCSec, Layout); 1183 CurrentAddressLocation = Csect.Address + Csect.Size; 1184 } 1185 } 1186 1187 // The size of the tail padding in a section is the end virtual address of 1188 // the current section minus the the end virtual address of the last csect 1189 // in that section. 1190 if (uint64_t PaddingSize = 1191 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) { 1192 W.OS.write_zeros(PaddingSize); 1193 CurrentAddressLocation += PaddingSize; 1194 } 1195 } 1196 1197 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry( 1198 const MCAssembler &Asm, const MCAsmLayout &Layout, 1199 const DwarfSectionEntry &DwarfEntry, uint64_t &CurrentAddressLocation) { 1200 // There could be a gap (without corresponding zero padding) between 1201 // sections. For example DWARF section alignment is bigger than 1202 // DefaultSectionAlign. 1203 assert(CurrentAddressLocation <= DwarfEntry.Address && 1204 "CurrentAddressLocation should be less than or equal to section " 1205 "address."); 1206 1207 if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation) 1208 W.OS.write_zeros(PaddingSize); 1209 1210 if (DwarfEntry.Size) 1211 Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout); 1212 1213 CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size; 1214 1215 // DWARF section size is not aligned to DefaultSectionAlign. 1216 // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign. 1217 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign; 1218 uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0; 1219 if (TailPaddingSize) 1220 W.OS.write_zeros(TailPaddingSize); 1221 1222 CurrentAddressLocation += TailPaddingSize; 1223 } 1224 1225 // Takes the log base 2 of the alignment and shifts the result into the 5 most 1226 // significant bits of a byte, then or's in the csect type into the least 1227 // significant 3 bits. 1228 uint8_t getEncodedType(const MCSectionXCOFF *Sec) { 1229 unsigned Align = Sec->getAlignment(); 1230 assert(isPowerOf2_32(Align) && "Alignment must be a power of 2."); 1231 unsigned Log2Align = Log2_32(Align); 1232 // Result is a number in the range [0, 31] which fits in the 5 least 1233 // significant bits. Shift this value into the 5 most significant bits, and 1234 // bitwise-or in the csect type. 1235 uint8_t EncodedAlign = Log2Align << 3; 1236 return EncodedAlign | Sec->getCSectType(); 1237 } 1238 1239 } // end anonymous namespace 1240 1241 std::unique_ptr<MCObjectWriter> 1242 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 1243 raw_pwrite_stream &OS) { 1244 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS); 1245 } 1246