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