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/MCAssembler.h" 16 #include "llvm/MC/MCFixup.h" 17 #include "llvm/MC/MCFixupKindInfo.h" 18 #include "llvm/MC/MCObjectWriter.h" 19 #include "llvm/MC/MCSectionXCOFF.h" 20 #include "llvm/MC/MCSymbolXCOFF.h" 21 #include "llvm/MC/MCValue.h" 22 #include "llvm/MC/MCXCOFFObjectWriter.h" 23 #include "llvm/MC/StringTableBuilder.h" 24 #include "llvm/Support/Casting.h" 25 #include "llvm/Support/EndianStream.h" 26 #include "llvm/Support/ErrorHandling.h" 27 #include "llvm/Support/MathExtras.h" 28 29 #include <deque> 30 #include <map> 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 these 110 // values are equivalent, except for in the overflow section header, where 111 // the physical address specifies the number of relocation entries and the 112 // virtual address specifies the number of line number entries. 113 // TODO: Divide Address into PhysicalAddress and VirtualAddress when line 114 // number entries are supported. 115 uint64_t Address; 116 uint64_t Size; 117 uint64_t FileOffsetToData; 118 uint64_t FileOffsetToRelocations; 119 uint32_t RelocationCount; 120 int32_t Flags; 121 122 int16_t Index; 123 124 virtual uint64_t advanceFileOffset(const uint64_t MaxRawDataSize, 125 const uint64_t RawPointer) { 126 FileOffsetToData = RawPointer; 127 uint64_t NewPointer = RawPointer + Size; 128 if (NewPointer > MaxRawDataSize) 129 report_fatal_error("Section raw data overflowed this object file."); 130 return NewPointer; 131 } 132 133 // XCOFF has special section numbers for symbols: 134 // -2 Specifies N_DEBUG, a special symbolic debugging symbol. 135 // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not 136 // relocatable. 137 // 0 Specifies N_UNDEF, an undefined external symbol. 138 // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that 139 // hasn't been initialized. 140 static constexpr int16_t UninitializedIndex = 141 XCOFF::ReservedSectionNum::N_DEBUG - 1; 142 143 SectionEntry(StringRef N, int32_t Flags) 144 : Name(), Address(0), Size(0), FileOffsetToData(0), 145 FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags), 146 Index(UninitializedIndex) { 147 assert(N.size() <= XCOFF::NameSize && "section name too long"); 148 memcpy(Name, N.data(), N.size()); 149 } 150 151 virtual void reset() { 152 Address = 0; 153 Size = 0; 154 FileOffsetToData = 0; 155 FileOffsetToRelocations = 0; 156 RelocationCount = 0; 157 Index = UninitializedIndex; 158 } 159 160 virtual ~SectionEntry() = default; 161 }; 162 163 // Represents the data related to a section excluding the csects that make up 164 // the raw data of the section. The csects are stored separately as not all 165 // sections contain csects, and some sections contain csects which are better 166 // stored separately, e.g. the .data section containing read-write, descriptor, 167 // TOCBase and TOC-entry csects. 168 struct CsectSectionEntry : public SectionEntry { 169 // Virtual sections do not need storage allocated in the object file. 170 const bool IsVirtual; 171 172 // This is a section containing csect groups. 173 CsectGroups Groups; 174 175 CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual, 176 CsectGroups Groups) 177 : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) { 178 assert(N.size() <= XCOFF::NameSize && "section name too long"); 179 memcpy(Name, N.data(), N.size()); 180 } 181 182 void reset() override { 183 SectionEntry::reset(); 184 // Clear any csects we have stored. 185 for (auto *Group : Groups) 186 Group->clear(); 187 } 188 189 virtual ~CsectSectionEntry() = default; 190 }; 191 192 struct DwarfSectionEntry : public SectionEntry { 193 // For DWARF section entry. 194 std::unique_ptr<XCOFFSection> DwarfSect; 195 196 // For DWARF section, we must use real size in the section header. MemorySize 197 // is for the size the DWARF section occupies including paddings. 198 uint32_t MemorySize; 199 200 // TODO: Remove this override. Loadable sections (e.g., .text, .data) may need 201 // to be aligned. Other sections generally don't need any alignment, but if 202 // they're aligned, the RawPointer should be adjusted before writing the 203 // section. Then a dwarf-specific function wouldn't be needed. 204 uint64_t advanceFileOffset(const uint64_t MaxRawDataSize, 205 const uint64_t RawPointer) override { 206 FileOffsetToData = RawPointer; 207 uint64_t NewPointer = RawPointer + MemorySize; 208 assert(NewPointer <= MaxRawDataSize && 209 "Section raw data overflowed this object file."); 210 return NewPointer; 211 } 212 213 DwarfSectionEntry(StringRef N, int32_t Flags, 214 std::unique_ptr<XCOFFSection> Sect) 215 : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)), 216 MemorySize(0) { 217 assert(DwarfSect->MCSec->isDwarfSect() && 218 "This should be a DWARF section!"); 219 assert(N.size() <= XCOFF::NameSize && "section name too long"); 220 memcpy(Name, N.data(), N.size()); 221 } 222 223 DwarfSectionEntry(DwarfSectionEntry &&s) = default; 224 225 virtual ~DwarfSectionEntry() = default; 226 }; 227 228 struct ExceptionTableEntry { 229 const MCSymbol *Trap; 230 uint64_t TrapAddress = ~0ul; 231 unsigned Lang; 232 unsigned Reason; 233 234 ExceptionTableEntry(const MCSymbol *Trap, unsigned Lang, unsigned Reason) 235 : Trap(Trap), Lang(Lang), Reason(Reason) {} 236 }; 237 238 struct ExceptionInfo { 239 const MCSymbol *FunctionSymbol; 240 unsigned FunctionSize; 241 std::vector<ExceptionTableEntry> Entries; 242 }; 243 244 struct ExceptionSectionEntry : public SectionEntry { 245 std::map<const StringRef, ExceptionInfo> ExceptionTable; 246 bool isDebugEnabled = false; 247 248 ExceptionSectionEntry(StringRef N, int32_t Flags) 249 : SectionEntry(N, Flags | XCOFF::STYP_EXCEPT) { 250 assert(N.size() <= XCOFF::NameSize && "Section too long."); 251 memcpy(Name, N.data(), N.size()); 252 } 253 254 virtual ~ExceptionSectionEntry() = default; 255 }; 256 257 struct CInfoSymInfo { 258 // Name of the C_INFO symbol associated with the section 259 std::string Name; 260 std::string Metadata; 261 // Offset into the start of the metadata in the section 262 uint64_t Offset; 263 264 CInfoSymInfo(std::string Name, std::string Metadata) 265 : Name(Name), Metadata(Metadata) {} 266 // Metadata needs to be padded out to an even word size. 267 uint32_t paddingSize() const { 268 return alignTo(Metadata.size(), sizeof(uint32_t)) - Metadata.size(); 269 }; 270 271 // Total size of the entry, including the 4 byte length 272 uint32_t size() const { 273 return Metadata.size() + paddingSize() + sizeof(uint32_t); 274 }; 275 }; 276 277 struct CInfoSymSectionEntry : public SectionEntry { 278 std::unique_ptr<CInfoSymInfo> Entry; 279 280 CInfoSymSectionEntry(StringRef N, int32_t Flags) : SectionEntry(N, Flags) {} 281 virtual ~CInfoSymSectionEntry() = default; 282 void addEntry(std::unique_ptr<CInfoSymInfo> NewEntry) { 283 Entry = std::move(NewEntry); 284 Entry->Offset = sizeof(uint32_t); 285 Size += Entry->size(); 286 } 287 void reset() override { 288 SectionEntry::reset(); 289 Entry.reset(); 290 } 291 }; 292 293 class XCOFFWriter final : public XCOFFObjectWriter { 294 uint32_t SymbolTableEntryCount = 0; 295 uint64_t SymbolTableOffset = 0; 296 uint16_t SectionCount = 0; 297 uint32_t PaddingsBeforeDwarf = 0; 298 bool HasVisibility = false; 299 300 support::endian::Writer W; 301 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter; 302 StringTableBuilder Strings; 303 304 const uint64_t MaxRawDataSize = 305 TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX; 306 307 // Maps the MCSection representation to its corresponding XCOFFSection 308 // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into 309 // from its containing MCSectionXCOFF. 310 DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap; 311 312 // Maps the MCSymbol representation to its corrresponding symbol table index. 313 // Needed for relocation. 314 DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap; 315 316 // CsectGroups. These store the csects which make up different parts of 317 // the sections. Should have one for each set of csects that get mapped into 318 // the same section and get handled in a 'similar' way. 319 CsectGroup UndefinedCsects; 320 CsectGroup ProgramCodeCsects; 321 CsectGroup ReadOnlyCsects; 322 CsectGroup DataCsects; 323 CsectGroup FuncDSCsects; 324 CsectGroup TOCCsects; 325 CsectGroup BSSCsects; 326 CsectGroup TDataCsects; 327 CsectGroup TBSSCsects; 328 329 // The Predefined sections. 330 CsectSectionEntry Text; 331 CsectSectionEntry Data; 332 CsectSectionEntry BSS; 333 CsectSectionEntry TData; 334 CsectSectionEntry TBSS; 335 336 // All the XCOFF sections, in the order they will appear in the section header 337 // table. 338 std::array<CsectSectionEntry *const, 5> Sections{ 339 {&Text, &Data, &BSS, &TData, &TBSS}}; 340 341 std::vector<DwarfSectionEntry> DwarfSections; 342 std::vector<SectionEntry> OverflowSections; 343 344 ExceptionSectionEntry ExceptionSection; 345 CInfoSymSectionEntry CInfoSymSection; 346 347 CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); 348 349 void reset() override; 350 351 void executePostLayoutBinding(MCAssembler &) override; 352 353 void recordRelocation(MCAssembler &, const MCFragment *, const MCFixup &, 354 MCValue, uint64_t &) override; 355 356 uint64_t writeObject(MCAssembler &) override; 357 358 bool is64Bit() const { return TargetObjectWriter->is64Bit(); } 359 bool nameShouldBeInStringTable(const StringRef &); 360 void writeSymbolName(const StringRef &); 361 bool auxFileSymNameShouldBeInStringTable(const StringRef &); 362 void writeAuxFileSymName(const StringRef &); 363 364 void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef, 365 const XCOFFSection &CSectionRef, 366 int16_t SectionIndex, 367 uint64_t SymbolOffset); 368 void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef, 369 int16_t SectionIndex, 370 XCOFF::StorageClass StorageClass); 371 void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef, 372 int16_t SectionIndex); 373 void writeFileHeader(); 374 void writeAuxFileHeader(); 375 void writeSectionHeader(const SectionEntry *Sec); 376 void writeSectionHeaderTable(); 377 void writeSections(const MCAssembler &Asm); 378 void writeSectionForControlSectionEntry(const MCAssembler &Asm, 379 const CsectSectionEntry &CsectEntry, 380 uint64_t &CurrentAddressLocation); 381 void writeSectionForDwarfSectionEntry(const MCAssembler &Asm, 382 const DwarfSectionEntry &DwarfEntry, 383 uint64_t &CurrentAddressLocation); 384 void 385 writeSectionForExceptionSectionEntry(const MCAssembler &Asm, 386 ExceptionSectionEntry &ExceptionEntry, 387 uint64_t &CurrentAddressLocation); 388 void writeSectionForCInfoSymSectionEntry(const MCAssembler &Asm, 389 CInfoSymSectionEntry &CInfoSymEntry, 390 uint64_t &CurrentAddressLocation); 391 void writeSymbolTable(MCAssembler &Asm); 392 void writeSymbolAuxFileEntry(StringRef &Name, uint8_t ftype); 393 void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion, 394 uint64_t NumberOfRelocEnt = 0); 395 void writeSymbolAuxCsectEntry(uint64_t SectionOrLength, 396 uint8_t SymbolAlignmentAndType, 397 uint8_t StorageMappingClass); 398 void writeSymbolAuxFunctionEntry(uint32_t EntryOffset, uint32_t FunctionSize, 399 uint64_t LineNumberPointer, 400 uint32_t EndIndex); 401 void writeSymbolAuxExceptionEntry(uint64_t EntryOffset, uint32_t FunctionSize, 402 uint32_t EndIndex); 403 void writeSymbolEntry(StringRef SymbolName, uint64_t Value, 404 int16_t SectionNumber, uint16_t SymbolType, 405 uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1); 406 void writeRelocations(); 407 void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section); 408 409 // Called after all the csects and symbols have been processed by 410 // `executePostLayoutBinding`, this function handles building up the majority 411 // of the structures in the object file representation. Namely: 412 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section 413 // sizes. 414 // *) Assigns symbol table indices. 415 // *) Builds up the section header table by adding any non-empty sections to 416 // `Sections`. 417 void assignAddressesAndIndices(MCAssembler &Asm); 418 // Called after relocations are recorded. 419 void finalizeSectionInfo(); 420 void finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount); 421 void calcOffsetToRelocations(SectionEntry *Sec, uint64_t &RawPointer); 422 423 bool hasExceptionSection() { 424 return !ExceptionSection.ExceptionTable.empty(); 425 } 426 unsigned getExceptionSectionSize(); 427 unsigned getExceptionOffset(const MCSymbol *Symbol); 428 429 size_t auxiliaryHeaderSize() const { 430 // 64-bit object files have no auxiliary header. 431 return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0; 432 } 433 434 public: 435 XCOFFWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 436 raw_pwrite_stream &OS); 437 438 void writeWord(uint64_t Word) { 439 is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word); 440 } 441 442 void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap, 443 unsigned LanguageCode, unsigned ReasonCode, 444 unsigned FunctionSize, bool hasDebug) override; 445 void addCInfoSymEntry(StringRef Name, StringRef Metadata) override; 446 }; 447 448 XCOFFWriter::XCOFFWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 449 raw_pwrite_stream &OS) 450 : W(OS, llvm::endianness::big), TargetObjectWriter(std::move(MOTW)), 451 Strings(StringTableBuilder::XCOFF), 452 Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false, 453 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}), 454 Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false, 455 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}), 456 BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true, 457 CsectGroups{&BSSCsects}), 458 TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false, 459 CsectGroups{&TDataCsects}), 460 TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true, 461 CsectGroups{&TBSSCsects}), 462 ExceptionSection(".except", XCOFF::STYP_EXCEPT), 463 CInfoSymSection(".info", XCOFF::STYP_INFO) {} 464 465 void XCOFFWriter::reset() { 466 // Clear the mappings we created. 467 SymbolIndexMap.clear(); 468 SectionMap.clear(); 469 470 UndefinedCsects.clear(); 471 // Reset any sections we have written to, and empty the section header table. 472 for (auto *Sec : Sections) 473 Sec->reset(); 474 for (auto &DwarfSec : DwarfSections) 475 DwarfSec.reset(); 476 for (auto &OverflowSec : OverflowSections) 477 OverflowSec.reset(); 478 ExceptionSection.reset(); 479 CInfoSymSection.reset(); 480 481 // Reset states in XCOFFWriter. 482 SymbolTableEntryCount = 0; 483 SymbolTableOffset = 0; 484 SectionCount = 0; 485 PaddingsBeforeDwarf = 0; 486 Strings.clear(); 487 488 MCObjectWriter::reset(); 489 } 490 491 CsectGroup &XCOFFWriter::getCsectGroup(const MCSectionXCOFF *MCSec) { 492 switch (MCSec->getMappingClass()) { 493 case XCOFF::XMC_PR: 494 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 495 "Only an initialized csect can contain program code."); 496 return ProgramCodeCsects; 497 case XCOFF::XMC_RO: 498 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 499 "Only an initialized csect can contain read only data."); 500 return ReadOnlyCsects; 501 case XCOFF::XMC_RW: 502 if (XCOFF::XTY_CM == MCSec->getCSectType()) 503 return BSSCsects; 504 505 if (XCOFF::XTY_SD == MCSec->getCSectType()) 506 return DataCsects; 507 508 report_fatal_error("Unhandled mapping of read-write csect to section."); 509 case XCOFF::XMC_DS: 510 return FuncDSCsects; 511 case XCOFF::XMC_BS: 512 assert(XCOFF::XTY_CM == MCSec->getCSectType() && 513 "Mapping invalid csect. CSECT with bss storage class must be " 514 "common type."); 515 return BSSCsects; 516 case XCOFF::XMC_TL: 517 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 518 "Mapping invalid csect. CSECT with tdata storage class must be " 519 "an initialized csect."); 520 return TDataCsects; 521 case XCOFF::XMC_UL: 522 assert(XCOFF::XTY_CM == MCSec->getCSectType() && 523 "Mapping invalid csect. CSECT with tbss storage class must be " 524 "an uninitialized csect."); 525 return TBSSCsects; 526 case XCOFF::XMC_TC0: 527 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 528 "Only an initialized csect can contain TOC-base."); 529 assert(TOCCsects.empty() && 530 "We should have only one TOC-base, and it should be the first csect " 531 "in this CsectGroup."); 532 return TOCCsects; 533 case XCOFF::XMC_TC: 534 case XCOFF::XMC_TE: 535 assert(XCOFF::XTY_SD == MCSec->getCSectType() && 536 "A TOC symbol must be an initialized csect."); 537 assert(!TOCCsects.empty() && 538 "We should at least have a TOC-base in this CsectGroup."); 539 return TOCCsects; 540 case XCOFF::XMC_TD: 541 assert((XCOFF::XTY_SD == MCSec->getCSectType() || 542 XCOFF::XTY_CM == MCSec->getCSectType()) && 543 "Symbol type incompatible with toc-data."); 544 assert(!TOCCsects.empty() && 545 "We should at least have a TOC-base in this CsectGroup."); 546 return TOCCsects; 547 default: 548 report_fatal_error("Unhandled mapping of csect to section."); 549 } 550 } 551 552 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) { 553 if (XSym->isDefined()) 554 return cast<MCSectionXCOFF>(XSym->getFragment()->getParent()); 555 return XSym->getRepresentedCsect(); 556 } 557 558 void XCOFFWriter::executePostLayoutBinding(MCAssembler &Asm) { 559 for (const auto &S : Asm) { 560 const auto *MCSec = cast<const MCSectionXCOFF>(&S); 561 assert(!SectionMap.contains(MCSec) && "Cannot add a section twice."); 562 563 // If the name does not fit in the storage provided in the symbol table 564 // entry, add it to the string table. 565 if (nameShouldBeInStringTable(MCSec->getSymbolTableName())) 566 Strings.add(MCSec->getSymbolTableName()); 567 if (MCSec->isCsect()) { 568 // A new control section. Its CsectSectionEntry should already be staticly 569 // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of 570 // the CsectSectionEntry. 571 assert(XCOFF::XTY_ER != MCSec->getCSectType() && 572 "An undefined csect should not get registered."); 573 CsectGroup &Group = getCsectGroup(MCSec); 574 Group.emplace_back(MCSec); 575 SectionMap[MCSec] = &Group.back(); 576 } else if (MCSec->isDwarfSect()) { 577 // A new DwarfSectionEntry. 578 std::unique_ptr<XCOFFSection> DwarfSec = 579 std::make_unique<XCOFFSection>(MCSec); 580 SectionMap[MCSec] = DwarfSec.get(); 581 582 DwarfSectionEntry SecEntry(MCSec->getName(), 583 *MCSec->getDwarfSubtypeFlags(), 584 std::move(DwarfSec)); 585 DwarfSections.push_back(std::move(SecEntry)); 586 } else 587 llvm_unreachable("unsupport section type!"); 588 } 589 590 for (const MCSymbol &S : Asm.symbols()) { 591 // Nothing to do for temporary symbols. 592 if (S.isTemporary()) 593 continue; 594 595 const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S); 596 const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym); 597 598 if (ContainingCsect->isDwarfSect()) 599 continue; 600 601 if (XSym->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED) 602 HasVisibility = true; 603 604 if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) { 605 // Handle undefined symbol. 606 UndefinedCsects.emplace_back(ContainingCsect); 607 SectionMap[ContainingCsect] = &UndefinedCsects.back(); 608 if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName())) 609 Strings.add(ContainingCsect->getSymbolTableName()); 610 continue; 611 } 612 613 // If the symbol is the csect itself, we don't need to put the symbol 614 // into csect's Syms. 615 if (XSym == ContainingCsect->getQualNameSymbol()) 616 continue; 617 618 // Only put a label into the symbol table when it is an external label. 619 if (!XSym->isExternal()) 620 continue; 621 622 assert(SectionMap.contains(ContainingCsect) && 623 "Expected containing csect to exist in map"); 624 XCOFFSection *Csect = SectionMap[ContainingCsect]; 625 // Lookup the containing csect and add the symbol to it. 626 assert(Csect->MCSec->isCsect() && "only csect is supported now!"); 627 Csect->Syms.emplace_back(XSym); 628 629 // If the name does not fit in the storage provided in the symbol table 630 // entry, add it to the string table. 631 if (nameShouldBeInStringTable(XSym->getSymbolTableName())) 632 Strings.add(XSym->getSymbolTableName()); 633 } 634 635 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry; 636 if (CISI && nameShouldBeInStringTable(CISI->Name)) 637 Strings.add(CISI->Name); 638 639 // Emit ".file" as the source file name when there is no file name. 640 if (FileNames.empty()) 641 FileNames.emplace_back(".file", 0); 642 for (const std::pair<std::string, size_t> &F : FileNames) { 643 if (auxFileSymNameShouldBeInStringTable(F.first)) 644 Strings.add(F.first); 645 } 646 647 // Always add ".file" to the symbol table. The actual file name will be in 648 // the AUX_FILE auxiliary entry. 649 if (nameShouldBeInStringTable(".file")) 650 Strings.add(".file"); 651 StringRef Vers = CompilerVersion; 652 if (auxFileSymNameShouldBeInStringTable(Vers)) 653 Strings.add(Vers); 654 655 Strings.finalize(); 656 assignAddressesAndIndices(Asm); 657 } 658 659 void XCOFFWriter::recordRelocation(MCAssembler &Asm, const MCFragment *Fragment, 660 const MCFixup &Fixup, MCValue Target, 661 uint64_t &FixedValue) { 662 auto getIndex = [this](const MCSymbol *Sym, 663 const MCSectionXCOFF *ContainingCsect) { 664 // If we could not find the symbol directly in SymbolIndexMap, this symbol 665 // could either be a temporary symbol or an undefined symbol. In this case, 666 // we would need to have the relocation reference its csect instead. 667 auto It = SymbolIndexMap.find(Sym); 668 return It != SymbolIndexMap.end() 669 ? It->second 670 : SymbolIndexMap[ContainingCsect->getQualNameSymbol()]; 671 }; 672 673 auto getVirtualAddress = 674 [this, &Asm](const MCSymbol *Sym, 675 const MCSectionXCOFF *ContainingSect) -> uint64_t { 676 // A DWARF section. 677 if (ContainingSect->isDwarfSect()) 678 return Asm.getSymbolOffset(*Sym); 679 680 // A csect. 681 if (!Sym->isDefined()) 682 return SectionMap[ContainingSect]->Address; 683 684 // A label. 685 assert(Sym->isDefined() && "not a valid object that has address!"); 686 return SectionMap[ContainingSect]->Address + Asm.getSymbolOffset(*Sym); 687 }; 688 689 const MCSymbol *const SymA = &Target.getSymA()->getSymbol(); 690 691 MCAsmBackend &Backend = Asm.getBackend(); 692 bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & 693 MCFixupKindInfo::FKF_IsPCRel; 694 695 uint8_t Type; 696 uint8_t SignAndSize; 697 std::tie(Type, SignAndSize) = 698 TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel); 699 700 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA)); 701 assert(SectionMap.contains(SymASec) && 702 "Expected containing csect to exist in map."); 703 704 assert((Fixup.getOffset() <= 705 MaxRawDataSize - Asm.getFragmentOffset(*Fragment)) && 706 "Fragment offset + fixup offset is overflowed."); 707 uint32_t FixupOffsetInCsect = 708 Asm.getFragmentOffset(*Fragment) + Fixup.getOffset(); 709 710 const uint32_t Index = getIndex(SymA, SymASec); 711 if (Type == XCOFF::RelocationType::R_POS || 712 Type == XCOFF::RelocationType::R_TLS || 713 Type == XCOFF::RelocationType::R_TLS_LE || 714 Type == XCOFF::RelocationType::R_TLS_IE || 715 Type == XCOFF::RelocationType::R_TLS_LD) 716 // The FixedValue should be symbol's virtual address in this object file 717 // plus any constant value that we might get. 718 FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant(); 719 else if (Type == XCOFF::RelocationType::R_TLSM) 720 // The FixedValue should always be zero since the region handle is only 721 // known at load time. 722 FixedValue = 0; 723 else if (Type == XCOFF::RelocationType::R_TOC || 724 Type == XCOFF::RelocationType::R_TOCL) { 725 // For non toc-data external symbols, R_TOC type relocation will relocate to 726 // data symbols that have XCOFF::XTY_SD type csect. For toc-data external 727 // symbols, R_TOC type relocation will relocate to data symbols that have 728 // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC 729 // entry for them, so the FixedValue should always be 0. 730 if (SymASec->getCSectType() == XCOFF::XTY_ER) { 731 FixedValue = 0; 732 } else { 733 // The FixedValue should be the TOC entry offset from the TOC-base plus 734 // any constant offset value. 735 int64_t TOCEntryOffset = SectionMap[SymASec]->Address - 736 TOCCsects.front().Address + Target.getConstant(); 737 // For small code model, if the TOCEntryOffset overflows the 16-bit value, 738 // we truncate it back down to 16 bits. The linker will be able to insert 739 // fix-up code when needed. 740 // For non toc-data symbols, we already did the truncation in 741 // PPCAsmPrinter.cpp through setting Target.getConstant() in the 742 // expression above by calling getTOCEntryLoadingExprForXCOFF for the 743 // various TOC PseudoOps. 744 // For toc-data symbols, we were not able to calculate the offset from 745 // the TOC in PPCAsmPrinter.cpp since the TOC has not been finalized at 746 // that point, so we are adjusting it here though 747 // llvm::SignExtend64<16>(TOCEntryOffset); 748 // TODO: Since the time that the handling for offsets over 16-bits was 749 // added in PPCAsmPrinter.cpp using getTOCEntryLoadingExprForXCOFF, the 750 // system assembler and linker have been updated to be able to handle the 751 // overflowing offsets, so we no longer need to keep 752 // getTOCEntryLoadingExprForXCOFF. 753 if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset)) 754 TOCEntryOffset = llvm::SignExtend64<16>(TOCEntryOffset); 755 756 FixedValue = TOCEntryOffset; 757 } 758 } else if (Type == XCOFF::RelocationType::R_RBR) { 759 MCSectionXCOFF *ParentSec = cast<MCSectionXCOFF>(Fragment->getParent()); 760 assert((SymASec->getMappingClass() == XCOFF::XMC_PR && 761 ParentSec->getMappingClass() == XCOFF::XMC_PR) && 762 "Only XMC_PR csect may have the R_RBR relocation."); 763 764 // The address of the branch instruction should be the sum of section 765 // address, fragment offset and Fixup offset. 766 uint64_t BRInstrAddress = 767 SectionMap[ParentSec]->Address + FixupOffsetInCsect; 768 // The FixedValue should be the difference between symbol's virtual address 769 // and BR instr address plus any constant value. 770 FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress + 771 Target.getConstant(); 772 } else if (Type == XCOFF::RelocationType::R_REF) { 773 // The FixedValue and FixupOffsetInCsect should always be 0 since it 774 // specifies a nonrelocating reference. 775 FixedValue = 0; 776 FixupOffsetInCsect = 0; 777 } 778 779 XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type}; 780 MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent()); 781 assert(SectionMap.contains(RelocationSec) && 782 "Expected containing csect to exist in map."); 783 SectionMap[RelocationSec]->Relocations.push_back(Reloc); 784 785 if (!Target.getSymB()) 786 return; 787 788 const MCSymbol *const SymB = &Target.getSymB()->getSymbol(); 789 if (SymA == SymB) 790 report_fatal_error("relocation for opposite term is not yet supported"); 791 792 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB)); 793 assert(SectionMap.contains(SymBSec) && 794 "Expected containing csect to exist in map."); 795 if (SymASec == SymBSec) 796 report_fatal_error( 797 "relocation for paired relocatable term is not yet supported"); 798 799 assert(Type == XCOFF::RelocationType::R_POS && 800 "SymA must be R_POS here if it's not opposite term or paired " 801 "relocatable term."); 802 const uint32_t IndexB = getIndex(SymB, SymBSec); 803 // SymB must be R_NEG here, given the general form of Target(MCValue) is 804 // "SymbolA - SymbolB + imm64". 805 const uint8_t TypeB = XCOFF::RelocationType::R_NEG; 806 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB}; 807 SectionMap[RelocationSec]->Relocations.push_back(RelocB); 808 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA, 809 // now we just need to fold "- SymbolB" here. 810 FixedValue -= getVirtualAddress(SymB, SymBSec); 811 } 812 813 void XCOFFWriter::writeSections(const MCAssembler &Asm) { 814 uint64_t CurrentAddressLocation = 0; 815 for (const auto *Section : Sections) 816 writeSectionForControlSectionEntry(Asm, *Section, CurrentAddressLocation); 817 for (const auto &DwarfSection : DwarfSections) 818 writeSectionForDwarfSectionEntry(Asm, DwarfSection, CurrentAddressLocation); 819 writeSectionForExceptionSectionEntry(Asm, ExceptionSection, 820 CurrentAddressLocation); 821 writeSectionForCInfoSymSectionEntry(Asm, CInfoSymSection, 822 CurrentAddressLocation); 823 } 824 825 uint64_t XCOFFWriter::writeObject(MCAssembler &Asm) { 826 // We always emit a timestamp of 0 for reproducibility, so ensure incremental 827 // linking is not enabled, in case, like with Windows COFF, such a timestamp 828 // is incompatible with incremental linking of XCOFF. 829 830 finalizeSectionInfo(); 831 uint64_t StartOffset = W.OS.tell(); 832 833 writeFileHeader(); 834 writeAuxFileHeader(); 835 writeSectionHeaderTable(); 836 writeSections(Asm); 837 writeRelocations(); 838 writeSymbolTable(Asm); 839 // Write the string table. 840 Strings.write(W.OS); 841 842 return W.OS.tell() - StartOffset; 843 } 844 845 bool XCOFFWriter::nameShouldBeInStringTable(const StringRef &SymbolName) { 846 return SymbolName.size() > XCOFF::NameSize || is64Bit(); 847 } 848 849 void XCOFFWriter::writeSymbolName(const StringRef &SymbolName) { 850 // Magic, Offset or SymbolName. 851 if (nameShouldBeInStringTable(SymbolName)) { 852 W.write<int32_t>(0); 853 W.write<uint32_t>(Strings.getOffset(SymbolName)); 854 } else { 855 char Name[XCOFF::NameSize + 1]; 856 std::strncpy(Name, SymbolName.data(), XCOFF::NameSize); 857 ArrayRef<char> NameRef(Name, XCOFF::NameSize); 858 W.write(NameRef); 859 } 860 } 861 862 void XCOFFWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value, 863 int16_t SectionNumber, uint16_t SymbolType, 864 uint8_t StorageClass, 865 uint8_t NumberOfAuxEntries) { 866 if (is64Bit()) { 867 W.write<uint64_t>(Value); 868 W.write<uint32_t>(Strings.getOffset(SymbolName)); 869 } else { 870 writeSymbolName(SymbolName); 871 W.write<uint32_t>(Value); 872 } 873 W.write<int16_t>(SectionNumber); 874 W.write<uint16_t>(SymbolType); 875 W.write<uint8_t>(StorageClass); 876 W.write<uint8_t>(NumberOfAuxEntries); 877 } 878 879 void XCOFFWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength, 880 uint8_t SymbolAlignmentAndType, 881 uint8_t StorageMappingClass) { 882 W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength); 883 W.write<uint32_t>(0); // ParameterHashIndex 884 W.write<uint16_t>(0); // TypeChkSectNum 885 W.write<uint8_t>(SymbolAlignmentAndType); 886 W.write<uint8_t>(StorageMappingClass); 887 if (is64Bit()) { 888 W.write<uint32_t>(Hi_32(SectionOrLength)); 889 W.OS.write_zeros(1); // Reserved 890 W.write<uint8_t>(XCOFF::AUX_CSECT); 891 } else { 892 W.write<uint32_t>(0); // StabInfoIndex 893 W.write<uint16_t>(0); // StabSectNum 894 } 895 } 896 897 bool XCOFFWriter::auxFileSymNameShouldBeInStringTable( 898 const StringRef &SymbolName) { 899 return SymbolName.size() > XCOFF::AuxFileEntNameSize; 900 } 901 902 void XCOFFWriter::writeAuxFileSymName(const StringRef &SymbolName) { 903 // Magic, Offset or SymbolName. 904 if (auxFileSymNameShouldBeInStringTable(SymbolName)) { 905 W.write<int32_t>(0); 906 W.write<uint32_t>(Strings.getOffset(SymbolName)); 907 W.OS.write_zeros(XCOFF::FileNamePadSize); 908 } else { 909 char Name[XCOFF::AuxFileEntNameSize + 1]; 910 std::strncpy(Name, SymbolName.data(), XCOFF::AuxFileEntNameSize); 911 ArrayRef<char> NameRef(Name, XCOFF::AuxFileEntNameSize); 912 W.write(NameRef); 913 } 914 } 915 916 void XCOFFWriter::writeSymbolAuxFileEntry(StringRef &Name, uint8_t ftype) { 917 writeAuxFileSymName(Name); 918 W.write<uint8_t>(ftype); 919 W.OS.write_zeros(2); 920 if (is64Bit()) 921 W.write<uint8_t>(XCOFF::AUX_FILE); 922 else 923 W.OS.write_zeros(1); 924 } 925 926 void XCOFFWriter::writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion, 927 uint64_t NumberOfRelocEnt) { 928 writeWord(LengthOfSectionPortion); 929 if (!is64Bit()) 930 W.OS.write_zeros(4); // Reserved 931 writeWord(NumberOfRelocEnt); 932 if (is64Bit()) { 933 W.OS.write_zeros(1); // Reserved 934 W.write<uint8_t>(XCOFF::AUX_SECT); 935 } else { 936 W.OS.write_zeros(6); // Reserved 937 } 938 } 939 940 void XCOFFWriter::writeSymbolEntryForCsectMemberLabel( 941 const Symbol &SymbolRef, const XCOFFSection &CSectionRef, 942 int16_t SectionIndex, uint64_t SymbolOffset) { 943 assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address && 944 "Symbol address overflowed."); 945 946 auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName()); 947 if (Entry != ExceptionSection.ExceptionTable.end()) { 948 writeSymbolEntry(SymbolRef.getSymbolTableName(), 949 CSectionRef.Address + SymbolOffset, SectionIndex, 950 // In the old version of the 32-bit XCOFF interpretation, 951 // symbols may require bit 10 (0x0020) to be set if the 952 // symbol is a function, otherwise the bit should be 0. 953 is64Bit() ? SymbolRef.getVisibilityType() 954 : SymbolRef.getVisibilityType() | 0x0020, 955 SymbolRef.getStorageClass(), 956 (is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2); 957 if (is64Bit() && ExceptionSection.isDebugEnabled) { 958 // On 64 bit with debugging enabled, we have a csect, exception, and 959 // function auxilliary entries, so we must increment symbol index by 4. 960 writeSymbolAuxExceptionEntry( 961 ExceptionSection.FileOffsetToData + 962 getExceptionOffset(Entry->second.FunctionSymbol), 963 Entry->second.FunctionSize, 964 SymbolIndexMap[Entry->second.FunctionSymbol] + 4); 965 } 966 // For exception section entries, csect and function auxilliary entries 967 // must exist. On 64-bit there is also an exception auxilliary entry. 968 writeSymbolAuxFunctionEntry( 969 ExceptionSection.FileOffsetToData + 970 getExceptionOffset(Entry->second.FunctionSymbol), 971 Entry->second.FunctionSize, 0, 972 (is64Bit() && ExceptionSection.isDebugEnabled) 973 ? SymbolIndexMap[Entry->second.FunctionSymbol] + 4 974 : SymbolIndexMap[Entry->second.FunctionSymbol] + 3); 975 } else { 976 writeSymbolEntry(SymbolRef.getSymbolTableName(), 977 CSectionRef.Address + SymbolOffset, SectionIndex, 978 SymbolRef.getVisibilityType(), 979 SymbolRef.getStorageClass()); 980 } 981 writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD, 982 CSectionRef.MCSec->getMappingClass()); 983 } 984 985 void XCOFFWriter::writeSymbolEntryForDwarfSection( 986 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) { 987 assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!"); 988 989 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0, 990 SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF); 991 992 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size); 993 } 994 995 void XCOFFWriter::writeSymbolEntryForControlSection( 996 const XCOFFSection &CSectionRef, int16_t SectionIndex, 997 XCOFF::StorageClass StorageClass) { 998 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address, 999 SectionIndex, CSectionRef.getVisibilityType(), StorageClass); 1000 1001 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec), 1002 CSectionRef.MCSec->getMappingClass()); 1003 } 1004 1005 void XCOFFWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset, 1006 uint32_t FunctionSize, 1007 uint64_t LineNumberPointer, 1008 uint32_t EndIndex) { 1009 if (is64Bit()) 1010 writeWord(LineNumberPointer); 1011 else 1012 W.write<uint32_t>(EntryOffset); 1013 W.write<uint32_t>(FunctionSize); 1014 if (!is64Bit()) 1015 writeWord(LineNumberPointer); 1016 W.write<uint32_t>(EndIndex); 1017 if (is64Bit()) { 1018 W.OS.write_zeros(1); 1019 W.write<uint8_t>(XCOFF::AUX_FCN); 1020 } else { 1021 W.OS.write_zeros(2); 1022 } 1023 } 1024 1025 void XCOFFWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset, 1026 uint32_t FunctionSize, 1027 uint32_t EndIndex) { 1028 assert(is64Bit() && "Exception auxilliary entries are 64-bit only."); 1029 W.write<uint64_t>(EntryOffset); 1030 W.write<uint32_t>(FunctionSize); 1031 W.write<uint32_t>(EndIndex); 1032 W.OS.write_zeros(1); // Pad (unused) 1033 W.write<uint8_t>(XCOFF::AUX_EXCEPT); 1034 } 1035 1036 void XCOFFWriter::writeFileHeader() { 1037 W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32); 1038 W.write<uint16_t>(SectionCount); 1039 W.write<int32_t>(0); // TimeStamp 1040 writeWord(SymbolTableOffset); 1041 if (is64Bit()) { 1042 W.write<uint16_t>(auxiliaryHeaderSize()); 1043 W.write<uint16_t>(0); // Flags 1044 W.write<int32_t>(SymbolTableEntryCount); 1045 } else { 1046 W.write<int32_t>(SymbolTableEntryCount); 1047 W.write<uint16_t>(auxiliaryHeaderSize()); 1048 W.write<uint16_t>(0); // Flags 1049 } 1050 } 1051 1052 void XCOFFWriter::writeAuxFileHeader() { 1053 if (!auxiliaryHeaderSize()) 1054 return; 1055 W.write<uint16_t>(0); // Magic 1056 W.write<uint16_t>( 1057 XCOFF::NEW_XCOFF_INTERPRET); // Version. The new interpretation of the 1058 // n_type field in the symbol table entry is 1059 // used in XCOFF32. 1060 W.write<uint32_t>(Sections[0]->Size); // TextSize 1061 W.write<uint32_t>(Sections[1]->Size); // InitDataSize 1062 W.write<uint32_t>(Sections[2]->Size); // BssDataSize 1063 W.write<uint32_t>(0); // EntryPointAddr 1064 W.write<uint32_t>(Sections[0]->Address); // TextStartAddr 1065 W.write<uint32_t>(Sections[1]->Address); // DataStartAddr 1066 } 1067 1068 void XCOFFWriter::writeSectionHeader(const SectionEntry *Sec) { 1069 bool IsDwarf = (Sec->Flags & XCOFF::STYP_DWARF) != 0; 1070 bool IsOvrflo = (Sec->Flags & XCOFF::STYP_OVRFLO) != 0; 1071 // Nothing to write for this Section. 1072 if (Sec->Index == SectionEntry::UninitializedIndex) 1073 return; 1074 1075 // Write Name. 1076 ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize); 1077 W.write(NameRef); 1078 1079 // Write the Physical Address and Virtual Address. 1080 // We use 0 for DWARF sections' Physical and Virtual Addresses. 1081 writeWord(IsDwarf ? 0 : Sec->Address); 1082 // Since line number is not supported, we set it to 0 for overflow sections. 1083 writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address); 1084 1085 writeWord(Sec->Size); 1086 writeWord(Sec->FileOffsetToData); 1087 writeWord(Sec->FileOffsetToRelocations); 1088 writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet. 1089 1090 if (is64Bit()) { 1091 W.write<uint32_t>(Sec->RelocationCount); 1092 W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet. 1093 W.write<int32_t>(Sec->Flags); 1094 W.OS.write_zeros(4); 1095 } else { 1096 // For the overflow section header, s_nreloc provides a reference to the 1097 // primary section header and s_nlnno must have the same value. 1098 // For common section headers, if either of s_nreloc or s_nlnno are set to 1099 // 65535, the other one must also be set to 65535. 1100 W.write<uint16_t>(Sec->RelocationCount); 1101 W.write<uint16_t>((IsOvrflo || Sec->RelocationCount == XCOFF::RelocOverflow) 1102 ? Sec->RelocationCount 1103 : 0); // NumberOfLineNumbers. Not supported yet. 1104 W.write<int32_t>(Sec->Flags); 1105 } 1106 } 1107 1108 void XCOFFWriter::writeSectionHeaderTable() { 1109 for (const auto *CsectSec : Sections) 1110 writeSectionHeader(CsectSec); 1111 for (const auto &DwarfSec : DwarfSections) 1112 writeSectionHeader(&DwarfSec); 1113 for (const auto &OverflowSec : OverflowSections) 1114 writeSectionHeader(&OverflowSec); 1115 if (hasExceptionSection()) 1116 writeSectionHeader(&ExceptionSection); 1117 if (CInfoSymSection.Entry) 1118 writeSectionHeader(&CInfoSymSection); 1119 } 1120 1121 void XCOFFWriter::writeRelocation(XCOFFRelocation Reloc, 1122 const XCOFFSection &Section) { 1123 if (Section.MCSec->isCsect()) 1124 writeWord(Section.Address + Reloc.FixupOffsetInCsect); 1125 else { 1126 // DWARF sections' address is set to 0. 1127 assert(Section.MCSec->isDwarfSect() && "unsupport section type!"); 1128 writeWord(Reloc.FixupOffsetInCsect); 1129 } 1130 W.write<uint32_t>(Reloc.SymbolTableIndex); 1131 W.write<uint8_t>(Reloc.SignAndSize); 1132 W.write<uint8_t>(Reloc.Type); 1133 } 1134 1135 void XCOFFWriter::writeRelocations() { 1136 for (const auto *Section : Sections) { 1137 if (Section->Index == SectionEntry::UninitializedIndex) 1138 // Nothing to write for this Section. 1139 continue; 1140 1141 for (const auto *Group : Section->Groups) { 1142 if (Group->empty()) 1143 continue; 1144 1145 for (const auto &Csect : *Group) { 1146 for (const auto Reloc : Csect.Relocations) 1147 writeRelocation(Reloc, Csect); 1148 } 1149 } 1150 } 1151 1152 for (const auto &DwarfSection : DwarfSections) 1153 for (const auto &Reloc : DwarfSection.DwarfSect->Relocations) 1154 writeRelocation(Reloc, *DwarfSection.DwarfSect); 1155 } 1156 1157 void XCOFFWriter::writeSymbolTable(MCAssembler &Asm) { 1158 // Write C_FILE symbols. 1159 StringRef Vers = CompilerVersion; 1160 1161 for (const std::pair<std::string, size_t> &F : FileNames) { 1162 // The n_name of a C_FILE symbol is the source file's name when no auxiliary 1163 // entries are present. 1164 StringRef FileName = F.first; 1165 1166 // For C_FILE symbols, the Source Language ID overlays the high-order byte 1167 // of the SymbolType field, and the CPU Version ID is defined as the 1168 // low-order byte. 1169 // AIX's system assembler determines the source language ID based on the 1170 // source file's name suffix, and the behavior here is consistent with it. 1171 uint8_t LangID; 1172 if (FileName.ends_with(".c")) 1173 LangID = XCOFF::TB_C; 1174 else if (FileName.ends_with_insensitive(".f") || 1175 FileName.ends_with_insensitive(".f77") || 1176 FileName.ends_with_insensitive(".f90") || 1177 FileName.ends_with_insensitive(".f95") || 1178 FileName.ends_with_insensitive(".f03") || 1179 FileName.ends_with_insensitive(".f08")) 1180 LangID = XCOFF::TB_Fortran; 1181 else 1182 LangID = XCOFF::TB_CPLUSPLUS; 1183 1184 uint8_t CpuID = XCOFF::getCpuID(getCPUType()); 1185 1186 int NumberOfFileAuxEntries = 1; 1187 if (!Vers.empty()) 1188 ++NumberOfFileAuxEntries; 1189 writeSymbolEntry(".file", /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG, 1190 /*SymbolType=*/(LangID << 8) | CpuID, XCOFF::C_FILE, 1191 NumberOfFileAuxEntries); 1192 writeSymbolAuxFileEntry(FileName, XCOFF::XFT_FN); 1193 if (!Vers.empty()) 1194 writeSymbolAuxFileEntry(Vers, XCOFF::XFT_CV); 1195 } 1196 1197 if (CInfoSymSection.Entry) 1198 writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset, 1199 CInfoSymSection.Index, 1200 /*SymbolType=*/0, XCOFF::C_INFO, 1201 /*NumberOfAuxEntries=*/0); 1202 1203 for (const auto &Csect : UndefinedCsects) { 1204 writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF, 1205 Csect.MCSec->getStorageClass()); 1206 } 1207 1208 for (const auto *Section : Sections) { 1209 if (Section->Index == SectionEntry::UninitializedIndex) 1210 // Nothing to write for this Section. 1211 continue; 1212 1213 for (const auto *Group : Section->Groups) { 1214 if (Group->empty()) 1215 continue; 1216 1217 const int16_t SectionIndex = Section->Index; 1218 for (const auto &Csect : *Group) { 1219 // Write out the control section first and then each symbol in it. 1220 writeSymbolEntryForControlSection(Csect, SectionIndex, 1221 Csect.MCSec->getStorageClass()); 1222 1223 for (const auto &Sym : Csect.Syms) 1224 writeSymbolEntryForCsectMemberLabel( 1225 Sym, Csect, SectionIndex, Asm.getSymbolOffset(*(Sym.MCSym))); 1226 } 1227 } 1228 } 1229 1230 for (const auto &DwarfSection : DwarfSections) 1231 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect, 1232 DwarfSection.Index); 1233 } 1234 1235 void XCOFFWriter::finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount) { 1236 // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file 1237 // may not contain an overflow section header. 1238 if (!is64Bit() && (RelCount >= static_cast<uint32_t>(XCOFF::RelocOverflow))) { 1239 // Generate an overflow section header. 1240 SectionEntry SecEntry(".ovrflo", XCOFF::STYP_OVRFLO); 1241 1242 // This field specifies the file section number of the section header that 1243 // overflowed. 1244 SecEntry.RelocationCount = Sec->Index; 1245 1246 // This field specifies the number of relocation entries actually 1247 // required. 1248 SecEntry.Address = RelCount; 1249 SecEntry.Index = ++SectionCount; 1250 OverflowSections.push_back(std::move(SecEntry)); 1251 1252 // The field in the primary section header is always 65535 1253 // (XCOFF::RelocOverflow). 1254 Sec->RelocationCount = XCOFF::RelocOverflow; 1255 } else { 1256 Sec->RelocationCount = RelCount; 1257 } 1258 } 1259 1260 void XCOFFWriter::calcOffsetToRelocations(SectionEntry *Sec, 1261 uint64_t &RawPointer) { 1262 if (!Sec->RelocationCount) 1263 return; 1264 1265 Sec->FileOffsetToRelocations = RawPointer; 1266 uint64_t RelocationSizeInSec = 0; 1267 if (!is64Bit() && 1268 Sec->RelocationCount == static_cast<uint32_t>(XCOFF::RelocOverflow)) { 1269 // Find its corresponding overflow section. 1270 for (auto &OverflowSec : OverflowSections) { 1271 if (OverflowSec.RelocationCount == static_cast<uint32_t>(Sec->Index)) { 1272 RelocationSizeInSec = 1273 OverflowSec.Address * XCOFF::RelocationSerializationSize32; 1274 1275 // This field must have the same values as in the corresponding 1276 // primary section header. 1277 OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations; 1278 } 1279 } 1280 assert(RelocationSizeInSec && "Overflow section header doesn't exist."); 1281 } else { 1282 RelocationSizeInSec = Sec->RelocationCount * 1283 (is64Bit() ? XCOFF::RelocationSerializationSize64 1284 : XCOFF::RelocationSerializationSize32); 1285 } 1286 1287 RawPointer += RelocationSizeInSec; 1288 if (RawPointer > MaxRawDataSize) 1289 report_fatal_error("Relocation data overflowed this object file."); 1290 } 1291 1292 void XCOFFWriter::finalizeSectionInfo() { 1293 for (auto *Section : Sections) { 1294 if (Section->Index == SectionEntry::UninitializedIndex) 1295 // Nothing to record for this Section. 1296 continue; 1297 1298 uint64_t RelCount = 0; 1299 for (const auto *Group : Section->Groups) { 1300 if (Group->empty()) 1301 continue; 1302 1303 for (auto &Csect : *Group) 1304 RelCount += Csect.Relocations.size(); 1305 } 1306 finalizeRelocationInfo(Section, RelCount); 1307 } 1308 1309 for (auto &DwarfSection : DwarfSections) 1310 finalizeRelocationInfo(&DwarfSection, 1311 DwarfSection.DwarfSect->Relocations.size()); 1312 1313 // Calculate the RawPointer value for all headers. 1314 uint64_t RawPointer = 1315 (is64Bit() ? (XCOFF::FileHeaderSize64 + 1316 SectionCount * XCOFF::SectionHeaderSize64) 1317 : (XCOFF::FileHeaderSize32 + 1318 SectionCount * XCOFF::SectionHeaderSize32)) + 1319 auxiliaryHeaderSize(); 1320 1321 // Calculate the file offset to the section data. 1322 for (auto *Sec : Sections) { 1323 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual) 1324 continue; 1325 1326 RawPointer = Sec->advanceFileOffset(MaxRawDataSize, RawPointer); 1327 } 1328 1329 if (!DwarfSections.empty()) { 1330 RawPointer += PaddingsBeforeDwarf; 1331 for (auto &DwarfSection : DwarfSections) { 1332 RawPointer = DwarfSection.advanceFileOffset(MaxRawDataSize, RawPointer); 1333 } 1334 } 1335 1336 if (hasExceptionSection()) 1337 RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer); 1338 1339 if (CInfoSymSection.Entry) 1340 RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer); 1341 1342 for (auto *Sec : Sections) { 1343 if (Sec->Index != SectionEntry::UninitializedIndex) 1344 calcOffsetToRelocations(Sec, RawPointer); 1345 } 1346 1347 for (auto &DwarfSec : DwarfSections) 1348 calcOffsetToRelocations(&DwarfSec, RawPointer); 1349 1350 // TODO Error check that the number of symbol table entries fits in 32-bits 1351 // signed ... 1352 if (SymbolTableEntryCount) 1353 SymbolTableOffset = RawPointer; 1354 } 1355 1356 void XCOFFWriter::addExceptionEntry(const MCSymbol *Symbol, 1357 const MCSymbol *Trap, unsigned LanguageCode, 1358 unsigned ReasonCode, unsigned FunctionSize, 1359 bool hasDebug) { 1360 // If a module had debug info, debugging is enabled and XCOFF emits the 1361 // exception auxilliary entry. 1362 if (hasDebug) 1363 ExceptionSection.isDebugEnabled = true; 1364 auto Entry = ExceptionSection.ExceptionTable.find(Symbol->getName()); 1365 if (Entry != ExceptionSection.ExceptionTable.end()) { 1366 Entry->second.Entries.push_back( 1367 ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); 1368 return; 1369 } 1370 ExceptionInfo NewEntry; 1371 NewEntry.FunctionSymbol = Symbol; 1372 NewEntry.FunctionSize = FunctionSize; 1373 NewEntry.Entries.push_back( 1374 ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); 1375 ExceptionSection.ExceptionTable.insert( 1376 std::pair<const StringRef, ExceptionInfo>(Symbol->getName(), NewEntry)); 1377 } 1378 1379 unsigned XCOFFWriter::getExceptionSectionSize() { 1380 unsigned EntryNum = 0; 1381 1382 for (const auto &TableEntry : ExceptionSection.ExceptionTable) 1383 // The size() gets +1 to account for the initial entry containing the 1384 // symbol table index. 1385 EntryNum += TableEntry.second.Entries.size() + 1; 1386 1387 return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64 1388 : XCOFF::ExceptionSectionEntrySize32); 1389 } 1390 1391 unsigned XCOFFWriter::getExceptionOffset(const MCSymbol *Symbol) { 1392 unsigned EntryNum = 0; 1393 for (const auto &TableEntry : ExceptionSection.ExceptionTable) { 1394 if (Symbol == TableEntry.second.FunctionSymbol) 1395 break; 1396 EntryNum += TableEntry.second.Entries.size() + 1; 1397 } 1398 return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64 1399 : XCOFF::ExceptionSectionEntrySize32); 1400 } 1401 1402 void XCOFFWriter::addCInfoSymEntry(StringRef Name, StringRef Metadata) { 1403 assert(!CInfoSymSection.Entry && "Multiple entries are not supported"); 1404 CInfoSymSection.addEntry( 1405 std::make_unique<CInfoSymInfo>(Name.str(), Metadata.str())); 1406 } 1407 1408 void XCOFFWriter::assignAddressesAndIndices(MCAssembler &Asm) { 1409 // The symbol table starts with all the C_FILE symbols. Each C_FILE symbol 1410 // requires 1 or 2 auxiliary entries. 1411 uint32_t SymbolTableIndex = 1412 (2 + (CompilerVersion.empty() ? 0 : 1)) * FileNames.size(); 1413 1414 if (CInfoSymSection.Entry) 1415 SymbolTableIndex++; 1416 1417 // Calculate indices for undefined symbols. 1418 for (auto &Csect : UndefinedCsects) { 1419 Csect.Size = 0; 1420 Csect.Address = 0; 1421 Csect.SymbolTableIndex = SymbolTableIndex; 1422 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 1423 // 1 main and 1 auxiliary symbol table entry for each contained symbol. 1424 SymbolTableIndex += 2; 1425 } 1426 1427 // The address corrresponds to the address of sections and symbols in the 1428 // object file. We place the shared address 0 immediately after the 1429 // section header table. 1430 uint64_t Address = 0; 1431 // Section indices are 1-based in XCOFF. 1432 int32_t SectionIndex = 1; 1433 bool HasTDataSection = false; 1434 1435 for (auto *Section : Sections) { 1436 const bool IsEmpty = 1437 llvm::all_of(Section->Groups, 1438 [](const CsectGroup *Group) { return Group->empty(); }); 1439 if (IsEmpty) 1440 continue; 1441 1442 if (SectionIndex > MaxSectionIndex) 1443 report_fatal_error("Section index overflow!"); 1444 Section->Index = SectionIndex++; 1445 SectionCount++; 1446 1447 bool SectionAddressSet = false; 1448 // Reset the starting address to 0 for TData section. 1449 if (Section->Flags == XCOFF::STYP_TDATA) { 1450 Address = 0; 1451 HasTDataSection = true; 1452 } 1453 // Reset the starting address to 0 for TBSS section if the object file does 1454 // not contain TData Section. 1455 if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection) 1456 Address = 0; 1457 1458 for (auto *Group : Section->Groups) { 1459 if (Group->empty()) 1460 continue; 1461 1462 for (auto &Csect : *Group) { 1463 const MCSectionXCOFF *MCSec = Csect.MCSec; 1464 Csect.Address = alignTo(Address, MCSec->getAlign()); 1465 Csect.Size = Asm.getSectionAddressSize(*MCSec); 1466 Address = Csect.Address + Csect.Size; 1467 Csect.SymbolTableIndex = SymbolTableIndex; 1468 SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 1469 // 1 main and 1 auxiliary symbol table entry for the csect. 1470 SymbolTableIndex += 2; 1471 1472 for (auto &Sym : Csect.Syms) { 1473 bool hasExceptEntry = false; 1474 auto Entry = 1475 ExceptionSection.ExceptionTable.find(Sym.MCSym->getName()); 1476 if (Entry != ExceptionSection.ExceptionTable.end()) { 1477 hasExceptEntry = true; 1478 for (auto &TrapEntry : Entry->second.Entries) { 1479 TrapEntry.TrapAddress = Asm.getSymbolOffset(*(Sym.MCSym)) + 1480 TrapEntry.Trap->getOffset(); 1481 } 1482 } 1483 Sym.SymbolTableIndex = SymbolTableIndex; 1484 SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex; 1485 // 1 main and 1 auxiliary symbol table entry for each contained 1486 // symbol. For symbols with exception section entries, a function 1487 // auxilliary entry is needed, and on 64-bit XCOFF with debugging 1488 // enabled, an additional exception auxilliary entry is needed. 1489 SymbolTableIndex += 2; 1490 if (hasExceptionSection() && hasExceptEntry) { 1491 if (is64Bit() && ExceptionSection.isDebugEnabled) 1492 SymbolTableIndex += 2; 1493 else 1494 SymbolTableIndex += 1; 1495 } 1496 } 1497 } 1498 1499 if (!SectionAddressSet) { 1500 Section->Address = Group->front().Address; 1501 SectionAddressSet = true; 1502 } 1503 } 1504 1505 // Make sure the address of the next section aligned to 1506 // DefaultSectionAlign. 1507 Address = alignTo(Address, DefaultSectionAlign); 1508 Section->Size = Address - Section->Address; 1509 } 1510 1511 // Start to generate DWARF sections. Sections other than DWARF section use 1512 // DefaultSectionAlign as the default alignment, while DWARF sections have 1513 // their own alignments. If these two alignments are not the same, we need 1514 // some paddings here and record the paddings bytes for FileOffsetToData 1515 // calculation. 1516 if (!DwarfSections.empty()) 1517 PaddingsBeforeDwarf = 1518 alignTo(Address, 1519 (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) - 1520 Address; 1521 1522 DwarfSectionEntry *LastDwarfSection = nullptr; 1523 for (auto &DwarfSection : DwarfSections) { 1524 assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!"); 1525 1526 XCOFFSection &DwarfSect = *DwarfSection.DwarfSect; 1527 const MCSectionXCOFF *MCSec = DwarfSect.MCSec; 1528 1529 // Section index. 1530 DwarfSection.Index = SectionIndex++; 1531 SectionCount++; 1532 1533 // Symbol index. 1534 DwarfSect.SymbolTableIndex = SymbolTableIndex; 1535 SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex; 1536 // 1 main and 1 auxiliary symbol table entry for the csect. 1537 SymbolTableIndex += 2; 1538 1539 // Section address. Make it align to section alignment. 1540 // We use address 0 for DWARF sections' Physical and Virtual Addresses. 1541 // This address is used to tell where is the section in the final object. 1542 // See writeSectionForDwarfSectionEntry(). 1543 DwarfSection.Address = DwarfSect.Address = 1544 alignTo(Address, MCSec->getAlign()); 1545 1546 // Section size. 1547 // For DWARF section, we must use the real size which may be not aligned. 1548 DwarfSection.Size = DwarfSect.Size = Asm.getSectionAddressSize(*MCSec); 1549 1550 Address = DwarfSection.Address + DwarfSection.Size; 1551 1552 if (LastDwarfSection) 1553 LastDwarfSection->MemorySize = 1554 DwarfSection.Address - LastDwarfSection->Address; 1555 LastDwarfSection = &DwarfSection; 1556 } 1557 if (LastDwarfSection) { 1558 // Make the final DWARF section address align to the default section 1559 // alignment for follow contents. 1560 Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size, 1561 DefaultSectionAlign); 1562 LastDwarfSection->MemorySize = Address - LastDwarfSection->Address; 1563 } 1564 if (hasExceptionSection()) { 1565 ExceptionSection.Index = SectionIndex++; 1566 SectionCount++; 1567 ExceptionSection.Address = 0; 1568 ExceptionSection.Size = getExceptionSectionSize(); 1569 Address += ExceptionSection.Size; 1570 Address = alignTo(Address, DefaultSectionAlign); 1571 } 1572 1573 if (CInfoSymSection.Entry) { 1574 CInfoSymSection.Index = SectionIndex++; 1575 SectionCount++; 1576 CInfoSymSection.Address = 0; 1577 Address += CInfoSymSection.Size; 1578 Address = alignTo(Address, DefaultSectionAlign); 1579 } 1580 1581 SymbolTableEntryCount = SymbolTableIndex; 1582 } 1583 1584 void XCOFFWriter::writeSectionForControlSectionEntry( 1585 const MCAssembler &Asm, const CsectSectionEntry &CsectEntry, 1586 uint64_t &CurrentAddressLocation) { 1587 // Nothing to write for this Section. 1588 if (CsectEntry.Index == SectionEntry::UninitializedIndex) 1589 return; 1590 1591 // There could be a gap (without corresponding zero padding) between 1592 // sections. 1593 // There could be a gap (without corresponding zero padding) between 1594 // sections. 1595 assert(((CurrentAddressLocation <= CsectEntry.Address) || 1596 (CsectEntry.Flags == XCOFF::STYP_TDATA) || 1597 (CsectEntry.Flags == XCOFF::STYP_TBSS)) && 1598 "CurrentAddressLocation should be less than or equal to section " 1599 "address if the section is not TData or TBSS."); 1600 1601 CurrentAddressLocation = CsectEntry.Address; 1602 1603 // For virtual sections, nothing to write. But need to increase 1604 // CurrentAddressLocation for later sections like DWARF section has a correct 1605 // writing location. 1606 if (CsectEntry.IsVirtual) { 1607 CurrentAddressLocation += CsectEntry.Size; 1608 return; 1609 } 1610 1611 for (const auto &Group : CsectEntry.Groups) { 1612 for (const auto &Csect : *Group) { 1613 if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation) 1614 W.OS.write_zeros(PaddingSize); 1615 if (Csect.Size) 1616 Asm.writeSectionData(W.OS, Csect.MCSec); 1617 CurrentAddressLocation = Csect.Address + Csect.Size; 1618 } 1619 } 1620 1621 // The size of the tail padding in a section is the end virtual address of 1622 // the current section minus the end virtual address of the last csect 1623 // in that section. 1624 if (uint64_t PaddingSize = 1625 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) { 1626 W.OS.write_zeros(PaddingSize); 1627 CurrentAddressLocation += PaddingSize; 1628 } 1629 } 1630 1631 void XCOFFWriter::writeSectionForDwarfSectionEntry( 1632 const MCAssembler &Asm, const DwarfSectionEntry &DwarfEntry, 1633 uint64_t &CurrentAddressLocation) { 1634 // There could be a gap (without corresponding zero padding) between 1635 // sections. For example DWARF section alignment is bigger than 1636 // DefaultSectionAlign. 1637 assert(CurrentAddressLocation <= DwarfEntry.Address && 1638 "CurrentAddressLocation should be less than or equal to section " 1639 "address."); 1640 1641 if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation) 1642 W.OS.write_zeros(PaddingSize); 1643 1644 if (DwarfEntry.Size) 1645 Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec); 1646 1647 CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size; 1648 1649 // DWARF section size is not aligned to DefaultSectionAlign. 1650 // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign. 1651 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign; 1652 uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0; 1653 if (TailPaddingSize) 1654 W.OS.write_zeros(TailPaddingSize); 1655 1656 CurrentAddressLocation += TailPaddingSize; 1657 } 1658 1659 void XCOFFWriter::writeSectionForExceptionSectionEntry( 1660 const MCAssembler &Asm, ExceptionSectionEntry &ExceptionEntry, 1661 uint64_t &CurrentAddressLocation) { 1662 for (const auto &TableEntry : ExceptionEntry.ExceptionTable) { 1663 // For every symbol that has exception entries, you must start the entries 1664 // with an initial symbol table index entry 1665 W.write<uint32_t>(SymbolIndexMap[TableEntry.second.FunctionSymbol]); 1666 if (is64Bit()) { 1667 // 4-byte padding on 64-bit. 1668 W.OS.write_zeros(4); 1669 } 1670 W.OS.write_zeros(2); 1671 for (auto &TrapEntry : TableEntry.second.Entries) { 1672 writeWord(TrapEntry.TrapAddress); 1673 W.write<uint8_t>(TrapEntry.Lang); 1674 W.write<uint8_t>(TrapEntry.Reason); 1675 } 1676 } 1677 1678 CurrentAddressLocation += getExceptionSectionSize(); 1679 } 1680 1681 void XCOFFWriter::writeSectionForCInfoSymSectionEntry( 1682 const MCAssembler &Asm, CInfoSymSectionEntry &CInfoSymEntry, 1683 uint64_t &CurrentAddressLocation) { 1684 if (!CInfoSymSection.Entry) 1685 return; 1686 1687 constexpr int WordSize = sizeof(uint32_t); 1688 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry; 1689 const std::string &Metadata = CISI->Metadata; 1690 1691 // Emit the 4-byte length of the metadata. 1692 W.write<uint32_t>(Metadata.size()); 1693 1694 if (Metadata.size() == 0) 1695 return; 1696 1697 // Write out the payload one word at a time. 1698 size_t Index = 0; 1699 while (Index + WordSize <= Metadata.size()) { 1700 uint32_t NextWord = 1701 llvm::support::endian::read32be(Metadata.data() + Index); 1702 W.write<uint32_t>(NextWord); 1703 Index += WordSize; 1704 } 1705 1706 // If there is padding, we have at least one byte of payload left to emit. 1707 if (CISI->paddingSize()) { 1708 std::array<uint8_t, WordSize> LastWord = {0}; 1709 ::memcpy(LastWord.data(), Metadata.data() + Index, Metadata.size() - Index); 1710 W.write<uint32_t>(llvm::support::endian::read32be(LastWord.data())); 1711 } 1712 1713 CurrentAddressLocation += CISI->size(); 1714 } 1715 1716 // Takes the log base 2 of the alignment and shifts the result into the 5 most 1717 // significant bits of a byte, then or's in the csect type into the least 1718 // significant 3 bits. 1719 uint8_t getEncodedType(const MCSectionXCOFF *Sec) { 1720 unsigned Log2Align = Log2(Sec->getAlign()); 1721 // Result is a number in the range [0, 31] which fits in the 5 least 1722 // significant bits. Shift this value into the 5 most significant bits, and 1723 // bitwise-or in the csect type. 1724 uint8_t EncodedAlign = Log2Align << 3; 1725 return EncodedAlign | Sec->getCSectType(); 1726 } 1727 1728 } // end anonymous namespace 1729 1730 std::unique_ptr<MCObjectWriter> 1731 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 1732 raw_pwrite_stream &OS) { 1733 return std::make_unique<XCOFFWriter>(std::move(MOTW), OS); 1734 } 1735