};
class ELFObjectWriter : public MCObjectWriter {
- 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 MCSymbol &Symbol,
bool Used, bool Renamed);
- static bool isLocal(const MCSymbolData &Data, bool isUsedInReloc);
- static bool IsELFMetaDataSection(const MCSectionData &SD);
-
- void writeDataSectionData(MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCSectionData &SD);
+ static bool isLocal(const MCSymbol &Symbol, bool isUsedInReloc);
/// Helper struct for containing some precomputed information on symbols.
struct ELFSymbolData {
- MCSymbolData *SymbolData;
+ const MCSymbol *Symbol;
uint64_t StringIndex;
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 = MCELF::GetType(Symbol->getData());
+ unsigned RHSType = MCELF::GetType(RHS.Symbol->getData());
if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION)
return false;
if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION)
unsigned ShstrtabIndex;
+ // Sections in the order they are to be output in the section table.
+ std::vector<MCSectionELF *> SectionTable;
+ unsigned addToSectionTable(MCSectionELF *Sec);
// TargetObjectWriter wrappers.
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
LocalSymbolData.clear();
ExternalSymbolData.clear();
UndefinedSymbolData.clear();
+ NeedsGOT = false;
+ SectionTable.clear();
MCObjectWriter::reset();
}
support::endian::Writer<support::big>(OS).write(Val);
}
- template <typename T> void write(MCDataFragment &F, T Value);
-
void writeHeader(const MCAssembler &Asm);
void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout);
// Start and end offset of each section
- typedef std::vector<std::pair<uint64_t, uint64_t>> SectionOffsetsTy;
+ typedef std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>
+ SectionOffsetsTy;
void WriteSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
- std::vector<const MCSectionELF *> &Sections,
SectionOffsetsTy &SectionOffsets);
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(MCAssembler &Asm, const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
const RevGroupMapTy &RevGroupMap);
- void maybeAddToGroup(MCAssembler &Asm,
- ArrayRef<const MCSectionELF *> Sections,
- const RevGroupMapTy &RevGroupMap,
- const MCSectionELF &Section, unsigned Index);
-
- void computeIndexMap(MCAssembler &Asm,
- std::vector<const MCSectionELF *> &Sections,
- SectionIndexMapTy &SectionIndexMap,
- const RevGroupMapTy &RevGroupMap);
-
- void createRelocationSection(MCAssembler &Asm, const MCSectionELF &Sec);
-
- void CompressDebugSections(MCAssembler &Asm, MCAsmLayout &Layout);
-
- void
- createSectionHeaderStringTable(MCAssembler &Asm,
- std::vector<const MCSectionELF *> &Sections);
- void createStringTable(MCAssembler &Asm,
- std::vector<const MCSectionELF *> &Sections);
+ MCSectionELF *createRelocationSection(MCAssembler &Asm,
+ const MCSectionELF &Sec);
- // 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, const MCAsmLayout &Layout,
- RevGroupMapTy &RevGroupMap,
- std::vector<const MCSectionELF *> &Sections,
- SectionIndexMapTy &SectionIndexMap);
+ const MCSectionELF *createSectionHeaderStringTable();
+ const MCSectionELF *createStringTable(MCContext &Ctx);
void ExecutePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) override;
- void writeSectionHeader(ArrayRef<const MCSectionELF *> Sections,
- MCAssembler &Asm, const MCAsmLayout &Layout,
+ void writeSectionHeader(MCAssembler &Asm, const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
const SectionOffsetsTy &SectionOffsets);
+ void writeSectionData(const MCAssembler &Asm, const MCSectionData &SD,
+ const MCAsmLayout &Layout);
+
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);
+ uint64_t Address, uint64_t Offset, uint64_t Size,
+ uint32_t Link, uint32_t Info, uint64_t Alignment,
+ uint64_t EntrySize);
void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec);
- bool
- IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
- const MCSymbolData &DataA,
- const MCFragment &FB,
- bool InSet,
- bool IsPCRel) const override;
+ bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
+ const MCSymbol &SymA,
+ const MCFragment &FB,
+ bool InSet,
+ bool IsPCRel) const override;
- bool isWeak(const MCSymbolData &SD) const override;
+ bool isWeak(const MCSymbol &Sym) 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,
+ uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size,
const MCSectionELF &Section);
};
}
-template <typename T> void ELFObjectWriter::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(MCSectionELF *Sec) {
+ SectionTable.push_back(Sec);
+ ShStrTabBuilder.add(Sec->getSectionName());
+ return SectionTable.size();
}
void SymbolTableWriter::createSymtabShndx() {
Write16(ShstrtabIndex);
}
-uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,
+uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
const MCAsmLayout &Layout) {
+ MCSymbolData &Data = Sym.getData();
if (Data.isCommon() && Data.isExternal())
return Data.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;
// 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 &Alias : Asm.symbols()) {
+ MCSymbolData &OriginalData = Alias.getData();
// Not an alias.
if (!Alias.isVariable())
void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout) {
- MCSymbolData &OrigData = *MSD.SymbolData;
+ MCSymbolData &OrigData = MSD.Symbol->getData();
assert((!OrigData.getFragment() ||
(&OrigData.getFragment()->getParent()->getSection() ==
- &OrigData.getSymbol().getSection())) &&
+ &MSD.Symbol->getSection())) &&
"The symbol's section doesn't match the fragment's symbol");
- const MCSymbol *Base = Layout.getBaseSymbol(OrigData.getSymbol());
+ const MCSymbol *Base = Layout.getBaseSymbol(*MSD.Symbol);
// This has to be in sync with when computeSymbolTable uses SHN_ABS or
// SHN_COMMON.
uint8_t Other = MCELF::getOther(OrigData) << (ELF_STO_Shift - ELF_STV_Shift);
Other |= Visibility;
- uint64_t Value = SymbolValue(OrigData, Layout);
+ uint64_t Value = SymbolValue(*MSD.Symbol, Layout);
uint64_t Size = 0;
const MCExpr *ESize = OrigData.getSize();
MSD.SectionIndex, IsReserved);
}
-void ELFObjectWriter::WriteSymbolTable(
- MCAssembler &Asm, const MCAsmLayout &Layout,
- std::vector<const MCSectionELF *> &Sections,
- SectionOffsetsTy &SectionOffsets) {
+void ELFObjectWriter::WriteSymbolTable(MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ SectionOffsetsTy &SectionOffsets) {
MCContext &Ctx = Asm.getContext();
unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
// Symbol table
- const MCSectionELF *SymtabSection =
+ MCSectionELF *SymtabSection =
Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, "");
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
SymtabSD.setAlignment(is64Bit() ? 8 : 4);
- SymbolTableIndex = Sections.size() + 1;
- Sections.push_back(SymtabSection);
+ SymbolTableIndex = addToSectionTable(SymtabSection);
// The string table must be emitted first because we need the index
// into the string table for all the symbol names.
for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = ExternalSymbolData[i];
- MCSymbolData &Data = *MSD.SymbolData;
+ MCSymbolData &Data = MSD.Symbol->getData();
assert(((Data.getFlags() & ELF_STB_Global) ||
(Data.getFlags() & ELF_STB_Weak)) &&
"External symbol requires STB_GLOBAL or STB_WEAK flag");
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = UndefinedSymbolData[i];
- MCSymbolData &Data = *MSD.SymbolData;
+ MCSymbolData &Data = MSD.Symbol->getData();
WriteSymbol(Writer, MSD, Layout);
if (MCELF::GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
uint64_t SecEnd = OS.tell();
- SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
+ SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
if (ShndxIndexes.empty())
return;
SecStart = OS.tell();
- const MCSectionELF *SymtabShndxSection =
+ MCSectionELF *SymtabShndxSection =
Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
- Sections.push_back(SymtabShndxSection);
+ addToSectionTable(SymtabShndxSection);
MCSectionData *SymtabShndxSD =
&Asm.getOrCreateSectionData(*SymtabShndxSection);
SymtabShndxSD->setAlignment(4);
for (uint32_t Index : ShndxIndexes)
write(Index);
SecEnd = OS.tell();
- SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
+ SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
}
// It is always valid to create a relocation with a symbol. It is preferable
// 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 *Sym, uint64_t C,
unsigned Type) const {
+ MCSymbolData *SD = Sym ? &Sym->getData() : nullptr;
+
// A PCRel relocation to an absolute value has no symbol (or section). We
// represent that with a relocation to a null section.
if (!RefA)
// 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);
// 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)
// 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))
// 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();
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)
- Asm.getContext().FatalError(
+ Asm.getContext().reportFatalError(
Fixup.getLoc(), "Cannot represent a difference across sections");
- const MCSymbolData &SymBD = Asm.getSymbolData(SymB);
- if (::isWeak(SymBD))
- Asm.getContext().FatalError(
+ if (::isWeak(SymB.getData()))
+ Asm.getContext().reportFatalError(
Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol");
- uint64_t SymBOffset = Layout.getSymbolOffset(&SymBD);
+ uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
uint64_t K = SymBOffset - FixupOffset;
IsPCRel = true;
C -= K;
// 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;
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()) {
}
bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout,
- const MCSymbolData &Data, bool Used,
+ const MCSymbol &Symbol, bool Used,
bool Renamed) {
- const MCSymbol &Symbol = Data.getSymbol();
+ const MCSymbolData &Data = Symbol.getData();
if (Symbol.isVariable()) {
const MCExpr *Expr = Symbol.getVariableValue();
if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
return true;
}
-bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isUsedInReloc) {
+bool ELFObjectWriter::isLocal(const MCSymbol &Symbol, bool isUsedInReloc) {
+ const MCSymbolData &Data = Symbol.getData();
if (Data.isExternal())
return false;
- const MCSymbol &Symbol = Data.getSymbol();
if (Symbol.isDefined())
return true;
return true;
}
-void ELFObjectWriter::maybeAddToGroup(MCAssembler &Asm,
- ArrayRef<const MCSectionELF *> Sections,
- const RevGroupMapTy &RevGroupMap,
- const MCSectionELF &Section,
- unsigned Index) {
- const MCSymbol *Sym = Section.getGroup();
- if (!Sym)
- return;
- const MCSectionELF *Group = Sections[RevGroupMap.lookup(Sym) - 1];
- MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
- // FIXME: we could use the previous fragment
- MCDataFragment *F = new MCDataFragment(&Data);
- write(*F, Index);
-}
-
-void ELFObjectWriter::computeIndexMap(
- MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections,
- SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap) {
- for (const MCSectionData &SD : Asm) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(SD.getSection());
- if (Section.getType() == ELF::SHT_GROUP)
- continue;
- Sections.push_back(&Section);
- unsigned Index = Sections.size();
- SectionIndexMap[&Section] = Index;
- maybeAddToGroup(Asm, Sections, RevGroupMap, Section, Index);
- createRelocationSection(Asm, Section);
- }
-}
-
void ELFObjectWriter::computeSymbolTable(
MCAssembler &Asm, const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
// FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed?
if (NeedsGOT) {
StringRef Name = "_GLOBAL_OFFSET_TABLE_";
- MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name);
+ MCSymbol *Sym = Asm.getContext().getOrCreateSymbol(Name);
MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym);
Data.setExternal(true);
MCELF::SetBinding(Data, ELF::STB_GLOBAL);
}
// Add the data for the symbols.
- for (MCSymbolData &SD : Asm.symbols()) {
- const MCSymbol &Symbol = SD.getSymbol();
+ for (const MCSymbol &Symbol : Asm.symbols()) {
+ MCSymbolData &SD = Symbol.getData();
bool Used = UsedInReloc.count(&Symbol);
bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol);
bool isSignature = RevGroupMap.count(&Symbol);
- if (!isInSymtab(Layout, SD,
- Used || WeakrefUsed || isSignature,
+ if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature,
Renames.count(&Symbol)))
continue;
ELFSymbolData MSD;
- MSD.SymbolData = &SD;
+ MSD.Symbol = &Symbol;
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);
+ bool Local = isLocal(Symbol, Used);
if (!Local && MCELF::GetBinding(SD) == ELF::STB_LOCAL) {
assert(BaseSymbol);
MCSymbolData &BaseData = Asm.getSymbolData(*BaseSymbol);
FileSymbolData.push_back(StrTabBuilder.getOffset(*i));
for (ELFSymbolData &MSD : LocalSymbolData)
- MSD.StringIndex = MCELF::GetType(*MSD.SymbolData) == ELF::STT_SECTION
+ MSD.StringIndex = MCELF::GetType(MSD.Symbol->getData()) == ELF::STT_SECTION
? 0
: StrTabBuilder.getOffset(MSD.Name);
for (ELFSymbolData &MSD : ExternalSymbolData)
// 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++);
+ LocalSymbolData[i].Symbol->getData().setIndex(Index++);
for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
- ExternalSymbolData[i].SymbolData->setIndex(Index++);
+ ExternalSymbolData[i].Symbol->getData().setIndex(Index++);
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
- UndefinedSymbolData[i].SymbolData->setIndex(Index++);
+ UndefinedSymbolData[i].Symbol->getData().setIndex(Index++);
}
-void ELFObjectWriter::createRelocationSection(MCAssembler &Asm,
- const MCSectionELF &Sec) {
+MCSectionELF *
+ELFObjectWriter::createRelocationSection(MCAssembler &Asm,
+ const MCSectionELF &Sec) {
if (Relocations[&Sec].empty())
- return;
+ return nullptr;
MCContext &Ctx = Asm.getContext();
const StringRef SectionName = Sec.getSectionName();
if (Sec.getFlags() & ELF::SHF_GROUP)
Flags = ELF::SHF_GROUP;
- const MCSectionELF *RelaSection = Ctx.createELFRelSection(
+ MCSectionELF *RelaSection = Ctx.createELFRelSection(
RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
Flags, EntrySize, Sec.getGroup(), &Sec);
MCSectionData &RelSD = Asm.getOrCreateSectionData(*RelaSection);
RelSD.setAlignment(is64Bit() ? 8 : 4);
+ return RelaSection;
}
static SmallVector<char, 128>
getUncompressedData(const MCAsmLayout &Layout,
- MCSectionData::FragmentListType &Fragments) {
+ const MCSectionData::FragmentListType &Fragments) {
SmallVector<char, 128> UncompressedData;
for (const MCFragment &F : Fragments) {
const SmallVectorImpl<char> *Contents;
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(const MCAsmLayout &Layout,
- MCSectionData::FragmentListType &Fragments) {
- std::unique_ptr<MCDataFragment> CompressedFragment(new MCDataFragment());
+void ELFObjectWriter::writeSectionData(const MCAssembler &Asm,
+ const MCSectionData &SD,
+ const MCAsmLayout &Layout) {
+ MCSectionELF &Section = static_cast<MCSectionELF &>(SD.getSection());
+ StringRef SectionName = Section.getSectionName();
- // Gather the uncompressed data from all the fragments, recording the
- // alignment fragment, if seen, and any fixups.
+ // 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(&SD, Layout);
+ return;
+ }
+
+ // Gather the uncompressed data from all the fragments.
+ const MCSectionData::FragmentListType &Fragments = SD.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(&SD, 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(&SD, 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);
- }
+ OS << CompressedContents;
}
void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
}
}
-void ELFObjectWriter::createSectionHeaderStringTable(
- MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections) {
- const MCSectionELF *ShstrtabSection = Sections[ShstrtabIndex - 1];
-
- Asm.getOrCreateSectionData(*ShstrtabSection);
-
- for (MCSectionData &SD : Asm) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(SD.getSection());
- ShStrTabBuilder.add(Section.getSectionName());
- }
+const MCSectionELF *ELFObjectWriter::createSectionHeaderStringTable() {
+ const MCSectionELF *ShstrtabSection = SectionTable[ShstrtabIndex - 1];
ShStrTabBuilder.finalize(StringTableBuilder::ELF);
OS << ShStrTabBuilder.data();
+ return ShstrtabSection;
}
-void ELFObjectWriter::createStringTable(
- MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections) {
- MCContext &Ctx = Asm.getContext();
- const MCSectionELF *StrtabSection =
+const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
+ MCSectionELF *StrtabSection =
Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
- Asm.getOrCreateSectionData(*StrtabSection);
- Sections.push_back(StrtabSection);
- StringTableIndex = Sections.size();
+ StringTableIndex = addToSectionTable(StrtabSection);
OS << StrTabBuilder.data();
-}
-
-void ELFObjectWriter::createIndexedSections(
- MCAssembler &Asm, const MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap,
- std::vector<const MCSectionELF *> &Sections,
- SectionIndexMapTy &SectionIndexMap) {
- MCContext &Ctx = Asm.getContext();
-
- const MCSectionELF *ShstrtabSection =
- Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0);
- Sections.push_back(ShstrtabSection);
- ShstrtabIndex = Sections.size();
- assert(ShstrtabIndex == 1);
-
- // Build the groups
- for (const MCSectionData &SD : Asm) {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(SD.getSection());
- if (!(Section.getFlags() & ELF::SHF_GROUP))
- continue;
-
- const MCSymbol *SignatureSymbol = Section.getGroup();
- Asm.getOrCreateSymbolData(*SignatureSymbol);
- unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
- if (!GroupIdx) {
- const MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
- Sections.push_back(Group);
- GroupIdx = Sections.size();
-
- MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
- Data.setAlignment(4);
- MCDataFragment *F = new MCDataFragment(&Data);
- write(*F, uint32_t(ELF::GRP_COMDAT));
- }
- }
-
- computeIndexMap(Asm, Sections, SectionIndexMap, RevGroupMap);
+ 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) {
uint64_t sh_link = 0;
uint64_t sh_info = 0;
break;
case ELF::SHT_DYNAMIC:
- sh_link = ShStrTabBuilder.getOffset(Section.getSectionName());
- break;
+ llvm_unreachable("SHT_DYNAMIC in a relocatable object");
case ELF::SHT_REL:
case ELF::SHT_RELA: {
sh_link = SectionIndexMap.lookup(Section.getAssociatedSection());
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();
-}
-
-void ELFObjectWriter::writeDataSectionData(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCSectionData &SD) {
- 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);
- }
+ Section.getType(), Section.getFlags(), 0, Offset, Size,
+ sh_link, sh_info, Section.getAlignment(),
+ Section.getEntrySize());
}
void ELFObjectWriter::writeSectionHeader(
- ArrayRef<const MCSectionELF *> Sections, MCAssembler &Asm,
- const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap,
+ MCAssembler &Asm, const MCAsmLayout &Layout,
+ const SectionIndexMapTy &SectionIndexMap,
const SectionOffsetsTy &SectionOffsets) {
- const unsigned NumSections = Asm.size();
+ const unsigned NumSections = SectionTable.size();
// Null section first.
uint64_t FirstSectionSize =
(NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;
WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0);
- for (unsigned i = 0; i < NumSections; ++i) {
- const MCSectionELF &Section = *Sections[i];
- const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
+ for (MCSectionELF *Section : SectionTable) {
+ const MCSectionData &SD = Asm.getOrCreateSectionData(*Section);
uint32_t GroupSymbolIndex;
- if (Section.getType() != ELF::SHT_GROUP)
+ unsigned Type = Section->getType();
+ if (Type != ELF::SHT_GROUP)
GroupSymbolIndex = 0;
else
- GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, Section.getGroup());
+ GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, Section->getGroup());
- const std::pair<uint64_t, uint64_t> &Offsets = SectionOffsets[i];
- uint64_t Size = Section.getType() == ELF::SHT_NOBITS
- ? Layout.getSectionAddressSize(&SD)
- : Offsets.second - Offsets.first;
+ const std::pair<uint64_t, uint64_t> &Offsets =
+ SectionOffsets.find(Section)->second;
+ uint64_t Size = Type == ELF::SHT_NOBITS ? Layout.getSectionAddressSize(&SD)
+ : Offsets.second - Offsets.first;
writeSection(Asm, SectionIndexMap, GroupSymbolIndex, Offsets.first, Size,
- SD.getAlignment(), Section);
+ *Section);
}
}
void ELFObjectWriter::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
+ MCContext &Ctx = Asm.getContext();
+ MCSectionELF *ShstrtabSection =
+ Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0);
+ ShstrtabIndex = addToSectionTable(ShstrtabSection);
+
RevGroupMapTy RevGroupMap;
SectionIndexMapTy SectionIndexMap;
- CompressDebugSections(Asm, const_cast<MCAsmLayout &>(Layout));
- std::vector<const MCSectionELF *> Sections;
- createIndexedSections(Asm, Layout, RevGroupMap, Sections, SectionIndexMap);
-
- // Compute symbol table information.
- computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap);
-
- SectionOffsetsTy SectionOffsets;
+ std::map<const MCSymbol *, std::vector<const MCSectionELF *>> GroupMembers;
// Write out the ELF header ...
writeHeader(Asm);
// ... then the sections ...
- SectionOffsets.push_back(std::make_pair(0, 0));
- for (auto I = ++Sections.begin(), E = Sections.end(); I != E; ++I) {
- const MCSectionELF &Sec = **I;
- const MCSectionData &SD = Asm.getOrCreateSectionData(Sec);
+ SectionOffsetsTy SectionOffsets;
+ bool ComputedSymtab = false;
+ for (const MCSectionData &SD : Asm) {
+ MCSectionELF &Section = static_cast<MCSectionELF &>(SD.getSection());
+
uint64_t Padding = OffsetToAlignment(OS.tell(), SD.getAlignment());
WriteZeros(Padding);
// Remember the offset into the file for this section.
uint64_t SecStart = OS.tell();
- unsigned Type = Sec.getType();
- if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
- writeDataSectionData(Asm, Layout, SD);
- else
- writeRelocations(Asm, *Sec.getAssociatedSection());
+ const MCSymbol *SignatureSymbol = Section.getGroup();
+ unsigned Type = Section.getType();
+ if (Type == ELF::SHT_GROUP) {
+ assert(SignatureSymbol);
+ write(uint32_t(ELF::GRP_COMDAT));
+ for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) {
+ uint32_t SecIndex = SectionIndexMap.lookup(Member);
+ write(SecIndex);
+ }
+ } else if (Type == ELF::SHT_REL || Type == ELF::SHT_RELA) {
+ if (!ComputedSymtab) {
+ // Compute symbol table information.
+ computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap);
+ ComputedSymtab = true;
+ }
+ writeRelocations(Asm, *Section.getAssociatedSection());
+ } else {
+ writeSectionData(Asm, SD, Layout);
+ }
uint64_t SecEnd = OS.tell();
- SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
+ SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd);
+
+ if (Type == ELF::SHT_GROUP || Type == ELF::SHT_REL || Type == ELF::SHT_RELA)
+ continue;
+
+ MCSectionELF *RelSection = createRelocationSection(Asm, Section);
+
+ if (SignatureSymbol) {
+ Asm.getOrCreateSymbolData(*SignatureSymbol);
+ unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
+ if (!GroupIdx) {
+ MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
+ GroupIdx = addToSectionTable(Group);
+ MCSectionData *GroupD = &Asm.getOrCreateSectionData(*Group);
+ GroupD->setAlignment(4);
+ }
+ GroupMembers[SignatureSymbol].push_back(&Section);
+ if (RelSection)
+ GroupMembers[SignatureSymbol].push_back(RelSection);
+ }
+
+ SectionIndexMap[&Section] = addToSectionTable(&Section);
+ if (RelSection)
+ SectionIndexMap[RelSection] = addToSectionTable(RelSection);
+ }
+
+ if (!ComputedSymtab) {
+ // Compute symbol table information.
+ computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap);
+ ComputedSymtab = true;
}
- WriteSymbolTable(Asm, Layout, Sections, SectionOffsets);
+ WriteSymbolTable(Asm, Layout, SectionOffsets);
{
uint64_t SecStart = OS.tell();
- createStringTable(Asm, Sections);
+ const MCSectionELF *Sec = createStringTable(Ctx);
uint64_t SecEnd = OS.tell();
- SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
+ SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
}
{
uint64_t SecStart = OS.tell();
- createSectionHeaderStringTable(Asm, Sections);
+ const MCSectionELF *Sec = createSectionHeaderStringTable();
uint64_t SecEnd = OS.tell();
- SectionOffsets[0] = std::make_pair(SecStart, SecEnd);
+ SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
}
uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
const unsigned SectionHeaderOffset = OS.tell();
// ... then the section header table ...
- writeSectionHeader(Sections, Asm, Layout, SectionIndexMap, SectionOffsets);
+ writeSectionHeader(Asm, Layout, SectionIndexMap, SectionOffsets);
- uint16_t NumSections = (Sections.size() + 1 >= ELF::SHN_LORESERVE)
+ uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE)
? (uint16_t)ELF::SHN_UNDEF
- : Sections.size() + 1;
+ : SectionTable.size() + 1;
if (sys::IsLittleEndianHost != IsLittleEndian)
sys::swapByteOrder(NumSections);
unsigned NumSectionsOffset;
}
bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
- const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB,
+ const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
bool InSet, bool IsPCRel) const {
if (IsPCRel) {
assert(!InSet);
- if (::isWeak(DataA))
+ if (::isWeak(SymA.getData()))
return false;
}
- return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA, FB,
+ return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
InSet, IsPCRel);
}
-bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const {
+bool ELFObjectWriter::isWeak(const MCSymbol &Sym) const {
+ const MCSymbolData &SD = Sym.getData();
if (::isWeak(SD))
return true;
if (MCELF::GetBinding(SD) != ELF::STB_GLOBAL)
return false;
- const MCSymbol &Sym = SD.getSymbol();
if (!Sym.isInSection())
return false;