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