Skip to content

Commit

Permalink
[yaml2obj][ELF] Rudimentary symbol table support.
Browse files Browse the repository at this point in the history
Currently, we only output the name.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184255 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
chisophugis committed Jun 18, 2013
1 parent bd4bd36 commit afcf60f
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 2 deletions.
11 changes: 11 additions & 0 deletions include/llvm/Object/ELFYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ struct FileHeader {
ELF_EM Machine;
llvm::yaml::Hex64 Entry;
};
struct Symbol {
StringRef Name;
};
struct Section {
StringRef Name;
ELF_SHT Type;
Expand All @@ -57,6 +60,8 @@ struct Section {
object::yaml::BinaryRef Content;
StringRef Link;
llvm::yaml::Hex64 AddressAlign;
// For SHT_SYMTAB; should be empty otherwise.
std::vector<Symbol> Symbols;
};
struct Object {
FileHeader Header;
Expand All @@ -67,6 +72,7 @@ struct Object {
} // end namespace llvm

LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Section)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)

namespace llvm {
namespace yaml {
Expand Down Expand Up @@ -106,6 +112,11 @@ struct MappingTraits<ELFYAML::FileHeader> {
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
};

template <>
struct MappingTraits<ELFYAML::Symbol> {
static void mapping(IO &IO, ELFYAML::Symbol &Symbol);
};

template <>
struct MappingTraits<ELFYAML::Section> {
static void mapping(IO &IO, ELFYAML::Section &Section);
Expand Down
10 changes: 10 additions & 0 deletions lib/Object/ELFYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
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,
ELFYAML::Section &Section) {
IO.mapOptional("Name", Section.Name, StringRef());
Expand All @@ -269,6 +273,12 @@ void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
IO.mapOptional("Content", Section.Content);
IO.mapOptional("Link", Section.Link);
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) {
Expand Down
22 changes: 22 additions & 0 deletions test/Object/yaml2obj-elf-symbol-basic.yaml
Original file line number Diff line number Diff line change
@@ -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
45 changes: 43 additions & 2 deletions tools/yaml2obj/yaml2elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,42 @@ static void createStringTableSectionHeader(Elf_Shdr &SHeader,
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>
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
using namespace llvm::ELF;
Expand Down Expand Up @@ -181,6 +217,7 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Header.e_shnum = Sections.size() + 2;
// Place section header string table last.
Header.e_shstrndx = Sections.size() + 1;
const unsigned DotStrtabSecNo = Sections.size();

SectionNameToIdxMap SN2I;
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
Expand All @@ -202,6 +239,7 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
ContiguousBlobAccumulator CBA(SectionContentBeginOffset, Buf);
std::vector<Elf_Shdr> SHeaders;
StringTableBuilder DotStrTab;
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
const ELFYAML::Section &Sec = Sections[i];
Elf_Shdr SHeader;
Expand All @@ -227,11 +265,14 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
SHeader.sh_info = 0;
SHeader.sh_addralign = Sec.AddressAlign;
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);
}

// .strtab string table header. Currently emitted empty.
StringTableBuilder DotStrTab;
// .strtab string table header.
Elf_Shdr DotStrTabSHeader;
zero(DotStrTabSHeader);
DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab"));
Expand Down

0 comments on commit afcf60f

Please sign in to comment.