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/MCAsmLayout.h" 15 #include "llvm/MC/MCAssembler.h" 16 #include "llvm/MC/MCObjectWriter.h" 17 #include "llvm/MC/MCSectionXCOFF.h" 18 #include "llvm/MC/MCSymbolXCOFF.h" 19 #include "llvm/MC/MCValue.h" 20 #include "llvm/MC/MCXCOFFObjectWriter.h" 21 #include "llvm/MC/StringTableBuilder.h" 22 #include "llvm/Support/Error.h" 23 #include "llvm/Support/MathExtras.h" 24 25 #include <deque> 26 27 using namespace llvm; 28 29 // An XCOFF object file has a limited set of predefined sections. The most 30 // important ones for us (right now) are: 31 // .text --> contains program code and read-only data. 32 // .data --> contains initialized data, function descriptors, and the TOC. 33 // .bss --> contains uninitialized data. 34 // Each of these sections is composed of 'Control Sections'. A Control Section 35 // is more commonly referred to as a csect. A csect is an indivisible unit of 36 // code or data, and acts as a container for symbols. A csect is mapped 37 // into a section based on its storage-mapping class, with the exception of 38 // XMC_RW which gets mapped to either .data or .bss based on whether it's 39 // explicitly initialized or not. 40 // 41 // We don't represent the sections in the MC layer as there is nothing 42 // interesting about them at at that level: they carry information that is 43 // only relevant to the ObjectWriter, so we materialize them in this class. 44 namespace { 45 46 constexpr unsigned DefaultSectionAlign = 4; 47 constexpr int16_t MaxSectionIndex = INT16_MAX; 48 49 // Packs the csect's alignment and type into a byte. 50 uint8_t getEncodedType(const MCSectionXCOFF *); 51 52 // Wrapper around an MCSymbolXCOFF. 53 struct Symbol { 54 const MCSymbolXCOFF *const MCSym; 55 uint32_t SymbolTableIndex; 56 57 XCOFF::StorageClass getStorageClass() const { 58 return MCSym->getStorageClass(); 59 } 60 StringRef getName() const { return MCSym->getName(); } 61 Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {} 62 }; 63 64 // Wrapper for an MCSectionXCOFF. 65 struct ControlSection { 66 const MCSectionXCOFF *const MCCsect; 67 uint32_t SymbolTableIndex; 68 uint32_t Address; 69 uint32_t Size; 70 71 SmallVector<Symbol, 1> Syms; 72 StringRef getName() const { return MCCsect->getSectionName(); } 73 ControlSection(const MCSectionXCOFF *MCSec) 74 : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {} 75 }; 76 77 // Type to be used for a container representing a set of csects with 78 // (approximately) the same storage mapping class. For example all the csects 79 // with a storage mapping class of `xmc_pr` will get placed into the same 80 // container. 81 using CsectGroup = std::deque<ControlSection>; 82 83 using CsectGroups = std::deque<CsectGroup *>; 84 85 // Represents the data related to a section excluding the csects that make up 86 // the raw data of the section. The csects are stored separately as not all 87 // sections contain csects, and some sections contain csects which are better 88 // stored separately, e.g. the .data section containing read-write, descriptor, 89 // TOCBase and TOC-entry csects. 90 struct Section { 91 char Name[XCOFF::NameSize]; 92 // The physical/virtual address of the section. For an object file 93 // these values are equivalent. 94 uint32_t Address; 95 uint32_t Size; 96 uint32_t FileOffsetToData; 97 uint32_t FileOffsetToRelocations; 98 uint32_t RelocationCount; 99 int32_t Flags; 100 101 int16_t Index; 102 103 // Virtual sections do not need storage allocated in the object file. 104 const bool IsVirtual; 105 106 // XCOFF has special section numbers for symbols: 107 // -2 Specifies N_DEBUG, a special symbolic debugging symbol. 108 // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not 109 // relocatable. 110 // 0 Specifies N_UNDEF, an undefined external symbol. 111 // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that 112 // hasn't been initialized. 113 static constexpr int16_t UninitializedIndex = 114 XCOFF::ReservedSectionNum::N_DEBUG - 1; 115 116 CsectGroups Groups; 117 118 void reset() { 119 Address = 0; 120 Size = 0; 121 FileOffsetToData = 0; 122 FileOffsetToRelocations = 0; 123 RelocationCount = 0; 124 Index = UninitializedIndex; 125 // Clear any csects we have stored. 126 for (auto *Group : Groups) 127 Group->clear(); 128 } 129 130 Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual, 131 CsectGroups Groups) 132 : Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0), 133 RelocationCount(0), Flags(Flags), Index(UninitializedIndex), 134 IsVirtual(IsVirtual), Groups(Groups) { 135 strncpy(Name, N, XCOFF::NameSize); 136 } 137 }; 138 139 class XCOFFObjectWriter : public MCObjectWriter { 140 141 uint32_t SymbolTableEntryCount = 0; 142 uint32_t SymbolTableOffset = 0; 143 uint16_t SectionCount = 0; 144 145 support::endian::Writer W; 146 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter; 147 StringTableBuilder Strings; 148 149 // CsectGroups. These store the csects which make up different parts of 150 // the sections. Should have one for each set of csects that get mapped into 151 // the same section and get handled in a 'similar' way. 152 CsectGroup ProgramCodeCsects; 153 CsectGroup DataCsects; 154 CsectGroup BSSCsects; 155 156 // The Predefined sections. 157 Section Text; 158 Section Data; 159 Section BSS; 160 161 // All the XCOFF sections, in the order they will appear in the section header 162 // table. 163 std::array<Section *const, 3> Sections{{&Text, &Data, &BSS}}; 164 165 CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); 166 167 virtual void reset() override; 168 169 void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override; 170 171 void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *, 172 const MCFixup &, MCValue, uint64_t &) override; 173 174 uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override; 175 176 static bool nameShouldBeInStringTable(const StringRef &); 177 void writeSymbolName(const StringRef &); 178 void writeSymbolTableEntryForCsectMemberLabel(const Symbol &, 179 const ControlSection &, int16_t, 180 uint64_t); 181 void writeSymbolTableEntryForControlSection(const ControlSection &, int16_t, 182 XCOFF::StorageClass); 183 void writeFileHeader(); 184 void writeSectionHeaderTable(); 185 void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout); 186 void writeSymbolTable(const MCAsmLayout &Layout); 187 188 // Called after all the csects and symbols have been processed by 189 // `executePostLayoutBinding`, this function handles building up the majority 190 // of the structures in the object file representation. Namely: 191 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section 192 // sizes. 193 // *) Assigns symbol table indices. 194 // *) Builds up the section header table by adding any non-empty sections to 195 // `Sections`. 196 void assignAddressesAndIndices(const MCAsmLayout &); 197 198 bool 199 needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */ 200 return false; 201 } 202 203 // Returns the size of the auxiliary header to be written to the object file. 204 size_t auxiliaryHeaderSize() const { 205 assert(!needsAuxiliaryHeader() && 206 "Auxiliary header support not implemented."); 207 return 0; 208 } 209 210 public: 211 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 212 raw_pwrite_stream &OS); 213 }; 214 215 XCOFFObjectWriter::XCOFFObjectWriter( 216 std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) 217 : W(OS, support::big), TargetObjectWriter(std::move(MOTW)), 218 Strings(StringTableBuilder::XCOFF), 219 Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false, 220 CsectGroups{&ProgramCodeCsects}), 221 Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false, 222 CsectGroups{&DataCsects}), 223 BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true, 224 CsectGroups{&BSSCsects}) {} 225 226 void XCOFFObjectWriter::reset() { 227 // Reset any sections we have written to, and empty the section header table. 228 for (auto *Sec : Sections) 229 Sec->reset(); 230 231 // Reset the symbol table and string table. 232 SymbolTableEntryCount = 0; 233 SymbolTableOffset = 0; 234 SectionCount = 0; 235 Strings.clear(); 236 237 MCObjectWriter::reset(); 238 } 239 240 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) { 241 switch (MCSec->getMappingClass()) { 242 case XCOFF::XMC_PR: 243 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 244 "Only an initialized csect can contain program code."); 245 return ProgramCodeCsects; 246 case XCOFF::XMC_RW: 247 if (XCOFF::XTY_CM == MCSec->getCSectType()) 248 return BSSCsects; 249 250 if (XCOFF::XTY_SD == MCSec->getCSectType()) 251 return DataCsects; 252 253 report_fatal_error("Unhandled mapping of read-write csect to section."); 254 case XCOFF::XMC_BS: 255 assert(XCOFF::XTY_CM == MCSec->getCSectType() && 256 "Mapping invalid csect. CSECT with bss storage class must be " 257 "common type."); 258 return BSSCsects; 259 default: 260 report_fatal_error("Unhandled mapping of csect to section."); 261 } 262 } 263 264 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, 265 const MCAsmLayout &Layout) { 266 if (TargetObjectWriter->is64Bit()) 267 report_fatal_error("64-bit XCOFF object files are not supported yet."); 268 269 // Maps the MC Section representation to its corresponding ControlSection 270 // wrapper. Needed for finding the ControlSection to insert an MCSymbol into 271 // from its containing MCSectionXCOFF. 272 DenseMap<const MCSectionXCOFF *, ControlSection *> WrapperMap; 273 274 for (const auto &S : Asm) { 275 const auto *MCSec = cast<const MCSectionXCOFF>(&S); 276 assert(WrapperMap.find(MCSec) == WrapperMap.end() && 277 "Cannot add a csect twice."); 278 279 // If the name does not fit in the storage provided in the symbol table 280 // entry, add it to the string table. 281 if (nameShouldBeInStringTable(MCSec->getSectionName())) 282 Strings.add(MCSec->getSectionName()); 283 284 // TODO FIXME Handle emiting the TOC base. 285 if (MCSec->getMappingClass() == XCOFF::XMC_TC0) 286 continue; 287 288 CsectGroup &Group = getCsectGroup(MCSec); 289 Group.emplace_back(MCSec); 290 WrapperMap[MCSec] = &Group.back(); 291 } 292 293 for (const MCSymbol &S : Asm.symbols()) { 294 // Nothing to do for temporary symbols. 295 if (S.isTemporary()) 296 continue; 297 const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S); 298 299 // Map the symbol into its containing csect. 300 const MCSectionXCOFF *ContainingCsect = XSym->getContainingCsect(); 301 assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() && 302 "Expected containing csect to exist in map"); 303 304 // If the symbol is the Csect itself, we don't need to put the symbol 305 // into Csect's Syms. 306 if (XSym == ContainingCsect->getQualNameSymbol()) 307 continue; 308 309 // Lookup the containing csect and add the symbol to it. 310 WrapperMap[ContainingCsect]->Syms.emplace_back(XSym); 311 312 // If the name does not fit in the storage provided in the symbol table 313 // entry, add it to the string table. 314 if (nameShouldBeInStringTable(XSym->getName())) 315 Strings.add(XSym->getName()); 316 } 317 318 Strings.finalize(); 319 assignAddressesAndIndices(Layout); 320 } 321 322 void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &, 323 const MCFragment *, const MCFixup &, 324 MCValue, uint64_t &) { 325 report_fatal_error("XCOFF relocations not supported."); 326 } 327 328 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm, 329 const MCAsmLayout &Layout) { 330 uint32_t CurrentAddressLocation = 0; 331 for (const auto *Section : Sections) { 332 // Nothing to write for this Section. 333 if (Section->Index == Section::UninitializedIndex || Section->IsVirtual) 334 continue; 335 336 assert(CurrentAddressLocation == Section->Address && 337 "We should have no padding between sections."); 338 for (const auto *Group : Section->Groups) { 339 for (const auto &Csect : *Group) { 340 if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation) 341 W.OS.write_zeros(PaddingSize); 342 Asm.writeSectionData(W.OS, Csect.MCCsect, Layout); 343 CurrentAddressLocation = Csect.Address + Csect.Size; 344 } 345 } 346 347 // The size of the tail padding in a section is the end virtual address of 348 // the current section minus the the end virtual address of the last csect 349 // in that section. 350 if (uint32_t PaddingSize = 351 Section->Address + Section->Size - CurrentAddressLocation) 352 W.OS.write_zeros(PaddingSize); 353 } 354 } 355 356 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, 357 const MCAsmLayout &Layout) { 358 // We always emit a timestamp of 0 for reproducibility, so ensure incremental 359 // linking is not enabled, in case, like with Windows COFF, such a timestamp 360 // is incompatible with incremental linking of XCOFF. 361 if (Asm.isIncrementalLinkerCompatible()) 362 report_fatal_error("Incremental linking not supported for XCOFF."); 363 364 if (TargetObjectWriter->is64Bit()) 365 report_fatal_error("64-bit XCOFF object files are not supported yet."); 366 367 uint64_t StartOffset = W.OS.tell(); 368 369 writeFileHeader(); 370 writeSectionHeaderTable(); 371 writeSections(Asm, Layout); 372 // TODO writeRelocations(); 373 374 writeSymbolTable(Layout); 375 // Write the string table. 376 Strings.write(W.OS); 377 378 return W.OS.tell() - StartOffset; 379 } 380 381 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) { 382 return SymbolName.size() > XCOFF::NameSize; 383 } 384 385 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) { 386 if (nameShouldBeInStringTable(SymbolName)) { 387 W.write<int32_t>(0); 388 W.write<uint32_t>(Strings.getOffset(SymbolName)); 389 } else { 390 char Name[XCOFF::NameSize]; 391 std::strncpy(Name, SymbolName.data(), XCOFF::NameSize); 392 ArrayRef<char> NameRef(Name, XCOFF::NameSize); 393 W.write(NameRef); 394 } 395 } 396 397 void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel( 398 const Symbol &SymbolRef, const ControlSection &CSectionRef, 399 int16_t SectionIndex, uint64_t SymbolOffset) { 400 // Name or Zeros and string table offset 401 writeSymbolName(SymbolRef.getName()); 402 assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address && 403 "Symbol address overflows."); 404 W.write<uint32_t>(CSectionRef.Address + SymbolOffset); 405 W.write<int16_t>(SectionIndex); 406 // Basic/Derived type. See the description of the n_type field for symbol 407 // table entries for a detailed description. Since we don't yet support 408 // visibility, and all other bits are either optionally set or reserved, this 409 // is always zero. 410 // TODO FIXME How to assert a symbol's visibilty is default? 411 // TODO Set the function indicator (bit 10, 0x0020) for functions 412 // when debugging is enabled. 413 W.write<uint16_t>(0); 414 W.write<uint8_t>(SymbolRef.getStorageClass()); 415 // Always 1 aux entry for now. 416 W.write<uint8_t>(1); 417 418 // Now output the auxiliary entry. 419 W.write<uint32_t>(CSectionRef.SymbolTableIndex); 420 // Parameter typecheck hash. Not supported. 421 W.write<uint32_t>(0); 422 // Typecheck section number. Not supported. 423 W.write<uint16_t>(0); 424 // Symbol type: Label 425 W.write<uint8_t>(XCOFF::XTY_LD); 426 // Storage mapping class. 427 W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass()); 428 // Reserved (x_stab). 429 W.write<uint32_t>(0); 430 // Reserved (x_snstab). 431 W.write<uint16_t>(0); 432 } 433 434 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection( 435 const ControlSection &CSectionRef, int16_t SectionIndex, 436 XCOFF::StorageClass StorageClass) { 437 // n_name, n_zeros, n_offset 438 writeSymbolName(CSectionRef.getName()); 439 // n_value 440 W.write<uint32_t>(CSectionRef.Address); 441 // n_scnum 442 W.write<int16_t>(SectionIndex); 443 // Basic/Derived type. See the description of the n_type field for symbol 444 // table entries for a detailed description. Since we don't yet support 445 // visibility, and all other bits are either optionally set or reserved, this 446 // is always zero. 447 // TODO FIXME How to assert a symbol's visibilty is default? 448 // TODO Set the function indicator (bit 10, 0x0020) for functions 449 // when debugging is enabled. 450 W.write<uint16_t>(0); 451 // n_sclass 452 W.write<uint8_t>(StorageClass); 453 // Always 1 aux entry for now. 454 W.write<uint8_t>(1); 455 456 // Now output the auxiliary entry. 457 W.write<uint32_t>(CSectionRef.Size); 458 // Parameter typecheck hash. Not supported. 459 W.write<uint32_t>(0); 460 // Typecheck section number. Not supported. 461 W.write<uint16_t>(0); 462 // Symbol type. 463 W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect)); 464 // Storage mapping class. 465 W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass()); 466 // Reserved (x_stab). 467 W.write<uint32_t>(0); 468 // Reserved (x_snstab). 469 W.write<uint16_t>(0); 470 } 471 472 void XCOFFObjectWriter::writeFileHeader() { 473 // Magic. 474 W.write<uint16_t>(0x01df); 475 // Number of sections. 476 W.write<uint16_t>(SectionCount); 477 // Timestamp field. For reproducible output we write a 0, which represents no 478 // timestamp. 479 W.write<int32_t>(0); 480 // Byte Offset to the start of the symbol table. 481 W.write<uint32_t>(SymbolTableOffset); 482 // Number of entries in the symbol table. 483 W.write<int32_t>(SymbolTableEntryCount); 484 // Size of the optional header. 485 W.write<uint16_t>(0); 486 // Flags. 487 W.write<uint16_t>(0); 488 } 489 490 void XCOFFObjectWriter::writeSectionHeaderTable() { 491 for (const auto *Sec : Sections) { 492 // Nothing to write for this Section. 493 if (Sec->Index == Section::UninitializedIndex) 494 continue; 495 496 // Write Name. 497 ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize); 498 W.write(NameRef); 499 500 // Write the Physical Address and Virtual Address. In an object file these 501 // are the same. 502 W.write<uint32_t>(Sec->Address); 503 W.write<uint32_t>(Sec->Address); 504 505 W.write<uint32_t>(Sec->Size); 506 W.write<uint32_t>(Sec->FileOffsetToData); 507 508 // Relocation pointer and Lineno pointer. Not supported yet. 509 W.write<uint32_t>(0); 510 W.write<uint32_t>(0); 511 512 // Relocation and line-number counts. Not supported yet. 513 W.write<uint16_t>(0); 514 W.write<uint16_t>(0); 515 516 W.write<int32_t>(Sec->Flags); 517 } 518 } 519 520 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) { 521 for (const auto *Section : Sections) { 522 // Nothing to write for this Section. 523 if (Section->Index == Section::UninitializedIndex) 524 continue; 525 526 for (const auto *Group : Section->Groups) { 527 if (Group->empty()) 528 continue; 529 530 const int16_t SectionIndex = Section->Index; 531 for (const auto &Csect : *Group) { 532 // Write out the control section first and then each symbol in it. 533 writeSymbolTableEntryForControlSection( 534 Csect, SectionIndex, Csect.MCCsect->getStorageClass()); 535 536 for (const auto Sym : Csect.Syms) 537 writeSymbolTableEntryForCsectMemberLabel( 538 Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym))); 539 } 540 } 541 } 542 } 543 544 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) { 545 // The address corrresponds to the address of sections and symbols in the 546 // object file. We place the shared address 0 immediately after the 547 // section header table. 548 uint32_t Address = 0; 549 // Section indices are 1-based in XCOFF. 550 int32_t SectionIndex = 1; 551 // The first symbol table entry is for the file name. We are not emitting it 552 // yet, so start at index 0. 553 uint32_t SymbolTableIndex = 0; 554 555 for (auto *Section : Sections) { 556 const bool IsEmpty = 557 llvm::all_of(Section->Groups, 558 [](const CsectGroup *Group) { return Group->empty(); }); 559 if (IsEmpty) 560 continue; 561 562 if (SectionIndex > MaxSectionIndex) 563 report_fatal_error("Section index overflow!"); 564 Section->Index = SectionIndex++; 565 SectionCount++; 566 567 bool SectionAddressSet = false; 568 for (auto *Group : Section->Groups) { 569 if (Group->empty()) 570 continue; 571 572 for (auto &Csect : *Group) { 573 const MCSectionXCOFF *MCSec = Csect.MCCsect; 574 Csect.Address = alignTo(Address, MCSec->getAlignment()); 575 Csect.Size = Layout.getSectionAddressSize(MCSec); 576 Address = Csect.Address + Csect.Size; 577 Csect.SymbolTableIndex = SymbolTableIndex; 578 // 1 main and 1 auxiliary symbol table entry for the csect. 579 SymbolTableIndex += 2; 580 581 for (auto &Sym : Csect.Syms) { 582 Sym.SymbolTableIndex = SymbolTableIndex; 583 // 1 main and 1 auxiliary symbol table entry for each contained 584 // symbol. 585 SymbolTableIndex += 2; 586 } 587 } 588 589 if (!SectionAddressSet) { 590 Section->Address = Group->front().Address; 591 SectionAddressSet = true; 592 } 593 } 594 595 // Make sure the address of the next section aligned to 596 // DefaultSectionAlign. 597 Address = alignTo(Address, DefaultSectionAlign); 598 Section->Size = Address - Section->Address; 599 } 600 601 SymbolTableEntryCount = SymbolTableIndex; 602 603 // Calculate the RawPointer value for each section. 604 uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() + 605 SectionCount * sizeof(XCOFF::SectionHeader32); 606 for (auto *Sec : Sections) { 607 if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual) 608 continue; 609 610 Sec->FileOffsetToData = RawPointer; 611 RawPointer += Sec->Size; 612 } 613 614 // TODO Add in Relocation storage to the RawPointer Calculation. 615 // TODO What to align the SymbolTable to? 616 // TODO Error check that the number of symbol table entries fits in 32-bits 617 // signed ... 618 if (SymbolTableEntryCount) 619 SymbolTableOffset = RawPointer; 620 } 621 622 // Takes the log base 2 of the alignment and shifts the result into the 5 most 623 // significant bits of a byte, then or's in the csect type into the least 624 // significant 3 bits. 625 uint8_t getEncodedType(const MCSectionXCOFF *Sec) { 626 unsigned Align = Sec->getAlignment(); 627 assert(isPowerOf2_32(Align) && "Alignment must be a power of 2."); 628 unsigned Log2Align = Log2_32(Align); 629 // Result is a number in the range [0, 31] which fits in the 5 least 630 // significant bits. Shift this value into the 5 most significant bits, and 631 // bitwise-or in the csect type. 632 uint8_t EncodedAlign = Log2Align << 3; 633 return EncodedAlign | Sec->getCSectType(); 634 } 635 636 } // end anonymous namespace 637 638 std::unique_ptr<MCObjectWriter> 639 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 640 raw_pwrite_stream &OS) { 641 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS); 642 } 643