aboutsummaryrefslogtreecommitdiff
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.cpp1230
1 files changed, 725 insertions, 505 deletions
diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
index 9899bb2eac22..5779b27a2c40 100644
--- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
@@ -12,12 +12,12 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCELFObjectWriter.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
@@ -28,7 +28,10 @@
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Compression.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include <vector>
@@ -38,16 +41,76 @@ 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 SymbolTableWriter {
+ MCAssembler &Asm;
+ FragmentWriter &FWriter;
+ bool Is64Bit;
+ SectionIndexMapTy &SectionIndexMap;
+
+ // The symbol .symtab fragment we are writting to.
+ MCDataFragment *SymtabF;
+
+ // .symtab_shndx fragment we are writting to.
+ MCDataFragment *ShndxF;
+
+ // The numbel of symbols written so far.
+ unsigned NumWritten;
+
+ void createSymtabShndx();
+
+ template <typename T> void write(MCDataFragment &F, T Value);
+
+public:
+ SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit,
+ SectionIndexMapTy &SectionIndexMap,
+ MCDataFragment *SymtabF);
+
+ 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.
+ bool UseSymbol; // Relocate with a symbol, not the section.
+ union {
+ const MCSymbol *Symbol; // The symbol to relocate with.
+ const MCSectionData *Section; // The section 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), UseSymbol(true), Symbol(Symbol), Type(Type),
+ Addend(Addend) {}
+
+ ELFRelocationEntry(uint64_t Offset, const MCSectionData *Section,
+ unsigned Type, uint64_t Addend)
+ : Offset(Offset), UseSymbol(false), Section(Section), Type(Type),
+ Addend(Addend) {}
+};
+
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 MCAssembler &Asm, const MCSymbolData &Data,
+ static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolData &Data,
bool Used, bool Renamed);
- static bool isLocal(const MCSymbolData &Data, bool isSignature,
- bool isUsedInReloc);
+ 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,
@@ -70,30 +133,30 @@ class ELFObjectWriter : public MCObjectWriter {
MCSymbolData *SymbolData;
uint64_t StringIndex;
uint32_t SectionIndex;
+ StringRef Name;
// Support lexicographic sorting.
bool operator<(const ELFSymbolData &RHS) const {
- return SymbolData->getSymbol().getName() <
- RHS.SymbolData->getSymbol().getName();
+ return Name < RHS.Name;
}
};
/// The target specific ELF writer instance.
- llvm::OwningPtr<MCELFObjectTargetWriter> TargetObjectWriter;
+ std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter;
SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc;
DenseMap<const MCSymbol *, const MCSymbol *> Renames;
- llvm::DenseMap<const MCSectionData*,
- std::vector<ELFRelocationEntry> > Relocations;
- DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
+ llvm::DenseMap<const MCSectionData *, std::vector<ELFRelocationEntry>>
+ Relocations;
+ StringTableBuilder ShStrTabBuilder;
/// @}
/// @name Symbol Table Data
/// @{
- SmallString<256> StringTable;
+ StringTableBuilder StrTabBuilder;
std::vector<uint64_t> FileSymbolData;
std::vector<ELFSymbolData> LocalSymbolData;
std::vector<ELFSymbolData> ExternalSymbolData;
@@ -103,8 +166,6 @@ class ELFObjectWriter : public MCObjectWriter {
bool NeedsGOT;
- bool NeedsSymtabShndx;
-
// This holds the symbol table index of the last local symbol.
unsigned LastLocalSymbolIndex;
// This holds the .strtab section index.
@@ -115,45 +176,21 @@ class ELFObjectWriter : public MCObjectWriter {
unsigned ShstrtabIndex;
- const MCSymbol *SymbolToReloc(const MCAssembler &Asm,
- const MCValue &Target,
- const MCFragment &F,
- const MCFixup &Fixup,
- bool IsPCRel) const;
-
// TargetObjectWriter wrappers.
- const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
- const MCValue &Target,
- const MCFragment &F,
- const MCFixup &Fixup,
- bool IsPCRel) const {
- return TargetObjectWriter->ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
- }
- const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
- const MCFixup &Fixup,
- bool IsPCRel) const {
- return TargetObjectWriter->undefinedExplicitRelSym(Target, Fixup,
- IsPCRel);
- }
-
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
bool hasRelocationAddend() const {
return TargetObjectWriter->hasRelocationAddend();
}
unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
- bool IsPCRel, bool IsRelocWithSymbol,
- int64_t Addend) const {
- return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel,
- IsRelocWithSymbol, Addend);
+ bool IsPCRel) const {
+ return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel);
}
public:
- ELFObjectWriter(MCELFObjectTargetWriter *MOTW,
- raw_ostream &_OS, bool IsLittleEndian)
- : MCObjectWriter(_OS, IsLittleEndian),
- TargetObjectWriter(MOTW),
- NeedsGOT(false), NeedsSymtabShndx(false) {
- }
+ ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &_OS,
+ bool IsLittleEndian)
+ : MCObjectWriter(_OS, IsLittleEndian), FWriter(IsLittleEndian),
+ TargetObjectWriter(MOTW), NeedsGOT(false) {}
virtual ~ELFObjectWriter();
@@ -164,96 +201,30 @@ class ELFObjectWriter : public MCObjectWriter {
Write32(W);
}
- void StringLE16(char *buf, uint16_t Value) {
- buf[0] = char(Value >> 0);
- buf[1] = char(Value >> 8);
- }
-
- void StringLE32(char *buf, uint32_t Value) {
- StringLE16(buf, uint16_t(Value >> 0));
- StringLE16(buf + 2, uint16_t(Value >> 16));
- }
-
- void StringLE64(char *buf, uint64_t Value) {
- StringLE32(buf, uint32_t(Value >> 0));
- StringLE32(buf + 4, uint32_t(Value >> 32));
- }
-
- void StringBE16(char *buf ,uint16_t Value) {
- buf[0] = char(Value >> 8);
- buf[1] = char(Value >> 0);
- }
-
- void StringBE32(char *buf, uint32_t Value) {
- StringBE16(buf, uint16_t(Value >> 16));
- StringBE16(buf + 2, uint16_t(Value >> 0));
- }
-
- void StringBE64(char *buf, uint64_t Value) {
- StringBE32(buf, uint32_t(Value >> 32));
- StringBE32(buf + 4, uint32_t(Value >> 0));
- }
-
- void String8(MCDataFragment &F, uint8_t Value) {
- char buf[1];
- buf[0] = Value;
- F.getContents().append(&buf[0], &buf[1]);
- }
-
- void String16(MCDataFragment &F, uint16_t Value) {
- char buf[2];
- if (isLittleEndian())
- StringLE16(buf, Value);
- else
- StringBE16(buf, Value);
- F.getContents().append(&buf[0], &buf[2]);
- }
-
- void String32(MCDataFragment &F, uint32_t Value) {
- char buf[4];
- if (isLittleEndian())
- StringLE32(buf, Value);
- else
- StringBE32(buf, Value);
- F.getContents().append(&buf[0], &buf[4]);
- }
-
- void String64(MCDataFragment &F, uint64_t Value) {
- char buf[8];
- if (isLittleEndian())
- StringLE64(buf, Value);
- else
- StringBE64(buf, Value);
- F.getContents().append(&buf[0], &buf[8]);
+ template <typename T> void write(MCDataFragment &F, T Value) {
+ FWriter.write(F, Value);
}
void WriteHeader(const MCAssembler &Asm,
uint64_t SectionDataSize,
unsigned NumberOfSections);
- void WriteSymbolEntry(MCDataFragment *SymtabF,
- MCDataFragment *ShndxF,
- uint64_t name, uint8_t info,
- uint64_t value, uint64_t size,
- uint8_t other, uint32_t shndx,
- bool Reserved);
-
- void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
- ELFSymbolData &MSD,
+ void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout);
- typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy;
- void WriteSymbolTable(MCDataFragment *SymtabF,
- MCDataFragment *ShndxF,
- const MCAssembler &Asm,
+ void WriteSymbolTable(MCDataFragment *SymtabF, MCAssembler &Asm,
const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap);
+ SectionIndexMapTy &SectionIndexMap);
+
+ bool shouldRelocateWithSymbol(const MCAssembler &Asm,
+ const MCSymbolRefExpr *RefA,
+ const MCSymbolData *SD, uint64_t C,
+ unsigned Type) const;
- virtual void RecordRelocation(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue);
+ void RecordRelocation(const 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);
@@ -267,13 +238,13 @@ class ELFObjectWriter : public MCObjectWriter {
// Map from a section to its offset
typedef DenseMap<const MCSectionELF*, uint64_t> SectionOffsetMapTy;
- /// ComputeSymbolTable - Compute the symbol table data
+ /// 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,
+ void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
RevGroupMapTy RevGroupMap,
unsigned NumRegularSections);
@@ -285,6 +256,8 @@ class ELFObjectWriter : public MCObjectWriter {
void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout,
RelMapTy &RelMap);
+ void CompressDebugSections(MCAssembler &Asm, MCAsmLayout &Layout);
+
void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout,
const RelMapTy &RelMap);
@@ -300,8 +273,8 @@ class ELFObjectWriter : public MCObjectWriter {
SectionIndexMapTy &SectionIndexMap,
const RelMapTy &RelMap);
- virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout);
+ void ExecutePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) override;
void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap,
const MCAsmLayout &Layout,
@@ -320,14 +293,14 @@ class ELFObjectWriter : public MCObjectWriter {
MCDataFragment *F,
const MCSectionData *SD);
- virtual bool
+ bool
IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCSymbolData &DataA,
const MCFragment &FB,
bool InSet,
- bool IsPCRel) const;
+ bool IsPCRel) const override;
- virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
+ void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
void WriteSection(MCAssembler &Asm,
const SectionIndexMapTy &SectionIndexMap,
uint32_t GroupSymbolIndex,
@@ -336,6 +309,88 @@ class ELFObjectWriter : public MCObjectWriter {
};
}
+FragmentWriter::FragmentWriter(bool IsLittleEndian)
+ : IsLittleEndian(IsLittleEndian) {}
+
+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));
+}
+
+void SymbolTableWriter::createSymtabShndx() {
+ if (ShndxF)
+ 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));
+}
+
+template <typename T>
+void SymbolTableWriter::write(MCDataFragment &F, T Value) {
+ FWriter.write(F, 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) {}
+
+void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
+ uint64_t size, uint8_t other,
+ uint32_t shndx, bool Reserved) {
+ bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved;
+
+ if (LargeIndex)
+ createSymtabShndx();
+
+ if (ShndxF) {
+ if (LargeIndex)
+ write(*ShndxF, shndx);
+ else
+ write(*ShndxF, uint32_t(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
+ } 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
+ }
+
+ ++NumWritten;
+}
+
bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
const MCFixupKindInfo &FKI =
Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind);
@@ -431,67 +486,19 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
Write16(ShstrtabIndex);
}
-void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF,
- MCDataFragment *ShndxF,
- uint64_t name,
- uint8_t info, uint64_t value,
- uint64_t size, uint8_t other,
- uint32_t shndx,
- bool Reserved) {
- if (ShndxF) {
- if (shndx >= ELF::SHN_LORESERVE && !Reserved)
- String32(*ShndxF, shndx);
- else
- String32(*ShndxF, 0);
- }
-
- uint16_t Index = (shndx >= ELF::SHN_LORESERVE && !Reserved) ?
- uint16_t(ELF::SHN_XINDEX) : shndx;
-
- if (is64Bit()) {
- String32(*SymtabF, name); // st_name
- String8(*SymtabF, info); // st_info
- String8(*SymtabF, other); // st_other
- String16(*SymtabF, Index); // st_shndx
- String64(*SymtabF, value); // st_value
- String64(*SymtabF, size); // st_size
- } else {
- String32(*SymtabF, name); // st_name
- String32(*SymtabF, value); // st_value
- String32(*SymtabF, size); // st_size
- String8(*SymtabF, info); // st_info
- String8(*SymtabF, other); // st_other
- String16(*SymtabF, Index); // st_shndx
- }
-}
-
uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,
const MCAsmLayout &Layout) {
if (Data.isCommon() && Data.isExternal())
return Data.getCommonAlignment();
- const MCSymbol &Symbol = Data.getSymbol();
-
- if (Symbol.isAbsolute() && Symbol.isVariable()) {
- if (const MCExpr *Value = Symbol.getVariableValue()) {
- int64_t IntValue;
- if (Value->EvaluateAsAbsolute(IntValue, Layout))
- return (uint64_t)IntValue;
- }
- }
-
- if (!Symbol.isInSection())
+ uint64_t Res;
+ if (!Layout.getSymbolOffset(&Data, Res))
return 0;
+ if (Layout.getAssembler().isThumbFunc(&Data.getSymbol()))
+ Res |= 1;
- if (Data.getFragment()) {
- if (Data.getFlags() & ELF_Other_ThumbFunc)
- return Layout.getSymbolOffset(&Data)+1;
- else
- return Layout.getSymbolOffset(&Data);
- }
-
- return 0;
+ return Res;
}
void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
@@ -499,15 +506,17 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
// The presence of symbol versions causes undefined symbols and
// versions declared with @@@ to be renamed.
- for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
- ie = Asm.symbol_end(); it != ie; ++it) {
- const MCSymbol &Alias = it->getSymbol();
- const MCSymbol &Symbol = Alias.AliasedSymbol();
- MCSymbolData &SD = Asm.getSymbolData(Symbol);
+ for (MCSymbolData &OriginalData : Asm.symbols()) {
+ const MCSymbol &Alias = OriginalData.getSymbol();
// Not an alias.
- if (&Symbol == &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);
StringRef AliasName = Alias.getName();
size_t Pos = AliasName.find('@');
@@ -516,8 +525,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.
- it->setExternal(SD.isExternal());
- MCELF::SetBinding(*it, MCELF::GetBinding(SD));
+ OriginalData.setExternal(SD.isExternal());
+ MCELF::SetBinding(OriginalData, MCELF::GetBinding(SD));
StringRef Rest = AliasName.substr(Pos);
if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
@@ -532,35 +541,77 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
}
}
-void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
- MCDataFragment *ShndxF,
- ELFSymbolData &MSD,
+static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
+ uint8_t Type = newType;
+
+ // Propagation rules:
+ // IFUNC > FUNC > OBJECT > NOTYPE
+ // TLS_OBJECT > OBJECT > NOTYPE
+ //
+ // dont let the new type degrade the old type
+ switch (origType) {
+ default:
+ break;
+ case ELF::STT_GNU_IFUNC:
+ if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT ||
+ Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS)
+ Type = ELF::STT_GNU_IFUNC;
+ break;
+ case ELF::STT_FUNC:
+ if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||
+ Type == ELF::STT_TLS)
+ Type = ELF::STT_FUNC;
+ break;
+ case ELF::STT_OBJECT:
+ if (Type == ELF::STT_NOTYPE)
+ Type = ELF::STT_OBJECT;
+ break;
+ case ELF::STT_TLS:
+ if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||
+ Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC)
+ Type = ELF::STT_TLS;
+ break;
+ }
+
+ return Type;
+}
+
+void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout) {
MCSymbolData &OrigData = *MSD.SymbolData;
- MCSymbolData &Data =
- Layout.getAssembler().getSymbolData(OrigData.getSymbol().AliasedSymbol());
+ assert((!OrigData.getFragment() ||
+ (&OrigData.getFragment()->getParent()->getSection() ==
+ &OrigData.getSymbol().getSection())) &&
+ "The symbol's section doesn't match the fragment's symbol");
+ const MCSymbol *Base = Layout.getBaseSymbol(OrigData.getSymbol());
- bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() ||
- Data.getSymbol().isVariable();
+ // This has to be in sync with when computeSymbolTable uses SHN_ABS or
+ // SHN_COMMON.
+ bool IsReserved = !Base || OrigData.isCommon();
// Binding and Type share the same byte as upper and lower nibbles
uint8_t Binding = MCELF::GetBinding(OrigData);
- uint8_t Type = MCELF::GetType(Data);
+ uint8_t Type = MCELF::GetType(OrigData);
+ MCSymbolData *BaseSD = nullptr;
+ if (Base) {
+ BaseSD = &Layout.getAssembler().getSymbolData(*Base);
+ Type = mergeTypeForSet(Type, MCELF::GetType(*BaseSD));
+ }
uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift);
// 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_Other_Shift - ELF_STV_Shift);
+ uint8_t Other = MCELF::getOther(OrigData) << (ELF_STO_Shift - ELF_STV_Shift);
Other |= Visibility;
- uint64_t Value = SymbolValue(Data, Layout);
+ uint64_t Value = SymbolValue(OrigData, Layout);
uint64_t Size = 0;
- assert(!(Data.isCommon() && !Data.isExternal()));
+ const MCExpr *ESize = OrigData.getSize();
+ if (!ESize && Base)
+ ESize = BaseSD->getSize();
- const MCExpr *ESize = Data.getSize();
if (ESize) {
int64_t Res;
if (!ESize->EvaluateAsAbsolute(Res, Layout))
@@ -569,28 +620,27 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
}
// Write out the symbol table entry
- WriteSymbolEntry(SymtabF, ShndxF, MSD.StringIndex, Info, Value,
- Size, Other, MSD.SectionIndex, IsReserved);
+ Writer.writeSymbol(MSD.StringIndex, Info, Value, Size, Other,
+ MSD.SectionIndex, IsReserved);
}
void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
- MCDataFragment *ShndxF,
- const MCAssembler &Asm,
+ MCAssembler &Asm,
const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap) {
+ SectionIndexMapTy &SectionIndexMap) {
// The string table must be emitted first because we need the index
// into the string table for all the symbol names.
- assert(StringTable.size() && "Missing string table");
// 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.
- WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false);
+ Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
for (unsigned i = 0, e = FileSymbolData.size(); i != e; ++i) {
- WriteSymbolEntry(SymtabF, ShndxF, FileSymbolData[i],
- ELF::STT_FILE | ELF::STB_LOCAL, 0, 0,
- ELF::STV_DEFAULT, ELF::SHN_ABS, true);
+ Writer.writeSymbol(FileSymbolData[i], ELF::STT_FILE | ELF::STB_LOCAL, 0, 0,
+ ELF::STV_DEFAULT, ELF::SHN_ABS, true);
}
// Write the symbol table entries.
@@ -598,7 +648,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = LocalSymbolData[i];
- WriteSymbol(SymtabF, ShndxF, MSD, Layout);
+ WriteSymbol(Writer, MSD, Layout);
}
// Write out a symbol table entry for each regular section.
@@ -612,9 +662,8 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
Section.getType() == ELF::SHT_SYMTAB ||
Section.getType() == ELF::SHT_SYMTAB_SHNDX)
continue;
- WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0,
- ELF::STV_DEFAULT, SectionIndexMap.lookup(&Section),
- false);
+ Writer.writeSymbol(0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT,
+ SectionIndexMap.lookup(&Section), false);
LastLocalSymbolIndex++;
}
@@ -624,7 +673,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
assert(((Data.getFlags() & ELF_STB_Global) ||
(Data.getFlags() & ELF_STB_Weak)) &&
"External symbol requires STB_GLOBAL or STB_WEAK flag");
- WriteSymbol(SymtabF, ShndxF, MSD, Layout);
+ WriteSymbol(Writer, MSD, Layout);
if (MCELF::GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
@@ -632,162 +681,245 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = UndefinedSymbolData[i];
MCSymbolData &Data = *MSD.SymbolData;
- WriteSymbol(SymtabF, ShndxF, MSD, Layout);
+ WriteSymbol(Writer, MSD, Layout);
if (MCELF::GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
}
-const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
- const MCValue &Target,
- const MCFragment &F,
- const MCFixup &Fixup,
- bool IsPCRel) const {
- const MCSymbol &Symbol = Target.getSymA()->getSymbol();
- const MCSymbol &ASymbol = Symbol.AliasedSymbol();
- const MCSymbol *Renamed = Renames.lookup(&Symbol);
- const MCSymbolData &SD = Asm.getSymbolData(Symbol);
-
- if (ASymbol.isUndefined()) {
- if (Renamed)
- return Renamed;
- return undefinedExplicitRelSym(Target, Fixup, IsPCRel);
- }
+// It is always valid to create a relocation with a symbol. It is preferable
+// to use a relocation with a section if that is possible. Using the section
+// 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,
+ unsigned Type) const {
+ // A PCRel relocation to an absolute value has no symbol (or section). We
+ // represent that with a relocation to a null section.
+ if (!RefA)
+ return false;
- if (SD.isExternal()) {
- if (Renamed)
- return Renamed;
- return &Symbol;
- }
+ MCSymbolRefExpr::VariantKind Kind = RefA->getKind();
+ switch (Kind) {
+ default:
+ break;
+ // The .odp creation emits a relocation against the symbol ".TOC." which
+ // create a R_PPC64_TOC relocation. However the relocation symbol name
+ // in final object creation should be NULL, since the symbol does not
+ // really exist, it is just the reference to TOC base for the current
+ // object file. Since the symbol is undefined, returning false results
+ // in a relocation with a null section which is the desired result.
+ case MCSymbolRefExpr::VK_PPC_TOCBASE:
+ return false;
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(ASymbol.getSection());
- const SectionKind secKind = Section.getKind();
+ // These VariantKind cause the relocation to refer to something other than
+ // the symbol itself, like a linker generated table. Since the address of
+ // symbol is not relevant, we cannot replace the symbol with the
+ // section and patch the difference in the addend.
+ case MCSymbolRefExpr::VK_GOT:
+ case MCSymbolRefExpr::VK_PLT:
+ case MCSymbolRefExpr::VK_GOTPCREL:
+ case MCSymbolRefExpr::VK_Mips_GOT:
+ case MCSymbolRefExpr::VK_PPC_GOT_LO:
+ case MCSymbolRefExpr::VK_PPC_GOT_HI:
+ case MCSymbolRefExpr::VK_PPC_GOT_HA:
+ return true;
+ }
- if (secKind.isBSS())
- return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
+ // 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())
+ return true;
- if (secKind.isThreadLocal()) {
- if (Renamed)
- return Renamed;
- return &Symbol;
+ unsigned Binding = MCELF::GetBinding(*SD);
+ switch(Binding) {
+ default:
+ llvm_unreachable("Invalid Binding");
+ case ELF::STB_LOCAL:
+ break;
+ case ELF::STB_WEAK:
+ // If the symbol is weak, it might be overridden by a symbol in another
+ // file. The relocation has to point to the symbol so that the linker
+ // can update it.
+ return true;
+ case ELF::STB_GLOBAL:
+ // Global ELF symbols can be preempted by the dynamic linker. The relocation
+ // has to point to the symbol for a reason analogous to the STB_WEAK case.
+ return true;
}
- MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind();
- const MCSectionELF &Sec2 =
- static_cast<const MCSectionELF&>(F.getParent()->getSection());
-
- if (&Sec2 != &Section &&
- (Kind == MCSymbolRefExpr::VK_PLT ||
- Kind == MCSymbolRefExpr::VK_GOTPCREL ||
- Kind == MCSymbolRefExpr::VK_GOTOFF)) {
- if (Renamed)
- return Renamed;
- return &Symbol;
- }
+ // If a relocation points to a mergeable section, we have to be careful.
+ // If the offset is zero, a relocation with the section will encode the
+ // same information. With a non-zero offset, the situation is different.
+ // For example, a relocation can point 42 bytes past the end of a string.
+ // 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());
+ unsigned Flags = Sec.getFlags();
+ if (Flags & ELF::SHF_MERGE) {
+ if (C != 0)
+ return true;
- if (Section.getFlags() & ELF::SHF_MERGE) {
- if (Target.getConstant() == 0)
- return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
- if (Renamed)
- return Renamed;
- return &Symbol;
+ // It looks like gold has a bug (http://sourceware.org/PR16794) and can
+ // only handle section relocations to mergeable sections if using RELA.
+ if (!hasRelocationAddend())
+ return true;
}
- return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
+ // Most TLS relocations use a got, so they need the symbol. Even those that
+ // are just an offset (@tpoff), require a symbol in some linkers (gold,
+ // but not bfd ld).
+ if (Flags & ELF::SHF_TLS)
+ return true;
+
+ // If the symbol is a thumb function the final relocation must set the lowest
+ // 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))
+ return true;
+ if (TargetObjectWriter->needsRelocateWithSymbol(*SD, 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;
+
+ if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
+ return &Inner->getSymbol();
+ return nullptr;
+}
void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup,
MCValue Target,
+ bool &IsPCRel,
uint64_t &FixedValue) {
- int64_t Addend = 0;
- int Index = 0;
- int64_t Value = Target.getConstant();
- const MCSymbol *RelocSymbol = NULL;
-
- bool IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
- if (!Target.isAbsolute()) {
- const MCSymbol &Symbol = Target.getSymA()->getSymbol();
- const MCSymbol &ASymbol = Symbol.AliasedSymbol();
- RelocSymbol = SymbolToReloc(Asm, Target, *Fragment, Fixup, IsPCRel);
-
- if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
- const MCSymbol &SymbolB = RefB->getSymbol();
- MCSymbolData &SDB = Asm.getSymbolData(SymbolB);
- IsPCRel = true;
-
- // Offset of the symbol in the section
- int64_t a = Layout.getSymbolOffset(&SDB);
-
- // Offset of the relocation in the section
- int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
- Value += b - a;
- }
+ const MCSectionData *FixupSection = Fragment->getParent();
+ uint64_t C = Target.getConstant();
+ uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
+
+ if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
+ assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
+ "Should not have constructed this");
+
+ // Let A, B and C being the components of Target and R be the location of
+ // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
+ // If it is pcrel, we want to compute (A - B + C - R).
+
+ // In general, ELF has no relocations for -B. It can only represent (A + C)
+ // 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(
+ Fixup.getLoc(),
+ "No relocation available to represent this relative expression");
+
+ const MCSymbol &SymB = RefB->getSymbol();
+
+ if (SymB.isUndefined())
+ Asm.getContext().FatalError(
+ 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(
+ Fixup.getLoc(), "Cannot represent a difference across sections");
+
+ const MCSymbolData &SymBD = Asm.getSymbolData(SymB);
+ uint64_t SymBOffset = Layout.getSymbolOffset(&SymBD);
+ uint64_t K = SymBOffset - FixupOffset;
+ IsPCRel = true;
+ C -= K;
+ }
- if (!RelocSymbol) {
- MCSymbolData &SD = Asm.getSymbolData(ASymbol);
- MCFragment *F = SD.getFragment();
+ // 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;
- if (F) {
- Index = F->getParent()->getOrdinal() + 1;
- // Offset of the symbol in the section
- Value += Layout.getSymbolOffset(&SD);
- } else {
- Index = 0;
- }
- } else {
- if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref)
- WeakrefUsedInReloc.insert(RelocSymbol);
- else
- UsedInReloc.insert(RelocSymbol);
- Index = -1;
- }
- Addend = Value;
- if (hasRelocationAddend())
- Value = 0;
+ unsigned Type = GetRelocType(Target, Fixup, IsPCRel);
+ bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymAD, C, Type);
+ if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
+ C += Layout.getSymbolOffset(SymAD);
+
+ uint64_t Addend = 0;
+ if (hasRelocationAddend()) {
+ Addend = C;
+ C = 0;
}
- FixedValue = Value;
- unsigned Type = GetRelocType(Target, Fixup, IsPCRel,
- (RelocSymbol != 0), Addend);
- MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
- MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
+ FixedValue = C;
+
+ // FIXME: What is this!?!?
+ MCSymbolRefExpr::VariantKind Modifier =
+ RefA ? RefA->getKind() : MCSymbolRefExpr::VK_None;
if (RelocNeedsGOT(Modifier))
NeedsGOT = true;
- uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) +
- Fixup.getOffset();
+ if (!RelocateWithSymbol) {
+ const MCSection *SecA =
+ (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
+ const MCSectionData *SecAD = SecA ? &Asm.getSectionData(*SecA) : nullptr;
+ ELFRelocationEntry Rec(FixupOffset, SecAD, Type, Addend);
+ Relocations[FixupSection].push_back(Rec);
+ return;
+ }
- if (!hasRelocationAddend())
- Addend = 0;
+ if (SymA) {
+ if (const MCSymbol *R = Renames.lookup(SymA))
+ SymA = R;
- if (is64Bit())
- assert(isInt<64>(Addend));
- else
- assert(isInt<32>(Addend));
-
- ELFRelocationEntry ERE(RelocOffset, Index, Type, RelocSymbol, Addend, Fixup);
- Relocations[Fragment->getParent()].push_back(ERE);
+ if (const MCSymbol *WeakRef = getWeakRef(*RefA))
+ WeakrefUsedInReloc.insert(WeakRef);
+ else
+ UsedInReloc.insert(SymA);
+ }
+ ELFRelocationEntry Rec(FixupOffset, SymA, Type, Addend);
+ Relocations[FixupSection].push_back(Rec);
+ return;
}
uint64_t
ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
const MCSymbol *S) {
- MCSymbolData &SD = Asm.getSymbolData(*S);
+ const MCSymbolData &SD = Asm.getSymbolData(*S);
return SD.getIndex();
}
-bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm,
- const MCSymbolData &Data,
- bool Used, bool Renamed) {
- if (Data.getFlags() & ELF_Other_Weakref)
- return false;
+bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout,
+ const MCSymbolData &Data, 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)) {
+ if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF)
+ return false;
+ }
+ }
if (Used)
return true;
@@ -795,42 +927,35 @@ bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm,
if (Renamed)
return false;
- const MCSymbol &Symbol = Data.getSymbol();
-
if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_")
return true;
- const MCSymbol &A = Symbol.AliasedSymbol();
- if (Symbol.isVariable() && !A.isVariable() && A.isUndefined())
- return false;
+ if (Symbol.isVariable()) {
+ const MCSymbol *Base = Layout.getBaseSymbol(Symbol);
+ if (Base && Base->isUndefined())
+ return false;
+ }
bool IsGlobal = MCELF::GetBinding(Data) == ELF::STB_GLOBAL;
if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal)
return false;
- if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined())
- return false;
-
if (Symbol.isTemporary())
return false;
return true;
}
-bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isSignature,
- bool isUsedInReloc) {
+bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isUsedInReloc) {
if (Data.isExternal())
return false;
const MCSymbol &Symbol = Data.getSymbol();
- const MCSymbol &RefSymbol = Symbol.AliasedSymbol();
-
- if (RefSymbol.isUndefined() && !RefSymbol.isVariable()) {
- if (isSignature && !isUsedInReloc)
- return true;
+ if (Symbol.isDefined())
+ return true;
+ if (isUsedInReloc)
return false;
- }
return true;
}
@@ -863,10 +988,11 @@ void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm,
}
}
-void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
- const SectionIndexMapTy &SectionIndexMap,
- RevGroupMapTy RevGroupMap,
- unsigned NumRegularSections) {
+void
+ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
+ const SectionIndexMapTy &SectionIndexMap,
+ 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) {
@@ -877,73 +1003,49 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
MCELF::SetBinding(Data, ELF::STB_GLOBAL);
}
- // Index 0 is always the empty string.
- StringMap<uint64_t> StringIndexMap;
- StringTable += '\x00';
-
- // FIXME: We could optimize suffixes in strtab in the same way we
- // optimize them in shstrtab.
-
- for (MCAssembler::const_file_name_iterator it = Asm.file_names_begin(),
- ie = Asm.file_names_end();
- it != ie;
- ++it) {
- StringRef Name = *it;
- uint64_t &Entry = StringIndexMap[Name];
- if (!Entry) {
- Entry = StringTable.size();
- StringTable += Name;
- StringTable += '\x00';
- }
- FileSymbolData.push_back(Entry);
- }
-
// Add the data for the symbols.
- for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
- ie = Asm.symbol_end(); it != ie; ++it) {
- const MCSymbol &Symbol = it->getSymbol();
+ for (MCSymbolData &SD : Asm.symbols()) {
+ const MCSymbol &Symbol = SD.getSymbol();
bool Used = UsedInReloc.count(&Symbol);
bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol);
bool isSignature = RevGroupMap.count(&Symbol);
- if (!isInSymtab(Asm, *it,
+ if (!isInSymtab(Layout, SD,
Used || WeakrefUsed || isSignature,
Renames.count(&Symbol)))
continue;
ELFSymbolData MSD;
- MSD.SymbolData = it;
- const MCSymbol &RefSymbol = Symbol.AliasedSymbol();
+ 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(*it, isSignature, Used);
- if (!Local && MCELF::GetBinding(*it) == ELF::STB_LOCAL) {
- MCSymbolData &SD = Asm.getSymbolData(RefSymbol);
- MCELF::SetBinding(*it, ELF::STB_GLOBAL);
+ 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);
}
- if (RefSymbol.isUndefined() && !Used && WeakrefUsed)
- MCELF::SetBinding(*it, ELF::STB_WEAK);
-
- if (it->isCommon()) {
+ if (!BaseSymbol) {
+ MSD.SectionIndex = ELF::SHN_ABS;
+ } else if (SD.isCommon()) {
assert(!Local);
MSD.SectionIndex = ELF::SHN_COMMON;
- } else if (Symbol.isAbsolute() || RefSymbol.isVariable()) {
- MSD.SectionIndex = ELF::SHN_ABS;
- } else if (RefSymbol.isUndefined()) {
+ } else if (BaseSymbol->isUndefined()) {
if (isSignature && !Used)
MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap[&Symbol]);
else
MSD.SectionIndex = ELF::SHN_UNDEF;
+ if (!Used && WeakrefUsed)
+ MCELF::SetBinding(SD, ELF::STB_WEAK);
} else {
const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(RefSymbol.getSection());
+ static_cast<const MCSectionELF&>(BaseSymbol->getSection());
MSD.SectionIndex = SectionIndexMap.lookup(&Section);
- if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
- NeedsSymtabShndx = true;
assert(MSD.SectionIndex && "Invalid section index!");
}
@@ -951,7 +1053,6 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
// @@ in defined ones.
StringRef Name = Symbol.getName();
SmallString<32> Buf;
-
size_t Pos = Name.find("@@@");
if (Pos != StringRef::npos) {
Buf += Name.substr(0, Pos);
@@ -959,14 +1060,8 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
Buf += Name.substr(Pos + Skip);
Name = Buf;
}
+ MSD.Name = StrTabBuilder.add(Name);
- uint64_t &Entry = StringIndexMap[Name];
- if (!Entry) {
- Entry = StringTable.size();
- StringTable += Name;
- StringTable += '\x00';
- }
- MSD.StringIndex = Entry;
if (MSD.SectionIndex == ELF::SHN_UNDEF)
UndefinedSymbolData.push_back(MSD);
else if (Local)
@@ -975,6 +1070,21 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
ExternalSymbolData.push_back(MSD);
}
+ for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
+ StrTabBuilder.add(*i);
+
+ StrTabBuilder.finalize();
+
+ for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
+ FileSymbolData.push_back(StrTabBuilder.getOffset(*i));
+
+ for (ELFSymbolData& MSD : LocalSymbolData)
+ MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
+ for (ELFSymbolData& MSD : ExternalSymbolData)
+ MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
+ for (ELFSymbolData& MSD : UndefinedSymbolData)
+ MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
+
// Symbols are required to be in lexicographic order.
array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end());
array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
@@ -992,9 +1102,6 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
ExternalSymbolData[i].SymbolData->setIndex(Index++);
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
UndefinedSymbolData[i].SymbolData->setIndex(Index++);
-
- if (Index >= ELF::SHN_LORESERVE)
- NeedsSymtabShndx = true;
}
void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm,
@@ -1037,6 +1144,151 @@ void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm,
}
}
+static SmallVector<char, 128>
+getUncompressedData(MCAsmLayout &Layout,
+ MCSectionData::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.
+static bool
+prependCompressionHeader(uint64_t Size,
+ SmallVectorImpl<char> &CompressedContents) {
+ static const StringRef Magic = "ZLIB";
+ if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size())
+ return false;
+ if (sys::IsLittleEndianHost)
+ sys::swapByteOrder(Size);
+ CompressedContents.insert(CompressedContents.begin(),
+ Magic.size() + sizeof(Size), 0);
+ std::copy(Magic.begin(), Magic.end(), CompressedContents.begin());
+ std::copy(reinterpret_cast<char *>(&Size),
+ reinterpret_cast<char *>(&Size + 1),
+ CompressedContents.begin() + Magic.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());
+
+ // Gather the uncompressed data from all the fragments, recording the
+ // alignment fragment, if seen, and any fixups.
+ SmallVector<char, 128> UncompressedData =
+ getUncompressedData(Layout, Fragments);
+
+ SmallVectorImpl<char> &CompressedContents = CompressedFragment->getContents();
+
+ 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);
+ }
+}
+
+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)
+ 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(),
@@ -1074,71 +1326,75 @@ void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
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];
- // Sort the relocation entries. Most targets just sort by r_offset, but some
- // (e.g., MIPS) have additional constraints.
- TargetObjectWriter->sortRelocs(Asm, Relocs);
+ sortRelocs(Asm, Relocs);
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
- ELFRelocationEntry entry = Relocs[e - i - 1];
+ const ELFRelocationEntry &Entry = Relocs[e - i - 1];
+
+ unsigned Index;
+ if (Entry.UseSymbol) {
+ Index = getSymbolIndexInSymbolTable(Asm, Entry.Symbol);
+ } else {
+ const MCSectionData *Sec = Entry.Section;
+ if (Sec)
+ Index = Sec->getOrdinal() + FileSymbolData.size() +
+ LocalSymbolData.size() + 1;
+ else
+ Index = 0;
+ }
- if (!entry.Index)
- ;
- else if (entry.Index < 0)
- entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol);
- else
- entry.Index += FileSymbolData.size() + LocalSymbolData.size();
if (is64Bit()) {
- String64(*F, entry.r_offset);
+ write(*F, Entry.Offset);
if (TargetObjectWriter->isN64()) {
- String32(*F, entry.Index);
+ write(*F, uint32_t(Index));
- String8(*F, TargetObjectWriter->getRSsym(entry.Type));
- String8(*F, TargetObjectWriter->getRType3(entry.Type));
- String8(*F, TargetObjectWriter->getRType2(entry.Type));
- String8(*F, TargetObjectWriter->getRType(entry.Type));
- }
- else {
+ write(*F, TargetObjectWriter->getRSsym(Entry.Type));
+ write(*F, TargetObjectWriter->getRType3(Entry.Type));
+ write(*F, TargetObjectWriter->getRType2(Entry.Type));
+ write(*F, TargetObjectWriter->getRType(Entry.Type));
+ } else {
struct ELF::Elf64_Rela ERE64;
- ERE64.setSymbolAndType(entry.Index, entry.Type);
- String64(*F, ERE64.r_info);
+ ERE64.setSymbolAndType(Index, Entry.Type);
+ write(*F, ERE64.r_info);
}
if (hasRelocationAddend())
- String64(*F, entry.r_addend);
+ write(*F, Entry.Addend);
} else {
- String32(*F, entry.r_offset);
+ write(*F, uint32_t(Entry.Offset));
struct ELF::Elf32_Rela ERE32;
- ERE32.setSymbolAndType(entry.Index, entry.Type);
- String32(*F, ERE32.r_info);
+ ERE32.setSymbolAndType(Index, Entry.Type);
+ write(*F, ERE32.r_info);
if (hasRelocationAddend())
- String32(*F, entry.r_addend);
+ write(*F, uint32_t(Entry.Addend));
}
}
}
-static int compareBySuffix(const MCSectionELF *const *a,
- const MCSectionELF *const *b) {
- const StringRef &NameA = (*a)->getSectionName();
- const StringRef &NameB = (*b)->getSectionName();
- const unsigned sizeA = NameA.size();
- const unsigned sizeB = NameB.size();
- const unsigned len = std::min(sizeA, sizeB);
- for (unsigned int i = 0; i < len; ++i) {
- char ca = NameA[sizeA - i - 1];
- char cb = NameB[sizeB - i - 1];
- if (ca != cb)
- return cb - ca;
- }
-
- return sizeB - sizeA;
-}
-
void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
MCAsmLayout &Layout,
SectionIndexMapTy &SectionIndexMap,
@@ -1162,16 +1418,6 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
SymtabSD.setAlignment(is64Bit() ? 8 : 4);
- MCSectionData *SymtabShndxSD = NULL;
-
- if (NeedsSymtabShndx) {
- const MCSectionELF *SymtabShndxSection =
- Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0,
- SectionKind::getReadOnly(), 4, "");
- SymtabShndxSD = &Asm.getOrCreateSectionData(*SymtabShndxSection);
- SymtabShndxSD->setAlignment(4);
- }
-
const MCSectionELF *StrtabSection;
StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0,
SectionKind::getReadOnly());
@@ -1186,52 +1432,23 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
// Symbol table
F = new MCDataFragment(&SymtabSD);
- MCDataFragment *ShndxF = NULL;
- if (NeedsSymtabShndx) {
- ShndxF = new MCDataFragment(SymtabShndxSD);
- }
- WriteSymbolTable(F, ShndxF, Asm, Layout, SectionIndexMap);
+ WriteSymbolTable(F, Asm, Layout, SectionIndexMap);
F = new MCDataFragment(&StrtabSD);
- F->getContents().append(StringTable.begin(), StringTable.end());
+ F->getContents().append(StrTabBuilder.data().begin(),
+ StrTabBuilder.data().end());
F = new MCDataFragment(&ShstrtabSD);
- std::vector<const MCSectionELF*> Sections;
- for (MCAssembler::const_iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
+ // Section header string table.
+ for (auto it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
const MCSectionELF &Section =
static_cast<const MCSectionELF&>(it->getSection());
- Sections.push_back(&Section);
- }
- array_pod_sort(Sections.begin(), Sections.end(), compareBySuffix);
-
- // Section header string table.
- //
- // The first entry of a string table holds a null character so skip
- // section 0.
- uint64_t Index = 1;
- F->getContents().push_back('\x00');
-
- for (unsigned int I = 0, E = Sections.size(); I != E; ++I) {
- const MCSectionELF &Section = *Sections[I];
-
- StringRef Name = Section.getSectionName();
- if (I != 0) {
- StringRef PreviousName = Sections[I - 1]->getSectionName();
- if (PreviousName.endswith(Name)) {
- SectionStringTableIndex[&Section] = Index - Name.size() - 1;
- continue;
- }
- }
- // Remember the index into the string table so we can write it
- // into the sh_name field of the section header table.
- SectionStringTableIndex[&Section] = Index;
-
- Index += Name.size() + 1;
- F->getContents().append(Name.begin(), Name.end());
- F->getContents().push_back('\x00');
+ ShStrTabBuilder.add(Section.getSectionName());
}
+ ShStrTabBuilder.finalize();
+ F->getContents().append(ShStrTabBuilder.data().begin(),
+ ShStrTabBuilder.data().end());
}
void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm,
@@ -1265,7 +1482,7 @@ void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm,
MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
Data.setAlignment(4);
MCDataFragment *F = new MCDataFragment(&Data);
- String32(*F, ELF::GRP_COMDAT);
+ write(*F, uint32_t(ELF::GRP_COMDAT));
}
GroupMap[Group] = SignatureSymbol;
}
@@ -1283,8 +1500,8 @@ void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm,
MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
// FIXME: we could use the previous fragment
MCDataFragment *F = new MCDataFragment(&Data);
- unsigned Index = SectionIndexMap.lookup(&Section);
- String32(*F, Index);
+ uint32_t Index = SectionIndexMap.lookup(&Section);
+ write(*F, Index);
}
}
@@ -1299,7 +1516,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
switch(Section.getType()) {
case ELF::SHT_DYNAMIC:
- sh_link = SectionStringTableIndex[&Section];
+ sh_link = ShStrTabBuilder.getOffset(Section.getSectionName());
sh_info = 0;
break;
@@ -1348,6 +1565,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
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;
@@ -1357,8 +1575,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
break;
default:
- assert(0 && "FIXME: sh_type value not supported!");
- break;
+ llvm_unreachable("FIXME: sh_type value not supported!");
}
if (TargetObjectWriter->getEMachine() == ELF::EM_ARM &&
@@ -1380,7 +1597,8 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
}
}
- WriteSecHdrEntry(SectionStringTableIndex[&Section], Section.getType(),
+ WriteSecHdrEntry(ShStrTabBuilder.getOffset(Section.getSectionName()),
+ Section.getType(),
Section.getFlags(), 0, Offset, Size, sh_link, sh_info,
Alignment, Section.getEntrySize());
}
@@ -1514,6 +1732,8 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
unsigned NumUserSections = Asm.size();
+ CompressDebugSections(Asm, const_cast<MCAsmLayout &>(Layout));
+
DenseMap<const MCSectionELF*, const MCSectionELF*> RelMap;
CreateRelocationSections(Asm, const_cast<MCAsmLayout&>(Layout), RelMap);
@@ -1526,8 +1746,8 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
unsigned NumRegularSections = NumUserSections + NumIndexedSections;
// Compute symbol table information.
- ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap, NumRegularSections);
-
+ computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap,
+ NumRegularSections);
WriteRelocations(Asm, const_cast<MCAsmLayout&>(Layout), RelMap);
@@ -1605,7 +1825,7 @@ ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCFragment &FB,
bool InSet,
bool IsPCRel) const {
- if (DataA.getFlags() & ELF_STB_Weak)
+ if (DataA.getFlags() & ELF_STB_Weak || MCELF::GetType(DataA) == ELF::STT_GNU_IFUNC)
return false;
return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
Asm, DataA, FB,InSet, IsPCRel);