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