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