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