mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-04 12:15:46 +00:00
Add ELF dynamic symbol support to yaml2obj/obj2yaml
Summary: This change introduces a `DynamicSymbols` field to the ELF specific YAML supported by `yaml2obj` and `obj2yaml`. This grouping of symbols provides a way to represent ELF dynamic symbols. The `DynamicSymbols` structure is identical to the existing `Symbols`. Reviewers: compnerd, jakehehrlich, silvas Reviewed By: silvas Subscribers: silvas, jakehehrlich, llvm-commits Differential Revision: https://reviews.llvm.org/D39582 llvm-svn: 318433
This commit is contained in:
parent
d1dcda1969
commit
67b4966ccd
@ -207,6 +207,7 @@ struct Object {
|
||||
// top-level key, which automatically ensures that invariants like there
|
||||
// being a single SHT_SYMTAB section are upheld.
|
||||
LocalGlobalWeakSymbols Symbols;
|
||||
LocalGlobalWeakSymbols DynamicSymbols;
|
||||
};
|
||||
|
||||
} // end namespace ELFYAML
|
||||
|
@ -933,6 +933,7 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
|
||||
IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
|
||||
IO.mapOptional("Sections", Object.Sections);
|
||||
IO.mapOptional("Symbols", Object.Symbols);
|
||||
IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
|
||||
IO.setContext(nullptr);
|
||||
}
|
||||
|
||||
|
41
llvm/test/tools/yaml2obj/dynamic-symbols.yaml
Normal file
41
llvm/test/tools/yaml2obj/dynamic-symbols.yaml
Normal file
@ -0,0 +1,41 @@
|
||||
# Ensures that implicitly added sections can be ordered within Sections.
|
||||
# RUN: yaml2obj %s -o %t
|
||||
# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=SECTION
|
||||
# RUN: llvm-nm -dynamic %t | FileCheck %s --check-prefix=SYMBOL
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_DYN
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .data
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_WRITE ]
|
||||
DynamicSymbols:
|
||||
Global:
|
||||
- Name: dynglobal
|
||||
Type: STT_OBJECT
|
||||
Section: .data
|
||||
Weak:
|
||||
- Name: dynweak
|
||||
Type: STT_OBJECT
|
||||
Section: .data
|
||||
Local:
|
||||
- Name: dynlocal
|
||||
Type: STT_OBJECT
|
||||
Section: .data
|
||||
|
||||
# SECTION: Name: .dynsym
|
||||
# SECTION-NEXT: Type: SHT_DYNSYM
|
||||
# SECTION-NEXT: Flags
|
||||
# SECTION-NEXT: SHF_ALLOC
|
||||
# SECTION: Name: .dynstr
|
||||
# SECTION-NEXT: Type: SHT_STRTAB
|
||||
# SECTION-NEXT: Flags
|
||||
# SECTION-NEXT: SHF_ALLOC
|
||||
|
||||
# SYMBOL-DAG: D dynglobal
|
||||
# SYMBOL-DAG: V dynweak
|
||||
# SYMBOL-DAG: d dynlocal
|
@ -1322,6 +1322,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer)
|
||||
DynSymRegion = createDRIFrom(&Sec);
|
||||
// This is only used (if Elf_Shdr present)for naming section in GNU style
|
||||
DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec));
|
||||
DynamicStringTable = unwrapOrError(Obj->getStringTableForSymtab(Sec));
|
||||
break;
|
||||
case ELF::SHT_SYMTAB_SHNDX:
|
||||
ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec));
|
||||
|
@ -42,6 +42,8 @@ class ELFDumper {
|
||||
const object::ELFFile<ELFT> &Obj;
|
||||
ArrayRef<Elf_Word> ShndxTable;
|
||||
|
||||
std::error_code dumpSymbols(const Elf_Shdr *Symtab,
|
||||
ELFYAML::LocalGlobalWeakSymbols &Symbols);
|
||||
std::error_code dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
|
||||
StringRef StrTable, ELFYAML::Symbol &S);
|
||||
std::error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S);
|
||||
@ -119,6 +121,7 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
Y->Header.Entry = Obj.getHeader()->e_entry;
|
||||
|
||||
const Elf_Shdr *Symtab = nullptr;
|
||||
const Elf_Shdr *DynSymtab = nullptr;
|
||||
|
||||
// Dump sections
|
||||
auto SectionsOrErr = Obj.sections();
|
||||
@ -129,13 +132,15 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
for (const Elf_Shdr &Sec : Sections) {
|
||||
switch (Sec.sh_type) {
|
||||
case ELF::SHT_NULL:
|
||||
case ELF::SHT_DYNSYM:
|
||||
case ELF::SHT_STRTAB:
|
||||
// Do not dump these sections.
|
||||
break;
|
||||
case ELF::SHT_SYMTAB:
|
||||
Symtab = &Sec;
|
||||
break;
|
||||
case ELF::SHT_DYNSYM:
|
||||
DynSymtab = &Sec;
|
||||
break;
|
||||
case ELF::SHT_SYMTAB_SHNDX: {
|
||||
auto TableOrErr = Obj.getSHNDXTable(Sec);
|
||||
if (!TableOrErr)
|
||||
@ -187,46 +192,57 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
}
|
||||
}
|
||||
|
||||
// Dump symbols
|
||||
if (auto EC = dumpSymbols(Symtab, Y->Symbols))
|
||||
return EC;
|
||||
if (auto EC = dumpSymbols(DynSymtab, Y->DynamicSymbols))
|
||||
return EC;
|
||||
|
||||
return Y.release();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::error_code
|
||||
ELFDumper<ELFT>::dumpSymbols(const Elf_Shdr *Symtab,
|
||||
ELFYAML::LocalGlobalWeakSymbols &Symbols) {
|
||||
if (!Symtab)
|
||||
return Y.release(); // if the symbol table is missing return early
|
||||
return std::error_code();
|
||||
|
||||
auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab);
|
||||
if (!StrTableOrErr)
|
||||
return errorToErrorCode(StrTableOrErr.takeError());
|
||||
StringRef StrTable = *StrTableOrErr;
|
||||
|
||||
bool IsFirstSym = true;
|
||||
auto SymtabOrErr = Obj.symbols(Symtab);
|
||||
if (!SymtabOrErr)
|
||||
return errorToErrorCode(SymtabOrErr.takeError());
|
||||
for (const Elf_Sym &Sym : *SymtabOrErr) {
|
||||
|
||||
bool IsFirstSym = true;
|
||||
for (const auto &Sym : *SymtabOrErr) {
|
||||
if (IsFirstSym) {
|
||||
IsFirstSym = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
ELFYAML::Symbol S;
|
||||
if (std::error_code EC =
|
||||
ELFDumper<ELFT>::dumpSymbol(&Sym, Symtab, StrTable, S))
|
||||
if (auto EC = dumpSymbol(&Sym, Symtab, StrTable, S))
|
||||
return EC;
|
||||
|
||||
switch (Sym.getBinding())
|
||||
{
|
||||
switch (Sym.getBinding()) {
|
||||
case ELF::STB_LOCAL:
|
||||
Y->Symbols.Local.push_back(S);
|
||||
Symbols.Local.push_back(S);
|
||||
break;
|
||||
case ELF::STB_GLOBAL:
|
||||
Y->Symbols.Global.push_back(S);
|
||||
Symbols.Global.push_back(S);
|
||||
break;
|
||||
case ELF::STB_WEAK:
|
||||
Y->Symbols.Weak.push_back(S);
|
||||
Symbols.Weak.push_back(S);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unknown ELF symbol binding");
|
||||
}
|
||||
}
|
||||
|
||||
return Y.release();
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -114,12 +114,17 @@ class ELFState {
|
||||
typedef typename object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
|
||||
typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
|
||||
|
||||
enum class SymtabType { Static, Dynamic };
|
||||
|
||||
/// \brief The future ".strtab" section.
|
||||
StringTableBuilder DotStrtab{StringTableBuilder::ELF};
|
||||
|
||||
/// \brief The future ".shstrtab" section.
|
||||
StringTableBuilder DotShStrtab{StringTableBuilder::ELF};
|
||||
|
||||
/// \brief The future ".dynstr" section.
|
||||
StringTableBuilder DotDynstr{StringTableBuilder::ELF};
|
||||
|
||||
NameToIdxMap SN2I;
|
||||
NameToIdxMap SymN2I;
|
||||
const ELFYAML::Object &Doc;
|
||||
@ -131,7 +136,7 @@ class ELFState {
|
||||
void initProgramHeaders(std::vector<Elf_Phdr> &PHeaders);
|
||||
bool initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
void initSymtabSectionHeader(Elf_Shdr &SHeader,
|
||||
void initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
|
||||
StringTableBuilder &STB,
|
||||
@ -139,7 +144,8 @@ class ELFState {
|
||||
void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
|
||||
std::vector<Elf_Shdr> &SHeaders);
|
||||
void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
|
||||
std::vector<Elf_Sym> &Syms, unsigned SymbolBinding);
|
||||
std::vector<Elf_Sym> &Syms, unsigned SymbolBinding,
|
||||
const StringTableBuilder &Strtab);
|
||||
void writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::RawContentSection &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
@ -151,14 +157,20 @@ class ELFState {
|
||||
bool writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::MipsABIFlags &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
bool hasDynamicSymbols() const;
|
||||
SmallVector<const char *, 5> implicitSectionNames() const;
|
||||
|
||||
// - SHT_NULL entry (placed first, i.e. 0'th entry)
|
||||
// - symbol table (.symtab) (defaults to third to last)
|
||||
// - string table (.strtab) (defaults to second to last)
|
||||
// - section header string table (.shstrtab) (defaults to last)
|
||||
// - symbol table (.symtab) (defaults to after last yaml section)
|
||||
// - string table (.strtab) (defaults to after .symtab)
|
||||
// - section header string table (.shstrtab) (defaults to after .strtab)
|
||||
// - dynamic symbol table (.dynsym) (defaults to after .shstrtab)
|
||||
// - dynamic string table (.dynstr) (defaults to after .dynsym)
|
||||
unsigned getDotSymTabSecNo() const { return SN2I.get(".symtab"); }
|
||||
unsigned getDotStrTabSecNo() const { return SN2I.get(".strtab"); }
|
||||
unsigned getDotShStrTabSecNo() const { return SN2I.get(".shstrtab"); }
|
||||
unsigned getDotDynSymSecNo() const { return SN2I.get(".dynsym"); }
|
||||
unsigned getDotDynStrSecNo() const { return SN2I.get(".dynstr"); }
|
||||
unsigned getSectionCount() const { return SN2I.size() + 1; }
|
||||
|
||||
ELFState(const ELFYAML::Object &D) : Doc(D) {}
|
||||
@ -166,8 +178,6 @@ class ELFState {
|
||||
public:
|
||||
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
|
||||
};
|
||||
|
||||
static const char * const ImplicitSecNames[] = {".symtab", ".strtab", ".shstrtab"};
|
||||
} // end anonymous namespace
|
||||
|
||||
template <class ELFT>
|
||||
@ -288,13 +298,17 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
||||
|
||||
template <class ELFT>
|
||||
void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
|
||||
SymtabType STType,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
zero(SHeader);
|
||||
SHeader.sh_name = DotShStrtab.getOffset(".symtab");
|
||||
SHeader.sh_type = ELF::SHT_SYMTAB;
|
||||
SHeader.sh_link = getDotStrTabSecNo();
|
||||
bool IsStatic = STType == SymtabType::Static;
|
||||
SHeader.sh_name = DotShStrtab.getOffset(IsStatic ? ".symtab" : ".dynsym");
|
||||
SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM;
|
||||
SHeader.sh_link = IsStatic ? getDotStrTabSecNo() : getDotDynStrSecNo();
|
||||
const auto &Symbols = IsStatic ? Doc.Symbols : Doc.DynamicSymbols;
|
||||
auto &Strtab = IsStatic ? DotStrtab : DotDynstr;
|
||||
// One greater than symbol table index of the last local symbol.
|
||||
SHeader.sh_info = Doc.Symbols.Local.size() + 1;
|
||||
SHeader.sh_info = Symbols.Local.size() + 1;
|
||||
SHeader.sh_entsize = sizeof(Elf_Sym);
|
||||
SHeader.sh_addralign = 8;
|
||||
|
||||
@ -306,18 +320,18 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
|
||||
Syms.push_back(Sym);
|
||||
}
|
||||
|
||||
// Add symbol names to .strtab.
|
||||
for (const auto &Sym : Doc.Symbols.Local)
|
||||
DotStrtab.add(Sym.Name);
|
||||
for (const auto &Sym : Doc.Symbols.Global)
|
||||
DotStrtab.add(Sym.Name);
|
||||
for (const auto &Sym : Doc.Symbols.Weak)
|
||||
DotStrtab.add(Sym.Name);
|
||||
DotStrtab.finalize();
|
||||
// Add symbol names to .strtab or .dynstr.
|
||||
for (const auto &Sym : Symbols.Local)
|
||||
Strtab.add(Sym.Name);
|
||||
for (const auto &Sym : Symbols.Global)
|
||||
Strtab.add(Sym.Name);
|
||||
for (const auto &Sym : Symbols.Weak)
|
||||
Strtab.add(Sym.Name);
|
||||
Strtab.finalize();
|
||||
|
||||
addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
|
||||
addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
|
||||
addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
|
||||
addSymbols(Symbols.Local, Syms, ELF::STB_LOCAL, Strtab);
|
||||
addSymbols(Symbols.Global, Syms, ELF::STB_GLOBAL, Strtab);
|
||||
addSymbols(Symbols.Weak, Syms, ELF::STB_WEAK, Strtab);
|
||||
|
||||
writeArrayData(
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign),
|
||||
@ -405,12 +419,13 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
|
||||
template <class ELFT>
|
||||
void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
|
||||
std::vector<Elf_Sym> &Syms,
|
||||
unsigned SymbolBinding) {
|
||||
unsigned SymbolBinding,
|
||||
const StringTableBuilder &Strtab) {
|
||||
for (const auto &Sym : Symbols) {
|
||||
Elf_Sym Symbol;
|
||||
zero(Symbol);
|
||||
if (!Sym.Name.empty())
|
||||
Symbol.st_name = DotStrtab.getOffset(Sym.Name);
|
||||
Symbol.st_name = Strtab.getOffset(Sym.Name);
|
||||
Symbol.setBindingAndType(SymbolBinding, Sym.Type);
|
||||
if (!Sym.Section.empty()) {
|
||||
unsigned Index;
|
||||
@ -567,7 +582,7 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
|
||||
|
||||
auto SecNo = 1 + Doc.Sections.size();
|
||||
// Add special sections after input sections, if necessary.
|
||||
for (const auto &Name : ImplicitSecNames)
|
||||
for (const auto &Name : implicitSectionNames())
|
||||
if (!SN2I.addName(Name, SecNo)) {
|
||||
// Account for this section, since it wasn't in the Doc
|
||||
++SecNo;
|
||||
@ -626,17 +641,25 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
|
||||
return 1;
|
||||
|
||||
// Populate SHeaders with implicit sections not present in the Doc
|
||||
for (const auto &Name : ImplicitSecNames)
|
||||
for (const auto &Name : State.implicitSectionNames())
|
||||
if (State.SN2I.get(Name) >= SHeaders.size())
|
||||
SHeaders.push_back({});
|
||||
|
||||
// Initialize the implicit sections
|
||||
auto Index = State.SN2I.get(".symtab");
|
||||
State.initSymtabSectionHeader(SHeaders[Index], CBA);
|
||||
State.initSymtabSectionHeader(SHeaders[Index], SymtabType::Static, CBA);
|
||||
Index = State.SN2I.get(".strtab");
|
||||
State.initStrtabSectionHeader(SHeaders[Index], ".strtab", State.DotStrtab, CBA);
|
||||
Index = State.SN2I.get(".shstrtab");
|
||||
State.initStrtabSectionHeader(SHeaders[Index], ".shstrtab", State.DotShStrtab, CBA);
|
||||
if (State.hasDynamicSymbols()) {
|
||||
Index = State.SN2I.get(".dynsym");
|
||||
State.initSymtabSectionHeader(SHeaders[Index], SymtabType::Dynamic, CBA);
|
||||
SHeaders[Index].sh_flags |= ELF::SHF_ALLOC;
|
||||
Index = State.SN2I.get(".dynstr");
|
||||
State.initStrtabSectionHeader(SHeaders[Index], ".dynstr", State.DotDynstr, CBA);
|
||||
SHeaders[Index].sh_flags |= ELF::SHF_ALLOC;
|
||||
}
|
||||
|
||||
// Now we can decide segment offsets
|
||||
State.setProgramHeaderLayout(PHeaders, SHeaders);
|
||||
@ -648,6 +671,18 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class ELFT> bool ELFState<ELFT>::hasDynamicSymbols() const {
|
||||
return Doc.DynamicSymbols.Global.size() > 0 ||
|
||||
Doc.DynamicSymbols.Weak.size() > 0 ||
|
||||
Doc.DynamicSymbols.Local.size() > 0;
|
||||
}
|
||||
|
||||
template <class ELFT> SmallVector<const char *, 5> ELFState<ELFT>::implicitSectionNames() const {
|
||||
if (!hasDynamicSymbols())
|
||||
return {".symtab", ".strtab", ".shstrtab"};
|
||||
return {".symtab", ".strtab", ".shstrtab", ".dynsym", ".dynstr"};
|
||||
}
|
||||
|
||||
static bool is64Bit(const ELFYAML::Object &Doc) {
|
||||
return Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user