forked from OSchip/llvm-project
[yaml2obj][ELF] Rudimentary symbol table support.
Currently, we only output the name. llvm-svn: 184255
This commit is contained in:
parent
e84854a125
commit
6b08388940
|
@ -49,6 +49,9 @@ struct FileHeader {
|
||||||
ELF_EM Machine;
|
ELF_EM Machine;
|
||||||
llvm::yaml::Hex64 Entry;
|
llvm::yaml::Hex64 Entry;
|
||||||
};
|
};
|
||||||
|
struct Symbol {
|
||||||
|
StringRef Name;
|
||||||
|
};
|
||||||
struct Section {
|
struct Section {
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
ELF_SHT Type;
|
ELF_SHT Type;
|
||||||
|
@ -57,6 +60,8 @@ struct Section {
|
||||||
object::yaml::BinaryRef Content;
|
object::yaml::BinaryRef Content;
|
||||||
StringRef Link;
|
StringRef Link;
|
||||||
llvm::yaml::Hex64 AddressAlign;
|
llvm::yaml::Hex64 AddressAlign;
|
||||||
|
// For SHT_SYMTAB; should be empty otherwise.
|
||||||
|
std::vector<Symbol> Symbols;
|
||||||
};
|
};
|
||||||
struct Object {
|
struct Object {
|
||||||
FileHeader Header;
|
FileHeader Header;
|
||||||
|
@ -67,6 +72,7 @@ struct Object {
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Section)
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Section)
|
||||||
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
@ -106,6 +112,11 @@ struct MappingTraits<ELFYAML::FileHeader> {
|
||||||
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
|
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MappingTraits<ELFYAML::Symbol> {
|
||||||
|
static void mapping(IO &IO, ELFYAML::Symbol &Symbol);
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct MappingTraits<ELFYAML::Section> {
|
struct MappingTraits<ELFYAML::Section> {
|
||||||
static void mapping(IO &IO, ELFYAML::Section &Section);
|
static void mapping(IO &IO, ELFYAML::Section &Section);
|
||||||
|
|
|
@ -260,6 +260,10 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
|
||||||
IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));
|
IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) {
|
||||||
|
IO.mapOptional("Name", Symbol.Name, StringRef());
|
||||||
|
}
|
||||||
|
|
||||||
void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
|
void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
|
||||||
ELFYAML::Section &Section) {
|
ELFYAML::Section &Section) {
|
||||||
IO.mapOptional("Name", Section.Name, StringRef());
|
IO.mapOptional("Name", Section.Name, StringRef());
|
||||||
|
@ -269,6 +273,12 @@ void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
|
||||||
IO.mapOptional("Content", Section.Content);
|
IO.mapOptional("Content", Section.Content);
|
||||||
IO.mapOptional("Link", Section.Link);
|
IO.mapOptional("Link", Section.Link);
|
||||||
IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0));
|
IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0));
|
||||||
|
// TODO: Error if `Type` is SHT_SYMTAB and this is not present, or if
|
||||||
|
// `Type` is *not* SHT_SYMTAB and this *is* present. (By SHT_SYMTAB I
|
||||||
|
// also mean SHT_DYNSYM, but for simplicity right now we just do
|
||||||
|
// SHT_SYMTAB). Want to be able to share the predicate with consumers of
|
||||||
|
// this structure.
|
||||||
|
IO.mapOptional("Symbols", Section.Symbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
|
void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# RUN: yaml2obj -format=elf %s | llvm-readobj -symbols - | FileCheck %s
|
||||||
|
!ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_REL
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Sections:
|
||||||
|
- Name: .text
|
||||||
|
Type: SHT_PROGBITS
|
||||||
|
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||||
|
- Name: .symtab
|
||||||
|
Type: SHT_SYMTAB
|
||||||
|
Symbols:
|
||||||
|
- Name: "" # TODO: Add STN_UNDEF automatically.
|
||||||
|
- Name: main
|
||||||
|
|
||||||
|
# CHECK: Symbols [
|
||||||
|
# CHECK-NEXT: Symbol {
|
||||||
|
# CHECK-NEXT: Name: (0)
|
||||||
|
# CHECK: Symbol {
|
||||||
|
# CHECK-NEXT: Name: main
|
|
@ -133,6 +133,42 @@ static void createStringTableSectionHeader(Elf_Shdr &SHeader,
|
||||||
SHeader.sh_addralign = 1;
|
SHeader.sh_addralign = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: This function is hideous. Between the sheer number of parameters
|
||||||
|
// and the hideous ELF typenames, it's just a travesty. Factor the ELF
|
||||||
|
// output into a class (templated on ELFT) and share some typedefs.
|
||||||
|
template <class ELFT>
|
||||||
|
static void handleSymtabSectionHeader(
|
||||||
|
const ELFYAML::Section &Sec,
|
||||||
|
const typename object::ELFObjectFile<ELFT>::Elf_Ehdr &Header,
|
||||||
|
typename object::ELFObjectFile<ELFT>::Elf_Shdr &SHeader,
|
||||||
|
StringTableBuilder &StrTab, ContiguousBlobAccumulator &CBA,
|
||||||
|
unsigned DotStrtabSecNo) {
|
||||||
|
|
||||||
|
typedef typename object::ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
|
||||||
|
// TODO: Ensure that a manually specified `Link` field is diagnosed as an
|
||||||
|
// error for SHT_SYMTAB.
|
||||||
|
SHeader.sh_link = DotStrtabSecNo;
|
||||||
|
// TODO: Once we handle symbol binding, this should be one greater than
|
||||||
|
// symbol table index of the last local symbol.
|
||||||
|
SHeader.sh_info = 0;
|
||||||
|
SHeader.sh_entsize = sizeof(Elf_Sym);
|
||||||
|
|
||||||
|
std::vector<Elf_Sym> Syms;
|
||||||
|
// FIXME: Ensure STN_UNDEF entry is present.
|
||||||
|
for (unsigned i = 0, e = Sec.Symbols.size(); i != e; ++i) {
|
||||||
|
const ELFYAML::Symbol &Sym = Sec.Symbols[i];
|
||||||
|
Elf_Sym Symbol;
|
||||||
|
zero(Symbol);
|
||||||
|
if (!Sym.Name.empty())
|
||||||
|
Symbol.st_name = StrTab.addString(Sym.Name);
|
||||||
|
Syms.push_back(Symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHeader.sh_offset = CBA.currentOffset();
|
||||||
|
SHeader.sh_size = vectorDataSize(Syms);
|
||||||
|
writeVectorData(CBA.getOS(), Syms);
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
|
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
|
||||||
using namespace llvm::ELF;
|
using namespace llvm::ELF;
|
||||||
|
@ -181,6 +217,7 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
|
||||||
Header.e_shnum = Sections.size() + 2;
|
Header.e_shnum = Sections.size() + 2;
|
||||||
// Place section header string table last.
|
// Place section header string table last.
|
||||||
Header.e_shstrndx = Sections.size() + 1;
|
Header.e_shstrndx = Sections.size() + 1;
|
||||||
|
const unsigned DotStrtabSecNo = Sections.size();
|
||||||
|
|
||||||
SectionNameToIdxMap SN2I;
|
SectionNameToIdxMap SN2I;
|
||||||
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
|
||||||
|
@ -202,6 +239,7 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
|
||||||
Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
|
Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
|
||||||
ContiguousBlobAccumulator CBA(SectionContentBeginOffset, Buf);
|
ContiguousBlobAccumulator CBA(SectionContentBeginOffset, Buf);
|
||||||
std::vector<Elf_Shdr> SHeaders;
|
std::vector<Elf_Shdr> SHeaders;
|
||||||
|
StringTableBuilder DotStrTab;
|
||||||
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
|
||||||
const ELFYAML::Section &Sec = Sections[i];
|
const ELFYAML::Section &Sec = Sections[i];
|
||||||
Elf_Shdr SHeader;
|
Elf_Shdr SHeader;
|
||||||
|
@ -227,11 +265,14 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
|
||||||
SHeader.sh_info = 0;
|
SHeader.sh_info = 0;
|
||||||
SHeader.sh_addralign = Sec.AddressAlign;
|
SHeader.sh_addralign = Sec.AddressAlign;
|
||||||
SHeader.sh_entsize = 0;
|
SHeader.sh_entsize = 0;
|
||||||
|
// XXX: Really ugly right now. Need to put common state into a class.
|
||||||
|
if (Sec.Type == ELFYAML::ELF_SHT(SHT_SYMTAB))
|
||||||
|
handleSymtabSectionHeader<ELFT>(Sec, Header, SHeader, DotStrTab, CBA,
|
||||||
|
DotStrtabSecNo);
|
||||||
SHeaders.push_back(SHeader);
|
SHeaders.push_back(SHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
// .strtab string table header. Currently emitted empty.
|
// .strtab string table header.
|
||||||
StringTableBuilder DotStrTab;
|
|
||||||
Elf_Shdr DotStrTabSHeader;
|
Elf_Shdr DotStrTabSHeader;
|
||||||
zero(DotStrTabSHeader);
|
zero(DotStrTabSHeader);
|
||||||
DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab"));
|
DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab"));
|
||||||
|
|
Loading…
Reference in New Issue