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