summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/MC/ELFObjectWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/MC/ELFObjectWriter.cpp')
-rw-r--r--contrib/llvm/lib/MC/ELFObjectWriter.cpp1657
1 files changed, 599 insertions, 1058 deletions
diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
index e2439ab..0765937 100644
--- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
@@ -21,12 +21,11 @@
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCELF.h"
-#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/Compression.h"
@@ -41,94 +40,50 @@ using namespace llvm;
#define DEBUG_TYPE "reloc-info"
namespace {
-class FragmentWriter {
- bool IsLittleEndian;
-
-public:
- FragmentWriter(bool IsLittleEndian);
- template <typename T> void write(MCDataFragment &F, T Val);
-};
typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy;
+class ELFObjectWriter;
+
class SymbolTableWriter {
- MCAssembler &Asm;
- FragmentWriter &FWriter;
+ ELFObjectWriter &EWriter;
bool Is64Bit;
- SectionIndexMapTy &SectionIndexMap;
-
- // The symbol .symtab fragment we are writting to.
- MCDataFragment *SymtabF;
- // .symtab_shndx fragment we are writting to.
- MCDataFragment *ShndxF;
+ // indexes we are going to write to .symtab_shndx.
+ std::vector<uint32_t> ShndxIndexes;
// The numbel of symbols written so far.
unsigned NumWritten;
void createSymtabShndx();
- template <typename T> void write(MCDataFragment &F, T Value);
+ template <typename T> void write(T Value);
public:
- SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit,
- SectionIndexMapTy &SectionIndexMap,
- MCDataFragment *SymtabF);
+ SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit);
void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
uint8_t other, uint32_t shndx, bool Reserved);
-};
-
-struct ELFRelocationEntry {
- uint64_t Offset; // Where is the relocation.
- const MCSymbol *Symbol; // The symbol to relocate with.
- unsigned Type; // The type of the relocation.
- uint64_t Addend; // The addend to use.
- ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type,
- uint64_t Addend)
- : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
+ ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; }
};
class ELFObjectWriter : public MCObjectWriter {
- FragmentWriter FWriter;
-
- protected:
-
static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
- static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant);
- static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout);
- static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolData &Data,
+ static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout);
+ static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
bool Used, bool Renamed);
- static bool isLocal(const MCSymbolData &Data, bool isUsedInReloc);
- static bool IsELFMetaDataSection(const MCSectionData &SD);
- static uint64_t DataSectionSize(const MCSectionData &SD);
- static uint64_t GetSectionFileSize(const MCAsmLayout &Layout,
- const MCSectionData &SD);
- static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout,
- const MCSectionData &SD);
-
- void WriteDataSectionData(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCSectionELF &Section);
-
- /*static bool isFixupKindX86RIPRel(unsigned Kind) {
- return Kind == X86::reloc_riprel_4byte ||
- Kind == X86::reloc_riprel_4byte_movq_load;
- }*/
-
- /// ELFSymbolData - Helper struct for containing some precomputed
- /// information on symbols.
+
+ /// Helper struct for containing some precomputed information on symbols.
struct ELFSymbolData {
- MCSymbolData *SymbolData;
- uint64_t StringIndex;
+ const MCSymbolELF *Symbol;
uint32_t SectionIndex;
StringRef Name;
// Support lexicographic sorting.
bool operator<(const ELFSymbolData &RHS) const {
- unsigned LHSType = MCELF::GetType(*SymbolData);
- unsigned RHSType = MCELF::GetType(*RHS.SymbolData);
+ unsigned LHSType = Symbol->getType();
+ unsigned RHSType = RHS.Symbol->getType();
if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION)
return false;
if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION)
@@ -142,37 +97,31 @@ class ELFObjectWriter : public MCObjectWriter {
/// The target specific ELF writer instance.
std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter;
- SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
- SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc;
- DenseMap<const MCSymbol *, const MCSymbol *> Renames;
+ DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
- llvm::DenseMap<const MCSectionData *, std::vector<ELFRelocationEntry>>
- Relocations;
- StringTableBuilder ShStrTabBuilder;
+ llvm::DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>>
+ Relocations;
/// @}
/// @name Symbol Table Data
/// @{
StringTableBuilder StrTabBuilder;
- std::vector<uint64_t> FileSymbolData;
- std::vector<ELFSymbolData> LocalSymbolData;
- std::vector<ELFSymbolData> ExternalSymbolData;
- std::vector<ELFSymbolData> UndefinedSymbolData;
/// @}
- bool NeedsGOT;
-
// This holds the symbol table index of the last local symbol.
unsigned LastLocalSymbolIndex;
// This holds the .strtab section index.
unsigned StringTableIndex;
// This holds the .symtab section index.
unsigned SymbolTableIndex;
+ // This holds the .symtab_shndx section index.
+ unsigned SymtabShndxSectionIndex = 0;
- unsigned ShstrtabIndex;
-
+ // Sections in the order they are to be output in the section table.
+ std::vector<const MCSectionELF *> SectionTable;
+ unsigned addToSectionTable(const MCSectionELF *Sec);
// TargetObjectWriter wrappers.
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
@@ -184,172 +133,130 @@ class ELFObjectWriter : public MCObjectWriter {
return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel);
}
+ void align(unsigned Alignment);
+
public:
- ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &_OS,
+ ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
bool IsLittleEndian)
- : MCObjectWriter(_OS, IsLittleEndian), FWriter(IsLittleEndian),
- TargetObjectWriter(MOTW), NeedsGOT(false) {}
+ : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
+
+ void reset() override {
+ Renames.clear();
+ Relocations.clear();
+ StrTabBuilder.clear();
+ SectionTable.clear();
+ MCObjectWriter::reset();
+ }
- virtual ~ELFObjectWriter();
+ ~ELFObjectWriter() override;
void WriteWord(uint64_t W) {
if (is64Bit())
- Write64(W);
+ write64(W);
else
- Write32(W);
+ write32(W);
}
- template <typename T> void write(MCDataFragment &F, T Value) {
- FWriter.write(F, Value);
+ template <typename T> void write(T Val) {
+ if (IsLittleEndian)
+ support::endian::Writer<support::little>(OS).write(Val);
+ else
+ support::endian::Writer<support::big>(OS).write(Val);
}
- void WriteHeader(const MCAssembler &Asm,
- uint64_t SectionDataSize,
- unsigned NumberOfSections);
+ void writeHeader(const MCAssembler &Asm);
- void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
- const MCAsmLayout &Layout);
+ void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
+ ELFSymbolData &MSD, const MCAsmLayout &Layout);
- void WriteSymbolTable(MCDataFragment *SymtabF, MCAssembler &Asm,
- const MCAsmLayout &Layout,
- SectionIndexMapTy &SectionIndexMap);
+ // Start and end offset of each section
+ typedef std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>
+ SectionOffsetsTy;
bool shouldRelocateWithSymbol(const MCAssembler &Asm,
const MCSymbolRefExpr *RefA,
- const MCSymbolData *SD, uint64_t C,
+ const MCSymbol *Sym, uint64_t C,
unsigned Type) const;
- void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override;
- uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm,
- const MCSymbol *S);
-
- // Map from a group section to the signature symbol
- typedef DenseMap<const MCSectionELF*, const MCSymbol*> GroupMapTy;
- // Map from a signature symbol to the group section
- typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy;
- // Map from a section to the section with the relocations
- typedef DenseMap<const MCSectionELF*, const MCSectionELF*> RelMapTy;
- // Map from a section to its offset
- typedef DenseMap<const MCSectionELF*, uint64_t> SectionOffsetMapTy;
+ // Map from a signature symbol to the group section index
+ typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy;
/// Compute the symbol table data
///
/// \param Asm - The assembler.
/// \param SectionIndexMap - Maps a section to its index.
/// \param RevGroupMap - Maps a signature symbol to the group section.
- /// \param NumRegularSections - Number of non-relocation sections.
void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
const RevGroupMapTy &RevGroupMap,
- unsigned NumRegularSections);
+ SectionOffsetsTy &SectionOffsets);
- void ComputeIndexMap(MCAssembler &Asm,
- SectionIndexMapTy &SectionIndexMap,
- const RelMapTy &RelMap);
+ MCSectionELF *createRelocationSection(MCContext &Ctx,
+ const MCSectionELF &Sec);
- void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout,
- RelMapTy &RelMap);
+ const MCSectionELF *createStringTable(MCContext &Ctx);
- void CompressDebugSections(MCAssembler &Asm, MCAsmLayout &Layout);
+ void executePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) override;
- void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout,
- const RelMapTy &RelMap);
+ void writeSectionHeader(const MCAsmLayout &Layout,
+ const SectionIndexMapTy &SectionIndexMap,
+ const SectionOffsetsTy &SectionOffsets);
- void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout,
- SectionIndexMapTy &SectionIndexMap,
- const RelMapTy &RelMap);
+ void writeSectionData(const MCAssembler &Asm, MCSection &Sec,
+ const MCAsmLayout &Layout);
- // Create the sections that show up in the symbol table. Currently
- // those are the .note.GNU-stack section and the group sections.
- void CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout,
- GroupMapTy &GroupMap,
- RevGroupMapTy &RevGroupMap,
- SectionIndexMapTy &SectionIndexMap,
- const RelMapTy &RelMap);
+ void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
+ uint64_t Address, uint64_t Offset, uint64_t Size,
+ uint32_t Link, uint32_t Info, uint64_t Alignment,
+ uint64_t EntrySize);
- void ExecutePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) override;
+ void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec);
- void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap,
- const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap,
- const SectionOffsetMapTy &SectionOffsetMap);
+ bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
+ const MCSymbol &SymA,
+ const MCFragment &FB,
+ bool InSet,
+ bool IsPCRel) const override;
- void ComputeSectionOrder(MCAssembler &Asm,
- std::vector<const MCSectionELF*> &Sections);
+ bool isWeak(const MCSymbol &Sym) const override;
- void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
- uint64_t Address, uint64_t Offset,
- uint64_t Size, uint32_t Link, uint32_t Info,
- uint64_t Alignment, uint64_t EntrySize);
-
- void WriteRelocationsFragment(const MCAssembler &Asm,
- MCDataFragment *F,
- const MCSectionData *SD);
-
- bool
- IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
- const MCSymbolData &DataA,
- const MCFragment &FB,
- bool InSet,
- bool IsPCRel) const override;
-
- void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
- void WriteSection(MCAssembler &Asm,
- const SectionIndexMapTy &SectionIndexMap,
- uint32_t GroupSymbolIndex,
- uint64_t Offset, uint64_t Size, uint64_t Alignment,
+ void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+ void writeSection(const SectionIndexMapTy &SectionIndexMap,
+ uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size,
const MCSectionELF &Section);
};
}
-FragmentWriter::FragmentWriter(bool IsLittleEndian)
- : IsLittleEndian(IsLittleEndian) {}
+void ELFObjectWriter::align(unsigned Alignment) {
+ uint64_t Padding = OffsetToAlignment(OS.tell(), Alignment);
+ WriteZeros(Padding);
+}
-template <typename T> void FragmentWriter::write(MCDataFragment &F, T Val) {
- if (IsLittleEndian)
- Val = support::endian::byte_swap<T, support::little>(Val);
- else
- Val = support::endian::byte_swap<T, support::big>(Val);
- const char *Start = (const char *)&Val;
- F.getContents().append(Start, Start + sizeof(T));
+unsigned ELFObjectWriter::addToSectionTable(const MCSectionELF *Sec) {
+ SectionTable.push_back(Sec);
+ StrTabBuilder.add(Sec->getSectionName());
+ return SectionTable.size();
}
void SymbolTableWriter::createSymtabShndx() {
- if (ShndxF)
+ if (!ShndxIndexes.empty())
return;
- MCContext &Ctx = Asm.getContext();
- const MCSectionELF *SymtabShndxSection =
- Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0,
- SectionKind::getReadOnly(), 4, "");
- MCSectionData *SymtabShndxSD =
- &Asm.getOrCreateSectionData(*SymtabShndxSection);
- SymtabShndxSD->setAlignment(4);
- ShndxF = new MCDataFragment(SymtabShndxSD);
- unsigned Index = SectionIndexMap.size() + 1;
- SectionIndexMap[SymtabShndxSection] = Index;
-
- for (unsigned I = 0; I < NumWritten; ++I)
- write(*ShndxF, uint32_t(0));
+ ShndxIndexes.resize(NumWritten);
}
-template <typename T>
-void SymbolTableWriter::write(MCDataFragment &F, T Value) {
- FWriter.write(F, Value);
+template <typename T> void SymbolTableWriter::write(T Value) {
+ EWriter.write(Value);
}
-SymbolTableWriter::SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter,
- bool Is64Bit,
- SectionIndexMapTy &SectionIndexMap,
- MCDataFragment *SymtabF)
- : Asm(Asm), FWriter(FWriter), Is64Bit(Is64Bit),
- SectionIndexMap(SectionIndexMap), SymtabF(SymtabF), ShndxF(nullptr),
- NumWritten(0) {}
+SymbolTableWriter::SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit)
+ : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}
void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
uint64_t size, uint8_t other,
@@ -359,31 +266,29 @@ void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
if (LargeIndex)
createSymtabShndx();
- if (ShndxF) {
+ if (!ShndxIndexes.empty()) {
if (LargeIndex)
- write(*ShndxF, shndx);
+ ShndxIndexes.push_back(shndx);
else
- write(*ShndxF, uint32_t(0));
+ ShndxIndexes.push_back(0);
}
uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx;
- raw_svector_ostream OS(SymtabF->getContents());
-
if (Is64Bit) {
- write(*SymtabF, name); // st_name
- write(*SymtabF, info); // st_info
- write(*SymtabF, other); // st_other
- write(*SymtabF, Index); // st_shndx
- write(*SymtabF, value); // st_value
- write(*SymtabF, size); // st_size
+ write(name); // st_name
+ write(info); // st_info
+ write(other); // st_other
+ write(Index); // st_shndx
+ write(value); // st_value
+ write(size); // st_size
} else {
- write(*SymtabF, name); // st_name
- write(*SymtabF, uint32_t(value)); // st_value
- write(*SymtabF, uint32_t(size)); // st_size
- write(*SymtabF, info); // st_info
- write(*SymtabF, other); // st_other
- write(*SymtabF, Index); // st_shndx
+ write(name); // st_name
+ write(uint32_t(value)); // st_value
+ write(uint32_t(size)); // st_size
+ write(info); // st_info
+ write(other); // st_other
+ write(Index); // st_shndx
}
++NumWritten;
@@ -396,34 +301,11 @@ bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel;
}
-bool ELFObjectWriter::RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) {
- switch (Variant) {
- default:
- return false;
- case MCSymbolRefExpr::VK_GOT:
- case MCSymbolRefExpr::VK_PLT:
- case MCSymbolRefExpr::VK_GOTPCREL:
- case MCSymbolRefExpr::VK_GOTOFF:
- case MCSymbolRefExpr::VK_TPOFF:
- case MCSymbolRefExpr::VK_TLSGD:
- case MCSymbolRefExpr::VK_GOTTPOFF:
- case MCSymbolRefExpr::VK_INDNTPOFF:
- case MCSymbolRefExpr::VK_NTPOFF:
- case MCSymbolRefExpr::VK_GOTNTPOFF:
- case MCSymbolRefExpr::VK_TLSLDM:
- case MCSymbolRefExpr::VK_DTPOFF:
- case MCSymbolRefExpr::VK_TLSLD:
- return true;
- }
-}
-
ELFObjectWriter::~ELFObjectWriter()
{}
// Emit the ELF header.
-void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
- uint64_t SectionDataSize,
- unsigned NumberOfSections) {
+void ELFObjectWriter::writeHeader(const MCAssembler &Asm) {
// ELF Header
// ----------
//
@@ -432,89 +314,78 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
// emitWord method behaves differently for ELF32 and ELF64, writing
// 4 bytes in the former and 8 in the latter.
- Write8(0x7f); // e_ident[EI_MAG0]
- Write8('E'); // e_ident[EI_MAG1]
- Write8('L'); // e_ident[EI_MAG2]
- Write8('F'); // e_ident[EI_MAG3]
+ writeBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to e_ident[EI_MAG3]
- Write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
+ write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
// e_ident[EI_DATA]
- Write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
+ write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
- Write8(ELF::EV_CURRENT); // e_ident[EI_VERSION]
+ write8(ELF::EV_CURRENT); // e_ident[EI_VERSION]
// e_ident[EI_OSABI]
- Write8(TargetObjectWriter->getOSABI());
- Write8(0); // e_ident[EI_ABIVERSION]
+ write8(TargetObjectWriter->getOSABI());
+ write8(0); // e_ident[EI_ABIVERSION]
WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD);
- Write16(ELF::ET_REL); // e_type
+ write16(ELF::ET_REL); // e_type
- Write16(TargetObjectWriter->getEMachine()); // e_machine = target
+ write16(TargetObjectWriter->getEMachine()); // e_machine = target
- Write32(ELF::EV_CURRENT); // e_version
+ write32(ELF::EV_CURRENT); // e_version
WriteWord(0); // e_entry, no entry point in .o file
WriteWord(0); // e_phoff, no program header for .o
- WriteWord(SectionDataSize + (is64Bit() ? sizeof(ELF::Elf64_Ehdr) :
- sizeof(ELF::Elf32_Ehdr))); // e_shoff = sec hdr table off in bytes
+ WriteWord(0); // e_shoff = sec hdr table off in bytes
// e_flags = whatever the target wants
- Write32(Asm.getELFHeaderEFlags());
+ write32(Asm.getELFHeaderEFlags());
// e_ehsize = ELF header size
- Write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr));
+ write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr));
- Write16(0); // e_phentsize = prog header entry size
- Write16(0); // e_phnum = # prog header entries = 0
+ write16(0); // e_phentsize = prog header entry size
+ write16(0); // e_phnum = # prog header entries = 0
// e_shentsize = Section header entry size
- Write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
+ write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
// e_shnum = # of section header ents
- if (NumberOfSections >= ELF::SHN_LORESERVE)
- Write16(ELF::SHN_UNDEF);
- else
- Write16(NumberOfSections);
+ write16(0);
// e_shstrndx = Section # of '.shstrtab'
- if (ShstrtabIndex >= ELF::SHN_LORESERVE)
- Write16(ELF::SHN_XINDEX);
- else
- Write16(ShstrtabIndex);
+ assert(StringTableIndex < ELF::SHN_LORESERVE);
+ write16(StringTableIndex);
}
-uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,
+uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
const MCAsmLayout &Layout) {
- if (Data.isCommon() && Data.isExternal())
- return Data.getCommonAlignment();
+ if (Sym.isCommon() && Sym.isExternal())
+ return Sym.getCommonAlignment();
uint64_t Res;
- if (!Layout.getSymbolOffset(&Data, Res))
+ if (!Layout.getSymbolOffset(Sym, Res))
return 0;
- if (Layout.getAssembler().isThumbFunc(&Data.getSymbol()))
+ if (Layout.getAssembler().isThumbFunc(&Sym))
Res |= 1;
return Res;
}
-void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
+void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
// The presence of symbol versions causes undefined symbols and
// versions declared with @@@ to be renamed.
- for (MCSymbolData &OriginalData : Asm.symbols()) {
- const MCSymbol &Alias = OriginalData.getSymbol();
-
+ for (const MCSymbol &A : Asm.symbols()) {
+ const auto &Alias = cast<MCSymbolELF>(A);
// Not an alias.
if (!Alias.isVariable())
continue;
auto *Ref = dyn_cast<MCSymbolRefExpr>(Alias.getVariableValue());
if (!Ref)
continue;
- const MCSymbol &Symbol = Ref->getSymbol();
- MCSymbolData &SD = Asm.getSymbolData(Symbol);
+ const auto &Symbol = cast<MCSymbolELF>(Ref->getSymbol());
StringRef AliasName = Alias.getName();
size_t Pos = AliasName.find('@');
@@ -523,8 +394,8 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
// Aliases defined with .symvar copy the binding from the symbol they alias.
// This is the first place we are able to copy this information.
- OriginalData.setExternal(SD.isExternal());
- MCELF::SetBinding(OriginalData, MCELF::GetBinding(SD));
+ Alias.setExternal(Symbol.isExternal());
+ Alias.setBinding(Symbol.getBinding());
StringRef Rest = AliasName.substr(Pos);
if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
@@ -574,99 +445,50 @@ static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
return Type;
}
-void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
+void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer,
+ uint32_t StringIndex, ELFSymbolData &MSD,
const MCAsmLayout &Layout) {
- MCSymbolData &OrigData = *MSD.SymbolData;
- assert((!OrigData.getFragment() ||
- (&OrigData.getFragment()->getParent()->getSection() ==
- &OrigData.getSymbol().getSection())) &&
+ const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
+ assert((!Symbol.getFragment() ||
+ (Symbol.getFragment()->getParent() == &Symbol.getSection())) &&
"The symbol's section doesn't match the fragment's symbol");
- const MCSymbol *Base = Layout.getBaseSymbol(OrigData.getSymbol());
+ const MCSymbolELF *Base =
+ cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol));
// This has to be in sync with when computeSymbolTable uses SHN_ABS or
// SHN_COMMON.
- bool IsReserved = !Base || OrigData.isCommon();
+ bool IsReserved = !Base || Symbol.isCommon();
// Binding and Type share the same byte as upper and lower nibbles
- uint8_t Binding = MCELF::GetBinding(OrigData);
- uint8_t Type = MCELF::GetType(OrigData);
- MCSymbolData *BaseSD = nullptr;
+ uint8_t Binding = Symbol.getBinding();
+ uint8_t Type = Symbol.getType();
if (Base) {
- BaseSD = &Layout.getAssembler().getSymbolData(*Base);
- Type = mergeTypeForSet(Type, MCELF::GetType(*BaseSD));
+ Type = mergeTypeForSet(Type, Base->getType());
}
- uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift);
+ uint8_t Info = (Binding << 4) | Type;
// Other and Visibility share the same byte with Visibility using the lower
// 2 bits
- uint8_t Visibility = MCELF::GetVisibility(OrigData);
- uint8_t Other = MCELF::getOther(OrigData) << (ELF_STO_Shift - ELF_STV_Shift);
- Other |= Visibility;
+ uint8_t Visibility = Symbol.getVisibility();
+ uint8_t Other = Symbol.getOther() | Visibility;
- uint64_t Value = SymbolValue(OrigData, Layout);
+ uint64_t Value = SymbolValue(*MSD.Symbol, Layout);
uint64_t Size = 0;
- const MCExpr *ESize = OrigData.getSize();
+ const MCExpr *ESize = MSD.Symbol->getSize();
if (!ESize && Base)
- ESize = BaseSD->getSize();
+ ESize = Base->getSize();
if (ESize) {
int64_t Res;
- if (!ESize->EvaluateAsAbsolute(Res, Layout))
+ if (!ESize->evaluateKnownAbsolute(Res, Layout))
report_fatal_error("Size expression must be absolute.");
Size = Res;
}
// Write out the symbol table entry
- Writer.writeSymbol(MSD.StringIndex, Info, Value, Size, Other,
- MSD.SectionIndex, IsReserved);
-}
-
-void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
- MCAssembler &Asm,
- const MCAsmLayout &Layout,
- SectionIndexMapTy &SectionIndexMap) {
- // The string table must be emitted first because we need the index
- // into the string table for all the symbol names.
-
- // FIXME: Make sure the start of the symbol table is aligned.
-
- SymbolTableWriter Writer(Asm, FWriter, is64Bit(), SectionIndexMap, SymtabF);
-
- // The first entry is the undefined symbol entry.
- Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
-
- for (unsigned i = 0, e = FileSymbolData.size(); i != e; ++i) {
- Writer.writeSymbol(FileSymbolData[i], ELF::STT_FILE | ELF::STB_LOCAL, 0, 0,
- ELF::STV_DEFAULT, ELF::SHN_ABS, true);
- }
-
- // Write the symbol table entries.
- LastLocalSymbolIndex = FileSymbolData.size() + LocalSymbolData.size() + 1;
-
- for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) {
- ELFSymbolData &MSD = LocalSymbolData[i];
- WriteSymbol(Writer, MSD, Layout);
- }
-
- for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) {
- ELFSymbolData &MSD = ExternalSymbolData[i];
- MCSymbolData &Data = *MSD.SymbolData;
- assert(((Data.getFlags() & ELF_STB_Global) ||
- (Data.getFlags() & ELF_STB_Weak)) &&
- "External symbol requires STB_GLOBAL or STB_WEAK flag");
- WriteSymbol(Writer, MSD, Layout);
- if (MCELF::GetBinding(Data) == ELF::STB_LOCAL)
- LastLocalSymbolIndex++;
- }
-
- for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
- ELFSymbolData &MSD = UndefinedSymbolData[i];
- MCSymbolData &Data = *MSD.SymbolData;
- WriteSymbol(Writer, MSD, Layout);
- if (MCELF::GetBinding(Data) == ELF::STB_LOCAL)
- LastLocalSymbolIndex++;
- }
+ Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex,
+ IsReserved);
}
// It is always valid to create a relocation with a symbol. It is preferable
@@ -674,9 +496,9 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
// allows us to omit some local symbols from the symbol table.
bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
const MCSymbolRefExpr *RefA,
- const MCSymbolData *SD,
- uint64_t C,
+ const MCSymbol *S, uint64_t C,
unsigned Type) const {
+ const auto *Sym = cast_or_null<MCSymbolELF>(S);
// A PCRel relocation to an absolute value has no symbol (or section). We
// represent that with a relocation to a null section.
if (!RefA)
@@ -711,11 +533,11 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
// An undefined symbol is not in any section, so the relocation has to point
// to the symbol itself.
- const MCSymbol &Sym = SD->getSymbol();
- if (Sym.isUndefined())
+ assert(Sym && "Expected a symbol");
+ if (Sym->isUndefined())
return true;
- unsigned Binding = MCELF::GetBinding(*SD);
+ unsigned Binding = Sym->getBinding();
switch(Binding) {
default:
llvm_unreachable("Invalid Binding");
@@ -739,7 +561,7 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
// If we change such a relocation to use the section, the linker would think
// that it pointed to another string and subtracting 42 at runtime will
// produce the wrong value.
- auto &Sec = cast<MCSectionELF>(Sym.getSection());
+ auto &Sec = cast<MCSectionELF>(Sym->getSection());
unsigned Flags = Sec.getFlags();
if (Flags & ELF::SHF_MERGE) {
if (C != 0)
@@ -762,41 +584,40 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
// bit. With a symbol that is done by just having the symbol have that bit
// set, so we would lose the bit if we relocated with the section.
// FIXME: We could use the section but add the bit to the relocation value.
- if (Asm.isThumbFunc(&Sym))
+ if (Asm.isThumbFunc(Sym))
return true;
- if (TargetObjectWriter->needsRelocateWithSymbol(*SD, Type))
+ if (TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type))
return true;
return false;
}
-static const MCSymbol *getWeakRef(const MCSymbolRefExpr &Ref) {
- const MCSymbol &Sym = Ref.getSymbol();
-
- if (Ref.getKind() == MCSymbolRefExpr::VK_WEAKREF)
- return &Sym;
-
- if (!Sym.isVariable())
- return nullptr;
-
- const MCExpr *Expr = Sym.getVariableValue();
- const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
- if (!Inner)
- return nullptr;
+// True if the assembler knows nothing about the final value of the symbol.
+// This doesn't cover the comdat issues, since in those cases the assembler
+// can at least know that all symbols in the section will move together.
+static bool isWeak(const MCSymbolELF &Sym) {
+ if (Sym.getType() == ELF::STT_GNU_IFUNC)
+ return true;
- if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
- return &Inner->getSymbol();
- return nullptr;
+ switch (Sym.getBinding()) {
+ default:
+ llvm_unreachable("Unknown binding");
+ case ELF::STB_LOCAL:
+ return false;
+ case ELF::STB_GLOBAL:
+ return false;
+ case ELF::STB_WEAK:
+ case ELF::STB_GNU_UNIQUE:
+ return true;
+ }
}
-void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
+void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- bool &IsPCRel,
- uint64_t &FixedValue) {
- const MCSectionData *FixupSection = Fragment->getParent();
+ const MCFixup &Fixup, MCValue Target,
+ bool &IsPCRel, uint64_t &FixedValue) {
+ const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
uint64_t C = Target.getConstant();
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
@@ -812,26 +633,29 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
// or (A + C - R). If B = R + K and the relocation is not pcrel, we can
// replace B to implement it: (A - R - K + C)
if (IsPCRel)
- Asm.getContext().FatalError(
+ Asm.getContext().reportFatalError(
Fixup.getLoc(),
"No relocation available to represent this relative expression");
- const MCSymbol &SymB = RefB->getSymbol();
+ const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());
if (SymB.isUndefined())
- Asm.getContext().FatalError(
+ Asm.getContext().reportFatalError(
Fixup.getLoc(),
Twine("symbol '") + SymB.getName() +
"' can not be undefined in a subtraction expression");
assert(!SymB.isAbsolute() && "Should have been folded");
const MCSection &SecB = SymB.getSection();
- if (&SecB != &FixupSection->getSection())
- Asm.getContext().FatalError(
+ if (&SecB != &FixupSection)
+ Asm.getContext().reportFatalError(
Fixup.getLoc(), "Cannot represent a difference across sections");
- const MCSymbolData &SymBD = Asm.getSymbolData(SymB);
- uint64_t SymBOffset = Layout.getSymbolOffset(&SymBD);
+ if (::isWeak(SymB))
+ Asm.getContext().reportFatalError(
+ Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol");
+
+ uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
uint64_t K = SymBOffset - FixupOffset;
IsPCRel = true;
C -= K;
@@ -839,13 +663,23 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
// We either rejected the fixup or folded B into C at this point.
const MCSymbolRefExpr *RefA = Target.getSymA();
- const MCSymbol *SymA = RefA ? &RefA->getSymbol() : nullptr;
- const MCSymbolData *SymAD = SymA ? &Asm.getSymbolData(*SymA) : nullptr;
+ const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr;
+
+ bool ViaWeakRef = false;
+ if (SymA && SymA->isVariable()) {
+ const MCExpr *Expr = SymA->getVariableValue();
+ if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
+ if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
+ SymA = cast<MCSymbolELF>(&Inner->getSymbol());
+ ViaWeakRef = true;
+ }
+ }
+ }
unsigned Type = GetRelocType(Target, Fixup, IsPCRel);
- bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymAD, C, Type);
+ bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type);
if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
- C += Layout.getSymbolOffset(SymAD);
+ C += Layout.getSymbolOffset(*SymA);
uint64_t Addend = 0;
if (hasRelocationAddend()) {
@@ -855,50 +689,36 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
FixedValue = C;
- // FIXME: What is this!?!?
- MCSymbolRefExpr::VariantKind Modifier =
- RefA ? RefA->getKind() : MCSymbolRefExpr::VK_None;
- if (RelocNeedsGOT(Modifier))
- NeedsGOT = true;
-
if (!RelocateWithSymbol) {
const MCSection *SecA =
(SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
auto *ELFSec = cast_or_null<MCSectionELF>(SecA);
- MCSymbol *SectionSymbol =
- ELFSec ? Asm.getContext().getOrCreateSectionSymbol(*ELFSec)
- : nullptr;
+ const auto *SectionSymbol =
+ ELFSec ? cast<MCSymbolELF>(ELFSec->getBeginSymbol()) : nullptr;
+ if (SectionSymbol)
+ SectionSymbol->setUsedInReloc();
ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend);
- Relocations[FixupSection].push_back(Rec);
+ Relocations[&FixupSection].push_back(Rec);
return;
}
if (SymA) {
- if (const MCSymbol *R = Renames.lookup(SymA))
+ if (const MCSymbolELF *R = Renames.lookup(SymA))
SymA = R;
- if (const MCSymbol *WeakRef = getWeakRef(*RefA))
- WeakrefUsedInReloc.insert(WeakRef);
+ if (ViaWeakRef)
+ SymA->setIsWeakrefUsedInReloc();
else
- UsedInReloc.insert(SymA);
+ SymA->setUsedInReloc();
}
ELFRelocationEntry Rec(FixupOffset, SymA, Type, Addend);
- Relocations[FixupSection].push_back(Rec);
+ Relocations[&FixupSection].push_back(Rec);
return;
}
-
-uint64_t
-ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
- const MCSymbol *S) {
- const MCSymbolData &SD = Asm.getSymbolData(*S);
- return SD.getIndex();
-}
-
bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout,
- const MCSymbolData &Data, bool Used,
+ const MCSymbolELF &Symbol, bool Used,
bool Renamed) {
- const MCSymbol &Symbol = Data.getSymbol();
if (Symbol.isVariable()) {
const MCExpr *Expr = Symbol.getVariableValue();
if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
@@ -913,229 +733,227 @@ bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout,
if (Renamed)
return false;
- if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_")
- return true;
-
- if (Symbol.isVariable()) {
- const MCSymbol *Base = Layout.getBaseSymbol(Symbol);
- if (Base && Base->isUndefined())
- return false;
+ if (Symbol.isVariable() && Symbol.isUndefined()) {
+ // FIXME: this is here just to diagnose the case of a var = commmon_sym.
+ Layout.getBaseSymbol(Symbol);
+ return false;
}
- bool IsGlobal = MCELF::GetBinding(Data) == ELF::STB_GLOBAL;
- if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal)
+ if (Symbol.isUndefined() && !Symbol.isBindingSet())
return false;
if (Symbol.isTemporary())
return false;
- return true;
-}
-
-bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isUsedInReloc) {
- if (Data.isExternal())
- return false;
-
- const MCSymbol &Symbol = Data.getSymbol();
- if (Symbol.isDefined())
- return true;
-
- if (isUsedInReloc)
+ if (Symbol.getType() == ELF::STT_SECTION)
return false;
return true;
}
-void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm,
- SectionIndexMapTy &SectionIndexMap,
- const RelMapTy &RelMap) {
- unsigned Index = 1;
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() != ELF::SHT_GROUP)
- continue;
- SectionIndexMap[&Section] = Index++;
- }
+void ELFObjectWriter::computeSymbolTable(
+ MCAssembler &Asm, const MCAsmLayout &Layout,
+ const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap,
+ SectionOffsetsTy &SectionOffsets) {
+ MCContext &Ctx = Asm.getContext();
+ SymbolTableWriter Writer(*this, is64Bit());
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() == ELF::SHT_GROUP ||
- Section.getType() == ELF::SHT_REL ||
- Section.getType() == ELF::SHT_RELA)
- continue;
- SectionIndexMap[&Section] = Index++;
- const MCSectionELF *RelSection = RelMap.lookup(&Section);
- if (RelSection)
- SectionIndexMap[RelSection] = Index++;
- }
-}
+ // Symbol table
+ unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
+ MCSectionELF *SymtabSection =
+ Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, "");
+ SymtabSection->setAlignment(is64Bit() ? 8 : 4);
+ SymbolTableIndex = addToSectionTable(SymtabSection);
-void
-ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap,
- const RevGroupMapTy &RevGroupMap,
- unsigned NumRegularSections) {
- // FIXME: Is this the correct place to do this?
- // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed?
- if (NeedsGOT) {
- StringRef Name = "_GLOBAL_OFFSET_TABLE_";
- MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name);
- MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym);
- Data.setExternal(true);
- MCELF::SetBinding(Data, ELF::STB_GLOBAL);
- }
+ align(SymtabSection->getAlignment());
+ uint64_t SecStart = OS.tell();
- // Add the data for the symbols.
- for (MCSymbolData &SD : Asm.symbols()) {
- const MCSymbol &Symbol = SD.getSymbol();
+ // The first entry is the undefined symbol entry.
+ Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
- bool Used = UsedInReloc.count(&Symbol);
- bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol);
- bool isSignature = RevGroupMap.count(&Symbol);
+ std::vector<ELFSymbolData> LocalSymbolData;
+ std::vector<ELFSymbolData> ExternalSymbolData;
- if (!isInSymtab(Layout, SD,
- Used || WeakrefUsed || isSignature,
+ // Add the data for the symbols.
+ bool HasLargeSectionIndex = false;
+ for (const MCSymbol &S : Asm.symbols()) {
+ const auto &Symbol = cast<MCSymbolELF>(S);
+ bool Used = Symbol.isUsedInReloc();
+ bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();
+ bool isSignature = Symbol.isSignature();
+
+ if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature,
Renames.count(&Symbol)))
continue;
ELFSymbolData MSD;
- MSD.SymbolData = &SD;
- const MCSymbol *BaseSymbol = Layout.getBaseSymbol(Symbol);
-
- // Undefined symbols are global, but this is the first place we
- // are able to set it.
- bool Local = isLocal(SD, Used);
- if (!Local && MCELF::GetBinding(SD) == ELF::STB_LOCAL) {
- assert(BaseSymbol);
- MCSymbolData &BaseData = Asm.getSymbolData(*BaseSymbol);
- MCELF::SetBinding(SD, ELF::STB_GLOBAL);
- MCELF::SetBinding(BaseData, ELF::STB_GLOBAL);
- }
+ MSD.Symbol = cast<MCSymbolELF>(&Symbol);
- if (!BaseSymbol) {
+ bool Local = Symbol.getBinding() == ELF::STB_LOCAL;
+ if (Symbol.isAbsolute()) {
MSD.SectionIndex = ELF::SHN_ABS;
- } else if (SD.isCommon()) {
+ } else if (Symbol.isCommon()) {
assert(!Local);
MSD.SectionIndex = ELF::SHN_COMMON;
- } else if (BaseSymbol->isUndefined()) {
- if (isSignature && !Used)
- MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap.lookup(&Symbol));
- else
+ } else if (Symbol.isUndefined()) {
+ if (isSignature && !Used) {
+ MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
+ if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
+ HasLargeSectionIndex = true;
+ } else {
MSD.SectionIndex = ELF::SHN_UNDEF;
- if (!Used && WeakrefUsed)
- MCELF::SetBinding(SD, ELF::STB_WEAK);
+ }
} else {
const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(BaseSymbol->getSection());
+ static_cast<const MCSectionELF &>(Symbol.getSection());
MSD.SectionIndex = SectionIndexMap.lookup(&Section);
assert(MSD.SectionIndex && "Invalid section index!");
+ if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
+ HasLargeSectionIndex = true;
}
- // The @@@ in symbol version is replaced with @ in undefined symbols and
- // @@ in defined ones.
+ // The @@@ in symbol version is replaced with @ in undefined symbols and @@
+ // in defined ones.
+ //
+ // FIXME: All name handling should be done before we get to the writer,
+ // including dealing with GNU-style version suffixes. Fixing this isn't
+ // trivial.
+ //
+ // We thus have to be careful to not perform the symbol version replacement
+ // blindly:
+ //
+ // The ELF format is used on Windows by the MCJIT engine. Thus, on
+ // Windows, the ELFObjectWriter can encounter symbols mangled using the MS
+ // Visual Studio C++ name mangling scheme. Symbols mangled using the MSVC
+ // C++ name mangling can legally have "@@@" as a sub-string. In that case,
+ // the EFLObjectWriter should not interpret the "@@@" sub-string as
+ // specifying GNU-style symbol versioning. The ELFObjectWriter therefore
+ // checks for the MSVC C++ name mangling prefix which is either "?", "@?",
+ // "__imp_?" or "__imp_@?".
+ //
+ // It would have been interesting to perform the MS mangling prefix check
+ // only when the target triple is of the form *-pc-windows-elf. But, it
+ // seems that this information is not easily accessible from the
+ // ELFObjectWriter.
StringRef Name = Symbol.getName();
- SmallString<32> Buf;
- size_t Pos = Name.find("@@@");
- if (Pos != StringRef::npos) {
- Buf += Name.substr(0, Pos);
- unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1;
- Buf += Name.substr(Pos + Skip);
- Name = Buf;
+ if (!Name.startswith("?") && !Name.startswith("@?") &&
+ !Name.startswith("__imp_?") && !Name.startswith("__imp_@?")) {
+ // This symbol isn't following the MSVC C++ name mangling convention. We
+ // can thus safely interpret the @@@ in symbol names as specifying symbol
+ // versioning.
+ SmallString<32> Buf;
+ size_t Pos = Name.find("@@@");
+ if (Pos != StringRef::npos) {
+ Buf += Name.substr(0, Pos);
+ unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1;
+ Buf += Name.substr(Pos + Skip);
+ Name = Buf;
+ }
}
// Sections have their own string table
- if (MCELF::GetType(SD) != ELF::STT_SECTION)
+ if (Symbol.getType() != ELF::STT_SECTION)
MSD.Name = StrTabBuilder.add(Name);
- if (MSD.SectionIndex == ELF::SHN_UNDEF)
- UndefinedSymbolData.push_back(MSD);
- else if (Local)
+ if (Local)
LocalSymbolData.push_back(MSD);
else
ExternalSymbolData.push_back(MSD);
}
- for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
- StrTabBuilder.add(*i);
+ if (HasLargeSectionIndex) {
+ MCSectionELF *SymtabShndxSection =
+ Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
+ SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
+ SymtabShndxSection->setAlignment(4);
+ }
- StrTabBuilder.finalize(StringTableBuilder::ELF);
+ ArrayRef<std::string> FileNames = Asm.getFileNames();
+ for (const std::string &Name : FileNames)
+ StrTabBuilder.add(Name);
- for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
- FileSymbolData.push_back(StrTabBuilder.getOffset(*i));
+ StrTabBuilder.finalize(StringTableBuilder::ELF);
- for (ELFSymbolData &MSD : LocalSymbolData)
- MSD.StringIndex = MCELF::GetType(*MSD.SymbolData) == ELF::STT_SECTION
- ? 0
- : StrTabBuilder.getOffset(MSD.Name);
- for (ELFSymbolData &MSD : ExternalSymbolData)
- MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
- for (ELFSymbolData& MSD : UndefinedSymbolData)
- MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
+ for (const std::string &Name : FileNames)
+ Writer.writeSymbol(StrTabBuilder.getOffset(Name),
+ ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
+ ELF::SHN_ABS, true);
// Symbols are required to be in lexicographic order.
array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end());
array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
- array_pod_sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
// Set the symbol indices. Local symbols must come before all other
// symbols with non-local bindings.
- unsigned Index = FileSymbolData.size() + 1;
- for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
- LocalSymbolData[i].SymbolData->setIndex(Index++);
-
- for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
- ExternalSymbolData[i].SymbolData->setIndex(Index++);
- for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
- UndefinedSymbolData[i].SymbolData->setIndex(Index++);
-}
+ unsigned Index = FileNames.size() + 1;
+
+ for (ELFSymbolData &MSD : LocalSymbolData) {
+ unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
+ ? 0
+ : StrTabBuilder.getOffset(MSD.Name);
+ MSD.Symbol->setIndex(Index++);
+ writeSymbol(Writer, StringIndex, MSD, Layout);
+ }
-void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm,
- MCAsmLayout &Layout,
- RelMapTy &RelMap) {
- for (MCAssembler::const_iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionData &SD = *it;
- if (Relocations[&SD].empty())
- continue;
+ // Write the symbol table entries.
+ LastLocalSymbolIndex = Index;
- MCContext &Ctx = Asm.getContext();
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(SD.getSection());
+ for (ELFSymbolData &MSD : ExternalSymbolData) {
+ unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);
+ MSD.Symbol->setIndex(Index++);
+ writeSymbol(Writer, StringIndex, MSD, Layout);
+ assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
+ }
- const StringRef SectionName = Section.getSectionName();
- std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel";
- RelaSectionName += SectionName;
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
- unsigned EntrySize;
- if (hasRelocationAddend())
- EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela);
- else
- EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);
+ ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
+ if (ShndxIndexes.empty()) {
+ assert(SymtabShndxSectionIndex == 0);
+ return;
+ }
+ assert(SymtabShndxSectionIndex != 0);
- unsigned Flags = 0;
- StringRef Group = "";
- if (Section.getFlags() & ELF::SHF_GROUP) {
- Flags = ELF::SHF_GROUP;
- Group = Section.getGroup()->getName();
- }
+ SecStart = OS.tell();
+ const MCSectionELF *SymtabShndxSection =
+ SectionTable[SymtabShndxSectionIndex - 1];
+ for (uint32_t Index : ShndxIndexes)
+ write(Index);
+ SecEnd = OS.tell();
+ SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
+}
- const MCSectionELF *RelaSection =
- Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ?
- ELF::SHT_RELA : ELF::SHT_REL, Flags,
- SectionKind::getReadOnly(),
- EntrySize, Group);
- RelMap[&Section] = RelaSection;
- Asm.getOrCreateSectionData(*RelaSection);
- }
+MCSectionELF *
+ELFObjectWriter::createRelocationSection(MCContext &Ctx,
+ const MCSectionELF &Sec) {
+ if (Relocations[&Sec].empty())
+ return nullptr;
+
+ const StringRef SectionName = Sec.getSectionName();
+ std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel";
+ RelaSectionName += SectionName;
+
+ unsigned EntrySize;
+ if (hasRelocationAddend())
+ EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela);
+ else
+ EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);
+
+ unsigned Flags = 0;
+ if (Sec.getFlags() & ELF::SHF_GROUP)
+ Flags = ELF::SHF_GROUP;
+
+ MCSectionELF *RelaSection = Ctx.createELFRelSection(
+ RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
+ Flags, EntrySize, Sec.getGroup(), &Sec);
+ RelaSection->setAlignment(is64Bit() ? 8 : 4);
+ return RelaSection;
}
static SmallVector<char, 128>
-getUncompressedData(MCAsmLayout &Layout,
- MCSectionData::FragmentListType &Fragments) {
+getUncompressedData(const MCAsmLayout &Layout,
+ const MCSection::FragmentListType &Fragments) {
SmallVector<char, 128> UncompressedData;
for (const MCFragment &F : Fragments) {
const SmallVectorImpl<char> *Contents;
@@ -1164,7 +982,7 @@ getUncompressedData(MCAsmLayout &Layout,
static bool
prependCompressionHeader(uint64_t Size,
SmallVectorImpl<char> &CompressedContents) {
- static const StringRef Magic = "ZLIB";
+ const StringRef Magic = "ZLIB";
if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size())
return false;
if (sys::IsLittleEndianHost)
@@ -1178,123 +996,41 @@ prependCompressionHeader(uint64_t Size,
return true;
}
-// Return a single fragment containing the compressed contents of the whole
-// section. Null if the section was not compressed for any reason.
-static std::unique_ptr<MCDataFragment>
-getCompressedFragment(MCAsmLayout &Layout,
- MCSectionData::FragmentListType &Fragments) {
- std::unique_ptr<MCDataFragment> CompressedFragment(new MCDataFragment());
+void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
+ const MCAsmLayout &Layout) {
+ MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
+ StringRef SectionName = Section.getSectionName();
+
+ // Compressing debug_frame requires handling alignment fragments which is
+ // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow
+ // for writing to arbitrary buffers) for little benefit.
+ if (!Asm.getContext().getAsmInfo()->compressDebugSections() ||
+ !SectionName.startswith(".debug_") || SectionName == ".debug_frame") {
+ Asm.writeSectionData(&Section, Layout);
+ return;
+ }
- // Gather the uncompressed data from all the fragments, recording the
- // alignment fragment, if seen, and any fixups.
+ // Gather the uncompressed data from all the fragments.
+ const MCSection::FragmentListType &Fragments = Section.getFragmentList();
SmallVector<char, 128> UncompressedData =
getUncompressedData(Layout, Fragments);
- SmallVectorImpl<char> &CompressedContents = CompressedFragment->getContents();
-
+ SmallVector<char, 128> CompressedContents;
zlib::Status Success = zlib::compress(
StringRef(UncompressedData.data(), UncompressedData.size()),
CompressedContents);
- if (Success != zlib::StatusOK)
- return nullptr;
-
- if (!prependCompressionHeader(UncompressedData.size(), CompressedContents))
- return nullptr;
-
- return CompressedFragment;
-}
-
-typedef DenseMap<const MCSectionData *, std::vector<MCSymbolData *>>
-DefiningSymbolMap;
-
-static void UpdateSymbols(const MCAsmLayout &Layout,
- const std::vector<MCSymbolData *> &Symbols,
- MCFragment &NewFragment) {
- for (MCSymbolData *Sym : Symbols) {
- Sym->setOffset(Sym->getOffset() +
- Layout.getFragmentOffset(Sym->getFragment()));
- Sym->setFragment(&NewFragment);
+ if (Success != zlib::StatusOK) {
+ Asm.writeSectionData(&Section, Layout);
+ return;
}
-}
-static void CompressDebugSection(MCAssembler &Asm, MCAsmLayout &Layout,
- const DefiningSymbolMap &DefiningSymbols,
- const MCSectionELF &Section,
- MCSectionData &SD) {
- StringRef SectionName = Section.getSectionName();
- MCSectionData::FragmentListType &Fragments = SD.getFragmentList();
-
- std::unique_ptr<MCDataFragment> CompressedFragment =
- getCompressedFragment(Layout, Fragments);
-
- // Leave the section as-is if the fragments could not be compressed.
- if (!CompressedFragment)
+ if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) {
+ Asm.writeSectionData(&Section, Layout);
return;
-
- // Update the fragment+offsets of any symbols referring to fragments in this
- // section to refer to the new fragment.
- auto I = DefiningSymbols.find(&SD);
- if (I != DefiningSymbols.end())
- UpdateSymbols(Layout, I->second, *CompressedFragment);
-
- // Invalidate the layout for the whole section since it will have new and
- // different fragments now.
- Layout.invalidateFragmentsFrom(&Fragments.front());
- Fragments.clear();
-
- // Complete the initialization of the new fragment
- CompressedFragment->setParent(&SD);
- CompressedFragment->setLayoutOrder(0);
- Fragments.push_back(CompressedFragment.release());
-
- // Rename from .debug_* to .zdebug_*
+ }
Asm.getContext().renameELFSection(&Section,
(".z" + SectionName.drop_front(1)).str());
-}
-
-void ELFObjectWriter::CompressDebugSections(MCAssembler &Asm,
- MCAsmLayout &Layout) {
- if (!Asm.getContext().getAsmInfo()->compressDebugSections())
- return;
-
- DefiningSymbolMap DefiningSymbols;
-
- for (MCSymbolData &SD : Asm.symbols())
- if (MCFragment *F = SD.getFragment())
- DefiningSymbols[F->getParent()].push_back(&SD);
-
- for (MCSectionData &SD : Asm) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(SD.getSection());
- StringRef SectionName = Section.getSectionName();
-
- // Compressing debug_frame requires handling alignment fragments which is
- // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow
- // for writing to arbitrary buffers) for little benefit.
- if (!SectionName.startswith(".debug_") || SectionName == ".debug_frame")
- continue;
-
- CompressDebugSection(Asm, Layout, DefiningSymbols, Section, SD);
- }
-}
-
-void ELFObjectWriter::WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout,
- const RelMapTy &RelMap) {
- for (MCAssembler::const_iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionData &SD = *it;
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(SD.getSection());
-
- const MCSectionELF *RelaSection = RelMap.lookup(&Section);
- if (!RelaSection)
- continue;
- MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection);
- RelaSD.setAlignment(is64Bit() ? 8 : 4);
-
- MCDataFragment *F = new MCDataFragment(&RelaSD);
- WriteRelocationsFragment(Asm, F, &*it);
- }
+ OS << CompressedContents;
}
void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
@@ -1303,214 +1039,84 @@ void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
uint32_t Link, uint32_t Info,
uint64_t Alignment,
uint64_t EntrySize) {
- Write32(Name); // sh_name: index into string table
- Write32(Type); // sh_type
+ write32(Name); // sh_name: index into string table
+ write32(Type); // sh_type
WriteWord(Flags); // sh_flags
WriteWord(Address); // sh_addr
WriteWord(Offset); // sh_offset
WriteWord(Size); // sh_size
- Write32(Link); // sh_link
- Write32(Info); // sh_info
+ write32(Link); // sh_link
+ write32(Info); // sh_info
WriteWord(Alignment); // sh_addralign
WriteWord(EntrySize); // sh_entsize
}
-// ELF doesn't require relocations to be in any order. We sort by the r_offset,
-// just to match gnu as for easier comparison. The use type is an arbitrary way
-// of making the sort deterministic.
-static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) {
- const ELFRelocationEntry &A = *AP;
- const ELFRelocationEntry &B = *BP;
- if (A.Offset != B.Offset)
- return B.Offset - A.Offset;
- if (B.Type != A.Type)
- return A.Type - B.Type;
- llvm_unreachable("ELFRelocs might be unstable!");
-}
-
-static void sortRelocs(const MCAssembler &Asm,
- std::vector<ELFRelocationEntry> &Relocs) {
- array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel);
-}
-
-void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
- MCDataFragment *F,
- const MCSectionData *SD) {
- std::vector<ELFRelocationEntry> &Relocs = Relocations[SD];
+void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
+ const MCSectionELF &Sec) {
+ std::vector<ELFRelocationEntry> &Relocs = Relocations[&Sec];
- sortRelocs(Asm, Relocs);
+ // Sort the relocation entries. Most targets just sort by Offset, but some
+ // (e.g., MIPS) have additional constraints.
+ TargetObjectWriter->sortRelocs(Asm, Relocs);
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
const ELFRelocationEntry &Entry = Relocs[e - i - 1];
- unsigned Index =
- Entry.Symbol ? getSymbolIndexInSymbolTable(Asm, Entry.Symbol) : 0;
+ unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
if (is64Bit()) {
- write(*F, Entry.Offset);
+ write(Entry.Offset);
if (TargetObjectWriter->isN64()) {
- write(*F, uint32_t(Index));
+ write(uint32_t(Index));
- write(*F, TargetObjectWriter->getRSsym(Entry.Type));
- write(*F, TargetObjectWriter->getRType3(Entry.Type));
- write(*F, TargetObjectWriter->getRType2(Entry.Type));
- write(*F, TargetObjectWriter->getRType(Entry.Type));
+ write(TargetObjectWriter->getRSsym(Entry.Type));
+ write(TargetObjectWriter->getRType3(Entry.Type));
+ write(TargetObjectWriter->getRType2(Entry.Type));
+ write(TargetObjectWriter->getRType(Entry.Type));
} else {
struct ELF::Elf64_Rela ERE64;
ERE64.setSymbolAndType(Index, Entry.Type);
- write(*F, ERE64.r_info);
+ write(ERE64.r_info);
}
if (hasRelocationAddend())
- write(*F, Entry.Addend);
+ write(Entry.Addend);
} else {
- write(*F, uint32_t(Entry.Offset));
+ write(uint32_t(Entry.Offset));
struct ELF::Elf32_Rela ERE32;
ERE32.setSymbolAndType(Index, Entry.Type);
- write(*F, ERE32.r_info);
+ write(ERE32.r_info);
if (hasRelocationAddend())
- write(*F, uint32_t(Entry.Addend));
+ write(uint32_t(Entry.Addend));
}
}
}
-void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
- MCAsmLayout &Layout,
- SectionIndexMapTy &SectionIndexMap,
- const RelMapTy &RelMap) {
- MCContext &Ctx = Asm.getContext();
- MCDataFragment *F;
-
- unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
-
- // We construct .shstrtab, .symtab and .strtab in this order to match gnu as.
- const MCSectionELF *ShstrtabSection =
- Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0,
- SectionKind::getReadOnly());
- MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection);
- ShstrtabSD.setAlignment(1);
-
- const MCSectionELF *SymtabSection =
- Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
- SectionKind::getReadOnly(),
- EntrySize, "");
- MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
- SymtabSD.setAlignment(is64Bit() ? 8 : 4);
-
- const MCSectionELF *StrtabSection;
- StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0,
- SectionKind::getReadOnly());
- MCSectionData &StrtabSD = Asm.getOrCreateSectionData(*StrtabSection);
- StrtabSD.setAlignment(1);
-
- ComputeIndexMap(Asm, SectionIndexMap, RelMap);
-
- ShstrtabIndex = SectionIndexMap.lookup(ShstrtabSection);
- SymbolTableIndex = SectionIndexMap.lookup(SymtabSection);
- StringTableIndex = SectionIndexMap.lookup(StrtabSection);
-
- // Symbol table
- F = new MCDataFragment(&SymtabSD);
- WriteSymbolTable(F, Asm, Layout, SectionIndexMap);
-
- F = new MCDataFragment(&StrtabSD);
- F->getContents().append(StrTabBuilder.data().begin(),
- StrTabBuilder.data().end());
-
- F = new MCDataFragment(&ShstrtabSD);
-
- // Section header string table.
- for (auto it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(it->getSection());
- ShStrTabBuilder.add(Section.getSectionName());
- }
- ShStrTabBuilder.finalize(StringTableBuilder::ELF);
- F->getContents().append(ShStrTabBuilder.data().begin(),
- ShStrTabBuilder.data().end());
-}
-
-void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm,
- MCAsmLayout &Layout,
- GroupMapTy &GroupMap,
- RevGroupMapTy &RevGroupMap,
- SectionIndexMapTy &SectionIndexMap,
- const RelMapTy &RelMap) {
- MCContext &Ctx = Asm.getContext();
-
- // Build the groups
- for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end();
- it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(it->getSection());
- if (!(Section.getFlags() & ELF::SHF_GROUP))
- continue;
-
- const MCSymbol *SignatureSymbol = Section.getGroup();
- Asm.getOrCreateSymbolData(*SignatureSymbol);
- const MCSectionELF *&Group = RevGroupMap[SignatureSymbol];
- if (!Group) {
- Group = Ctx.CreateELFGroupSection();
- MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
- Data.setAlignment(4);
- MCDataFragment *F = new MCDataFragment(&Data);
- write(*F, uint32_t(ELF::GRP_COMDAT));
- }
- GroupMap[Group] = SignatureSymbol;
- }
-
- ComputeIndexMap(Asm, SectionIndexMap, RelMap);
-
- // Add sections to the groups
- for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end();
- it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(it->getSection());
- if (!(Section.getFlags() & ELF::SHF_GROUP))
- continue;
- const MCSectionELF *Group = RevGroupMap[Section.getGroup()];
- MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
- // FIXME: we could use the previous fragment
- MCDataFragment *F = new MCDataFragment(&Data);
- uint32_t Index = SectionIndexMap.lookup(&Section);
- write(*F, Index);
- }
+const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
+ const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
+ OS << StrTabBuilder.data();
+ return StrtabSection;
}
-void ELFObjectWriter::WriteSection(MCAssembler &Asm,
- const SectionIndexMapTy &SectionIndexMap,
- uint32_t GroupSymbolIndex,
- uint64_t Offset, uint64_t Size,
- uint64_t Alignment,
- const MCSectionELF &Section) {
+void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
+ uint32_t GroupSymbolIndex, uint64_t Offset,
+ uint64_t Size, const MCSectionELF &Section) {
uint64_t sh_link = 0;
uint64_t sh_info = 0;
switch(Section.getType()) {
- case ELF::SHT_DYNAMIC:
- sh_link = ShStrTabBuilder.getOffset(Section.getSectionName());
- sh_info = 0;
+ default:
+ // Nothing to do.
break;
+ case ELF::SHT_DYNAMIC:
+ llvm_unreachable("SHT_DYNAMIC in a relocatable object");
+
case ELF::SHT_REL:
case ELF::SHT_RELA: {
- const MCSectionELF *SymtabSection;
- const MCSectionELF *InfoSection;
- SymtabSection = Asm.getContext().getELFSection(".symtab", ELF::SHT_SYMTAB,
- 0,
- SectionKind::getReadOnly());
- sh_link = SectionIndexMap.lookup(SymtabSection);
+ sh_link = SymbolTableIndex;
assert(sh_link && ".symtab not found");
-
- // Remove ".rel" and ".rela" prefixes.
- unsigned SecNameLen = (Section.getType() == ELF::SHT_REL) ? 4 : 5;
- StringRef SectionName = Section.getSectionName().substr(SecNameLen);
- StringRef GroupName =
- Section.getGroup() ? Section.getGroup()->getName() : "";
-
- InfoSection = Asm.getContext().getELFSection(SectionName, ELF::SHT_PROGBITS,
- 0, SectionKind::getReadOnly(),
- 0, GroupName);
+ const MCSectionELF *InfoSection = Section.getAssociatedSection();
sh_info = SectionIndexMap.lookup(InfoSection);
break;
}
@@ -1525,286 +1131,221 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
sh_link = SymbolTableIndex;
break;
- case ELF::SHT_PROGBITS:
- case ELF::SHT_STRTAB:
- case ELF::SHT_NOBITS:
- case ELF::SHT_NOTE:
- case ELF::SHT_NULL:
- case ELF::SHT_ARM_ATTRIBUTES:
- case ELF::SHT_INIT_ARRAY:
- case ELF::SHT_FINI_ARRAY:
- case ELF::SHT_PREINIT_ARRAY:
- case ELF::SHT_X86_64_UNWIND:
- case ELF::SHT_MIPS_REGINFO:
- case ELF::SHT_MIPS_OPTIONS:
- case ELF::SHT_MIPS_ABIFLAGS:
- // Nothing to do.
- break;
-
case ELF::SHT_GROUP:
sh_link = SymbolTableIndex;
sh_info = GroupSymbolIndex;
break;
-
- default:
- llvm_unreachable("FIXME: sh_type value not supported!");
}
if (TargetObjectWriter->getEMachine() == ELF::EM_ARM &&
- Section.getType() == ELF::SHT_ARM_EXIDX) {
- StringRef SecName(Section.getSectionName());
- if (SecName == ".ARM.exidx") {
- sh_link = SectionIndexMap.lookup(
- Asm.getContext().getELFSection(".text",
- ELF::SHT_PROGBITS,
- ELF::SHF_EXECINSTR | ELF::SHF_ALLOC,
- SectionKind::getText()));
- } else if (SecName.startswith(".ARM.exidx")) {
- StringRef GroupName =
- Section.getGroup() ? Section.getGroup()->getName() : "";
- sh_link = SectionIndexMap.lookup(Asm.getContext().getELFSection(
- SecName.substr(sizeof(".ARM.exidx") - 1), ELF::SHT_PROGBITS,
- ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, SectionKind::getText(), 0,
- GroupName));
- }
- }
-
- WriteSecHdrEntry(ShStrTabBuilder.getOffset(Section.getSectionName()),
- Section.getType(),
- Section.getFlags(), 0, Offset, Size, sh_link, sh_info,
- Alignment, Section.getEntrySize());
-}
-
-bool ELFObjectWriter::IsELFMetaDataSection(const MCSectionData &SD) {
- return SD.getOrdinal() == ~UINT32_C(0) &&
- !SD.getSection().isVirtualSection();
-}
-
-uint64_t ELFObjectWriter::DataSectionSize(const MCSectionData &SD) {
- uint64_t Ret = 0;
- for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e;
- ++i) {
- const MCFragment &F = *i;
- assert(F.getKind() == MCFragment::FT_Data);
- Ret += cast<MCDataFragment>(F).getContents().size();
- }
- return Ret;
-}
-
-uint64_t ELFObjectWriter::GetSectionFileSize(const MCAsmLayout &Layout,
- const MCSectionData &SD) {
- if (IsELFMetaDataSection(SD))
- return DataSectionSize(SD);
- return Layout.getSectionFileSize(&SD);
-}
-
-uint64_t ELFObjectWriter::GetSectionAddressSize(const MCAsmLayout &Layout,
- const MCSectionData &SD) {
- if (IsELFMetaDataSection(SD))
- return DataSectionSize(SD);
- return Layout.getSectionAddressSize(&SD);
-}
+ Section.getType() == ELF::SHT_ARM_EXIDX)
+ sh_link = SectionIndexMap.lookup(Section.getAssociatedSection());
-void ELFObjectWriter::WriteDataSectionData(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCSectionELF &Section) {
- const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
-
- uint64_t Padding = OffsetToAlignment(OS.tell(), SD.getAlignment());
- WriteZeros(Padding);
-
- if (IsELFMetaDataSection(SD)) {
- for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e;
- ++i) {
- const MCFragment &F = *i;
- assert(F.getKind() == MCFragment::FT_Data);
- WriteBytes(cast<MCDataFragment>(F).getContents());
- }
- } else {
- Asm.writeSectionData(&SD, Layout);
- }
+ WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()),
+ Section.getType(), Section.getFlags(), 0, Offset, Size,
+ sh_link, sh_info, Section.getAlignment(),
+ Section.getEntrySize());
}
-void ELFObjectWriter::WriteSectionHeader(MCAssembler &Asm,
- const GroupMapTy &GroupMap,
- const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap,
- const SectionOffsetMapTy &SectionOffsetMap) {
- const unsigned NumSections = Asm.size() + 1;
-
- std::vector<const MCSectionELF*> Sections;
- Sections.resize(NumSections - 1);
-
- for (SectionIndexMapTy::const_iterator i=
- SectionIndexMap.begin(), e = SectionIndexMap.end(); i != e; ++i) {
- const std::pair<const MCSectionELF*, uint32_t> &p = *i;
- Sections[p.second - 1] = p.first;
- }
+void ELFObjectWriter::writeSectionHeader(
+ const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap,
+ const SectionOffsetsTy &SectionOffsets) {
+ const unsigned NumSections = SectionTable.size();
// Null section first.
uint64_t FirstSectionSize =
- NumSections >= ELF::SHN_LORESERVE ? NumSections : 0;
- uint32_t FirstSectionLink =
- ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0;
- WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0);
-
- for (unsigned i = 0; i < NumSections - 1; ++i) {
- const MCSectionELF &Section = *Sections[i];
- const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
+ (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;
+ WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0);
+
+ for (const MCSectionELF *Section : SectionTable) {
uint32_t GroupSymbolIndex;
- if (Section.getType() != ELF::SHT_GROUP)
+ unsigned Type = Section->getType();
+ if (Type != ELF::SHT_GROUP)
GroupSymbolIndex = 0;
else
- GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm,
- GroupMap.lookup(&Section));
-
- uint64_t Size = GetSectionAddressSize(Layout, SD);
-
- WriteSection(Asm, SectionIndexMap, GroupSymbolIndex,
- SectionOffsetMap.lookup(&Section), Size,
- SD.getAlignment(), Section);
- }
-}
+ GroupSymbolIndex = Section->getGroup()->getIndex();
-void ELFObjectWriter::ComputeSectionOrder(MCAssembler &Asm,
- std::vector<const MCSectionELF*> &Sections) {
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() == ELF::SHT_GROUP)
- Sections.push_back(&Section);
- }
-
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() != ELF::SHT_GROUP &&
- Section.getType() != ELF::SHT_REL &&
- Section.getType() != ELF::SHT_RELA)
- Sections.push_back(&Section);
- }
+ const std::pair<uint64_t, uint64_t> &Offsets =
+ SectionOffsets.find(Section)->second;
+ uint64_t Size;
+ if (Type == ELF::SHT_NOBITS)
+ Size = Layout.getSectionAddressSize(Section);
+ else
+ Size = Offsets.second - Offsets.first;
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(it->getSection());
- if (Section.getType() == ELF::SHT_REL ||
- Section.getType() == ELF::SHT_RELA)
- Sections.push_back(&Section);
+ writeSection(SectionIndexMap, GroupSymbolIndex, Offsets.first, Size,
+ *Section);
}
}
-void ELFObjectWriter::WriteObject(MCAssembler &Asm,
+void ELFObjectWriter::writeObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
- GroupMapTy GroupMap;
+ MCContext &Ctx = Asm.getContext();
+ MCSectionELF *StrtabSection =
+ Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
+ StringTableIndex = addToSectionTable(StrtabSection);
+
RevGroupMapTy RevGroupMap;
SectionIndexMapTy SectionIndexMap;
- unsigned NumUserSections = Asm.size();
+ std::map<const MCSymbol *, std::vector<const MCSectionELF *>> GroupMembers;
- CompressDebugSections(Asm, const_cast<MCAsmLayout &>(Layout));
+ // Write out the ELF header ...
+ writeHeader(Asm);
- DenseMap<const MCSectionELF*, const MCSectionELF*> RelMap;
- CreateRelocationSections(Asm, const_cast<MCAsmLayout&>(Layout), RelMap);
+ // ... then the sections ...
+ SectionOffsetsTy SectionOffsets;
+ std::vector<MCSectionELF *> Groups;
+ std::vector<MCSectionELF *> Relocations;
+ for (MCSection &Sec : Asm) {
+ MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
- const unsigned NumUserAndRelocSections = Asm.size();
- CreateIndexedSections(Asm, const_cast<MCAsmLayout&>(Layout), GroupMap,
- RevGroupMap, SectionIndexMap, RelMap);
- const unsigned AllSections = Asm.size();
- const unsigned NumIndexedSections = AllSections - NumUserAndRelocSections;
+ align(Section.getAlignment());
- unsigned NumRegularSections = NumUserSections + NumIndexedSections;
+ // Remember the offset into the file for this section.
+ uint64_t SecStart = OS.tell();
- // Compute symbol table information.
- computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap,
- NumRegularSections);
+ const MCSymbolELF *SignatureSymbol = Section.getGroup();
+ writeSectionData(Asm, Section, Layout);
- WriteRelocations(Asm, const_cast<MCAsmLayout&>(Layout), RelMap);
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd);
- CreateMetadataSections(const_cast<MCAssembler&>(Asm),
- const_cast<MCAsmLayout&>(Layout),
- SectionIndexMap,
- RelMap);
+ MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
- uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
- uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) :
- sizeof(ELF::Elf32_Ehdr);
- uint64_t FileOff = HeaderSize;
+ if (SignatureSymbol) {
+ Asm.registerSymbol(*SignatureSymbol);
+ unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
+ if (!GroupIdx) {
+ MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
+ GroupIdx = addToSectionTable(Group);
+ Group->setAlignment(4);
+ Groups.push_back(Group);
+ }
+ std::vector<const MCSectionELF *> &Members =
+ GroupMembers[SignatureSymbol];
+ Members.push_back(&Section);
+ if (RelSection)
+ Members.push_back(RelSection);
+ }
- std::vector<const MCSectionELF*> Sections;
- ComputeSectionOrder(Asm, Sections);
- unsigned NumSections = Sections.size();
- SectionOffsetMapTy SectionOffsetMap;
- for (unsigned i = 0; i < NumRegularSections + 1; ++i) {
- const MCSectionELF &Section = *Sections[i];
- const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
+ SectionIndexMap[&Section] = addToSectionTable(&Section);
+ if (RelSection) {
+ SectionIndexMap[RelSection] = addToSectionTable(RelSection);
+ Relocations.push_back(RelSection);
+ }
+ }
- FileOff = RoundUpToAlignment(FileOff, SD.getAlignment());
+ for (MCSectionELF *Group : Groups) {
+ align(Group->getAlignment());
// Remember the offset into the file for this section.
- SectionOffsetMap[&Section] = FileOff;
+ uint64_t SecStart = OS.tell();
+
+ const MCSymbol *SignatureSymbol = Group->getGroup();
+ assert(SignatureSymbol);
+ write(uint32_t(ELF::GRP_COMDAT));
+ for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) {
+ uint32_t SecIndex = SectionIndexMap.lookup(Member);
+ write(SecIndex);
+ }
- // Get the size of the section in the output file (including padding).
- FileOff += GetSectionFileSize(Layout, SD);
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
}
- FileOff = RoundUpToAlignment(FileOff, NaturalAlignment);
-
- const unsigned SectionHeaderOffset = FileOff - HeaderSize;
-
- uint64_t SectionHeaderEntrySize = is64Bit() ?
- sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr);
- FileOff += (NumSections + 1) * SectionHeaderEntrySize;
-
- for (unsigned i = NumRegularSections + 1; i < NumSections; ++i) {
- const MCSectionELF &Section = *Sections[i];
- const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
+ // Compute symbol table information.
+ computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets);
- FileOff = RoundUpToAlignment(FileOff, SD.getAlignment());
+ for (MCSectionELF *RelSection : Relocations) {
+ align(RelSection->getAlignment());
// Remember the offset into the file for this section.
- SectionOffsetMap[&Section] = FileOff;
+ uint64_t SecStart = OS.tell();
+
+ writeRelocations(Asm, *RelSection->getAssociatedSection());
- // Get the size of the section in the output file (including padding).
- FileOff += GetSectionFileSize(Layout, SD);
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
}
- // Write out the ELF header ...
- WriteHeader(Asm, SectionHeaderOffset, NumSections + 1);
+ {
+ uint64_t SecStart = OS.tell();
+ const MCSectionELF *Sec = createStringTable(Ctx);
+ uint64_t SecEnd = OS.tell();
+ SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
+ }
- // ... then the regular sections ...
- // + because of .shstrtab
- for (unsigned i = 0; i < NumRegularSections + 1; ++i)
- WriteDataSectionData(Asm, Layout, *Sections[i]);
+ uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
+ align(NaturalAlignment);
- uint64_t Padding = OffsetToAlignment(OS.tell(), NaturalAlignment);
- WriteZeros(Padding);
+ const unsigned SectionHeaderOffset = OS.tell();
// ... then the section header table ...
- WriteSectionHeader(Asm, GroupMap, Layout, SectionIndexMap,
- SectionOffsetMap);
+ writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);
+
+ uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE)
+ ? (uint16_t)ELF::SHN_UNDEF
+ : SectionTable.size() + 1;
+ if (sys::IsLittleEndianHost != IsLittleEndian)
+ sys::swapByteOrder(NumSections);
+ unsigned NumSectionsOffset;
+
+ if (is64Bit()) {
+ uint64_t Val = SectionHeaderOffset;
+ if (sys::IsLittleEndianHost != IsLittleEndian)
+ sys::swapByteOrder(Val);
+ OS.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
+ offsetof(ELF::Elf64_Ehdr, e_shoff));
+ NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
+ } else {
+ uint32_t Val = SectionHeaderOffset;
+ if (sys::IsLittleEndianHost != IsLittleEndian)
+ sys::swapByteOrder(Val);
+ OS.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
+ offsetof(ELF::Elf32_Ehdr, e_shoff));
+ NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
+ }
+ OS.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
+ NumSectionsOffset);
+}
- // ... and then the remaining sections ...
- for (unsigned i = NumRegularSections + 1; i < NumSections; ++i)
- WriteDataSectionData(Asm, Layout, *Sections[i]);
+bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
+ const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB,
+ bool InSet, bool IsPCRel) const {
+ const auto &SymA = cast<MCSymbolELF>(SA);
+ if (IsPCRel) {
+ assert(!InSet);
+ if (::isWeak(SymA))
+ return false;
+ }
+ return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
+ InSet, IsPCRel);
}
-bool
-ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
- const MCSymbolData &DataA,
- const MCFragment &FB,
- bool InSet,
- bool IsPCRel) const {
- if (DataA.getFlags() & ELF_STB_Weak || MCELF::GetType(DataA) == ELF::STT_GNU_IFUNC)
+bool ELFObjectWriter::isWeak(const MCSymbol &S) const {
+ const auto &Sym = cast<MCSymbolELF>(S);
+ if (::isWeak(Sym))
+ return true;
+
+ // It is invalid to replace a reference to a global in a comdat
+ // with a reference to a local since out of comdat references
+ // to a local are forbidden.
+ // We could try to return false for more cases, like the reference
+ // being in the same comdat or Sym being an alias to another global,
+ // but it is not clear if it is worth the effort.
+ if (Sym.getBinding() != ELF::STB_GLOBAL)
+ return false;
+
+ if (!Sym.isInSection())
return false;
- return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
- Asm, DataA, FB,InSet, IsPCRel);
+
+ const auto &Sec = cast<MCSectionELF>(Sym.getSection());
+ return Sec.getGroup();
}
MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
- raw_ostream &OS,
+ raw_pwrite_stream &OS,
bool IsLittleEndian) {
return new ELFObjectWriter(MOTW, OS, IsLittleEndian);
}
OpenPOWER on IntegriCloud