10b57cec5SDimitry Andric //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements XCOFF object file writer information. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 138bcb0991SDimitry Andric #include "llvm/BinaryFormat/XCOFF.h" 145ffd83dbSDimitry Andric #include "llvm/MC/MCAsmBackend.h" 150b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 165ffd83dbSDimitry Andric #include "llvm/MC/MCFixup.h" 175ffd83dbSDimitry Andric #include "llvm/MC/MCFixupKindInfo.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 198bcb0991SDimitry Andric #include "llvm/MC/MCSectionXCOFF.h" 208bcb0991SDimitry Andric #include "llvm/MC/MCSymbolXCOFF.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCXCOFFObjectWriter.h" 238bcb0991SDimitry Andric #include "llvm/MC/StringTableBuilder.h" 2481ad6265SDimitry Andric #include "llvm/Support/Casting.h" 255ffd83dbSDimitry Andric #include "llvm/Support/EndianStream.h" 2681ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 278bcb0991SDimitry Andric #include "llvm/Support/MathExtras.h" 288bcb0991SDimitry Andric 298bcb0991SDimitry Andric #include <deque> 30bdd1243dSDimitry Andric #include <map> 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric using namespace llvm; 330b57cec5SDimitry Andric 348bcb0991SDimitry Andric // An XCOFF object file has a limited set of predefined sections. The most 358bcb0991SDimitry Andric // important ones for us (right now) are: 368bcb0991SDimitry Andric // .text --> contains program code and read-only data. 378bcb0991SDimitry Andric // .data --> contains initialized data, function descriptors, and the TOC. 388bcb0991SDimitry Andric // .bss --> contains uninitialized data. 398bcb0991SDimitry Andric // Each of these sections is composed of 'Control Sections'. A Control Section 408bcb0991SDimitry Andric // is more commonly referred to as a csect. A csect is an indivisible unit of 418bcb0991SDimitry Andric // code or data, and acts as a container for symbols. A csect is mapped 428bcb0991SDimitry Andric // into a section based on its storage-mapping class, with the exception of 438bcb0991SDimitry Andric // XMC_RW which gets mapped to either .data or .bss based on whether it's 448bcb0991SDimitry Andric // explicitly initialized or not. 458bcb0991SDimitry Andric // 468bcb0991SDimitry Andric // We don't represent the sections in the MC layer as there is nothing 478bcb0991SDimitry Andric // interesting about them at at that level: they carry information that is 488bcb0991SDimitry Andric // only relevant to the ObjectWriter, so we materialize them in this class. 490b57cec5SDimitry Andric namespace { 500b57cec5SDimitry Andric 518bcb0991SDimitry Andric constexpr unsigned DefaultSectionAlign = 4; 52480093f4SDimitry Andric constexpr int16_t MaxSectionIndex = INT16_MAX; 538bcb0991SDimitry Andric 548bcb0991SDimitry Andric // Packs the csect's alignment and type into a byte. 558bcb0991SDimitry Andric uint8_t getEncodedType(const MCSectionXCOFF *); 568bcb0991SDimitry Andric 575ffd83dbSDimitry Andric struct XCOFFRelocation { 585ffd83dbSDimitry Andric uint32_t SymbolTableIndex; 595ffd83dbSDimitry Andric uint32_t FixupOffsetInCsect; 605ffd83dbSDimitry Andric uint8_t SignAndSize; 615ffd83dbSDimitry Andric uint8_t Type; 625ffd83dbSDimitry Andric }; 635ffd83dbSDimitry Andric 648bcb0991SDimitry Andric // Wrapper around an MCSymbolXCOFF. 658bcb0991SDimitry Andric struct Symbol { 668bcb0991SDimitry Andric const MCSymbolXCOFF *const MCSym; 678bcb0991SDimitry Andric uint32_t SymbolTableIndex; 688bcb0991SDimitry Andric 6981ad6265SDimitry Andric XCOFF::VisibilityType getVisibilityType() const { 7081ad6265SDimitry Andric return MCSym->getVisibilityType(); 7181ad6265SDimitry Andric } 7281ad6265SDimitry Andric 738bcb0991SDimitry Andric XCOFF::StorageClass getStorageClass() const { 748bcb0991SDimitry Andric return MCSym->getStorageClass(); 758bcb0991SDimitry Andric } 765ffd83dbSDimitry Andric StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); } 778bcb0991SDimitry Andric Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {} 788bcb0991SDimitry Andric }; 798bcb0991SDimitry Andric 808bcb0991SDimitry Andric // Wrapper for an MCSectionXCOFF. 81fe6060f1SDimitry Andric // It can be a Csect or debug section or DWARF section and so on. 82fe6060f1SDimitry Andric struct XCOFFSection { 83fe6060f1SDimitry Andric const MCSectionXCOFF *const MCSec; 848bcb0991SDimitry Andric uint32_t SymbolTableIndex; 8581ad6265SDimitry Andric uint64_t Address; 8681ad6265SDimitry Andric uint64_t Size; 878bcb0991SDimitry Andric 888bcb0991SDimitry Andric SmallVector<Symbol, 1> Syms; 895ffd83dbSDimitry Andric SmallVector<XCOFFRelocation, 1> Relocations; 90fe6060f1SDimitry Andric StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); } 9181ad6265SDimitry Andric XCOFF::VisibilityType getVisibilityType() const { 9281ad6265SDimitry Andric return MCSec->getVisibilityType(); 9381ad6265SDimitry Andric } 94fe6060f1SDimitry Andric XCOFFSection(const MCSectionXCOFF *MCSec) 95fe6060f1SDimitry Andric : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {} 968bcb0991SDimitry Andric }; 978bcb0991SDimitry Andric 98480093f4SDimitry Andric // Type to be used for a container representing a set of csects with 99480093f4SDimitry Andric // (approximately) the same storage mapping class. For example all the csects 100480093f4SDimitry Andric // with a storage mapping class of `xmc_pr` will get placed into the same 101480093f4SDimitry Andric // container. 102fe6060f1SDimitry Andric using CsectGroup = std::deque<XCOFFSection>; 103480093f4SDimitry Andric using CsectGroups = std::deque<CsectGroup *>; 104480093f4SDimitry Andric 105fe6060f1SDimitry Andric // The basic section entry defination. This Section represents a section entry 106fe6060f1SDimitry Andric // in XCOFF section header table. 107fe6060f1SDimitry Andric struct SectionEntry { 1088bcb0991SDimitry Andric char Name[XCOFF::NameSize]; 109bdd1243dSDimitry Andric // The physical/virtual address of the section. For an object file these 110bdd1243dSDimitry Andric // values are equivalent, except for in the overflow section header, where 111bdd1243dSDimitry Andric // the physical address specifies the number of relocation entries and the 112bdd1243dSDimitry Andric // virtual address specifies the number of line number entries. 113bdd1243dSDimitry Andric // TODO: Divide Address into PhysicalAddress and VirtualAddress when line 114bdd1243dSDimitry Andric // number entries are supported. 11581ad6265SDimitry Andric uint64_t Address; 11681ad6265SDimitry Andric uint64_t Size; 11781ad6265SDimitry Andric uint64_t FileOffsetToData; 11881ad6265SDimitry Andric uint64_t FileOffsetToRelocations; 1198bcb0991SDimitry Andric uint32_t RelocationCount; 1208bcb0991SDimitry Andric int32_t Flags; 1218bcb0991SDimitry Andric 1228bcb0991SDimitry Andric int16_t Index; 1238bcb0991SDimitry Andric 12406c3fb27SDimitry Andric virtual uint64_t advanceFileOffset(const uint64_t MaxRawDataSize, 12506c3fb27SDimitry Andric const uint64_t RawPointer) { 12606c3fb27SDimitry Andric FileOffsetToData = RawPointer; 12706c3fb27SDimitry Andric uint64_t NewPointer = RawPointer + Size; 12806c3fb27SDimitry Andric if (NewPointer > MaxRawDataSize) 12906c3fb27SDimitry Andric report_fatal_error("Section raw data overflowed this object file."); 13006c3fb27SDimitry Andric return NewPointer; 13106c3fb27SDimitry Andric } 13206c3fb27SDimitry Andric 133480093f4SDimitry Andric // XCOFF has special section numbers for symbols: 134480093f4SDimitry Andric // -2 Specifies N_DEBUG, a special symbolic debugging symbol. 135480093f4SDimitry Andric // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not 136480093f4SDimitry Andric // relocatable. 137480093f4SDimitry Andric // 0 Specifies N_UNDEF, an undefined external symbol. 138480093f4SDimitry Andric // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that 139480093f4SDimitry Andric // hasn't been initialized. 140480093f4SDimitry Andric static constexpr int16_t UninitializedIndex = 141480093f4SDimitry Andric XCOFF::ReservedSectionNum::N_DEBUG - 1; 142480093f4SDimitry Andric 143fe6060f1SDimitry Andric SectionEntry(StringRef N, int32_t Flags) 144fe6060f1SDimitry Andric : Name(), Address(0), Size(0), FileOffsetToData(0), 145fe6060f1SDimitry Andric FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags), 146fe6060f1SDimitry Andric Index(UninitializedIndex) { 147fe6060f1SDimitry Andric assert(N.size() <= XCOFF::NameSize && "section name too long"); 148fe6060f1SDimitry Andric memcpy(Name, N.data(), N.size()); 149fe6060f1SDimitry Andric } 150480093f4SDimitry Andric 151fe6060f1SDimitry Andric virtual void reset() { 1528bcb0991SDimitry Andric Address = 0; 1538bcb0991SDimitry Andric Size = 0; 1548bcb0991SDimitry Andric FileOffsetToData = 0; 1558bcb0991SDimitry Andric FileOffsetToRelocations = 0; 1568bcb0991SDimitry Andric RelocationCount = 0; 157480093f4SDimitry Andric Index = UninitializedIndex; 158fe6060f1SDimitry Andric } 159fe6060f1SDimitry Andric 16081ad6265SDimitry Andric virtual ~SectionEntry() = default; 161fe6060f1SDimitry Andric }; 162fe6060f1SDimitry Andric 163fe6060f1SDimitry Andric // Represents the data related to a section excluding the csects that make up 164fe6060f1SDimitry Andric // the raw data of the section. The csects are stored separately as not all 165fe6060f1SDimitry Andric // sections contain csects, and some sections contain csects which are better 166fe6060f1SDimitry Andric // stored separately, e.g. the .data section containing read-write, descriptor, 167fe6060f1SDimitry Andric // TOCBase and TOC-entry csects. 168fe6060f1SDimitry Andric struct CsectSectionEntry : public SectionEntry { 169fe6060f1SDimitry Andric // Virtual sections do not need storage allocated in the object file. 170fe6060f1SDimitry Andric const bool IsVirtual; 171fe6060f1SDimitry Andric 172fe6060f1SDimitry Andric // This is a section containing csect groups. 173fe6060f1SDimitry Andric CsectGroups Groups; 174fe6060f1SDimitry Andric 175fe6060f1SDimitry Andric CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual, 176fe6060f1SDimitry Andric CsectGroups Groups) 177fe6060f1SDimitry Andric : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) { 178fe6060f1SDimitry Andric assert(N.size() <= XCOFF::NameSize && "section name too long"); 179fe6060f1SDimitry Andric memcpy(Name, N.data(), N.size()); 180fe6060f1SDimitry Andric } 181fe6060f1SDimitry Andric 182fe6060f1SDimitry Andric void reset() override { 183fe6060f1SDimitry Andric SectionEntry::reset(); 184480093f4SDimitry Andric // Clear any csects we have stored. 185480093f4SDimitry Andric for (auto *Group : Groups) 186480093f4SDimitry Andric Group->clear(); 1878bcb0991SDimitry Andric } 1888bcb0991SDimitry Andric 18981ad6265SDimitry Andric virtual ~CsectSectionEntry() = default; 1908bcb0991SDimitry Andric }; 1918bcb0991SDimitry Andric 192349cc55cSDimitry Andric struct DwarfSectionEntry : public SectionEntry { 193349cc55cSDimitry Andric // For DWARF section entry. 194349cc55cSDimitry Andric std::unique_ptr<XCOFFSection> DwarfSect; 195349cc55cSDimitry Andric 19681ad6265SDimitry Andric // For DWARF section, we must use real size in the section header. MemorySize 19781ad6265SDimitry Andric // is for the size the DWARF section occupies including paddings. 19881ad6265SDimitry Andric uint32_t MemorySize; 19981ad6265SDimitry Andric 20006c3fb27SDimitry Andric // TODO: Remove this override. Loadable sections (e.g., .text, .data) may need 20106c3fb27SDimitry Andric // to be aligned. Other sections generally don't need any alignment, but if 20206c3fb27SDimitry Andric // they're aligned, the RawPointer should be adjusted before writing the 20306c3fb27SDimitry Andric // section. Then a dwarf-specific function wouldn't be needed. 20406c3fb27SDimitry Andric uint64_t advanceFileOffset(const uint64_t MaxRawDataSize, 20506c3fb27SDimitry Andric const uint64_t RawPointer) override { 20606c3fb27SDimitry Andric FileOffsetToData = RawPointer; 20706c3fb27SDimitry Andric uint64_t NewPointer = RawPointer + MemorySize; 20806c3fb27SDimitry Andric assert(NewPointer <= MaxRawDataSize && 20906c3fb27SDimitry Andric "Section raw data overflowed this object file."); 21006c3fb27SDimitry Andric return NewPointer; 21106c3fb27SDimitry Andric } 21206c3fb27SDimitry Andric 213349cc55cSDimitry Andric DwarfSectionEntry(StringRef N, int32_t Flags, 214349cc55cSDimitry Andric std::unique_ptr<XCOFFSection> Sect) 21581ad6265SDimitry Andric : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)), 21681ad6265SDimitry Andric MemorySize(0) { 217349cc55cSDimitry Andric assert(DwarfSect->MCSec->isDwarfSect() && 218349cc55cSDimitry Andric "This should be a DWARF section!"); 219349cc55cSDimitry Andric assert(N.size() <= XCOFF::NameSize && "section name too long"); 220349cc55cSDimitry Andric memcpy(Name, N.data(), N.size()); 221349cc55cSDimitry Andric } 222349cc55cSDimitry Andric 223349cc55cSDimitry Andric DwarfSectionEntry(DwarfSectionEntry &&s) = default; 224349cc55cSDimitry Andric 22581ad6265SDimitry Andric virtual ~DwarfSectionEntry() = default; 226349cc55cSDimitry Andric }; 227349cc55cSDimitry Andric 228bdd1243dSDimitry Andric struct ExceptionTableEntry { 229bdd1243dSDimitry Andric const MCSymbol *Trap; 23006c3fb27SDimitry Andric uint64_t TrapAddress = ~0ul; 231bdd1243dSDimitry Andric unsigned Lang; 232bdd1243dSDimitry Andric unsigned Reason; 233bdd1243dSDimitry Andric 234bdd1243dSDimitry Andric ExceptionTableEntry(const MCSymbol *Trap, unsigned Lang, unsigned Reason) 235bdd1243dSDimitry Andric : Trap(Trap), Lang(Lang), Reason(Reason) {} 236bdd1243dSDimitry Andric }; 237bdd1243dSDimitry Andric 238bdd1243dSDimitry Andric struct ExceptionInfo { 239bdd1243dSDimitry Andric const MCSymbol *FunctionSymbol; 240bdd1243dSDimitry Andric unsigned FunctionSize; 241bdd1243dSDimitry Andric std::vector<ExceptionTableEntry> Entries; 242bdd1243dSDimitry Andric }; 243bdd1243dSDimitry Andric 244bdd1243dSDimitry Andric struct ExceptionSectionEntry : public SectionEntry { 245bdd1243dSDimitry Andric std::map<const StringRef, ExceptionInfo> ExceptionTable; 246bdd1243dSDimitry Andric bool isDebugEnabled = false; 247bdd1243dSDimitry Andric 248bdd1243dSDimitry Andric ExceptionSectionEntry(StringRef N, int32_t Flags) 249bdd1243dSDimitry Andric : SectionEntry(N, Flags | XCOFF::STYP_EXCEPT) { 250bdd1243dSDimitry Andric assert(N.size() <= XCOFF::NameSize && "Section too long."); 251bdd1243dSDimitry Andric memcpy(Name, N.data(), N.size()); 252bdd1243dSDimitry Andric } 253bdd1243dSDimitry Andric 254bdd1243dSDimitry Andric virtual ~ExceptionSectionEntry() = default; 255bdd1243dSDimitry Andric }; 256bdd1243dSDimitry Andric 25706c3fb27SDimitry Andric struct CInfoSymInfo { 25806c3fb27SDimitry Andric // Name of the C_INFO symbol associated with the section 25906c3fb27SDimitry Andric std::string Name; 26006c3fb27SDimitry Andric std::string Metadata; 26106c3fb27SDimitry Andric // Offset into the start of the metadata in the section 26206c3fb27SDimitry Andric uint64_t Offset; 26306c3fb27SDimitry Andric 26406c3fb27SDimitry Andric CInfoSymInfo(std::string Name, std::string Metadata) 26506c3fb27SDimitry Andric : Name(Name), Metadata(Metadata) {} 26606c3fb27SDimitry Andric // Metadata needs to be padded out to an even word size. 26706c3fb27SDimitry Andric uint32_t paddingSize() const { 26806c3fb27SDimitry Andric return alignTo(Metadata.size(), sizeof(uint32_t)) - Metadata.size(); 26906c3fb27SDimitry Andric }; 27006c3fb27SDimitry Andric 27106c3fb27SDimitry Andric // Total size of the entry, including the 4 byte length 27206c3fb27SDimitry Andric uint32_t size() const { 27306c3fb27SDimitry Andric return Metadata.size() + paddingSize() + sizeof(uint32_t); 27406c3fb27SDimitry Andric }; 27506c3fb27SDimitry Andric }; 27606c3fb27SDimitry Andric 27706c3fb27SDimitry Andric struct CInfoSymSectionEntry : public SectionEntry { 27806c3fb27SDimitry Andric std::unique_ptr<CInfoSymInfo> Entry; 27906c3fb27SDimitry Andric 28006c3fb27SDimitry Andric CInfoSymSectionEntry(StringRef N, int32_t Flags) : SectionEntry(N, Flags) {} 28106c3fb27SDimitry Andric virtual ~CInfoSymSectionEntry() = default; 28206c3fb27SDimitry Andric void addEntry(std::unique_ptr<CInfoSymInfo> NewEntry) { 28306c3fb27SDimitry Andric Entry = std::move(NewEntry); 28406c3fb27SDimitry Andric Entry->Offset = sizeof(uint32_t); 28506c3fb27SDimitry Andric Size += Entry->size(); 28606c3fb27SDimitry Andric } 28706c3fb27SDimitry Andric void reset() override { 28806c3fb27SDimitry Andric SectionEntry::reset(); 28906c3fb27SDimitry Andric Entry.reset(); 29006c3fb27SDimitry Andric } 29106c3fb27SDimitry Andric }; 29206c3fb27SDimitry Andric 2930b57cec5SDimitry Andric class XCOFFObjectWriter : public MCObjectWriter { 294480093f4SDimitry Andric 295480093f4SDimitry Andric uint32_t SymbolTableEntryCount = 0; 29681ad6265SDimitry Andric uint64_t SymbolTableOffset = 0; 297480093f4SDimitry Andric uint16_t SectionCount = 0; 298bdd1243dSDimitry Andric uint32_t PaddingsBeforeDwarf = 0; 299fcaf7f86SDimitry Andric bool HasVisibility = false; 3008bcb0991SDimitry Andric 3010b57cec5SDimitry Andric support::endian::Writer W; 3020b57cec5SDimitry Andric std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter; 3038bcb0991SDimitry Andric StringTableBuilder Strings; 3048bcb0991SDimitry Andric 30581ad6265SDimitry Andric const uint64_t MaxRawDataSize = 30681ad6265SDimitry Andric TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX; 30781ad6265SDimitry Andric 308fe6060f1SDimitry Andric // Maps the MCSection representation to its corresponding XCOFFSection 309fe6060f1SDimitry Andric // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into 3105ffd83dbSDimitry Andric // from its containing MCSectionXCOFF. 311fe6060f1SDimitry Andric DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap; 3125ffd83dbSDimitry Andric 3135ffd83dbSDimitry Andric // Maps the MCSymbol representation to its corrresponding symbol table index. 3145ffd83dbSDimitry Andric // Needed for relocation. 3155ffd83dbSDimitry Andric DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap; 3165ffd83dbSDimitry Andric 3178bcb0991SDimitry Andric // CsectGroups. These store the csects which make up different parts of 3188bcb0991SDimitry Andric // the sections. Should have one for each set of csects that get mapped into 3198bcb0991SDimitry Andric // the same section and get handled in a 'similar' way. 320480093f4SDimitry Andric CsectGroup UndefinedCsects; 3218bcb0991SDimitry Andric CsectGroup ProgramCodeCsects; 322480093f4SDimitry Andric CsectGroup ReadOnlyCsects; 323480093f4SDimitry Andric CsectGroup DataCsects; 324480093f4SDimitry Andric CsectGroup FuncDSCsects; 325480093f4SDimitry Andric CsectGroup TOCCsects; 3268bcb0991SDimitry Andric CsectGroup BSSCsects; 327fe6060f1SDimitry Andric CsectGroup TDataCsects; 328fe6060f1SDimitry Andric CsectGroup TBSSCsects; 3298bcb0991SDimitry Andric 330480093f4SDimitry Andric // The Predefined sections. 331fe6060f1SDimitry Andric CsectSectionEntry Text; 332fe6060f1SDimitry Andric CsectSectionEntry Data; 333fe6060f1SDimitry Andric CsectSectionEntry BSS; 334fe6060f1SDimitry Andric CsectSectionEntry TData; 335fe6060f1SDimitry Andric CsectSectionEntry TBSS; 336480093f4SDimitry Andric 337480093f4SDimitry Andric // All the XCOFF sections, in the order they will appear in the section header 338480093f4SDimitry Andric // table. 339fe6060f1SDimitry Andric std::array<CsectSectionEntry *const, 5> Sections{ 340fe6060f1SDimitry Andric {&Text, &Data, &BSS, &TData, &TBSS}}; 341480093f4SDimitry Andric 342349cc55cSDimitry Andric std::vector<DwarfSectionEntry> DwarfSections; 343bdd1243dSDimitry Andric std::vector<SectionEntry> OverflowSections; 344bdd1243dSDimitry Andric 345bdd1243dSDimitry Andric ExceptionSectionEntry ExceptionSection; 34606c3fb27SDimitry Andric CInfoSymSectionEntry CInfoSymSection; 347349cc55cSDimitry Andric 348480093f4SDimitry Andric CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); 3498bcb0991SDimitry Andric 350972a253aSDimitry Andric void reset() override; 3510b57cec5SDimitry Andric 352*0fca6ea1SDimitry Andric void executePostLayoutBinding(MCAssembler &) override; 3530b57cec5SDimitry Andric 354*0fca6ea1SDimitry Andric void recordRelocation(MCAssembler &, const MCFragment *, const MCFixup &, 355*0fca6ea1SDimitry Andric MCValue, uint64_t &) override; 3560b57cec5SDimitry Andric 357*0fca6ea1SDimitry Andric uint64_t writeObject(MCAssembler &) override; 3580b57cec5SDimitry Andric 35981ad6265SDimitry Andric bool is64Bit() const { return TargetObjectWriter->is64Bit(); } 36081ad6265SDimitry Andric bool nameShouldBeInStringTable(const StringRef &); 3618bcb0991SDimitry Andric void writeSymbolName(const StringRef &); 362*0fca6ea1SDimitry Andric bool auxFileSymNameShouldBeInStringTable(const StringRef &); 363*0fca6ea1SDimitry Andric void writeAuxFileSymName(const StringRef &); 36481ad6265SDimitry Andric 36581ad6265SDimitry Andric void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef, 36681ad6265SDimitry Andric const XCOFFSection &CSectionRef, 36781ad6265SDimitry Andric int16_t SectionIndex, 36881ad6265SDimitry Andric uint64_t SymbolOffset); 36981ad6265SDimitry Andric void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef, 37081ad6265SDimitry Andric int16_t SectionIndex, 37181ad6265SDimitry Andric XCOFF::StorageClass StorageClass); 37281ad6265SDimitry Andric void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef, 37381ad6265SDimitry Andric int16_t SectionIndex); 3748bcb0991SDimitry Andric void writeFileHeader(); 375fcaf7f86SDimitry Andric void writeAuxFileHeader(); 376bdd1243dSDimitry Andric void writeSectionHeader(const SectionEntry *Sec); 3778bcb0991SDimitry Andric void writeSectionHeaderTable(); 378*0fca6ea1SDimitry Andric void writeSections(const MCAssembler &Asm); 379349cc55cSDimitry Andric void writeSectionForControlSectionEntry(const MCAssembler &Asm, 380349cc55cSDimitry Andric const CsectSectionEntry &CsectEntry, 38181ad6265SDimitry Andric uint64_t &CurrentAddressLocation); 382349cc55cSDimitry Andric void writeSectionForDwarfSectionEntry(const MCAssembler &Asm, 383349cc55cSDimitry Andric const DwarfSectionEntry &DwarfEntry, 38481ad6265SDimitry Andric uint64_t &CurrentAddressLocation); 385*0fca6ea1SDimitry Andric void 386*0fca6ea1SDimitry Andric writeSectionForExceptionSectionEntry(const MCAssembler &Asm, 387*0fca6ea1SDimitry Andric ExceptionSectionEntry &ExceptionEntry, 388*0fca6ea1SDimitry Andric uint64_t &CurrentAddressLocation); 38906c3fb27SDimitry Andric void writeSectionForCInfoSymSectionEntry(const MCAssembler &Asm, 39006c3fb27SDimitry Andric CInfoSymSectionEntry &CInfoSymEntry, 39106c3fb27SDimitry Andric uint64_t &CurrentAddressLocation); 392*0fca6ea1SDimitry Andric void writeSymbolTable(MCAssembler &Asm); 393*0fca6ea1SDimitry Andric void writeSymbolAuxFileEntry(StringRef &Name, uint8_t ftype); 39481ad6265SDimitry Andric void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion, 39581ad6265SDimitry Andric uint64_t NumberOfRelocEnt = 0); 39681ad6265SDimitry Andric void writeSymbolAuxCsectEntry(uint64_t SectionOrLength, 39781ad6265SDimitry Andric uint8_t SymbolAlignmentAndType, 39881ad6265SDimitry Andric uint8_t StorageMappingClass); 399bdd1243dSDimitry Andric void writeSymbolAuxFunctionEntry(uint32_t EntryOffset, uint32_t FunctionSize, 400bdd1243dSDimitry Andric uint64_t LineNumberPointer, 401bdd1243dSDimitry Andric uint32_t EndIndex); 402bdd1243dSDimitry Andric void writeSymbolAuxExceptionEntry(uint64_t EntryOffset, uint32_t FunctionSize, 403bdd1243dSDimitry Andric uint32_t EndIndex); 40481ad6265SDimitry Andric void writeSymbolEntry(StringRef SymbolName, uint64_t Value, 40581ad6265SDimitry Andric int16_t SectionNumber, uint16_t SymbolType, 40681ad6265SDimitry Andric uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1); 4075ffd83dbSDimitry Andric void writeRelocations(); 408349cc55cSDimitry Andric void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section); 4098bcb0991SDimitry Andric 4108bcb0991SDimitry Andric // Called after all the csects and symbols have been processed by 4118bcb0991SDimitry Andric // `executePostLayoutBinding`, this function handles building up the majority 4128bcb0991SDimitry Andric // of the structures in the object file representation. Namely: 4138bcb0991SDimitry Andric // *) Calculates physical/virtual addresses, raw-pointer offsets, and section 4148bcb0991SDimitry Andric // sizes. 4158bcb0991SDimitry Andric // *) Assigns symbol table indices. 4168bcb0991SDimitry Andric // *) Builds up the section header table by adding any non-empty sections to 4178bcb0991SDimitry Andric // `Sections`. 418*0fca6ea1SDimitry Andric void assignAddressesAndIndices(MCAssembler &Asm); 419bdd1243dSDimitry Andric // Called after relocations are recorded. 4205ffd83dbSDimitry Andric void finalizeSectionInfo(); 421bdd1243dSDimitry Andric void finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount); 422bdd1243dSDimitry Andric void calcOffsetToRelocations(SectionEntry *Sec, uint64_t &RawPointer); 423bdd1243dSDimitry Andric 424bdd1243dSDimitry Andric bool hasExceptionSection() { 425bdd1243dSDimitry Andric return !ExceptionSection.ExceptionTable.empty(); 426bdd1243dSDimitry Andric } 427bdd1243dSDimitry Andric unsigned getExceptionSectionSize(); 428bdd1243dSDimitry Andric unsigned getExceptionOffset(const MCSymbol *Symbol); 4298bcb0991SDimitry Andric 4308bcb0991SDimitry Andric size_t auxiliaryHeaderSize() const { 431fcaf7f86SDimitry Andric // 64-bit object files have no auxiliary header. 432fcaf7f86SDimitry Andric return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0; 4338bcb0991SDimitry Andric } 4348bcb0991SDimitry Andric 4350b57cec5SDimitry Andric public: 4360b57cec5SDimitry Andric XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 4370b57cec5SDimitry Andric raw_pwrite_stream &OS); 43881ad6265SDimitry Andric 43981ad6265SDimitry Andric void writeWord(uint64_t Word) { 44081ad6265SDimitry Andric is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word); 44181ad6265SDimitry Andric } 442*0fca6ea1SDimitry Andric 443*0fca6ea1SDimitry Andric void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap, 444*0fca6ea1SDimitry Andric unsigned LanguageCode, unsigned ReasonCode, 445*0fca6ea1SDimitry Andric unsigned FunctionSize, bool hasDebug); 446*0fca6ea1SDimitry Andric void addCInfoSymEntry(StringRef Name, StringRef Metadata); 4470b57cec5SDimitry Andric }; 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric XCOFFObjectWriter::XCOFFObjectWriter( 4500b57cec5SDimitry Andric std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) 4515f757f3fSDimitry Andric : W(OS, llvm::endianness::big), TargetObjectWriter(std::move(MOTW)), 4528bcb0991SDimitry Andric Strings(StringTableBuilder::XCOFF), 453480093f4SDimitry Andric Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false, 454480093f4SDimitry Andric CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}), 455480093f4SDimitry Andric Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false, 456480093f4SDimitry Andric CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}), 457480093f4SDimitry Andric BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true, 458fe6060f1SDimitry Andric CsectGroups{&BSSCsects}), 459fe6060f1SDimitry Andric TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false, 460fe6060f1SDimitry Andric CsectGroups{&TDataCsects}), 461fe6060f1SDimitry Andric TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true, 462bdd1243dSDimitry Andric CsectGroups{&TBSSCsects}), 46306c3fb27SDimitry Andric ExceptionSection(".except", XCOFF::STYP_EXCEPT), 46406c3fb27SDimitry Andric CInfoSymSection(".info", XCOFF::STYP_INFO) {} 4650b57cec5SDimitry Andric 4668bcb0991SDimitry Andric void XCOFFObjectWriter::reset() { 4675ffd83dbSDimitry Andric // Clear the mappings we created. 4685ffd83dbSDimitry Andric SymbolIndexMap.clear(); 4695ffd83dbSDimitry Andric SectionMap.clear(); 470480093f4SDimitry Andric 4715ffd83dbSDimitry Andric UndefinedCsects.clear(); 4728bcb0991SDimitry Andric // Reset any sections we have written to, and empty the section header table. 4738bcb0991SDimitry Andric for (auto *Sec : Sections) 4748bcb0991SDimitry Andric Sec->reset(); 475349cc55cSDimitry Andric for (auto &DwarfSec : DwarfSections) 476349cc55cSDimitry Andric DwarfSec.reset(); 477bdd1243dSDimitry Andric for (auto &OverflowSec : OverflowSections) 478bdd1243dSDimitry Andric OverflowSec.reset(); 479bdd1243dSDimitry Andric ExceptionSection.reset(); 48006c3fb27SDimitry Andric CInfoSymSection.reset(); 4818bcb0991SDimitry Andric 4825ffd83dbSDimitry Andric // Reset states in XCOFFObjectWriter. 4838bcb0991SDimitry Andric SymbolTableEntryCount = 0; 4848bcb0991SDimitry Andric SymbolTableOffset = 0; 485480093f4SDimitry Andric SectionCount = 0; 486bdd1243dSDimitry Andric PaddingsBeforeDwarf = 0; 4878bcb0991SDimitry Andric Strings.clear(); 4888bcb0991SDimitry Andric 4898bcb0991SDimitry Andric MCObjectWriter::reset(); 4908bcb0991SDimitry Andric } 4918bcb0991SDimitry Andric 492480093f4SDimitry Andric CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) { 493480093f4SDimitry Andric switch (MCSec->getMappingClass()) { 494480093f4SDimitry Andric case XCOFF::XMC_PR: 495480093f4SDimitry Andric assert(XCOFF::XTY_SD == MCSec->getCSectType() && 496480093f4SDimitry Andric "Only an initialized csect can contain program code."); 497480093f4SDimitry Andric return ProgramCodeCsects; 498480093f4SDimitry Andric case XCOFF::XMC_RO: 499480093f4SDimitry Andric assert(XCOFF::XTY_SD == MCSec->getCSectType() && 500480093f4SDimitry Andric "Only an initialized csect can contain read only data."); 501480093f4SDimitry Andric return ReadOnlyCsects; 502480093f4SDimitry Andric case XCOFF::XMC_RW: 503480093f4SDimitry Andric if (XCOFF::XTY_CM == MCSec->getCSectType()) 504480093f4SDimitry Andric return BSSCsects; 505480093f4SDimitry Andric 506480093f4SDimitry Andric if (XCOFF::XTY_SD == MCSec->getCSectType()) 507480093f4SDimitry Andric return DataCsects; 508480093f4SDimitry Andric 509480093f4SDimitry Andric report_fatal_error("Unhandled mapping of read-write csect to section."); 510480093f4SDimitry Andric case XCOFF::XMC_DS: 511480093f4SDimitry Andric return FuncDSCsects; 512480093f4SDimitry Andric case XCOFF::XMC_BS: 513480093f4SDimitry Andric assert(XCOFF::XTY_CM == MCSec->getCSectType() && 514480093f4SDimitry Andric "Mapping invalid csect. CSECT with bss storage class must be " 515480093f4SDimitry Andric "common type."); 516480093f4SDimitry Andric return BSSCsects; 517fe6060f1SDimitry Andric case XCOFF::XMC_TL: 518fe6060f1SDimitry Andric assert(XCOFF::XTY_SD == MCSec->getCSectType() && 519fe6060f1SDimitry Andric "Mapping invalid csect. CSECT with tdata storage class must be " 520fe6060f1SDimitry Andric "an initialized csect."); 521fe6060f1SDimitry Andric return TDataCsects; 522fe6060f1SDimitry Andric case XCOFF::XMC_UL: 523fe6060f1SDimitry Andric assert(XCOFF::XTY_CM == MCSec->getCSectType() && 524fe6060f1SDimitry Andric "Mapping invalid csect. CSECT with tbss storage class must be " 525fe6060f1SDimitry Andric "an uninitialized csect."); 526fe6060f1SDimitry Andric return TBSSCsects; 527480093f4SDimitry Andric case XCOFF::XMC_TC0: 528480093f4SDimitry Andric assert(XCOFF::XTY_SD == MCSec->getCSectType() && 529480093f4SDimitry Andric "Only an initialized csect can contain TOC-base."); 530480093f4SDimitry Andric assert(TOCCsects.empty() && 531480093f4SDimitry Andric "We should have only one TOC-base, and it should be the first csect " 532480093f4SDimitry Andric "in this CsectGroup."); 533480093f4SDimitry Andric return TOCCsects; 534480093f4SDimitry Andric case XCOFF::XMC_TC: 535e8d8bef9SDimitry Andric case XCOFF::XMC_TE: 536480093f4SDimitry Andric assert(XCOFF::XTY_SD == MCSec->getCSectType() && 537*0fca6ea1SDimitry Andric "A TOC symbol must be an initialized csect."); 538*0fca6ea1SDimitry Andric assert(!TOCCsects.empty() && 539*0fca6ea1SDimitry Andric "We should at least have a TOC-base in this CsectGroup."); 540*0fca6ea1SDimitry Andric return TOCCsects; 541*0fca6ea1SDimitry Andric case XCOFF::XMC_TD: 542*0fca6ea1SDimitry Andric assert((XCOFF::XTY_SD == MCSec->getCSectType() || 543*0fca6ea1SDimitry Andric XCOFF::XTY_CM == MCSec->getCSectType()) && 544*0fca6ea1SDimitry Andric "Symbol type incompatible with toc-data."); 545480093f4SDimitry Andric assert(!TOCCsects.empty() && 546480093f4SDimitry Andric "We should at least have a TOC-base in this CsectGroup."); 547480093f4SDimitry Andric return TOCCsects; 548480093f4SDimitry Andric default: 549480093f4SDimitry Andric report_fatal_error("Unhandled mapping of csect to section."); 550480093f4SDimitry Andric } 551480093f4SDimitry Andric } 552480093f4SDimitry Andric 5535ffd83dbSDimitry Andric static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) { 5545ffd83dbSDimitry Andric if (XSym->isDefined()) 5555ffd83dbSDimitry Andric return cast<MCSectionXCOFF>(XSym->getFragment()->getParent()); 5565ffd83dbSDimitry Andric return XSym->getRepresentedCsect(); 5575ffd83dbSDimitry Andric } 5585ffd83dbSDimitry Andric 559*0fca6ea1SDimitry Andric void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm) { 5608bcb0991SDimitry Andric for (const auto &S : Asm) { 5618bcb0991SDimitry Andric const auto *MCSec = cast<const MCSectionXCOFF>(&S); 56206c3fb27SDimitry Andric assert(!SectionMap.contains(MCSec) && "Cannot add a section twice."); 5638bcb0991SDimitry Andric 5648bcb0991SDimitry Andric // If the name does not fit in the storage provided in the symbol table 5658bcb0991SDimitry Andric // entry, add it to the string table. 5665ffd83dbSDimitry Andric if (nameShouldBeInStringTable(MCSec->getSymbolTableName())) 5675ffd83dbSDimitry Andric Strings.add(MCSec->getSymbolTableName()); 568349cc55cSDimitry Andric if (MCSec->isCsect()) { 569349cc55cSDimitry Andric // A new control section. Its CsectSectionEntry should already be staticly 570349cc55cSDimitry Andric // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of 571349cc55cSDimitry Andric // the CsectSectionEntry. 572349cc55cSDimitry Andric assert(XCOFF::XTY_ER != MCSec->getCSectType() && 573349cc55cSDimitry Andric "An undefined csect should not get registered."); 574480093f4SDimitry Andric CsectGroup &Group = getCsectGroup(MCSec); 575480093f4SDimitry Andric Group.emplace_back(MCSec); 5765ffd83dbSDimitry Andric SectionMap[MCSec] = &Group.back(); 577349cc55cSDimitry Andric } else if (MCSec->isDwarfSect()) { 578349cc55cSDimitry Andric // A new DwarfSectionEntry. 579349cc55cSDimitry Andric std::unique_ptr<XCOFFSection> DwarfSec = 580349cc55cSDimitry Andric std::make_unique<XCOFFSection>(MCSec); 581349cc55cSDimitry Andric SectionMap[MCSec] = DwarfSec.get(); 582349cc55cSDimitry Andric 583349cc55cSDimitry Andric DwarfSectionEntry SecEntry(MCSec->getName(), 58481ad6265SDimitry Andric *MCSec->getDwarfSubtypeFlags(), 585349cc55cSDimitry Andric std::move(DwarfSec)); 586349cc55cSDimitry Andric DwarfSections.push_back(std::move(SecEntry)); 587349cc55cSDimitry Andric } else 588349cc55cSDimitry Andric llvm_unreachable("unsupport section type!"); 5898bcb0991SDimitry Andric } 5908bcb0991SDimitry Andric 5918bcb0991SDimitry Andric for (const MCSymbol &S : Asm.symbols()) { 5928bcb0991SDimitry Andric // Nothing to do for temporary symbols. 5938bcb0991SDimitry Andric if (S.isTemporary()) 5948bcb0991SDimitry Andric continue; 5958bcb0991SDimitry Andric 596480093f4SDimitry Andric const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S); 5975ffd83dbSDimitry Andric const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym); 598480093f4SDimitry Andric 599*0fca6ea1SDimitry Andric if (ContainingCsect->isDwarfSect()) 600*0fca6ea1SDimitry Andric continue; 601*0fca6ea1SDimitry Andric 602fcaf7f86SDimitry Andric if (XSym->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED) 603fcaf7f86SDimitry Andric HasVisibility = true; 604fcaf7f86SDimitry Andric 605480093f4SDimitry Andric if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) { 6065ffd83dbSDimitry Andric // Handle undefined symbol. 607480093f4SDimitry Andric UndefinedCsects.emplace_back(ContainingCsect); 6085ffd83dbSDimitry Andric SectionMap[ContainingCsect] = &UndefinedCsects.back(); 6095ffd83dbSDimitry Andric if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName())) 6105ffd83dbSDimitry Andric Strings.add(ContainingCsect->getSymbolTableName()); 611480093f4SDimitry Andric continue; 612480093f4SDimitry Andric } 613480093f4SDimitry Andric 614480093f4SDimitry Andric // If the symbol is the csect itself, we don't need to put the symbol 615480093f4SDimitry Andric // into csect's Syms. 616480093f4SDimitry Andric if (XSym == ContainingCsect->getQualNameSymbol()) 617480093f4SDimitry Andric continue; 618480093f4SDimitry Andric 6195ffd83dbSDimitry Andric // Only put a label into the symbol table when it is an external label. 6205ffd83dbSDimitry Andric if (!XSym->isExternal()) 6215ffd83dbSDimitry Andric continue; 6228bcb0991SDimitry Andric 62306c3fb27SDimitry Andric assert(SectionMap.contains(ContainingCsect) && 6245ffd83dbSDimitry Andric "Expected containing csect to exist in map"); 625fe6060f1SDimitry Andric XCOFFSection *Csect = SectionMap[ContainingCsect]; 6268bcb0991SDimitry Andric // Lookup the containing csect and add the symbol to it. 627fe6060f1SDimitry Andric assert(Csect->MCSec->isCsect() && "only csect is supported now!"); 628fe6060f1SDimitry Andric Csect->Syms.emplace_back(XSym); 6298bcb0991SDimitry Andric 6308bcb0991SDimitry Andric // If the name does not fit in the storage provided in the symbol table 6318bcb0991SDimitry Andric // entry, add it to the string table. 6325ffd83dbSDimitry Andric if (nameShouldBeInStringTable(XSym->getSymbolTableName())) 6335ffd83dbSDimitry Andric Strings.add(XSym->getSymbolTableName()); 6348bcb0991SDimitry Andric } 6358bcb0991SDimitry Andric 63606c3fb27SDimitry Andric std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry; 63706c3fb27SDimitry Andric if (CISI && nameShouldBeInStringTable(CISI->Name)) 63806c3fb27SDimitry Andric Strings.add(CISI->Name); 63906c3fb27SDimitry Andric 64081ad6265SDimitry Andric // Emit ".file" as the source file name when there is no file name. 64181ad6265SDimitry Andric if (FileNames.empty()) 64281ad6265SDimitry Andric FileNames.emplace_back(".file", 0); 64381ad6265SDimitry Andric for (const std::pair<std::string, size_t> &F : FileNames) { 644*0fca6ea1SDimitry Andric if (auxFileSymNameShouldBeInStringTable(F.first)) 64581ad6265SDimitry Andric Strings.add(F.first); 64681ad6265SDimitry Andric } 64781ad6265SDimitry Andric 648*0fca6ea1SDimitry Andric // Always add ".file" to the symbol table. The actual file name will be in 649*0fca6ea1SDimitry Andric // the AUX_FILE auxiliary entry. 650*0fca6ea1SDimitry Andric if (nameShouldBeInStringTable(".file")) 651*0fca6ea1SDimitry Andric Strings.add(".file"); 652*0fca6ea1SDimitry Andric StringRef Vers = CompilerVersion; 653*0fca6ea1SDimitry Andric if (auxFileSymNameShouldBeInStringTable(Vers)) 654*0fca6ea1SDimitry Andric Strings.add(Vers); 655*0fca6ea1SDimitry Andric 6568bcb0991SDimitry Andric Strings.finalize(); 657*0fca6ea1SDimitry Andric assignAddressesAndIndices(Asm); 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6605ffd83dbSDimitry Andric void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm, 6615ffd83dbSDimitry Andric const MCFragment *Fragment, 6625ffd83dbSDimitry Andric const MCFixup &Fixup, MCValue Target, 6635ffd83dbSDimitry Andric uint64_t &FixedValue) { 6645ffd83dbSDimitry Andric auto getIndex = [this](const MCSymbol *Sym, 6655ffd83dbSDimitry Andric const MCSectionXCOFF *ContainingCsect) { 6665ffd83dbSDimitry Andric // If we could not find the symbol directly in SymbolIndexMap, this symbol 6675ffd83dbSDimitry Andric // could either be a temporary symbol or an undefined symbol. In this case, 6685ffd83dbSDimitry Andric // we would need to have the relocation reference its csect instead. 66906c3fb27SDimitry Andric return SymbolIndexMap.contains(Sym) 6705ffd83dbSDimitry Andric ? SymbolIndexMap[Sym] 6715ffd83dbSDimitry Andric : SymbolIndexMap[ContainingCsect->getQualNameSymbol()]; 6725ffd83dbSDimitry Andric }; 6735ffd83dbSDimitry Andric 674349cc55cSDimitry Andric auto getVirtualAddress = 675*0fca6ea1SDimitry Andric [this, &Asm](const MCSymbol *Sym, 676349cc55cSDimitry Andric const MCSectionXCOFF *ContainingSect) -> uint64_t { 677349cc55cSDimitry Andric // A DWARF section. 678349cc55cSDimitry Andric if (ContainingSect->isDwarfSect()) 679*0fca6ea1SDimitry Andric return Asm.getSymbolOffset(*Sym); 680349cc55cSDimitry Andric 681349cc55cSDimitry Andric // A csect. 682349cc55cSDimitry Andric if (!Sym->isDefined()) 683349cc55cSDimitry Andric return SectionMap[ContainingSect]->Address; 684349cc55cSDimitry Andric 685349cc55cSDimitry Andric // A label. 686349cc55cSDimitry Andric assert(Sym->isDefined() && "not a valid object that has address!"); 687*0fca6ea1SDimitry Andric return SectionMap[ContainingSect]->Address + Asm.getSymbolOffset(*Sym); 6885ffd83dbSDimitry Andric }; 6895ffd83dbSDimitry Andric 6905ffd83dbSDimitry Andric const MCSymbol *const SymA = &Target.getSymA()->getSymbol(); 6915ffd83dbSDimitry Andric 6925ffd83dbSDimitry Andric MCAsmBackend &Backend = Asm.getBackend(); 6935ffd83dbSDimitry Andric bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & 6945ffd83dbSDimitry Andric MCFixupKindInfo::FKF_IsPCRel; 6955ffd83dbSDimitry Andric 6965ffd83dbSDimitry Andric uint8_t Type; 6975ffd83dbSDimitry Andric uint8_t SignAndSize; 6985ffd83dbSDimitry Andric std::tie(Type, SignAndSize) = 6995ffd83dbSDimitry Andric TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel); 7005ffd83dbSDimitry Andric 7015ffd83dbSDimitry Andric const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA)); 70206c3fb27SDimitry Andric assert(SectionMap.contains(SymASec) && 7035ffd83dbSDimitry Andric "Expected containing csect to exist in map."); 7045ffd83dbSDimitry Andric 70506c3fb27SDimitry Andric assert((Fixup.getOffset() <= 706*0fca6ea1SDimitry Andric MaxRawDataSize - Asm.getFragmentOffset(*Fragment)) && 70706c3fb27SDimitry Andric "Fragment offset + fixup offset is overflowed."); 70806c3fb27SDimitry Andric uint32_t FixupOffsetInCsect = 709*0fca6ea1SDimitry Andric Asm.getFragmentOffset(*Fragment) + Fixup.getOffset(); 71006c3fb27SDimitry Andric 7115ffd83dbSDimitry Andric const uint32_t Index = getIndex(SymA, SymASec); 712fe6060f1SDimitry Andric if (Type == XCOFF::RelocationType::R_POS || 71306c3fb27SDimitry Andric Type == XCOFF::RelocationType::R_TLS || 7145f757f3fSDimitry Andric Type == XCOFF::RelocationType::R_TLS_LE || 715*0fca6ea1SDimitry Andric Type == XCOFF::RelocationType::R_TLS_IE || 716*0fca6ea1SDimitry Andric Type == XCOFF::RelocationType::R_TLS_LD) 7175ffd83dbSDimitry Andric // The FixedValue should be symbol's virtual address in this object file 7185ffd83dbSDimitry Andric // plus any constant value that we might get. 7195ffd83dbSDimitry Andric FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant(); 720fe6060f1SDimitry Andric else if (Type == XCOFF::RelocationType::R_TLSM) 721fe6060f1SDimitry Andric // The FixedValue should always be zero since the region handle is only 722fe6060f1SDimitry Andric // known at load time. 723fe6060f1SDimitry Andric FixedValue = 0; 724e8d8bef9SDimitry Andric else if (Type == XCOFF::RelocationType::R_TOC || 725e8d8bef9SDimitry Andric Type == XCOFF::RelocationType::R_TOCL) { 726bdd1243dSDimitry Andric // For non toc-data external symbols, R_TOC type relocation will relocate to 727bdd1243dSDimitry Andric // data symbols that have XCOFF::XTY_SD type csect. For toc-data external 728bdd1243dSDimitry Andric // symbols, R_TOC type relocation will relocate to data symbols that have 729bdd1243dSDimitry Andric // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC 730bdd1243dSDimitry Andric // entry for them, so the FixedValue should always be 0. 731bdd1243dSDimitry Andric if (SymASec->getCSectType() == XCOFF::XTY_ER) { 732bdd1243dSDimitry Andric FixedValue = 0; 733bdd1243dSDimitry Andric } else { 734bdd1243dSDimitry Andric // The FixedValue should be the TOC entry offset from the TOC-base plus 735bdd1243dSDimitry Andric // any constant offset value. 736*0fca6ea1SDimitry Andric int64_t TOCEntryOffset = SectionMap[SymASec]->Address - 737*0fca6ea1SDimitry Andric TOCCsects.front().Address + Target.getConstant(); 738*0fca6ea1SDimitry Andric // For small code model, if the TOCEntryOffset overflows the 16-bit value, 739*0fca6ea1SDimitry Andric // we truncate it back down to 16 bits. The linker will be able to insert 740*0fca6ea1SDimitry Andric // fix-up code when needed. 741*0fca6ea1SDimitry Andric // For non toc-data symbols, we already did the truncation in 742*0fca6ea1SDimitry Andric // PPCAsmPrinter.cpp through setting Target.getConstant() in the 743*0fca6ea1SDimitry Andric // expression above by calling getTOCEntryLoadingExprForXCOFF for the 744*0fca6ea1SDimitry Andric // various TOC PseudoOps. 745*0fca6ea1SDimitry Andric // For toc-data symbols, we were not able to calculate the offset from 746*0fca6ea1SDimitry Andric // the TOC in PPCAsmPrinter.cpp since the TOC has not been finalized at 747*0fca6ea1SDimitry Andric // that point, so we are adjusting it here though 748*0fca6ea1SDimitry Andric // llvm::SignExtend64<16>(TOCEntryOffset); 749*0fca6ea1SDimitry Andric // TODO: Since the time that the handling for offsets over 16-bits was 750*0fca6ea1SDimitry Andric // added in PPCAsmPrinter.cpp using getTOCEntryLoadingExprForXCOFF, the 751*0fca6ea1SDimitry Andric // system assembler and linker have been updated to be able to handle the 752*0fca6ea1SDimitry Andric // overflowing offsets, so we no longer need to keep 753*0fca6ea1SDimitry Andric // getTOCEntryLoadingExprForXCOFF. 754e8d8bef9SDimitry Andric if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset)) 755*0fca6ea1SDimitry Andric TOCEntryOffset = llvm::SignExtend64<16>(TOCEntryOffset); 756e8d8bef9SDimitry Andric 757e8d8bef9SDimitry Andric FixedValue = TOCEntryOffset; 758e8d8bef9SDimitry Andric } 759bdd1243dSDimitry Andric } else if (Type == XCOFF::RelocationType::R_RBR) { 760bdd1243dSDimitry Andric MCSectionXCOFF *ParentSec = cast<MCSectionXCOFF>(Fragment->getParent()); 761bdd1243dSDimitry Andric assert((SymASec->getMappingClass() == XCOFF::XMC_PR && 762bdd1243dSDimitry Andric ParentSec->getMappingClass() == XCOFF::XMC_PR) && 763bdd1243dSDimitry Andric "Only XMC_PR csect may have the R_RBR relocation."); 764bdd1243dSDimitry Andric 765bdd1243dSDimitry Andric // The address of the branch instruction should be the sum of section 766bdd1243dSDimitry Andric // address, fragment offset and Fixup offset. 76706c3fb27SDimitry Andric uint64_t BRInstrAddress = 76806c3fb27SDimitry Andric SectionMap[ParentSec]->Address + FixupOffsetInCsect; 76906c3fb27SDimitry Andric // The FixedValue should be the difference between symbol's virtual address 77006c3fb27SDimitry Andric // and BR instr address plus any constant value. 77106c3fb27SDimitry Andric FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress + 77206c3fb27SDimitry Andric Target.getConstant(); 77306c3fb27SDimitry Andric } else if (Type == XCOFF::RelocationType::R_REF) { 77406c3fb27SDimitry Andric // The FixedValue and FixupOffsetInCsect should always be 0 since it 77506c3fb27SDimitry Andric // specifies a nonrelocating reference. 77606c3fb27SDimitry Andric FixedValue = 0; 77706c3fb27SDimitry Andric FixupOffsetInCsect = 0; 778bdd1243dSDimitry Andric } 7795ffd83dbSDimitry Andric 7805ffd83dbSDimitry Andric XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type}; 7815ffd83dbSDimitry Andric MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent()); 78206c3fb27SDimitry Andric assert(SectionMap.contains(RelocationSec) && 7835ffd83dbSDimitry Andric "Expected containing csect to exist in map."); 7845ffd83dbSDimitry Andric SectionMap[RelocationSec]->Relocations.push_back(Reloc); 7855ffd83dbSDimitry Andric 7865ffd83dbSDimitry Andric if (!Target.getSymB()) 7875ffd83dbSDimitry Andric return; 7885ffd83dbSDimitry Andric 7895ffd83dbSDimitry Andric const MCSymbol *const SymB = &Target.getSymB()->getSymbol(); 7905ffd83dbSDimitry Andric if (SymA == SymB) 7915ffd83dbSDimitry Andric report_fatal_error("relocation for opposite term is not yet supported"); 7925ffd83dbSDimitry Andric 7935ffd83dbSDimitry Andric const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB)); 79406c3fb27SDimitry Andric assert(SectionMap.contains(SymBSec) && 7955ffd83dbSDimitry Andric "Expected containing csect to exist in map."); 7965ffd83dbSDimitry Andric if (SymASec == SymBSec) 7975ffd83dbSDimitry Andric report_fatal_error( 7985ffd83dbSDimitry Andric "relocation for paired relocatable term is not yet supported"); 7995ffd83dbSDimitry Andric 8005ffd83dbSDimitry Andric assert(Type == XCOFF::RelocationType::R_POS && 8015ffd83dbSDimitry Andric "SymA must be R_POS here if it's not opposite term or paired " 8025ffd83dbSDimitry Andric "relocatable term."); 8035ffd83dbSDimitry Andric const uint32_t IndexB = getIndex(SymB, SymBSec); 8045ffd83dbSDimitry Andric // SymB must be R_NEG here, given the general form of Target(MCValue) is 8055ffd83dbSDimitry Andric // "SymbolA - SymbolB + imm64". 8065ffd83dbSDimitry Andric const uint8_t TypeB = XCOFF::RelocationType::R_NEG; 8075ffd83dbSDimitry Andric XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB}; 8085ffd83dbSDimitry Andric SectionMap[RelocationSec]->Relocations.push_back(RelocB); 8095ffd83dbSDimitry Andric // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA, 8105ffd83dbSDimitry Andric // now we just need to fold "- SymbolB" here. 8115ffd83dbSDimitry Andric FixedValue -= getVirtualAddress(SymB, SymBSec); 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 814*0fca6ea1SDimitry Andric void XCOFFObjectWriter::writeSections(const MCAssembler &Asm) { 81581ad6265SDimitry Andric uint64_t CurrentAddressLocation = 0; 816349cc55cSDimitry Andric for (const auto *Section : Sections) 817*0fca6ea1SDimitry Andric writeSectionForControlSectionEntry(Asm, *Section, CurrentAddressLocation); 818349cc55cSDimitry Andric for (const auto &DwarfSection : DwarfSections) 819*0fca6ea1SDimitry Andric writeSectionForDwarfSectionEntry(Asm, DwarfSection, CurrentAddressLocation); 820*0fca6ea1SDimitry Andric writeSectionForExceptionSectionEntry(Asm, ExceptionSection, 821349cc55cSDimitry Andric CurrentAddressLocation); 822*0fca6ea1SDimitry Andric writeSectionForCInfoSymSectionEntry(Asm, CInfoSymSection, 82306c3fb27SDimitry Andric CurrentAddressLocation); 8248bcb0991SDimitry Andric } 8258bcb0991SDimitry Andric 826*0fca6ea1SDimitry Andric uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm) { 8270b57cec5SDimitry Andric // We always emit a timestamp of 0 for reproducibility, so ensure incremental 8280b57cec5SDimitry Andric // linking is not enabled, in case, like with Windows COFF, such a timestamp 8290b57cec5SDimitry Andric // is incompatible with incremental linking of XCOFF. 8300b57cec5SDimitry Andric 8315ffd83dbSDimitry Andric finalizeSectionInfo(); 8320b57cec5SDimitry Andric uint64_t StartOffset = W.OS.tell(); 8330b57cec5SDimitry Andric 8348bcb0991SDimitry Andric writeFileHeader(); 835fcaf7f86SDimitry Andric writeAuxFileHeader(); 8368bcb0991SDimitry Andric writeSectionHeaderTable(); 837*0fca6ea1SDimitry Andric writeSections(Asm); 8385ffd83dbSDimitry Andric writeRelocations(); 839*0fca6ea1SDimitry Andric writeSymbolTable(Asm); 8408bcb0991SDimitry Andric // Write the string table. 8418bcb0991SDimitry Andric Strings.write(W.OS); 8420b57cec5SDimitry Andric 8438bcb0991SDimitry Andric return W.OS.tell() - StartOffset; 8448bcb0991SDimitry Andric } 8458bcb0991SDimitry Andric 8468bcb0991SDimitry Andric bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) { 84781ad6265SDimitry Andric return SymbolName.size() > XCOFF::NameSize || is64Bit(); 8488bcb0991SDimitry Andric } 8498bcb0991SDimitry Andric 8508bcb0991SDimitry Andric void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) { 85181ad6265SDimitry Andric // Magic, Offset or SymbolName. 8528bcb0991SDimitry Andric if (nameShouldBeInStringTable(SymbolName)) { 8538bcb0991SDimitry Andric W.write<int32_t>(0); 8548bcb0991SDimitry Andric W.write<uint32_t>(Strings.getOffset(SymbolName)); 8558bcb0991SDimitry Andric } else { 856480093f4SDimitry Andric char Name[XCOFF::NameSize + 1]; 8578bcb0991SDimitry Andric std::strncpy(Name, SymbolName.data(), XCOFF::NameSize); 8588bcb0991SDimitry Andric ArrayRef<char> NameRef(Name, XCOFF::NameSize); 8598bcb0991SDimitry Andric W.write(NameRef); 8608bcb0991SDimitry Andric } 8618bcb0991SDimitry Andric } 8628bcb0991SDimitry Andric 86381ad6265SDimitry Andric void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value, 86481ad6265SDimitry Andric int16_t SectionNumber, 86581ad6265SDimitry Andric uint16_t SymbolType, 86681ad6265SDimitry Andric uint8_t StorageClass, 86781ad6265SDimitry Andric uint8_t NumberOfAuxEntries) { 86881ad6265SDimitry Andric if (is64Bit()) { 86981ad6265SDimitry Andric W.write<uint64_t>(Value); 87081ad6265SDimitry Andric W.write<uint32_t>(Strings.getOffset(SymbolName)); 87181ad6265SDimitry Andric } else { 87281ad6265SDimitry Andric writeSymbolName(SymbolName); 87381ad6265SDimitry Andric W.write<uint32_t>(Value); 87481ad6265SDimitry Andric } 87581ad6265SDimitry Andric W.write<int16_t>(SectionNumber); 87681ad6265SDimitry Andric W.write<uint16_t>(SymbolType); 87781ad6265SDimitry Andric W.write<uint8_t>(StorageClass); 87881ad6265SDimitry Andric W.write<uint8_t>(NumberOfAuxEntries); 8798bcb0991SDimitry Andric } 8808bcb0991SDimitry Andric 88181ad6265SDimitry Andric void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength, 88281ad6265SDimitry Andric uint8_t SymbolAlignmentAndType, 88381ad6265SDimitry Andric uint8_t StorageMappingClass) { 88481ad6265SDimitry Andric W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength); 88581ad6265SDimitry Andric W.write<uint32_t>(0); // ParameterHashIndex 88681ad6265SDimitry Andric W.write<uint16_t>(0); // TypeChkSectNum 88781ad6265SDimitry Andric W.write<uint8_t>(SymbolAlignmentAndType); 88881ad6265SDimitry Andric W.write<uint8_t>(StorageMappingClass); 88981ad6265SDimitry Andric if (is64Bit()) { 89081ad6265SDimitry Andric W.write<uint32_t>(Hi_32(SectionOrLength)); 89181ad6265SDimitry Andric W.OS.write_zeros(1); // Reserved 89281ad6265SDimitry Andric W.write<uint8_t>(XCOFF::AUX_CSECT); 89381ad6265SDimitry Andric } else { 89481ad6265SDimitry Andric W.write<uint32_t>(0); // StabInfoIndex 89581ad6265SDimitry Andric W.write<uint16_t>(0); // StabSectNum 89681ad6265SDimitry Andric } 89781ad6265SDimitry Andric } 89881ad6265SDimitry Andric 899*0fca6ea1SDimitry Andric bool XCOFFObjectWriter::auxFileSymNameShouldBeInStringTable( 900*0fca6ea1SDimitry Andric const StringRef &SymbolName) { 901*0fca6ea1SDimitry Andric return SymbolName.size() > XCOFF::AuxFileEntNameSize; 902*0fca6ea1SDimitry Andric } 903*0fca6ea1SDimitry Andric 904*0fca6ea1SDimitry Andric void XCOFFObjectWriter::writeAuxFileSymName(const StringRef &SymbolName) { 905*0fca6ea1SDimitry Andric // Magic, Offset or SymbolName. 906*0fca6ea1SDimitry Andric if (auxFileSymNameShouldBeInStringTable(SymbolName)) { 907*0fca6ea1SDimitry Andric W.write<int32_t>(0); 908*0fca6ea1SDimitry Andric W.write<uint32_t>(Strings.getOffset(SymbolName)); 909*0fca6ea1SDimitry Andric W.OS.write_zeros(XCOFF::FileNamePadSize); 910*0fca6ea1SDimitry Andric } else { 911*0fca6ea1SDimitry Andric char Name[XCOFF::AuxFileEntNameSize + 1]; 912*0fca6ea1SDimitry Andric std::strncpy(Name, SymbolName.data(), XCOFF::AuxFileEntNameSize); 913*0fca6ea1SDimitry Andric ArrayRef<char> NameRef(Name, XCOFF::AuxFileEntNameSize); 914*0fca6ea1SDimitry Andric W.write(NameRef); 915*0fca6ea1SDimitry Andric } 916*0fca6ea1SDimitry Andric } 917*0fca6ea1SDimitry Andric 918*0fca6ea1SDimitry Andric void XCOFFObjectWriter::writeSymbolAuxFileEntry(StringRef &Name, 919*0fca6ea1SDimitry Andric uint8_t ftype) { 920*0fca6ea1SDimitry Andric writeAuxFileSymName(Name); 921*0fca6ea1SDimitry Andric W.write<uint8_t>(ftype); 922*0fca6ea1SDimitry Andric W.OS.write_zeros(2); 923*0fca6ea1SDimitry Andric if (is64Bit()) 924*0fca6ea1SDimitry Andric W.write<uint8_t>(XCOFF::AUX_FILE); 925*0fca6ea1SDimitry Andric else 926*0fca6ea1SDimitry Andric W.OS.write_zeros(1); 927*0fca6ea1SDimitry Andric } 928*0fca6ea1SDimitry Andric 92981ad6265SDimitry Andric void XCOFFObjectWriter::writeSymbolAuxDwarfEntry( 93081ad6265SDimitry Andric uint64_t LengthOfSectionPortion, uint64_t NumberOfRelocEnt) { 93181ad6265SDimitry Andric writeWord(LengthOfSectionPortion); 93281ad6265SDimitry Andric if (!is64Bit()) 93381ad6265SDimitry Andric W.OS.write_zeros(4); // Reserved 93481ad6265SDimitry Andric writeWord(NumberOfRelocEnt); 93581ad6265SDimitry Andric if (is64Bit()) { 93681ad6265SDimitry Andric W.OS.write_zeros(1); // Reserved 93781ad6265SDimitry Andric W.write<uint8_t>(XCOFF::AUX_SECT); 93881ad6265SDimitry Andric } else { 93981ad6265SDimitry Andric W.OS.write_zeros(6); // Reserved 94081ad6265SDimitry Andric } 94181ad6265SDimitry Andric } 94281ad6265SDimitry Andric 94381ad6265SDimitry Andric void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel( 94481ad6265SDimitry Andric const Symbol &SymbolRef, const XCOFFSection &CSectionRef, 94581ad6265SDimitry Andric int16_t SectionIndex, uint64_t SymbolOffset) { 94681ad6265SDimitry Andric assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address && 94781ad6265SDimitry Andric "Symbol address overflowed."); 94881ad6265SDimitry Andric 949bdd1243dSDimitry Andric auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName()); 950bdd1243dSDimitry Andric if (Entry != ExceptionSection.ExceptionTable.end()) { 95181ad6265SDimitry Andric writeSymbolEntry(SymbolRef.getSymbolTableName(), 95281ad6265SDimitry Andric CSectionRef.Address + SymbolOffset, SectionIndex, 953bdd1243dSDimitry Andric // In the old version of the 32-bit XCOFF interpretation, 954bdd1243dSDimitry Andric // symbols may require bit 10 (0x0020) to be set if the 955bdd1243dSDimitry Andric // symbol is a function, otherwise the bit should be 0. 956bdd1243dSDimitry Andric is64Bit() ? SymbolRef.getVisibilityType() 957bdd1243dSDimitry Andric : SymbolRef.getVisibilityType() | 0x0020, 958bdd1243dSDimitry Andric SymbolRef.getStorageClass(), 959bdd1243dSDimitry Andric (is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2); 960bdd1243dSDimitry Andric if (is64Bit() && ExceptionSection.isDebugEnabled) { 961bdd1243dSDimitry Andric // On 64 bit with debugging enabled, we have a csect, exception, and 962bdd1243dSDimitry Andric // function auxilliary entries, so we must increment symbol index by 4. 963bdd1243dSDimitry Andric writeSymbolAuxExceptionEntry( 964bdd1243dSDimitry Andric ExceptionSection.FileOffsetToData + 965bdd1243dSDimitry Andric getExceptionOffset(Entry->second.FunctionSymbol), 966bdd1243dSDimitry Andric Entry->second.FunctionSize, 967bdd1243dSDimitry Andric SymbolIndexMap[Entry->second.FunctionSymbol] + 4); 968bdd1243dSDimitry Andric } 969bdd1243dSDimitry Andric // For exception section entries, csect and function auxilliary entries 970bdd1243dSDimitry Andric // must exist. On 64-bit there is also an exception auxilliary entry. 971bdd1243dSDimitry Andric writeSymbolAuxFunctionEntry( 972bdd1243dSDimitry Andric ExceptionSection.FileOffsetToData + 973bdd1243dSDimitry Andric getExceptionOffset(Entry->second.FunctionSymbol), 974bdd1243dSDimitry Andric Entry->second.FunctionSize, 0, 975bdd1243dSDimitry Andric (is64Bit() && ExceptionSection.isDebugEnabled) 976bdd1243dSDimitry Andric ? SymbolIndexMap[Entry->second.FunctionSymbol] + 4 977bdd1243dSDimitry Andric : SymbolIndexMap[Entry->second.FunctionSymbol] + 3); 978bdd1243dSDimitry Andric } else { 979bdd1243dSDimitry Andric writeSymbolEntry(SymbolRef.getSymbolTableName(), 980bdd1243dSDimitry Andric CSectionRef.Address + SymbolOffset, SectionIndex, 981bdd1243dSDimitry Andric SymbolRef.getVisibilityType(), 982bdd1243dSDimitry Andric SymbolRef.getStorageClass()); 983bdd1243dSDimitry Andric } 98481ad6265SDimitry Andric writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD, 98581ad6265SDimitry Andric CSectionRef.MCSec->getMappingClass()); 98681ad6265SDimitry Andric } 98781ad6265SDimitry Andric 98881ad6265SDimitry Andric void XCOFFObjectWriter::writeSymbolEntryForDwarfSection( 989349cc55cSDimitry Andric const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) { 990349cc55cSDimitry Andric assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!"); 991349cc55cSDimitry Andric 99281ad6265SDimitry Andric writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0, 99381ad6265SDimitry Andric SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF); 994349cc55cSDimitry Andric 99581ad6265SDimitry Andric writeSymbolAuxDwarfEntry(DwarfSectionRef.Size); 996349cc55cSDimitry Andric } 997349cc55cSDimitry Andric 99881ad6265SDimitry Andric void XCOFFObjectWriter::writeSymbolEntryForControlSection( 999fe6060f1SDimitry Andric const XCOFFSection &CSectionRef, int16_t SectionIndex, 10008bcb0991SDimitry Andric XCOFF::StorageClass StorageClass) { 100181ad6265SDimitry Andric writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address, 100281ad6265SDimitry Andric SectionIndex, CSectionRef.getVisibilityType(), StorageClass); 10038bcb0991SDimitry Andric 100481ad6265SDimitry Andric writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec), 100581ad6265SDimitry Andric CSectionRef.MCSec->getMappingClass()); 10068bcb0991SDimitry Andric } 10078bcb0991SDimitry Andric 1008bdd1243dSDimitry Andric void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset, 1009bdd1243dSDimitry Andric uint32_t FunctionSize, 1010bdd1243dSDimitry Andric uint64_t LineNumberPointer, 1011bdd1243dSDimitry Andric uint32_t EndIndex) { 1012bdd1243dSDimitry Andric if (is64Bit()) 1013bdd1243dSDimitry Andric writeWord(LineNumberPointer); 1014bdd1243dSDimitry Andric else 1015bdd1243dSDimitry Andric W.write<uint32_t>(EntryOffset); 1016bdd1243dSDimitry Andric W.write<uint32_t>(FunctionSize); 1017bdd1243dSDimitry Andric if (!is64Bit()) 1018bdd1243dSDimitry Andric writeWord(LineNumberPointer); 1019bdd1243dSDimitry Andric W.write<uint32_t>(EndIndex); 1020bdd1243dSDimitry Andric if (is64Bit()) { 1021bdd1243dSDimitry Andric W.OS.write_zeros(1); 1022bdd1243dSDimitry Andric W.write<uint8_t>(XCOFF::AUX_FCN); 1023bdd1243dSDimitry Andric } else { 1024bdd1243dSDimitry Andric W.OS.write_zeros(2); 1025bdd1243dSDimitry Andric } 1026bdd1243dSDimitry Andric } 1027bdd1243dSDimitry Andric 1028bdd1243dSDimitry Andric void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset, 1029bdd1243dSDimitry Andric uint32_t FunctionSize, 1030bdd1243dSDimitry Andric uint32_t EndIndex) { 1031bdd1243dSDimitry Andric assert(is64Bit() && "Exception auxilliary entries are 64-bit only."); 1032bdd1243dSDimitry Andric W.write<uint64_t>(EntryOffset); 1033bdd1243dSDimitry Andric W.write<uint32_t>(FunctionSize); 1034bdd1243dSDimitry Andric W.write<uint32_t>(EndIndex); 1035bdd1243dSDimitry Andric W.OS.write_zeros(1); // Pad (unused) 1036bdd1243dSDimitry Andric W.write<uint8_t>(XCOFF::AUX_EXCEPT); 1037bdd1243dSDimitry Andric } 1038bdd1243dSDimitry Andric 10398bcb0991SDimitry Andric void XCOFFObjectWriter::writeFileHeader() { 104081ad6265SDimitry Andric W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32); 1041480093f4SDimitry Andric W.write<uint16_t>(SectionCount); 104281ad6265SDimitry Andric W.write<int32_t>(0); // TimeStamp 104381ad6265SDimitry Andric writeWord(SymbolTableOffset); 104481ad6265SDimitry Andric if (is64Bit()) { 1045fcaf7f86SDimitry Andric W.write<uint16_t>(auxiliaryHeaderSize()); 104681ad6265SDimitry Andric W.write<uint16_t>(0); // Flags 10478bcb0991SDimitry Andric W.write<int32_t>(SymbolTableEntryCount); 104881ad6265SDimitry Andric } else { 104981ad6265SDimitry Andric W.write<int32_t>(SymbolTableEntryCount); 1050fcaf7f86SDimitry Andric W.write<uint16_t>(auxiliaryHeaderSize()); 105181ad6265SDimitry Andric W.write<uint16_t>(0); // Flags 105281ad6265SDimitry Andric } 10538bcb0991SDimitry Andric } 10540b57cec5SDimitry Andric 1055fcaf7f86SDimitry Andric void XCOFFObjectWriter::writeAuxFileHeader() { 1056fcaf7f86SDimitry Andric if (!auxiliaryHeaderSize()) 1057fcaf7f86SDimitry Andric return; 1058fcaf7f86SDimitry Andric W.write<uint16_t>(0); // Magic 1059fcaf7f86SDimitry Andric W.write<uint16_t>( 1060fcaf7f86SDimitry Andric XCOFF::NEW_XCOFF_INTERPRET); // Version. The new interpretation of the 1061fcaf7f86SDimitry Andric // n_type field in the symbol table entry is 1062fcaf7f86SDimitry Andric // used in XCOFF32. 1063fcaf7f86SDimitry Andric W.write<uint32_t>(Sections[0]->Size); // TextSize 1064fcaf7f86SDimitry Andric W.write<uint32_t>(Sections[1]->Size); // InitDataSize 1065fcaf7f86SDimitry Andric W.write<uint32_t>(Sections[2]->Size); // BssDataSize 1066fcaf7f86SDimitry Andric W.write<uint32_t>(0); // EntryPointAddr 1067fcaf7f86SDimitry Andric W.write<uint32_t>(Sections[0]->Address); // TextStartAddr 1068fcaf7f86SDimitry Andric W.write<uint32_t>(Sections[1]->Address); // DataStartAddr 1069fcaf7f86SDimitry Andric } 1070fcaf7f86SDimitry Andric 1071bdd1243dSDimitry Andric void XCOFFObjectWriter::writeSectionHeader(const SectionEntry *Sec) { 1072bdd1243dSDimitry Andric bool IsDwarf = (Sec->Flags & XCOFF::STYP_DWARF) != 0; 1073bdd1243dSDimitry Andric bool IsOvrflo = (Sec->Flags & XCOFF::STYP_OVRFLO) != 0; 1074480093f4SDimitry Andric // Nothing to write for this Section. 1075fe6060f1SDimitry Andric if (Sec->Index == SectionEntry::UninitializedIndex) 1076bdd1243dSDimitry Andric return; 1077480093f4SDimitry Andric 10788bcb0991SDimitry Andric // Write Name. 10798bcb0991SDimitry Andric ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize); 10808bcb0991SDimitry Andric W.write(NameRef); 10818bcb0991SDimitry Andric 1082bdd1243dSDimitry Andric // Write the Physical Address and Virtual Address. 1083349cc55cSDimitry Andric // We use 0 for DWARF sections' Physical and Virtual Addresses. 108481ad6265SDimitry Andric writeWord(IsDwarf ? 0 : Sec->Address); 1085bdd1243dSDimitry Andric // Since line number is not supported, we set it to 0 for overflow sections. 1086bdd1243dSDimitry Andric writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address); 10878bcb0991SDimitry Andric 108881ad6265SDimitry Andric writeWord(Sec->Size); 108981ad6265SDimitry Andric writeWord(Sec->FileOffsetToData); 109081ad6265SDimitry Andric writeWord(Sec->FileOffsetToRelocations); 109181ad6265SDimitry Andric writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet. 10928bcb0991SDimitry Andric 109381ad6265SDimitry Andric if (is64Bit()) { 109481ad6265SDimitry Andric W.write<uint32_t>(Sec->RelocationCount); 109581ad6265SDimitry Andric W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet. 10968bcb0991SDimitry Andric W.write<int32_t>(Sec->Flags); 109781ad6265SDimitry Andric W.OS.write_zeros(4); 109881ad6265SDimitry Andric } else { 1099bdd1243dSDimitry Andric // For the overflow section header, s_nreloc provides a reference to the 1100bdd1243dSDimitry Andric // primary section header and s_nlnno must have the same value. 1101bdd1243dSDimitry Andric // For common section headers, if either of s_nreloc or s_nlnno are set to 1102bdd1243dSDimitry Andric // 65535, the other one must also be set to 65535. 110381ad6265SDimitry Andric W.write<uint16_t>(Sec->RelocationCount); 1104bdd1243dSDimitry Andric W.write<uint16_t>((IsOvrflo || Sec->RelocationCount == XCOFF::RelocOverflow) 1105bdd1243dSDimitry Andric ? Sec->RelocationCount 1106bdd1243dSDimitry Andric : 0); // NumberOfLineNumbers. Not supported yet. 110781ad6265SDimitry Andric W.write<int32_t>(Sec->Flags); 110881ad6265SDimitry Andric } 1109bdd1243dSDimitry Andric } 1110349cc55cSDimitry Andric 1111bdd1243dSDimitry Andric void XCOFFObjectWriter::writeSectionHeaderTable() { 1112349cc55cSDimitry Andric for (const auto *CsectSec : Sections) 1113bdd1243dSDimitry Andric writeSectionHeader(CsectSec); 1114349cc55cSDimitry Andric for (const auto &DwarfSec : DwarfSections) 1115bdd1243dSDimitry Andric writeSectionHeader(&DwarfSec); 1116bdd1243dSDimitry Andric for (const auto &OverflowSec : OverflowSections) 1117bdd1243dSDimitry Andric writeSectionHeader(&OverflowSec); 1118bdd1243dSDimitry Andric if (hasExceptionSection()) 1119bdd1243dSDimitry Andric writeSectionHeader(&ExceptionSection); 112006c3fb27SDimitry Andric if (CInfoSymSection.Entry) 112106c3fb27SDimitry Andric writeSectionHeader(&CInfoSymSection); 11228bcb0991SDimitry Andric } 11238bcb0991SDimitry Andric 11245ffd83dbSDimitry Andric void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc, 1125349cc55cSDimitry Andric const XCOFFSection &Section) { 1126349cc55cSDimitry Andric if (Section.MCSec->isCsect()) 112781ad6265SDimitry Andric writeWord(Section.Address + Reloc.FixupOffsetInCsect); 1128349cc55cSDimitry Andric else { 1129349cc55cSDimitry Andric // DWARF sections' address is set to 0. 1130349cc55cSDimitry Andric assert(Section.MCSec->isDwarfSect() && "unsupport section type!"); 113181ad6265SDimitry Andric writeWord(Reloc.FixupOffsetInCsect); 1132349cc55cSDimitry Andric } 11335ffd83dbSDimitry Andric W.write<uint32_t>(Reloc.SymbolTableIndex); 11345ffd83dbSDimitry Andric W.write<uint8_t>(Reloc.SignAndSize); 11355ffd83dbSDimitry Andric W.write<uint8_t>(Reloc.Type); 11365ffd83dbSDimitry Andric } 11375ffd83dbSDimitry Andric 11385ffd83dbSDimitry Andric void XCOFFObjectWriter::writeRelocations() { 11395ffd83dbSDimitry Andric for (const auto *Section : Sections) { 1140fe6060f1SDimitry Andric if (Section->Index == SectionEntry::UninitializedIndex) 11415ffd83dbSDimitry Andric // Nothing to write for this Section. 11425ffd83dbSDimitry Andric continue; 11435ffd83dbSDimitry Andric 11445ffd83dbSDimitry Andric for (const auto *Group : Section->Groups) { 11455ffd83dbSDimitry Andric if (Group->empty()) 11465ffd83dbSDimitry Andric continue; 11475ffd83dbSDimitry Andric 11485ffd83dbSDimitry Andric for (const auto &Csect : *Group) { 11495ffd83dbSDimitry Andric for (const auto Reloc : Csect.Relocations) 11505ffd83dbSDimitry Andric writeRelocation(Reloc, Csect); 11515ffd83dbSDimitry Andric } 11525ffd83dbSDimitry Andric } 11535ffd83dbSDimitry Andric } 1154349cc55cSDimitry Andric 1155349cc55cSDimitry Andric for (const auto &DwarfSection : DwarfSections) 1156349cc55cSDimitry Andric for (const auto &Reloc : DwarfSection.DwarfSect->Relocations) 1157349cc55cSDimitry Andric writeRelocation(Reloc, *DwarfSection.DwarfSect); 11585ffd83dbSDimitry Andric } 11595ffd83dbSDimitry Andric 1160*0fca6ea1SDimitry Andric void XCOFFObjectWriter::writeSymbolTable(MCAssembler &Asm) { 116181ad6265SDimitry Andric // Write C_FILE symbols. 1162*0fca6ea1SDimitry Andric StringRef Vers = CompilerVersion; 1163*0fca6ea1SDimitry Andric 116406c3fb27SDimitry Andric for (const std::pair<std::string, size_t> &F : FileNames) { 116581ad6265SDimitry Andric // The n_name of a C_FILE symbol is the source file's name when no auxiliary 116681ad6265SDimitry Andric // entries are present. 116706c3fb27SDimitry Andric StringRef FileName = F.first; 116806c3fb27SDimitry Andric 116906c3fb27SDimitry Andric // For C_FILE symbols, the Source Language ID overlays the high-order byte 117006c3fb27SDimitry Andric // of the SymbolType field, and the CPU Version ID is defined as the 117106c3fb27SDimitry Andric // low-order byte. 117206c3fb27SDimitry Andric // AIX's system assembler determines the source language ID based on the 117306c3fb27SDimitry Andric // source file's name suffix, and the behavior here is consistent with it. 117406c3fb27SDimitry Andric uint8_t LangID; 117506c3fb27SDimitry Andric if (FileName.ends_with(".c")) 117606c3fb27SDimitry Andric LangID = XCOFF::TB_C; 117706c3fb27SDimitry Andric else if (FileName.ends_with_insensitive(".f") || 117806c3fb27SDimitry Andric FileName.ends_with_insensitive(".f77") || 117906c3fb27SDimitry Andric FileName.ends_with_insensitive(".f90") || 118006c3fb27SDimitry Andric FileName.ends_with_insensitive(".f95") || 118106c3fb27SDimitry Andric FileName.ends_with_insensitive(".f03") || 118206c3fb27SDimitry Andric FileName.ends_with_insensitive(".f08")) 118306c3fb27SDimitry Andric LangID = XCOFF::TB_Fortran; 118406c3fb27SDimitry Andric else 118506c3fb27SDimitry Andric LangID = XCOFF::TB_CPLUSPLUS; 118606c3fb27SDimitry Andric uint8_t CpuID; 118706c3fb27SDimitry Andric if (is64Bit()) 118806c3fb27SDimitry Andric CpuID = XCOFF::TCPU_PPC64; 118906c3fb27SDimitry Andric else 119006c3fb27SDimitry Andric CpuID = XCOFF::TCPU_COM; 119106c3fb27SDimitry Andric 1192*0fca6ea1SDimitry Andric int NumberOfFileAuxEntries = 1; 1193*0fca6ea1SDimitry Andric if (!Vers.empty()) 1194*0fca6ea1SDimitry Andric ++NumberOfFileAuxEntries; 1195*0fca6ea1SDimitry Andric writeSymbolEntry(".file", /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG, 119606c3fb27SDimitry Andric /*SymbolType=*/(LangID << 8) | CpuID, XCOFF::C_FILE, 1197*0fca6ea1SDimitry Andric NumberOfFileAuxEntries); 1198*0fca6ea1SDimitry Andric writeSymbolAuxFileEntry(FileName, XCOFF::XFT_FN); 1199*0fca6ea1SDimitry Andric if (!Vers.empty()) 1200*0fca6ea1SDimitry Andric writeSymbolAuxFileEntry(Vers, XCOFF::XFT_CV); 120181ad6265SDimitry Andric } 1202fe6060f1SDimitry Andric 120306c3fb27SDimitry Andric if (CInfoSymSection.Entry) 120406c3fb27SDimitry Andric writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset, 120506c3fb27SDimitry Andric CInfoSymSection.Index, 120606c3fb27SDimitry Andric /*SymbolType=*/0, XCOFF::C_INFO, 120706c3fb27SDimitry Andric /*NumberOfAuxEntries=*/0); 120806c3fb27SDimitry Andric 1209480093f4SDimitry Andric for (const auto &Csect : UndefinedCsects) { 121081ad6265SDimitry Andric writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF, 1211fe6060f1SDimitry Andric Csect.MCSec->getStorageClass()); 12128bcb0991SDimitry Andric } 12138bcb0991SDimitry Andric 1214480093f4SDimitry Andric for (const auto *Section : Sections) { 1215fe6060f1SDimitry Andric if (Section->Index == SectionEntry::UninitializedIndex) 12165ffd83dbSDimitry Andric // Nothing to write for this Section. 1217480093f4SDimitry Andric continue; 1218480093f4SDimitry Andric 1219480093f4SDimitry Andric for (const auto *Group : Section->Groups) { 1220480093f4SDimitry Andric if (Group->empty()) 1221480093f4SDimitry Andric continue; 1222480093f4SDimitry Andric 1223480093f4SDimitry Andric const int16_t SectionIndex = Section->Index; 1224480093f4SDimitry Andric for (const auto &Csect : *Group) { 1225480093f4SDimitry Andric // Write out the control section first and then each symbol in it. 122681ad6265SDimitry Andric writeSymbolEntryForControlSection(Csect, SectionIndex, 1227fe6060f1SDimitry Andric Csect.MCSec->getStorageClass()); 1228480093f4SDimitry Andric 1229480093f4SDimitry Andric for (const auto &Sym : Csect.Syms) 123081ad6265SDimitry Andric writeSymbolEntryForCsectMemberLabel( 1231*0fca6ea1SDimitry Andric Sym, Csect, SectionIndex, Asm.getSymbolOffset(*(Sym.MCSym))); 1232480093f4SDimitry Andric } 1233480093f4SDimitry Andric } 12348bcb0991SDimitry Andric } 1235349cc55cSDimitry Andric 1236349cc55cSDimitry Andric for (const auto &DwarfSection : DwarfSections) 123781ad6265SDimitry Andric writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect, 1238349cc55cSDimitry Andric DwarfSection.Index); 12398bcb0991SDimitry Andric } 12408bcb0991SDimitry Andric 1241bdd1243dSDimitry Andric void XCOFFObjectWriter::finalizeRelocationInfo(SectionEntry *Sec, 1242bdd1243dSDimitry Andric uint64_t RelCount) { 1243bdd1243dSDimitry Andric // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file 1244bdd1243dSDimitry Andric // may not contain an overflow section header. 1245bdd1243dSDimitry Andric if (!is64Bit() && (RelCount >= static_cast<uint32_t>(XCOFF::RelocOverflow))) { 1246bdd1243dSDimitry Andric // Generate an overflow section header. 1247bdd1243dSDimitry Andric SectionEntry SecEntry(".ovrflo", XCOFF::STYP_OVRFLO); 1248bdd1243dSDimitry Andric 1249bdd1243dSDimitry Andric // This field specifies the file section number of the section header that 1250bdd1243dSDimitry Andric // overflowed. 1251bdd1243dSDimitry Andric SecEntry.RelocationCount = Sec->Index; 1252bdd1243dSDimitry Andric 1253bdd1243dSDimitry Andric // This field specifies the number of relocation entries actually 1254bdd1243dSDimitry Andric // required. 1255bdd1243dSDimitry Andric SecEntry.Address = RelCount; 1256bdd1243dSDimitry Andric SecEntry.Index = ++SectionCount; 1257bdd1243dSDimitry Andric OverflowSections.push_back(std::move(SecEntry)); 1258bdd1243dSDimitry Andric 1259bdd1243dSDimitry Andric // The field in the primary section header is always 65535 1260bdd1243dSDimitry Andric // (XCOFF::RelocOverflow). 1261bdd1243dSDimitry Andric Sec->RelocationCount = XCOFF::RelocOverflow; 1262bdd1243dSDimitry Andric } else { 1263bdd1243dSDimitry Andric Sec->RelocationCount = RelCount; 1264bdd1243dSDimitry Andric } 1265bdd1243dSDimitry Andric } 1266bdd1243dSDimitry Andric 1267bdd1243dSDimitry Andric void XCOFFObjectWriter::calcOffsetToRelocations(SectionEntry *Sec, 1268bdd1243dSDimitry Andric uint64_t &RawPointer) { 1269bdd1243dSDimitry Andric if (!Sec->RelocationCount) 1270bdd1243dSDimitry Andric return; 1271bdd1243dSDimitry Andric 1272bdd1243dSDimitry Andric Sec->FileOffsetToRelocations = RawPointer; 1273bdd1243dSDimitry Andric uint64_t RelocationSizeInSec = 0; 1274bdd1243dSDimitry Andric if (!is64Bit() && 1275bdd1243dSDimitry Andric Sec->RelocationCount == static_cast<uint32_t>(XCOFF::RelocOverflow)) { 1276bdd1243dSDimitry Andric // Find its corresponding overflow section. 1277bdd1243dSDimitry Andric for (auto &OverflowSec : OverflowSections) { 1278bdd1243dSDimitry Andric if (OverflowSec.RelocationCount == static_cast<uint32_t>(Sec->Index)) { 1279bdd1243dSDimitry Andric RelocationSizeInSec = 1280bdd1243dSDimitry Andric OverflowSec.Address * XCOFF::RelocationSerializationSize32; 1281bdd1243dSDimitry Andric 1282bdd1243dSDimitry Andric // This field must have the same values as in the corresponding 1283bdd1243dSDimitry Andric // primary section header. 1284bdd1243dSDimitry Andric OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations; 1285bdd1243dSDimitry Andric } 1286bdd1243dSDimitry Andric } 1287bdd1243dSDimitry Andric assert(RelocationSizeInSec && "Overflow section header doesn't exist."); 1288bdd1243dSDimitry Andric } else { 1289bdd1243dSDimitry Andric RelocationSizeInSec = Sec->RelocationCount * 1290bdd1243dSDimitry Andric (is64Bit() ? XCOFF::RelocationSerializationSize64 1291bdd1243dSDimitry Andric : XCOFF::RelocationSerializationSize32); 1292bdd1243dSDimitry Andric } 1293bdd1243dSDimitry Andric 1294bdd1243dSDimitry Andric RawPointer += RelocationSizeInSec; 1295bdd1243dSDimitry Andric if (RawPointer > MaxRawDataSize) 1296bdd1243dSDimitry Andric report_fatal_error("Relocation data overflowed this object file."); 1297bdd1243dSDimitry Andric } 1298bdd1243dSDimitry Andric 12995ffd83dbSDimitry Andric void XCOFFObjectWriter::finalizeSectionInfo() { 13005ffd83dbSDimitry Andric for (auto *Section : Sections) { 1301fe6060f1SDimitry Andric if (Section->Index == SectionEntry::UninitializedIndex) 13025ffd83dbSDimitry Andric // Nothing to record for this Section. 13035ffd83dbSDimitry Andric continue; 13045ffd83dbSDimitry Andric 1305bdd1243dSDimitry Andric uint64_t RelCount = 0; 13065ffd83dbSDimitry Andric for (const auto *Group : Section->Groups) { 13075ffd83dbSDimitry Andric if (Group->empty()) 13085ffd83dbSDimitry Andric continue; 13095ffd83dbSDimitry Andric 1310bdd1243dSDimitry Andric for (auto &Csect : *Group) 1311bdd1243dSDimitry Andric RelCount += Csect.Relocations.size(); 13125ffd83dbSDimitry Andric } 1313bdd1243dSDimitry Andric finalizeRelocationInfo(Section, RelCount); 13145ffd83dbSDimitry Andric } 13155ffd83dbSDimitry Andric 1316349cc55cSDimitry Andric for (auto &DwarfSection : DwarfSections) 1317bdd1243dSDimitry Andric finalizeRelocationInfo(&DwarfSection, 1318bdd1243dSDimitry Andric DwarfSection.DwarfSect->Relocations.size()); 1319349cc55cSDimitry Andric 1320bdd1243dSDimitry Andric // Calculate the RawPointer value for all headers. 1321bdd1243dSDimitry Andric uint64_t RawPointer = 1322bdd1243dSDimitry Andric (is64Bit() ? (XCOFF::FileHeaderSize64 + 1323bdd1243dSDimitry Andric SectionCount * XCOFF::SectionHeaderSize64) 1324bdd1243dSDimitry Andric : (XCOFF::FileHeaderSize32 + 1325bdd1243dSDimitry Andric SectionCount * XCOFF::SectionHeaderSize32)) + 1326bdd1243dSDimitry Andric auxiliaryHeaderSize(); 1327349cc55cSDimitry Andric 1328bdd1243dSDimitry Andric // Calculate the file offset to the section data. 1329bdd1243dSDimitry Andric for (auto *Sec : Sections) { 1330bdd1243dSDimitry Andric if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual) 1331bdd1243dSDimitry Andric continue; 13325ffd83dbSDimitry Andric 133306c3fb27SDimitry Andric RawPointer = Sec->advanceFileOffset(MaxRawDataSize, RawPointer); 1334bdd1243dSDimitry Andric } 1335349cc55cSDimitry Andric 1336bdd1243dSDimitry Andric if (!DwarfSections.empty()) { 1337bdd1243dSDimitry Andric RawPointer += PaddingsBeforeDwarf; 1338bdd1243dSDimitry Andric for (auto &DwarfSection : DwarfSections) { 133906c3fb27SDimitry Andric RawPointer = DwarfSection.advanceFileOffset(MaxRawDataSize, RawPointer); 1340bdd1243dSDimitry Andric } 1341bdd1243dSDimitry Andric } 1342349cc55cSDimitry Andric 134306c3fb27SDimitry Andric if (hasExceptionSection()) 134406c3fb27SDimitry Andric RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer); 1345bdd1243dSDimitry Andric 134606c3fb27SDimitry Andric if (CInfoSymSection.Entry) 134706c3fb27SDimitry Andric RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer); 1348bdd1243dSDimitry Andric 1349bdd1243dSDimitry Andric for (auto *Sec : Sections) { 1350bdd1243dSDimitry Andric if (Sec->Index != SectionEntry::UninitializedIndex) 1351bdd1243dSDimitry Andric calcOffsetToRelocations(Sec, RawPointer); 1352bdd1243dSDimitry Andric } 1353349cc55cSDimitry Andric 1354349cc55cSDimitry Andric for (auto &DwarfSec : DwarfSections) 1355bdd1243dSDimitry Andric calcOffsetToRelocations(&DwarfSec, RawPointer); 13565ffd83dbSDimitry Andric 13575ffd83dbSDimitry Andric // TODO Error check that the number of symbol table entries fits in 32-bits 13585ffd83dbSDimitry Andric // signed ... 13595ffd83dbSDimitry Andric if (SymbolTableEntryCount) 13605ffd83dbSDimitry Andric SymbolTableOffset = RawPointer; 13615ffd83dbSDimitry Andric } 13625ffd83dbSDimitry Andric 1363bdd1243dSDimitry Andric void XCOFFObjectWriter::addExceptionEntry( 1364bdd1243dSDimitry Andric const MCSymbol *Symbol, const MCSymbol *Trap, unsigned LanguageCode, 1365bdd1243dSDimitry Andric unsigned ReasonCode, unsigned FunctionSize, bool hasDebug) { 1366bdd1243dSDimitry Andric // If a module had debug info, debugging is enabled and XCOFF emits the 1367bdd1243dSDimitry Andric // exception auxilliary entry. 1368bdd1243dSDimitry Andric if (hasDebug) 1369bdd1243dSDimitry Andric ExceptionSection.isDebugEnabled = true; 1370bdd1243dSDimitry Andric auto Entry = ExceptionSection.ExceptionTable.find(Symbol->getName()); 1371bdd1243dSDimitry Andric if (Entry != ExceptionSection.ExceptionTable.end()) { 1372bdd1243dSDimitry Andric Entry->second.Entries.push_back( 1373bdd1243dSDimitry Andric ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); 1374bdd1243dSDimitry Andric return; 1375bdd1243dSDimitry Andric } 1376bdd1243dSDimitry Andric ExceptionInfo NewEntry; 1377bdd1243dSDimitry Andric NewEntry.FunctionSymbol = Symbol; 1378bdd1243dSDimitry Andric NewEntry.FunctionSize = FunctionSize; 1379bdd1243dSDimitry Andric NewEntry.Entries.push_back( 1380bdd1243dSDimitry Andric ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); 1381bdd1243dSDimitry Andric ExceptionSection.ExceptionTable.insert( 1382bdd1243dSDimitry Andric std::pair<const StringRef, ExceptionInfo>(Symbol->getName(), NewEntry)); 1383bdd1243dSDimitry Andric } 1384bdd1243dSDimitry Andric 1385bdd1243dSDimitry Andric unsigned XCOFFObjectWriter::getExceptionSectionSize() { 1386bdd1243dSDimitry Andric unsigned EntryNum = 0; 1387bdd1243dSDimitry Andric 1388*0fca6ea1SDimitry Andric for (const auto &TableEntry : ExceptionSection.ExceptionTable) 1389bdd1243dSDimitry Andric // The size() gets +1 to account for the initial entry containing the 1390bdd1243dSDimitry Andric // symbol table index. 1391*0fca6ea1SDimitry Andric EntryNum += TableEntry.second.Entries.size() + 1; 1392bdd1243dSDimitry Andric 1393bdd1243dSDimitry Andric return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64 1394bdd1243dSDimitry Andric : XCOFF::ExceptionSectionEntrySize32); 1395bdd1243dSDimitry Andric } 1396bdd1243dSDimitry Andric 1397bdd1243dSDimitry Andric unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol *Symbol) { 1398bdd1243dSDimitry Andric unsigned EntryNum = 0; 1399*0fca6ea1SDimitry Andric for (const auto &TableEntry : ExceptionSection.ExceptionTable) { 1400*0fca6ea1SDimitry Andric if (Symbol == TableEntry.second.FunctionSymbol) 1401bdd1243dSDimitry Andric break; 1402*0fca6ea1SDimitry Andric EntryNum += TableEntry.second.Entries.size() + 1; 1403bdd1243dSDimitry Andric } 1404bdd1243dSDimitry Andric return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64 1405bdd1243dSDimitry Andric : XCOFF::ExceptionSectionEntrySize32); 1406bdd1243dSDimitry Andric } 1407bdd1243dSDimitry Andric 140806c3fb27SDimitry Andric void XCOFFObjectWriter::addCInfoSymEntry(StringRef Name, StringRef Metadata) { 140906c3fb27SDimitry Andric assert(!CInfoSymSection.Entry && "Multiple entries are not supported"); 141006c3fb27SDimitry Andric CInfoSymSection.addEntry( 141106c3fb27SDimitry Andric std::make_unique<CInfoSymInfo>(Name.str(), Metadata.str())); 141206c3fb27SDimitry Andric } 141306c3fb27SDimitry Andric 1414*0fca6ea1SDimitry Andric void XCOFFObjectWriter::assignAddressesAndIndices(MCAssembler &Asm) { 1415*0fca6ea1SDimitry Andric // The symbol table starts with all the C_FILE symbols. Each C_FILE symbol 1416*0fca6ea1SDimitry Andric // requires 1 or 2 auxiliary entries. 1417*0fca6ea1SDimitry Andric uint32_t SymbolTableIndex = 1418*0fca6ea1SDimitry Andric (2 + (CompilerVersion.empty() ? 0 : 1)) * FileNames.size(); 1419480093f4SDimitry Andric 142006c3fb27SDimitry Andric if (CInfoSymSection.Entry) 142106c3fb27SDimitry Andric SymbolTableIndex++; 142206c3fb27SDimitry Andric 1423480093f4SDimitry Andric // Calculate indices for undefined symbols. 1424480093f4SDimitry Andric for (auto &Csect : UndefinedCsects) { 1425480093f4SDimitry Andric Csect.Size = 0; 1426480093f4SDimitry Andric Csect.Address = 0; 1427480093f4SDimitry Andric Csect.SymbolTableIndex = SymbolTableIndex; 1428fe6060f1SDimitry Andric SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 1429480093f4SDimitry Andric // 1 main and 1 auxiliary symbol table entry for each contained symbol. 1430480093f4SDimitry Andric SymbolTableIndex += 2; 1431480093f4SDimitry Andric } 1432480093f4SDimitry Andric 14338bcb0991SDimitry Andric // The address corrresponds to the address of sections and symbols in the 14348bcb0991SDimitry Andric // object file. We place the shared address 0 immediately after the 14358bcb0991SDimitry Andric // section header table. 143681ad6265SDimitry Andric uint64_t Address = 0; 14378bcb0991SDimitry Andric // Section indices are 1-based in XCOFF. 1438480093f4SDimitry Andric int32_t SectionIndex = 1; 1439fe6060f1SDimitry Andric bool HasTDataSection = false; 14408bcb0991SDimitry Andric 1441480093f4SDimitry Andric for (auto *Section : Sections) { 1442480093f4SDimitry Andric const bool IsEmpty = 1443480093f4SDimitry Andric llvm::all_of(Section->Groups, 1444480093f4SDimitry Andric [](const CsectGroup *Group) { return Group->empty(); }); 1445480093f4SDimitry Andric if (IsEmpty) 1446480093f4SDimitry Andric continue; 1447480093f4SDimitry Andric 1448480093f4SDimitry Andric if (SectionIndex > MaxSectionIndex) 1449480093f4SDimitry Andric report_fatal_error("Section index overflow!"); 1450480093f4SDimitry Andric Section->Index = SectionIndex++; 1451480093f4SDimitry Andric SectionCount++; 1452480093f4SDimitry Andric 1453480093f4SDimitry Andric bool SectionAddressSet = false; 1454fe6060f1SDimitry Andric // Reset the starting address to 0 for TData section. 1455fe6060f1SDimitry Andric if (Section->Flags == XCOFF::STYP_TDATA) { 1456fe6060f1SDimitry Andric Address = 0; 1457fe6060f1SDimitry Andric HasTDataSection = true; 1458fe6060f1SDimitry Andric } 1459fe6060f1SDimitry Andric // Reset the starting address to 0 for TBSS section if the object file does 1460fe6060f1SDimitry Andric // not contain TData Section. 1461fe6060f1SDimitry Andric if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection) 1462fe6060f1SDimitry Andric Address = 0; 1463fe6060f1SDimitry Andric 1464480093f4SDimitry Andric for (auto *Group : Section->Groups) { 1465480093f4SDimitry Andric if (Group->empty()) 1466480093f4SDimitry Andric continue; 1467480093f4SDimitry Andric 1468480093f4SDimitry Andric for (auto &Csect : *Group) { 1469fe6060f1SDimitry Andric const MCSectionXCOFF *MCSec = Csect.MCSec; 1470bdd1243dSDimitry Andric Csect.Address = alignTo(Address, MCSec->getAlign()); 1471*0fca6ea1SDimitry Andric Csect.Size = Asm.getSectionAddressSize(*MCSec); 14728bcb0991SDimitry Andric Address = Csect.Address + Csect.Size; 14738bcb0991SDimitry Andric Csect.SymbolTableIndex = SymbolTableIndex; 14745ffd83dbSDimitry Andric SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; 14758bcb0991SDimitry Andric // 1 main and 1 auxiliary symbol table entry for the csect. 14768bcb0991SDimitry Andric SymbolTableIndex += 2; 1477480093f4SDimitry Andric 14788bcb0991SDimitry Andric for (auto &Sym : Csect.Syms) { 1479bdd1243dSDimitry Andric bool hasExceptEntry = false; 1480bdd1243dSDimitry Andric auto Entry = 1481bdd1243dSDimitry Andric ExceptionSection.ExceptionTable.find(Sym.MCSym->getName()); 1482bdd1243dSDimitry Andric if (Entry != ExceptionSection.ExceptionTable.end()) { 1483bdd1243dSDimitry Andric hasExceptEntry = true; 1484bdd1243dSDimitry Andric for (auto &TrapEntry : Entry->second.Entries) { 1485*0fca6ea1SDimitry Andric TrapEntry.TrapAddress = Asm.getSymbolOffset(*(Sym.MCSym)) + 1486bdd1243dSDimitry Andric TrapEntry.Trap->getOffset(); 1487bdd1243dSDimitry Andric } 1488bdd1243dSDimitry Andric } 14898bcb0991SDimitry Andric Sym.SymbolTableIndex = SymbolTableIndex; 14905ffd83dbSDimitry Andric SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex; 1491480093f4SDimitry Andric // 1 main and 1 auxiliary symbol table entry for each contained 1492bdd1243dSDimitry Andric // symbol. For symbols with exception section entries, a function 1493bdd1243dSDimitry Andric // auxilliary entry is needed, and on 64-bit XCOFF with debugging 1494bdd1243dSDimitry Andric // enabled, an additional exception auxilliary entry is needed. 14958bcb0991SDimitry Andric SymbolTableIndex += 2; 1496bdd1243dSDimitry Andric if (hasExceptionSection() && hasExceptEntry) { 1497bdd1243dSDimitry Andric if (is64Bit() && ExceptionSection.isDebugEnabled) 1498bdd1243dSDimitry Andric SymbolTableIndex += 2; 1499bdd1243dSDimitry Andric else 1500bdd1243dSDimitry Andric SymbolTableIndex += 1; 1501bdd1243dSDimitry Andric } 15028bcb0991SDimitry Andric } 15038bcb0991SDimitry Andric } 15048bcb0991SDimitry Andric 1505480093f4SDimitry Andric if (!SectionAddressSet) { 1506480093f4SDimitry Andric Section->Address = Group->front().Address; 1507480093f4SDimitry Andric SectionAddressSet = true; 1508480093f4SDimitry Andric } 15098bcb0991SDimitry Andric } 15108bcb0991SDimitry Andric 1511480093f4SDimitry Andric // Make sure the address of the next section aligned to 1512480093f4SDimitry Andric // DefaultSectionAlign. 15138bcb0991SDimitry Andric Address = alignTo(Address, DefaultSectionAlign); 1514480093f4SDimitry Andric Section->Size = Address - Section->Address; 15158bcb0991SDimitry Andric } 15168bcb0991SDimitry Andric 151781ad6265SDimitry Andric // Start to generate DWARF sections. Sections other than DWARF section use 151881ad6265SDimitry Andric // DefaultSectionAlign as the default alignment, while DWARF sections have 151981ad6265SDimitry Andric // their own alignments. If these two alignments are not the same, we need 152081ad6265SDimitry Andric // some paddings here and record the paddings bytes for FileOffsetToData 152181ad6265SDimitry Andric // calculation. 152281ad6265SDimitry Andric if (!DwarfSections.empty()) 152381ad6265SDimitry Andric PaddingsBeforeDwarf = 152481ad6265SDimitry Andric alignTo(Address, 1525bdd1243dSDimitry Andric (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) - 152681ad6265SDimitry Andric Address; 152781ad6265SDimitry Andric 152881ad6265SDimitry Andric DwarfSectionEntry *LastDwarfSection = nullptr; 1529349cc55cSDimitry Andric for (auto &DwarfSection : DwarfSections) { 1530349cc55cSDimitry Andric assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!"); 1531349cc55cSDimitry Andric 1532349cc55cSDimitry Andric XCOFFSection &DwarfSect = *DwarfSection.DwarfSect; 1533349cc55cSDimitry Andric const MCSectionXCOFF *MCSec = DwarfSect.MCSec; 1534349cc55cSDimitry Andric 1535349cc55cSDimitry Andric // Section index. 1536349cc55cSDimitry Andric DwarfSection.Index = SectionIndex++; 1537349cc55cSDimitry Andric SectionCount++; 1538349cc55cSDimitry Andric 1539349cc55cSDimitry Andric // Symbol index. 1540349cc55cSDimitry Andric DwarfSect.SymbolTableIndex = SymbolTableIndex; 1541349cc55cSDimitry Andric SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex; 1542349cc55cSDimitry Andric // 1 main and 1 auxiliary symbol table entry for the csect. 1543349cc55cSDimitry Andric SymbolTableIndex += 2; 1544349cc55cSDimitry Andric 1545349cc55cSDimitry Andric // Section address. Make it align to section alignment. 1546349cc55cSDimitry Andric // We use address 0 for DWARF sections' Physical and Virtual Addresses. 1547349cc55cSDimitry Andric // This address is used to tell where is the section in the final object. 1548349cc55cSDimitry Andric // See writeSectionForDwarfSectionEntry(). 1549349cc55cSDimitry Andric DwarfSection.Address = DwarfSect.Address = 1550bdd1243dSDimitry Andric alignTo(Address, MCSec->getAlign()); 1551349cc55cSDimitry Andric 1552349cc55cSDimitry Andric // Section size. 1553349cc55cSDimitry Andric // For DWARF section, we must use the real size which may be not aligned. 1554*0fca6ea1SDimitry Andric DwarfSection.Size = DwarfSect.Size = Asm.getSectionAddressSize(*MCSec); 1555349cc55cSDimitry Andric 155681ad6265SDimitry Andric Address = DwarfSection.Address + DwarfSection.Size; 155781ad6265SDimitry Andric 155881ad6265SDimitry Andric if (LastDwarfSection) 155981ad6265SDimitry Andric LastDwarfSection->MemorySize = 156081ad6265SDimitry Andric DwarfSection.Address - LastDwarfSection->Address; 156181ad6265SDimitry Andric LastDwarfSection = &DwarfSection; 156281ad6265SDimitry Andric } 156381ad6265SDimitry Andric if (LastDwarfSection) { 156481ad6265SDimitry Andric // Make the final DWARF section address align to the default section 156581ad6265SDimitry Andric // alignment for follow contents. 156681ad6265SDimitry Andric Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size, 156781ad6265SDimitry Andric DefaultSectionAlign); 156881ad6265SDimitry Andric LastDwarfSection->MemorySize = Address - LastDwarfSection->Address; 1569349cc55cSDimitry Andric } 1570bdd1243dSDimitry Andric if (hasExceptionSection()) { 1571bdd1243dSDimitry Andric ExceptionSection.Index = SectionIndex++; 1572bdd1243dSDimitry Andric SectionCount++; 1573bdd1243dSDimitry Andric ExceptionSection.Address = 0; 1574bdd1243dSDimitry Andric ExceptionSection.Size = getExceptionSectionSize(); 1575bdd1243dSDimitry Andric Address += ExceptionSection.Size; 1576bdd1243dSDimitry Andric Address = alignTo(Address, DefaultSectionAlign); 1577bdd1243dSDimitry Andric } 1578349cc55cSDimitry Andric 157906c3fb27SDimitry Andric if (CInfoSymSection.Entry) { 158006c3fb27SDimitry Andric CInfoSymSection.Index = SectionIndex++; 158106c3fb27SDimitry Andric SectionCount++; 158206c3fb27SDimitry Andric CInfoSymSection.Address = 0; 158306c3fb27SDimitry Andric Address += CInfoSymSection.Size; 158406c3fb27SDimitry Andric Address = alignTo(Address, DefaultSectionAlign); 158506c3fb27SDimitry Andric } 158606c3fb27SDimitry Andric 15878bcb0991SDimitry Andric SymbolTableEntryCount = SymbolTableIndex; 15888bcb0991SDimitry Andric } 15898bcb0991SDimitry Andric 1590349cc55cSDimitry Andric void XCOFFObjectWriter::writeSectionForControlSectionEntry( 1591*0fca6ea1SDimitry Andric const MCAssembler &Asm, const CsectSectionEntry &CsectEntry, 1592*0fca6ea1SDimitry Andric uint64_t &CurrentAddressLocation) { 1593349cc55cSDimitry Andric // Nothing to write for this Section. 1594349cc55cSDimitry Andric if (CsectEntry.Index == SectionEntry::UninitializedIndex) 1595349cc55cSDimitry Andric return; 1596349cc55cSDimitry Andric 1597349cc55cSDimitry Andric // There could be a gap (without corresponding zero padding) between 1598349cc55cSDimitry Andric // sections. 1599349cc55cSDimitry Andric // There could be a gap (without corresponding zero padding) between 1600349cc55cSDimitry Andric // sections. 1601349cc55cSDimitry Andric assert(((CurrentAddressLocation <= CsectEntry.Address) || 1602349cc55cSDimitry Andric (CsectEntry.Flags == XCOFF::STYP_TDATA) || 1603349cc55cSDimitry Andric (CsectEntry.Flags == XCOFF::STYP_TBSS)) && 1604349cc55cSDimitry Andric "CurrentAddressLocation should be less than or equal to section " 1605349cc55cSDimitry Andric "address if the section is not TData or TBSS."); 1606349cc55cSDimitry Andric 1607349cc55cSDimitry Andric CurrentAddressLocation = CsectEntry.Address; 1608349cc55cSDimitry Andric 1609349cc55cSDimitry Andric // For virtual sections, nothing to write. But need to increase 1610349cc55cSDimitry Andric // CurrentAddressLocation for later sections like DWARF section has a correct 1611349cc55cSDimitry Andric // writing location. 1612349cc55cSDimitry Andric if (CsectEntry.IsVirtual) { 1613349cc55cSDimitry Andric CurrentAddressLocation += CsectEntry.Size; 1614349cc55cSDimitry Andric return; 1615349cc55cSDimitry Andric } 1616349cc55cSDimitry Andric 1617349cc55cSDimitry Andric for (const auto &Group : CsectEntry.Groups) { 1618349cc55cSDimitry Andric for (const auto &Csect : *Group) { 1619349cc55cSDimitry Andric if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation) 1620349cc55cSDimitry Andric W.OS.write_zeros(PaddingSize); 1621349cc55cSDimitry Andric if (Csect.Size) 1622*0fca6ea1SDimitry Andric Asm.writeSectionData(W.OS, Csect.MCSec); 1623349cc55cSDimitry Andric CurrentAddressLocation = Csect.Address + Csect.Size; 1624349cc55cSDimitry Andric } 1625349cc55cSDimitry Andric } 1626349cc55cSDimitry Andric 1627349cc55cSDimitry Andric // The size of the tail padding in a section is the end virtual address of 16285f757f3fSDimitry Andric // the current section minus the end virtual address of the last csect 1629349cc55cSDimitry Andric // in that section. 163081ad6265SDimitry Andric if (uint64_t PaddingSize = 1631349cc55cSDimitry Andric CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) { 1632349cc55cSDimitry Andric W.OS.write_zeros(PaddingSize); 1633349cc55cSDimitry Andric CurrentAddressLocation += PaddingSize; 1634349cc55cSDimitry Andric } 1635349cc55cSDimitry Andric } 1636349cc55cSDimitry Andric 1637349cc55cSDimitry Andric void XCOFFObjectWriter::writeSectionForDwarfSectionEntry( 1638*0fca6ea1SDimitry Andric const MCAssembler &Asm, const DwarfSectionEntry &DwarfEntry, 1639*0fca6ea1SDimitry Andric uint64_t &CurrentAddressLocation) { 1640349cc55cSDimitry Andric // There could be a gap (without corresponding zero padding) between 1641349cc55cSDimitry Andric // sections. For example DWARF section alignment is bigger than 1642349cc55cSDimitry Andric // DefaultSectionAlign. 1643349cc55cSDimitry Andric assert(CurrentAddressLocation <= DwarfEntry.Address && 1644349cc55cSDimitry Andric "CurrentAddressLocation should be less than or equal to section " 1645349cc55cSDimitry Andric "address."); 1646349cc55cSDimitry Andric 164781ad6265SDimitry Andric if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation) 1648349cc55cSDimitry Andric W.OS.write_zeros(PaddingSize); 1649349cc55cSDimitry Andric 1650349cc55cSDimitry Andric if (DwarfEntry.Size) 1651*0fca6ea1SDimitry Andric Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec); 1652349cc55cSDimitry Andric 1653349cc55cSDimitry Andric CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size; 1654349cc55cSDimitry Andric 1655349cc55cSDimitry Andric // DWARF section size is not aligned to DefaultSectionAlign. 1656349cc55cSDimitry Andric // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign. 1657349cc55cSDimitry Andric uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign; 1658349cc55cSDimitry Andric uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0; 1659349cc55cSDimitry Andric if (TailPaddingSize) 1660349cc55cSDimitry Andric W.OS.write_zeros(TailPaddingSize); 1661349cc55cSDimitry Andric 1662349cc55cSDimitry Andric CurrentAddressLocation += TailPaddingSize; 1663349cc55cSDimitry Andric } 1664349cc55cSDimitry Andric 1665bdd1243dSDimitry Andric void XCOFFObjectWriter::writeSectionForExceptionSectionEntry( 1666*0fca6ea1SDimitry Andric const MCAssembler &Asm, ExceptionSectionEntry &ExceptionEntry, 1667*0fca6ea1SDimitry Andric uint64_t &CurrentAddressLocation) { 1668*0fca6ea1SDimitry Andric for (const auto &TableEntry : ExceptionEntry.ExceptionTable) { 1669bdd1243dSDimitry Andric // For every symbol that has exception entries, you must start the entries 1670bdd1243dSDimitry Andric // with an initial symbol table index entry 1671*0fca6ea1SDimitry Andric W.write<uint32_t>(SymbolIndexMap[TableEntry.second.FunctionSymbol]); 1672bdd1243dSDimitry Andric if (is64Bit()) { 1673bdd1243dSDimitry Andric // 4-byte padding on 64-bit. 1674bdd1243dSDimitry Andric W.OS.write_zeros(4); 1675bdd1243dSDimitry Andric } 1676bdd1243dSDimitry Andric W.OS.write_zeros(2); 1677*0fca6ea1SDimitry Andric for (auto &TrapEntry : TableEntry.second.Entries) { 1678bdd1243dSDimitry Andric writeWord(TrapEntry.TrapAddress); 1679bdd1243dSDimitry Andric W.write<uint8_t>(TrapEntry.Lang); 1680bdd1243dSDimitry Andric W.write<uint8_t>(TrapEntry.Reason); 1681bdd1243dSDimitry Andric } 1682bdd1243dSDimitry Andric } 1683bdd1243dSDimitry Andric 1684bdd1243dSDimitry Andric CurrentAddressLocation += getExceptionSectionSize(); 1685bdd1243dSDimitry Andric } 1686bdd1243dSDimitry Andric 168706c3fb27SDimitry Andric void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry( 1688*0fca6ea1SDimitry Andric const MCAssembler &Asm, CInfoSymSectionEntry &CInfoSymEntry, 1689*0fca6ea1SDimitry Andric uint64_t &CurrentAddressLocation) { 169006c3fb27SDimitry Andric if (!CInfoSymSection.Entry) 169106c3fb27SDimitry Andric return; 169206c3fb27SDimitry Andric 169306c3fb27SDimitry Andric constexpr int WordSize = sizeof(uint32_t); 169406c3fb27SDimitry Andric std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry; 169506c3fb27SDimitry Andric const std::string &Metadata = CISI->Metadata; 169606c3fb27SDimitry Andric 169706c3fb27SDimitry Andric // Emit the 4-byte length of the metadata. 169806c3fb27SDimitry Andric W.write<uint32_t>(Metadata.size()); 169906c3fb27SDimitry Andric 170006c3fb27SDimitry Andric if (Metadata.size() == 0) 170106c3fb27SDimitry Andric return; 170206c3fb27SDimitry Andric 170306c3fb27SDimitry Andric // Write out the payload one word at a time. 170406c3fb27SDimitry Andric size_t Index = 0; 170506c3fb27SDimitry Andric while (Index + WordSize <= Metadata.size()) { 170606c3fb27SDimitry Andric uint32_t NextWord = 170706c3fb27SDimitry Andric llvm::support::endian::read32be(Metadata.data() + Index); 170806c3fb27SDimitry Andric W.write<uint32_t>(NextWord); 170906c3fb27SDimitry Andric Index += WordSize; 171006c3fb27SDimitry Andric } 171106c3fb27SDimitry Andric 171206c3fb27SDimitry Andric // If there is padding, we have at least one byte of payload left to emit. 171306c3fb27SDimitry Andric if (CISI->paddingSize()) { 171406c3fb27SDimitry Andric std::array<uint8_t, WordSize> LastWord = {0}; 171506c3fb27SDimitry Andric ::memcpy(LastWord.data(), Metadata.data() + Index, Metadata.size() - Index); 171606c3fb27SDimitry Andric W.write<uint32_t>(llvm::support::endian::read32be(LastWord.data())); 171706c3fb27SDimitry Andric } 171806c3fb27SDimitry Andric 171906c3fb27SDimitry Andric CurrentAddressLocation += CISI->size(); 172006c3fb27SDimitry Andric } 172106c3fb27SDimitry Andric 17228bcb0991SDimitry Andric // Takes the log base 2 of the alignment and shifts the result into the 5 most 17238bcb0991SDimitry Andric // significant bits of a byte, then or's in the csect type into the least 17248bcb0991SDimitry Andric // significant 3 bits. 17258bcb0991SDimitry Andric uint8_t getEncodedType(const MCSectionXCOFF *Sec) { 1726bdd1243dSDimitry Andric unsigned Log2Align = Log2(Sec->getAlign()); 17278bcb0991SDimitry Andric // Result is a number in the range [0, 31] which fits in the 5 least 17288bcb0991SDimitry Andric // significant bits. Shift this value into the 5 most significant bits, and 17298bcb0991SDimitry Andric // bitwise-or in the csect type. 17308bcb0991SDimitry Andric uint8_t EncodedAlign = Log2Align << 3; 17318bcb0991SDimitry Andric return EncodedAlign | Sec->getCSectType(); 17320b57cec5SDimitry Andric } 17330b57cec5SDimitry Andric 17340b57cec5SDimitry Andric } // end anonymous namespace 17350b57cec5SDimitry Andric 17360b57cec5SDimitry Andric std::unique_ptr<MCObjectWriter> 17370b57cec5SDimitry Andric llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, 17380b57cec5SDimitry Andric raw_pwrite_stream &OS) { 17398bcb0991SDimitry Andric return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS); 17400b57cec5SDimitry Andric } 1741*0fca6ea1SDimitry Andric 1742*0fca6ea1SDimitry Andric // TODO: Export XCOFFObjectWriter to llvm/MC/MCXCOFFObjectWriter.h and remove 1743*0fca6ea1SDimitry Andric // the forwarders. 1744*0fca6ea1SDimitry Andric void XCOFF::addExceptionEntry(MCObjectWriter &Writer, const MCSymbol *Symbol, 1745*0fca6ea1SDimitry Andric const MCSymbol *Trap, unsigned LanguageCode, 1746*0fca6ea1SDimitry Andric unsigned ReasonCode, unsigned FunctionSize, 1747*0fca6ea1SDimitry Andric bool hasDebug) { 1748*0fca6ea1SDimitry Andric static_cast<XCOFFObjectWriter &>(Writer).addExceptionEntry( 1749*0fca6ea1SDimitry Andric Symbol, Trap, LanguageCode, ReasonCode, FunctionSize, hasDebug); 1750*0fca6ea1SDimitry Andric } 1751*0fca6ea1SDimitry Andric 1752*0fca6ea1SDimitry Andric void XCOFF::addCInfoSymEntry(MCObjectWriter &Writer, StringRef Name, 1753*0fca6ea1SDimitry Andric StringRef Metadata) { 1754*0fca6ea1SDimitry Andric static_cast<XCOFFObjectWriter &>(Writer).addCInfoSymEntry(Name, Metadata); 1755*0fca6ea1SDimitry Andric } 1756