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 210 support::endian::Writer W; 211 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter; 212 StringTableBuilder Strings; 213 214 const uint64_t MaxRawDataSize = 215 TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX; 216 217 // Maps the MCSection representation to its corresponding XCOFFSection 218 // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into 219 // from its containing MCSectionXCOFF. 220 DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap; 221 222 // Maps the MCSymbol representation to its corrresponding symbol table index. 223 // Needed for relocation. 224 DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap; 225 226 // CsectGroups. These store the csects which make up different parts of 227 // the sections. Should have one for each set of csects that get mapped into 228 // the same section and get handled in a 'similar' way. 229 CsectGroup UndefinedCsects; 230 CsectGroup ProgramCodeCsects; 231 CsectGroup ReadOnlyCsects; 232 CsectGroup DataCsects; 233 CsectGroup FuncDSCsects; 234 CsectGroup TOCCsects; 235 CsectGroup BSSCsects; 236 CsectGroup TDataCsects; 237 CsectGroup TBSSCsects; 238 239 // The Predefined sections. 240 CsectSectionEntry Text; 241 CsectSectionEntry Data; 242 CsectSectionEntry BSS; 243 CsectSectionEntry TData; 244 CsectSectionEntry TBSS; 245 246 // All the XCOFF sections, in the order they will appear in the section header 247 // table. 248 std::array<CsectSectionEntry *const, 5> Sections{ 249 {&Text, &Data, &BSS, &TData, &TBSS}}; 250 251 std::vector<DwarfSectionEntry> DwarfSections; 252 253 CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); 254 255 virtual void reset() override; 256 257 void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override; 258 259 void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *, 260 const MCFixup &, MCValue, uint64_t &) override; 261 262 uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override; 263 264 bool is64Bit() const { return TargetObjectWriter->is64Bit(); } 265 bool nameShouldBeInStringTable(const StringRef &); 266 void writeSymbolName(const StringRef &); 267 268 void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef, 269 const XCOFFSection &CSectionRef, 270 int16_t SectionIndex, 271 uint64_t SymbolOffset); 272 void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef, 273 int16_t SectionIndex, 274 XCOFF::StorageClass StorageClass); 275 void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef, 276 int16_t SectionIndex); 277 void writeFileHeader(); 278 void writeSectionHeaderTable(); 279 void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout); 280 void writeSectionForControlSectionEntry(const MCAssembler &Asm, 281 const MCAsmLayout &Layout, 282 const CsectSectionEntry &CsectEntry, 283 uint64_t &CurrentAddressLocation); 284 void writeSectionForDwarfSectionEntry(const MCAssembler &Asm, 285 const MCAsmLayout &Layout, 286 const DwarfSectionEntry &DwarfEntry, 287 uint64_t &CurrentAddressLocation); 288 void writeSymbolTable(const MCAsmLayout &Layout); 289 void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion, 290 uint64_t NumberOfRelocEnt = 0); 291 void writeSymbolAuxCsectEntry(uint64_t SectionOrLength, 292 uint8_t SymbolAlignmentAndType, 293 uint8_t StorageMappingClass); 294 void writeSymbolEntry(StringRef SymbolName, uint64_t Value, 295 int16_t SectionNumber, uint16_t SymbolType, 296 uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1); 297 void writeRelocations(); 298 void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section); 299 300 // Called after all the csects and symbols have been processed by 301 // `executePostLayoutBinding`, this function handles building up the majority 302 // of the structures in the object file representation. Namely: 303 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section 304 // sizes. 305 // *) Assigns symbol table indices. 306 // *) Builds up the section header table by adding any non-empty sections to 307 // `Sections`. 308 void assignAddressesAndIndices(const MCAsmLayout &); 309 void finalizeSectionInfo(); 310 311 // TODO aux header support not implemented. 312 bool needsAuxiliaryHeader() const { return false; } 313 314 // Returns the size of the auxiliary header to be written to the object file. 315 size_t auxiliaryHeaderSize() const { 316 assert(!needsAuxiliaryHeader() && 317 "Auxiliary header support not implemented."); 318 return 0; 319 } 320 321 public: 322 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 323 raw_pwrite_stream &OS); 324 325 void writeWord(uint64_t Word) { 326 is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word); 327 } 328 }; 329 330 XCOFFObjectWriter::XCOFFObjectWriter( 331 std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) 332 : W(OS, support::big), TargetObjectWriter(std::move(MOTW)), 333 Strings(StringTableBuilder::XCOFF), 334 Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false, 335 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}), 336 Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false, 337 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}), 338 BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true, 339 CsectGroups{&BSSCsects}), 340 TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false, 341 CsectGroups{&TDataCsects}), 342 TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true, 343 CsectGroups{&TBSSCsects}) {} 344 345 void XCOFFObjectWriter::reset() { 346 // Clear the mappings we created. 347 SymbolIndexMap.clear(); 348 SectionMap.clear(); 349 350 UndefinedCsects.clear(); 351 // Reset any sections we have written to, and empty the section header table. 352 for (auto *Sec : Sections) 353 Sec->reset(); 354 for (auto &DwarfSec : DwarfSections) 355 DwarfSec.reset(); 356 357 // Reset states in XCOFFObjectWriter. 358 SymbolTableEntryCount = 0; 359 SymbolTableOffset = 0; 360 SectionCount = 0; 361 RelocationEntryOffset = 0; 362 Strings.clear(); 363 364 MCObjectWriter::reset(); 365 } 366 367 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) { 368 switch (MCSec->getMappingClass()) { 369 case XCOFF::XMC_PR: 370 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 371 "Only an initialized csect can contain program code."); 372 return ProgramCodeCsects; 373 case XCOFF::XMC_RO: 374 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 375 "Only an initialized csect can contain read only data."); 376 return ReadOnlyCsects; 377 case XCOFF::XMC_RW: 378 if (XCOFF::XTY_CM == MCSec->getCSectType()) 379 return BSSCsects; 380 381 if (XCOFF::XTY_SD == MCSec->getCSectType()) 382 return DataCsects; 383 384 report_fatal_error("Unhandled mapping of read-write csect to section."); 385 case XCOFF::XMC_DS: 386 return FuncDSCsects; 387 case XCOFF::XMC_BS: 388 assert(XCOFF::XTY_CM == MCSec->getCSectType() && 389 "Mapping invalid csect. CSECT with bss storage class must be " 390 "common type."); 391 return BSSCsects; 392 case XCOFF::XMC_TL: 393 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 394 "Mapping invalid csect. CSECT with tdata storage class must be " 395 "an initialized csect."); 396 return TDataCsects; 397 case XCOFF::XMC_UL: 398 assert(XCOFF::XTY_CM == MCSec->getCSectType() && 399 "Mapping invalid csect. CSECT with tbss storage class must be " 400 "an uninitialized csect."); 401 return TBSSCsects; 402 case XCOFF::XMC_TC0: 403 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 404 "Only an initialized csect can contain TOC-base."); 405 assert(TOCCsects.empty() && 406 "We should have only one TOC-base, and it should be the first csect " 407 "in this CsectGroup."); 408 return TOCCsects; 409 case XCOFF::XMC_TC: 410 case XCOFF::XMC_TE: 411 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 412 "Only an initialized csect can contain TC entry."); 413 assert(!TOCCsects.empty() && 414 "We should at least have a TOC-base in this CsectGroup."); 415 return TOCCsects; 416 case XCOFF::XMC_TD: 417 report_fatal_error("toc-data not yet supported when writing object files."); 418 default: 419 report_fatal_error("Unhandled mapping of csect to section."); 420 } 421 } 422 423 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) { 424 if (XSym->isDefined()) 425 return cast<MCSectionXCOFF>(XSym->getFragment()->getParent()); 426 return XSym->getRepresentedCsect(); 427 } 428 429 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, 430 const MCAsmLayout &Layout) { 431 for (const auto &S : Asm) { 432 const auto *MCSec = cast<const MCSectionXCOFF>(&S); 433 assert(SectionMap.find(MCSec) == SectionMap.end() && 434 "Cannot add a section twice."); 435 436 // If the name does not fit in the storage provided in the symbol table 437 // entry, add it to the string table. 438 if (nameShouldBeInStringTable(MCSec->getSymbolTableName())) 439 Strings.add(MCSec->getSymbolTableName()); 440 if (MCSec->isCsect()) { 441 // A new control section. Its CsectSectionEntry should already be staticly 442 // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of 443 // the CsectSectionEntry. 444 assert(XCOFF::XTY_ER != MCSec->getCSectType() && 445 "An undefined csect should not get registered."); 446 CsectGroup &Group = getCsectGroup(MCSec); 447 Group.emplace_back(MCSec); 448 SectionMap[MCSec] = &Group.back(); 449 } else if (MCSec->isDwarfSect()) { 450 // A new DwarfSectionEntry. 451 std::unique_ptr<XCOFFSection> DwarfSec = 452 std::make_unique<XCOFFSection>(MCSec); 453 SectionMap[MCSec] = DwarfSec.get(); 454 455 DwarfSectionEntry SecEntry(MCSec->getName(), 456 *MCSec->getDwarfSubtypeFlags(), 457 std::move(DwarfSec)); 458 DwarfSections.push_back(std::move(SecEntry)); 459 } else 460 llvm_unreachable("unsupport section type!"); 461 } 462 463 for (const MCSymbol &S : Asm.symbols()) { 464 // Nothing to do for temporary symbols. 465 if (S.isTemporary()) 466 continue; 467 468 const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S); 469 const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym); 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 writeSectionHeaderTable(); 652 writeSections(Asm, Layout); 653 writeRelocations(); 654 writeSymbolTable(Layout); 655 // Write the string table. 656 Strings.write(W.OS); 657 658 return W.OS.tell() - StartOffset; 659 } 660 661 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) { 662 return SymbolName.size() > XCOFF::NameSize || is64Bit(); 663 } 664 665 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) { 666 // Magic, Offset or SymbolName. 667 if (nameShouldBeInStringTable(SymbolName)) { 668 W.write<int32_t>(0); 669 W.write<uint32_t>(Strings.getOffset(SymbolName)); 670 } else { 671 char Name[XCOFF::NameSize + 1]; 672 std::strncpy(Name, SymbolName.data(), XCOFF::NameSize); 673 ArrayRef<char> NameRef(Name, XCOFF::NameSize); 674 W.write(NameRef); 675 } 676 } 677 678 void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value, 679 int16_t SectionNumber, 680 uint16_t SymbolType, 681 uint8_t StorageClass, 682 uint8_t NumberOfAuxEntries) { 683 if (is64Bit()) { 684 W.write<uint64_t>(Value); 685 W.write<uint32_t>(Strings.getOffset(SymbolName)); 686 } else { 687 writeSymbolName(SymbolName); 688 W.write<uint32_t>(Value); 689 } 690 W.write<int16_t>(SectionNumber); 691 // Basic/Derived type. See the description of the n_type field for symbol 692 // table entries for a detailed description. Since we don't yet support 693 // visibility, and all other bits are either optionally set or reserved, this 694 // is always zero. 695 if (SymbolType != 0) 696 report_fatal_error("Emitting non-zero visibilities is not supported yet."); 697 // TODO Set the function indicator (bit 10, 0x0020) for functions 698 // when debugging is enabled. 699 W.write<uint16_t>(SymbolType); 700 W.write<uint8_t>(StorageClass); 701 W.write<uint8_t>(NumberOfAuxEntries); 702 } 703 704 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength, 705 uint8_t SymbolAlignmentAndType, 706 uint8_t StorageMappingClass) { 707 W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength); 708 W.write<uint32_t>(0); // ParameterHashIndex 709 W.write<uint16_t>(0); // TypeChkSectNum 710 W.write<uint8_t>(SymbolAlignmentAndType); 711 W.write<uint8_t>(StorageMappingClass); 712 if (is64Bit()) { 713 W.write<uint32_t>(Hi_32(SectionOrLength)); 714 W.OS.write_zeros(1); // Reserved 715 W.write<uint8_t>(XCOFF::AUX_CSECT); 716 } else { 717 W.write<uint32_t>(0); // StabInfoIndex 718 W.write<uint16_t>(0); // StabSectNum 719 } 720 } 721 722 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry( 723 uint64_t LengthOfSectionPortion, uint64_t NumberOfRelocEnt) { 724 writeWord(LengthOfSectionPortion); 725 if (!is64Bit()) 726 W.OS.write_zeros(4); // Reserved 727 writeWord(NumberOfRelocEnt); 728 if (is64Bit()) { 729 W.OS.write_zeros(1); // Reserved 730 W.write<uint8_t>(XCOFF::AUX_SECT); 731 } else { 732 W.OS.write_zeros(6); // Reserved 733 } 734 } 735 736 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel( 737 const Symbol &SymbolRef, const XCOFFSection &CSectionRef, 738 int16_t SectionIndex, uint64_t SymbolOffset) { 739 assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address && 740 "Symbol address overflowed."); 741 742 writeSymbolEntry(SymbolRef.getSymbolTableName(), 743 CSectionRef.Address + SymbolOffset, SectionIndex, 744 SymbolRef.getVisibilityType(), SymbolRef.getStorageClass()); 745 746 writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD, 747 CSectionRef.MCSec->getMappingClass()); 748 } 749 750 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection( 751 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) { 752 assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!"); 753 754 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0, 755 SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF); 756 757 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size); 758 } 759 760 void XCOFFObjectWriter::writeSymbolEntryForControlSection( 761 const XCOFFSection &CSectionRef, int16_t SectionIndex, 762 XCOFF::StorageClass StorageClass) { 763 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address, 764 SectionIndex, CSectionRef.getVisibilityType(), StorageClass); 765 766 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec), 767 CSectionRef.MCSec->getMappingClass()); 768 } 769 770 void XCOFFObjectWriter::writeFileHeader() { 771 W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32); 772 W.write<uint16_t>(SectionCount); 773 W.write<int32_t>(0); // TimeStamp 774 writeWord(SymbolTableOffset); 775 if (is64Bit()) { 776 W.write<uint16_t>(0); // AuxHeaderSize. No optional header for an object 777 // file that is not to be loaded. 778 W.write<uint16_t>(0); // Flags 779 W.write<int32_t>(SymbolTableEntryCount); 780 } else { 781 W.write<int32_t>(SymbolTableEntryCount); 782 W.write<uint16_t>(0); // AuxHeaderSize. No optional header for an object 783 // file that is not to be loaded. 784 W.write<uint16_t>(0); // Flags 785 } 786 } 787 788 void XCOFFObjectWriter::writeSectionHeaderTable() { 789 auto writeSectionHeader = [&](const SectionEntry *Sec, bool IsDwarf) { 790 // Nothing to write for this Section. 791 if (Sec->Index == SectionEntry::UninitializedIndex) 792 return false; 793 794 // Write Name. 795 ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize); 796 W.write(NameRef); 797 798 // Write the Physical Address and Virtual Address. In an object file these 799 // are the same. 800 // We use 0 for DWARF sections' Physical and Virtual Addresses. 801 writeWord(IsDwarf ? 0 : Sec->Address); 802 writeWord(IsDwarf ? 0 : Sec->Address); 803 804 writeWord(Sec->Size); 805 writeWord(Sec->FileOffsetToData); 806 writeWord(Sec->FileOffsetToRelocations); 807 writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet. 808 809 if (is64Bit()) { 810 W.write<uint32_t>(Sec->RelocationCount); 811 W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet. 812 W.write<int32_t>(Sec->Flags); 813 W.OS.write_zeros(4); 814 } else { 815 W.write<uint16_t>(Sec->RelocationCount); 816 W.write<uint16_t>(0); // NumberOfLineNumbers. Not supported yet. 817 W.write<int32_t>(Sec->Flags); 818 } 819 820 return true; 821 }; 822 823 for (const auto *CsectSec : Sections) 824 writeSectionHeader(CsectSec, /* IsDwarf */ false); 825 for (const auto &DwarfSec : DwarfSections) 826 writeSectionHeader(&DwarfSec, /* IsDwarf */ true); 827 } 828 829 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc, 830 const XCOFFSection &Section) { 831 if (Section.MCSec->isCsect()) 832 writeWord(Section.Address + Reloc.FixupOffsetInCsect); 833 else { 834 // DWARF sections' address is set to 0. 835 assert(Section.MCSec->isDwarfSect() && "unsupport section type!"); 836 writeWord(Reloc.FixupOffsetInCsect); 837 } 838 W.write<uint32_t>(Reloc.SymbolTableIndex); 839 W.write<uint8_t>(Reloc.SignAndSize); 840 W.write<uint8_t>(Reloc.Type); 841 } 842 843 void XCOFFObjectWriter::writeRelocations() { 844 for (const auto *Section : Sections) { 845 if (Section->Index == SectionEntry::UninitializedIndex) 846 // Nothing to write for this Section. 847 continue; 848 849 for (const auto *Group : Section->Groups) { 850 if (Group->empty()) 851 continue; 852 853 for (const auto &Csect : *Group) { 854 for (const auto Reloc : Csect.Relocations) 855 writeRelocation(Reloc, Csect); 856 } 857 } 858 } 859 860 for (const auto &DwarfSection : DwarfSections) 861 for (const auto &Reloc : DwarfSection.DwarfSect->Relocations) 862 writeRelocation(Reloc, *DwarfSection.DwarfSect); 863 } 864 865 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) { 866 // Write C_FILE symbols. 867 // The n_name of a C_FILE symbol is the source file's name when no auxiliary 868 // entries are present. 869 for (const std::pair<std::string, size_t> &F : FileNames) { 870 writeSymbolEntry(F.first, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG, 871 /*SymbolType=*/0, XCOFF::C_FILE, 872 /*NumberOfAuxEntries=*/0); 873 } 874 875 for (const auto &Csect : UndefinedCsects) { 876 writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF, 877 Csect.MCSec->getStorageClass()); 878 } 879 880 for (const auto *Section : Sections) { 881 if (Section->Index == SectionEntry::UninitializedIndex) 882 // Nothing to write for this Section. 883 continue; 884 885 for (const auto *Group : Section->Groups) { 886 if (Group->empty()) 887 continue; 888 889 const int16_t SectionIndex = Section->Index; 890 for (const auto &Csect : *Group) { 891 // Write out the control section first and then each symbol in it. 892 writeSymbolEntryForControlSection(Csect, SectionIndex, 893 Csect.MCSec->getStorageClass()); 894 895 for (const auto &Sym : Csect.Syms) 896 writeSymbolEntryForCsectMemberLabel( 897 Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym))); 898 } 899 } 900 } 901 902 for (const auto &DwarfSection : DwarfSections) 903 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect, 904 DwarfSection.Index); 905 } 906 907 void XCOFFObjectWriter::finalizeSectionInfo() { 908 for (auto *Section : Sections) { 909 if (Section->Index == SectionEntry::UninitializedIndex) 910 // Nothing to record for this Section. 911 continue; 912 913 for (const auto *Group : Section->Groups) { 914 if (Group->empty()) 915 continue; 916 917 for (auto &Csect : *Group) { 918 const size_t CsectRelocCount = Csect.Relocations.size(); 919 // An XCOFF64 file may not contain an overflow section header. 920 if (!is64Bit() && (CsectRelocCount >= XCOFF::RelocOverflow || 921 Section->RelocationCount >= 922 XCOFF::RelocOverflow - CsectRelocCount)) 923 report_fatal_error( 924 "relocation entries overflowed; overflow section is " 925 "not implemented yet"); 926 927 Section->RelocationCount += CsectRelocCount; 928 } 929 } 930 } 931 932 for (auto &DwarfSection : DwarfSections) 933 DwarfSection.RelocationCount = DwarfSection.DwarfSect->Relocations.size(); 934 935 // Calculate the file offset to the relocation entries. 936 uint64_t RawPointer = RelocationEntryOffset; 937 auto calcOffsetToRelocations = [&](SectionEntry *Sec, bool IsDwarf) { 938 if (!IsDwarf && Sec->Index == SectionEntry::UninitializedIndex) 939 return false; 940 941 if (!Sec->RelocationCount) 942 return false; 943 944 Sec->FileOffsetToRelocations = RawPointer; 945 const uint64_t RelocationSizeInSec = 946 Sec->RelocationCount * (is64Bit() 947 ? XCOFF::RelocationSerializationSize64 948 : XCOFF::RelocationSerializationSize32); 949 RawPointer += RelocationSizeInSec; 950 if (RawPointer > MaxRawDataSize) 951 report_fatal_error("Relocation data overflowed this object file."); 952 953 return true; 954 }; 955 956 for (auto *Sec : Sections) 957 calcOffsetToRelocations(Sec, /* IsDwarf */ false); 958 959 for (auto &DwarfSec : DwarfSections) 960 calcOffsetToRelocations(&DwarfSec, /* IsDwarf */ true); 961 962 // TODO Error check that the number of symbol table entries fits in 32-bits 963 // signed ... 964 if (SymbolTableEntryCount) 965 SymbolTableOffset = RawPointer; 966 } 967 968 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) { 969 // The symbol table starts with all the C_FILE symbols. 970 uint32_t SymbolTableIndex = FileNames.size(); 971 972 // Calculate indices for undefined symbols. 973 for (auto &Csect : UndefinedCsects) { 974 Csect.Size = 0; 975 Csect.Address = 0; 976 Csect.SymbolTableIndex = SymbolTableIndex; 977 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 978 // 1 main and 1 auxiliary symbol table entry for each contained symbol. 979 SymbolTableIndex += 2; 980 } 981 982 // The address corrresponds to the address of sections and symbols in the 983 // object file. We place the shared address 0 immediately after the 984 // section header table. 985 uint64_t Address = 0; 986 // Section indices are 1-based in XCOFF. 987 int32_t SectionIndex = 1; 988 bool HasTDataSection = false; 989 uint32_t PaddingsBeforeDwarf = 0; 990 991 for (auto *Section : Sections) { 992 const bool IsEmpty = 993 llvm::all_of(Section->Groups, 994 [](const CsectGroup *Group) { return Group->empty(); }); 995 if (IsEmpty) 996 continue; 997 998 if (SectionIndex > MaxSectionIndex) 999 report_fatal_error("Section index overflow!"); 1000 Section->Index = SectionIndex++; 1001 SectionCount++; 1002 1003 bool SectionAddressSet = false; 1004 // Reset the starting address to 0 for TData section. 1005 if (Section->Flags == XCOFF::STYP_TDATA) { 1006 Address = 0; 1007 HasTDataSection = true; 1008 } 1009 // Reset the starting address to 0 for TBSS section if the object file does 1010 // not contain TData Section. 1011 if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection) 1012 Address = 0; 1013 1014 for (auto *Group : Section->Groups) { 1015 if (Group->empty()) 1016 continue; 1017 1018 for (auto &Csect : *Group) { 1019 const MCSectionXCOFF *MCSec = Csect.MCSec; 1020 Csect.Address = alignTo(Address, MCSec->getAlignment()); 1021 Csect.Size = Layout.getSectionAddressSize(MCSec); 1022 Address = Csect.Address + Csect.Size; 1023 Csect.SymbolTableIndex = SymbolTableIndex; 1024 SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 1025 // 1 main and 1 auxiliary symbol table entry for the csect. 1026 SymbolTableIndex += 2; 1027 1028 for (auto &Sym : Csect.Syms) { 1029 Sym.SymbolTableIndex = SymbolTableIndex; 1030 SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex; 1031 // 1 main and 1 auxiliary symbol table entry for each contained 1032 // symbol. 1033 SymbolTableIndex += 2; 1034 } 1035 } 1036 1037 if (!SectionAddressSet) { 1038 Section->Address = Group->front().Address; 1039 SectionAddressSet = true; 1040 } 1041 } 1042 1043 // Make sure the address of the next section aligned to 1044 // DefaultSectionAlign. 1045 Address = alignTo(Address, DefaultSectionAlign); 1046 Section->Size = Address - Section->Address; 1047 } 1048 1049 // Start to generate DWARF sections. Sections other than DWARF section use 1050 // DefaultSectionAlign as the default alignment, while DWARF sections have 1051 // their own alignments. If these two alignments are not the same, we need 1052 // some paddings here and record the paddings bytes for FileOffsetToData 1053 // calculation. 1054 if (!DwarfSections.empty()) 1055 PaddingsBeforeDwarf = 1056 alignTo(Address, 1057 (*DwarfSections.begin()).DwarfSect->MCSec->getAlignment()) - 1058 Address; 1059 1060 DwarfSectionEntry *LastDwarfSection = nullptr; 1061 1062 for (auto &DwarfSection : DwarfSections) { 1063 assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!"); 1064 1065 XCOFFSection &DwarfSect = *DwarfSection.DwarfSect; 1066 const MCSectionXCOFF *MCSec = DwarfSect.MCSec; 1067 1068 // Section index. 1069 DwarfSection.Index = SectionIndex++; 1070 SectionCount++; 1071 1072 // Symbol index. 1073 DwarfSect.SymbolTableIndex = SymbolTableIndex; 1074 SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex; 1075 // 1 main and 1 auxiliary symbol table entry for the csect. 1076 SymbolTableIndex += 2; 1077 1078 // Section address. Make it align to section alignment. 1079 // We use address 0 for DWARF sections' Physical and Virtual Addresses. 1080 // This address is used to tell where is the section in the final object. 1081 // See writeSectionForDwarfSectionEntry(). 1082 DwarfSection.Address = DwarfSect.Address = 1083 alignTo(Address, MCSec->getAlignment()); 1084 1085 // Section size. 1086 // For DWARF section, we must use the real size which may be not aligned. 1087 DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec); 1088 1089 Address = DwarfSection.Address + DwarfSection.Size; 1090 1091 if (LastDwarfSection) 1092 LastDwarfSection->MemorySize = 1093 DwarfSection.Address - LastDwarfSection->Address; 1094 LastDwarfSection = &DwarfSection; 1095 } 1096 if (LastDwarfSection) { 1097 // Make the final DWARF section address align to the default section 1098 // alignment for follow contents. 1099 Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size, 1100 DefaultSectionAlign); 1101 LastDwarfSection->MemorySize = Address - LastDwarfSection->Address; 1102 } 1103 1104 SymbolTableEntryCount = SymbolTableIndex; 1105 1106 // Calculate the RawPointer value for each section. 1107 uint64_t RawPointer = 1108 (is64Bit() ? (XCOFF::FileHeaderSize64 + 1109 SectionCount * XCOFF::SectionHeaderSize64) 1110 : (XCOFF::FileHeaderSize32 + 1111 SectionCount * XCOFF::SectionHeaderSize32)) + 1112 auxiliaryHeaderSize(); 1113 1114 for (auto *Sec : Sections) { 1115 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual) 1116 continue; 1117 1118 Sec->FileOffsetToData = RawPointer; 1119 RawPointer += Sec->Size; 1120 if (RawPointer > MaxRawDataSize) 1121 report_fatal_error("Section raw data overflowed this object file."); 1122 } 1123 1124 // Increase the raw pointer for the padding bytes between csect sections and 1125 // DWARF sections. 1126 if (!DwarfSections.empty()) 1127 RawPointer += PaddingsBeforeDwarf; 1128 1129 for (auto &DwarfSection : DwarfSections) { 1130 DwarfSection.FileOffsetToData = RawPointer; 1131 1132 RawPointer += DwarfSection.MemorySize; 1133 1134 assert(RawPointer <= MaxRawDataSize && 1135 "Section raw data overflowed this object file."); 1136 } 1137 1138 RelocationEntryOffset = RawPointer; 1139 } 1140 1141 void XCOFFObjectWriter::writeSectionForControlSectionEntry( 1142 const MCAssembler &Asm, const MCAsmLayout &Layout, 1143 const CsectSectionEntry &CsectEntry, uint64_t &CurrentAddressLocation) { 1144 // Nothing to write for this Section. 1145 if (CsectEntry.Index == SectionEntry::UninitializedIndex) 1146 return; 1147 1148 // There could be a gap (without corresponding zero padding) between 1149 // sections. 1150 // There could be a gap (without corresponding zero padding) between 1151 // sections. 1152 assert(((CurrentAddressLocation <= CsectEntry.Address) || 1153 (CsectEntry.Flags == XCOFF::STYP_TDATA) || 1154 (CsectEntry.Flags == XCOFF::STYP_TBSS)) && 1155 "CurrentAddressLocation should be less than or equal to section " 1156 "address if the section is not TData or TBSS."); 1157 1158 CurrentAddressLocation = CsectEntry.Address; 1159 1160 // For virtual sections, nothing to write. But need to increase 1161 // CurrentAddressLocation for later sections like DWARF section has a correct 1162 // writing location. 1163 if (CsectEntry.IsVirtual) { 1164 CurrentAddressLocation += CsectEntry.Size; 1165 return; 1166 } 1167 1168 for (const auto &Group : CsectEntry.Groups) { 1169 for (const auto &Csect : *Group) { 1170 if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation) 1171 W.OS.write_zeros(PaddingSize); 1172 if (Csect.Size) 1173 Asm.writeSectionData(W.OS, Csect.MCSec, Layout); 1174 CurrentAddressLocation = Csect.Address + Csect.Size; 1175 } 1176 } 1177 1178 // The size of the tail padding in a section is the end virtual address of 1179 // the current section minus the the end virtual address of the last csect 1180 // in that section. 1181 if (uint64_t PaddingSize = 1182 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) { 1183 W.OS.write_zeros(PaddingSize); 1184 CurrentAddressLocation += PaddingSize; 1185 } 1186 } 1187 1188 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry( 1189 const MCAssembler &Asm, const MCAsmLayout &Layout, 1190 const DwarfSectionEntry &DwarfEntry, uint64_t &CurrentAddressLocation) { 1191 // There could be a gap (without corresponding zero padding) between 1192 // sections. For example DWARF section alignment is bigger than 1193 // DefaultSectionAlign. 1194 assert(CurrentAddressLocation <= DwarfEntry.Address && 1195 "CurrentAddressLocation should be less than or equal to section " 1196 "address."); 1197 1198 if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation) 1199 W.OS.write_zeros(PaddingSize); 1200 1201 if (DwarfEntry.Size) 1202 Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout); 1203 1204 CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size; 1205 1206 // DWARF section size is not aligned to DefaultSectionAlign. 1207 // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign. 1208 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign; 1209 uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0; 1210 if (TailPaddingSize) 1211 W.OS.write_zeros(TailPaddingSize); 1212 1213 CurrentAddressLocation += TailPaddingSize; 1214 } 1215 1216 // Takes the log base 2 of the alignment and shifts the result into the 5 most 1217 // significant bits of a byte, then or's in the csect type into the least 1218 // significant 3 bits. 1219 uint8_t getEncodedType(const MCSectionXCOFF *Sec) { 1220 unsigned Align = Sec->getAlignment(); 1221 assert(isPowerOf2_32(Align) && "Alignment must be a power of 2."); 1222 unsigned Log2Align = Log2_32(Align); 1223 // Result is a number in the range [0, 31] which fits in the 5 least 1224 // significant bits. Shift this value into the 5 most significant bits, and 1225 // bitwise-or in the csect type. 1226 uint8_t EncodedAlign = Log2Align << 3; 1227 return EncodedAlign | Sec->getCSectType(); 1228 } 1229 1230 } // end anonymous namespace 1231 1232 std::unique_ptr<MCObjectWriter> 1233 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 1234 raw_pwrite_stream &OS) { 1235 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS); 1236 } 1237