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