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