#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"
class ELFObjectWriter : public MCObjectWriter {
static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout);
- static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbol &Symbol,
+ static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
bool Used, bool Renamed);
- static bool isLocal(const MCSymbol &Symbol, bool IsUsedInReloc,
- bool IsSignature);
/// Helper struct for containing some precomputed information on symbols.
struct ELFSymbolData {
- const MCSymbol *Symbol;
+ const MCSymbolELF *Symbol;
uint32_t SectionIndex;
StringRef Name;
// Support lexicographic sorting.
bool operator<(const ELFSymbolData &RHS) const {
- unsigned LHSType = MCELF::GetType(*Symbol);
- unsigned RHSType = MCELF::GetType(*RHS.Symbol);
+ 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)
/// 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 MCSectionELF *, std::vector<ELFRelocationEntry>>
Relocations;
unsigned StringTableIndex;
// This holds the .symtab section index.
unsigned SymbolTableIndex;
- // This holds the .symtab_shndx section index.
- unsigned SymtabShndxSectionIndex = 0;
// Sections in the order they are to be output in the section table.
std::vector<const MCSectionELF *> SectionTable;
return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel);
}
+ void align(unsigned Alignment);
+
public:
ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
bool IsLittleEndian)
: MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
void reset() override {
- UsedInReloc.clear();
- WeakrefUsedInReloc.clear();
Renames.clear();
Relocations.clear();
StrTabBuilder.clear();
void WriteWord(uint64_t W) {
if (is64Bit())
- Write64(W);
+ write64(W);
else
- Write32(W);
+ write32(W);
}
template <typename T> void write(T Val) {
if (IsLittleEndian)
- support::endian::Writer<support::little>(OS).write(Val);
+ support::endian::Writer<support::little>(getStream()).write(Val);
else
- support::endian::Writer<support::big>(OS).write(Val);
+ support::endian::Writer<support::big>(getStream()).write(Val);
}
void writeHeader(const MCAssembler &Asm);
const MCSymbol *Sym, uint64_t C,
unsigned Type) const;
- void RecordRelocation(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;
const MCSectionELF *createStringTable(MCContext &Ctx);
- void ExecutePostLayoutBinding(MCAssembler &Asm,
+ void executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) override;
- void writeSectionHeader(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ void writeSectionHeader(const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
const SectionOffsetsTy &SectionOffsets);
void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec);
- bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
+ bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCSymbol &SymA,
const MCFragment &FB,
bool InSet,
bool isWeak(const MCSymbol &Sym) const override;
- void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+ 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);
};
}
+void ELFObjectWriter::align(unsigned Alignment) {
+ uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment);
+ WriteZeros(Padding);
+}
+
unsigned ELFObjectWriter::addToSectionTable(const MCSectionELF *Sec) {
SectionTable.push_back(Sec);
StrTabBuilder.add(Sec->getSectionName());
// emitWord method behaves differently for ELF32 and ELF64, writing
// 4 bytes in the former and 8 in the latter.
- WriteBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to 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(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
- Write16(0);
+ write16(0);
// e_shstrndx = Section # of '.shstrtab'
assert(StringTableIndex < ELF::SHN_LORESERVE);
- Write16(StringTableIndex);
+ write16(StringTableIndex);
}
uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
const MCAsmLayout &Layout) {
- MCSymbolData &Data = Sym.getData();
- if (Sym.isCommon() && Data.isExternal())
+ if (Sym.isCommon() && Sym.isExternal())
return Sym.getCommonAlignment();
uint64_t Res;
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 (const MCSymbol &Alias : Asm.symbols()) {
- MCSymbolData &OriginalData = Alias.getData();
-
+ 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 = Symbol.getData();
+ const auto &Symbol = cast<MCSymbolELF>(Ref->getSymbol());
StringRef AliasName = Alias.getName();
size_t Pos = AliasName.find('@');
// 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(Alias, MCELF::GetBinding(Symbol));
+ Alias.setExternal(Symbol.isExternal());
+ Alias.setBinding(Symbol.getBinding());
StringRef Rest = AliasName.substr(Pos);
if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer,
uint32_t StringIndex, ELFSymbolData &MSD,
const MCAsmLayout &Layout) {
-#ifndef NDEBUG
- MCSymbolData &OrigData = MSD.Symbol->getData();
- assert((!OrigData.getFragment() ||
- (OrigData.getFragment()->getParent() == &MSD.Symbol->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");
-#endif
- const MCSymbol *Base = Layout.getBaseSymbol(*MSD.Symbol);
+ 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 || MSD.Symbol->isCommon();
+ bool IsReserved = !Base || Symbol.isCommon();
// Binding and Type share the same byte as upper and lower nibbles
- uint8_t Binding = MCELF::GetBinding(*MSD.Symbol);
- uint8_t Type = MCELF::GetType(*MSD.Symbol);
- MCSymbolData *BaseSD = nullptr;
+ uint8_t Binding = Symbol.getBinding();
+ uint8_t Type = Symbol.getType();
if (Base) {
- BaseSD = &Base->getData();
- Type = mergeTypeForSet(Type, MCELF::GetType(*Base));
+ 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(*MSD.Symbol);
- uint8_t Other = MCELF::getOther(*MSD.Symbol)
- << (ELF_STO_Shift - ELF_STV_Shift);
- Other |= Visibility;
+ uint8_t Visibility = Symbol.getVisibility();
+ uint8_t Other = Symbol.getOther() | Visibility;
uint64_t Value = SymbolValue(*MSD.Symbol, Layout);
uint64_t Size = 0;
// allows us to omit some local symbols from the symbol table.
bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
const MCSymbolRefExpr *RefA,
- const MCSymbol *Sym, 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)
if (Sym->isUndefined())
return true;
- unsigned Binding = MCELF::GetBinding(*Sym);
+ unsigned Binding = Sym->getBinding();
switch(Binding) {
default:
llvm_unreachable("Invalid Binding");
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;
-
- if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
- return &Inner->getSymbol();
- 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 MCSymbol &Sym) {
- if (MCELF::GetType(Sym) == ELF::STT_GNU_IFUNC)
+static bool isWeak(const MCSymbolELF &Sym) {
+ if (Sym.getType() == ELF::STT_GNU_IFUNC)
return true;
- switch (MCELF::GetBinding(Sym)) {
+ switch (Sym.getBinding()) {
default:
llvm_unreachable("Unknown binding");
case ELF::STB_LOCAL:
}
}
-void ELFObjectWriter::RecordRelocation(MCAssembler &Asm,
+void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
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().reportFatalError(
// 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 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, SymA, C, Type);
const MCSection *SecA =
(SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
auto *ELFSec = cast_or_null<MCSectionELF>(SecA);
- const MCSymbol *SectionSymbol = ELFSec ? ELFSec->getBeginSymbol() : 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);
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);
}
bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout,
- const MCSymbol &Symbol, bool Used,
+ const MCSymbolELF &Symbol, bool Used,
bool Renamed) {
if (Symbol.isVariable()) {
const MCExpr *Expr = Symbol.getVariableValue();
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(Symbol) == ELF::STB_GLOBAL;
- if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal)
+ if (Symbol.isUndefined() && !Symbol.isBindingSet())
return false;
- if (MCELF::GetType(Symbol) == ELF::STT_SECTION)
- return true;
-
if (Symbol.isTemporary())
return false;
- return true;
-}
-
-bool ELFObjectWriter::isLocal(const MCSymbol &Symbol, bool IsUsedInReloc,
- bool IsSignature) {
- const MCSymbolData &Data = Symbol.getData();
- if (Data.isExternal())
+ if (Symbol.getType() == ELF::STT_SECTION)
return false;
- if (Symbol.isDefined())
- return true;
-
- if (IsUsedInReloc)
- return false;
-
- return IsSignature;
+ return true;
}
void ELFObjectWriter::computeSymbolTable(
SymtabSection->setAlignment(is64Bit() ? 8 : 4);
SymbolTableIndex = addToSectionTable(SymtabSection);
- uint64_t Padding =
- OffsetToAlignment(OS.tell(), SymtabSection->getAlignment());
- WriteZeros(Padding);
-
- uint64_t SecStart = OS.tell();
+ align(SymtabSection->getAlignment());
+ uint64_t SecStart = getStream().tell();
// The first entry is the undefined symbol entry.
Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
// Add the data for the symbols.
bool HasLargeSectionIndex = false;
- for (const MCSymbol &Symbol : Asm.symbols()) {
- bool Used = UsedInReloc.count(&Symbol);
- bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol);
- bool isSignature = RevGroupMap.count(&Symbol);
+ 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;
+ if (Symbol.isTemporary() && Symbol.isUndefined())
+ Ctx.reportFatalError(SMLoc(), "Undefined temporary");
+
ELFSymbolData MSD;
- MSD.Symbol = &Symbol;
+ MSD.Symbol = cast<MCSymbolELF>(&Symbol);
- // Undefined symbols are global, but this is the first place we
- // are able to set it.
- bool Local = isLocal(Symbol, Used, isSignature);
- if (!Local && MCELF::GetBinding(Symbol) == ELF::STB_LOCAL)
- MCELF::SetBinding(Symbol, ELF::STB_GLOBAL);
+ bool Local = Symbol.getBinding() == ELF::STB_LOCAL;
+ assert(Local || !Symbol.isTemporary());
if (Symbol.isAbsolute()) {
MSD.SectionIndex = ELF::SHN_ABS;
} else {
MSD.SectionIndex = ELF::SHN_UNDEF;
}
- if (!Used && WeakrefUsed)
- MCELF::SetBinding(Symbol, ELF::STB_WEAK);
} else {
const MCSectionELF &Section =
static_cast<const MCSectionELF &>(Symbol.getSection());
// seems that this information is not easily accessible from the
// ELFObjectWriter.
StringRef Name = Symbol.getName();
+ SmallString<32> 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);
}
// Sections have their own string table
- if (MCELF::GetType(Symbol) != ELF::STT_SECTION)
+ if (Symbol.getType() != ELF::STT_SECTION)
MSD.Name = StrTabBuilder.add(Name);
if (Local)
ExternalSymbolData.push_back(MSD);
}
+ // This holds the .symtab_shndx section index.
+ unsigned SymtabShndxSectionIndex = 0;
+
if (HasLargeSectionIndex) {
MCSectionELF *SymtabShndxSection =
Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
unsigned Index = FileNames.size() + 1;
for (ELFSymbolData &MSD : LocalSymbolData) {
- unsigned StringIndex = MCELF::GetType(*MSD.Symbol) == ELF::STT_SECTION
+ unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
? 0
: StrTabBuilder.getOffset(MSD.Name);
MSD.Symbol->setIndex(Index++);
unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);
MSD.Symbol->setIndex(Index++);
writeSymbol(Writer, StringIndex, MSD, Layout);
- assert(MCELF::GetBinding(*MSD.Symbol) != ELF::STB_LOCAL);
+ assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
}
- uint64_t SecEnd = OS.tell();
+ uint64_t SecEnd = getStream().tell();
SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
}
assert(SymtabShndxSectionIndex != 0);
- SecStart = OS.tell();
+ SecStart = getStream().tell();
const MCSectionELF *SymtabShndxSection =
SectionTable[SymtabShndxSectionIndex - 1];
for (uint32_t Index : ShndxIndexes)
write(Index);
- SecEnd = OS.tell();
+ SecEnd = getStream().tell();
SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
}
return RelaSection;
}
-static SmallVector<char, 128>
-getUncompressedData(const MCAsmLayout &Layout,
- const MCSection::FragmentListType &Fragments) {
- SmallVector<char, 128> UncompressedData;
- for (const MCFragment &F : Fragments) {
- const SmallVectorImpl<char> *Contents;
- switch (F.getKind()) {
- case MCFragment::FT_Data:
- Contents = &cast<MCDataFragment>(F).getContents();
- break;
- case MCFragment::FT_Dwarf:
- Contents = &cast<MCDwarfLineAddrFragment>(F).getContents();
- break;
- case MCFragment::FT_DwarfFrame:
- Contents = &cast<MCDwarfCallFrameFragment>(F).getContents();
- break;
- default:
- llvm_unreachable(
- "Not expecting any other fragment types in a debug_* section");
- }
- UncompressedData.append(Contents->begin(), Contents->end());
- }
- return UncompressedData;
-}
-
// Include the debug info compression header:
// "ZLIB" followed by 8 bytes representing the uncompressed size of the section,
// useful for consumers to preallocate a buffer to decompress into.
return;
}
- // Gather the uncompressed data from all the fragments.
- const MCSection::FragmentListType &Fragments = Section.getFragmentList();
- SmallVector<char, 128> UncompressedData =
- getUncompressedData(Layout, Fragments);
+ SmallVector<char, 128> UncompressedData;
+ raw_svector_ostream VecOS(UncompressedData);
+ raw_pwrite_stream &OldStream = getStream();
+ setStream(VecOS);
+ Asm.writeSectionData(&Section, Layout);
+ setStream(OldStream);
SmallVector<char, 128> CompressedContents;
zlib::Status Success = zlib::compress(
StringRef(UncompressedData.data(), UncompressedData.size()),
CompressedContents);
if (Success != zlib::StatusOK) {
- Asm.writeSectionData(&Section, Layout);
+ getStream() << UncompressedData;
return;
}
if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) {
- Asm.writeSectionData(&Section, Layout);
+ getStream() << UncompressedData;
return;
}
Asm.getContext().renameELFSection(&Section,
(".z" + SectionName.drop_front(1)).str());
- OS << CompressedContents;
+ getStream() << CompressedContents;
}
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
}
const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
- OS << StrTabBuilder.data();
+ getStream() << StrTabBuilder.data();
return StrtabSection;
}
}
void ELFObjectWriter::writeSectionHeader(
- const MCAssembler &Asm, const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap,
+ const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap,
const SectionOffsetsTy &SectionOffsets) {
const unsigned NumSections = SectionTable.size();
}
}
-void ELFObjectWriter::WriteObject(MCAssembler &Asm,
+void ELFObjectWriter::writeObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
MCContext &Ctx = Asm.getContext();
MCSectionELF *StrtabSection =
for (MCSection &Sec : Asm) {
MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
- uint64_t Padding = OffsetToAlignment(OS.tell(), Section.getAlignment());
- WriteZeros(Padding);
+ align(Section.getAlignment());
// Remember the offset into the file for this section.
- uint64_t SecStart = OS.tell();
+ uint64_t SecStart = getStream().tell();
- const MCSymbol *SignatureSymbol = Section.getGroup();
+ const MCSymbolELF *SignatureSymbol = Section.getGroup();
writeSectionData(Asm, Section, Layout);
- uint64_t SecEnd = OS.tell();
+ uint64_t SecEnd = getStream().tell();
SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd);
MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
Group->setAlignment(4);
Groups.push_back(Group);
}
- GroupMembers[SignatureSymbol].push_back(&Section);
+ std::vector<const MCSectionELF *> &Members =
+ GroupMembers[SignatureSymbol];
+ Members.push_back(&Section);
if (RelSection)
- GroupMembers[SignatureSymbol].push_back(RelSection);
+ Members.push_back(RelSection);
}
SectionIndexMap[&Section] = addToSectionTable(&Section);
}
for (MCSectionELF *Group : Groups) {
- uint64_t Padding = OffsetToAlignment(OS.tell(), Group->getAlignment());
- WriteZeros(Padding);
+ align(Group->getAlignment());
// Remember the offset into the file for this section.
- uint64_t SecStart = OS.tell();
+ uint64_t SecStart = getStream().tell();
const MCSymbol *SignatureSymbol = Group->getGroup();
assert(SignatureSymbol);
write(SecIndex);
}
- uint64_t SecEnd = OS.tell();
+ uint64_t SecEnd = getStream().tell();
SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
}
computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets);
for (MCSectionELF *RelSection : Relocations) {
- uint64_t Padding = OffsetToAlignment(OS.tell(), RelSection->getAlignment());
- WriteZeros(Padding);
+ align(RelSection->getAlignment());
// Remember the offset into the file for this section.
- uint64_t SecStart = OS.tell();
+ uint64_t SecStart = getStream().tell();
writeRelocations(Asm, *RelSection->getAssociatedSection());
- uint64_t SecEnd = OS.tell();
+ uint64_t SecEnd = getStream().tell();
SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
}
{
- uint64_t SecStart = OS.tell();
+ uint64_t SecStart = getStream().tell();
const MCSectionELF *Sec = createStringTable(Ctx);
- uint64_t SecEnd = OS.tell();
+ uint64_t SecEnd = getStream().tell();
SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
}
uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
- uint64_t Padding = OffsetToAlignment(OS.tell(), NaturalAlignment);
- WriteZeros(Padding);
+ align(NaturalAlignment);
- const unsigned SectionHeaderOffset = OS.tell();
+ const unsigned SectionHeaderOffset = getStream().tell();
// ... then the section header table ...
- writeSectionHeader(Asm, Layout, SectionIndexMap, SectionOffsets);
+ writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);
uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE)
? (uint16_t)ELF::SHN_UNDEF
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));
+ getStream().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));
+ getStream().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);
+ getStream().pwrite(reinterpret_cast<char *>(&NumSections),
+ sizeof(NumSections), NumSectionsOffset);
}
-bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
- const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
+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,
+ return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
InSet, IsPCRel);
}
-bool ELFObjectWriter::isWeak(const MCSymbol &Sym) const {
+bool ELFObjectWriter::isWeak(const MCSymbol &S) const {
+ const auto &Sym = cast<MCSymbolELF>(S);
if (::isWeak(Sym))
return true;
// 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 (MCELF::GetBinding(Sym) != ELF::STB_GLOBAL)
+ if (Sym.getBinding() != ELF::STB_GLOBAL)
return false;
if (!Sym.isInSection())