summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorSean Silva <silvas@purdue.edu>2013-06-13 22:19:48 +0000
committerSean Silva <silvas@purdue.edu>2013-06-13 22:19:48 +0000
commit274264ce2ba93d26702f7ebfe6aea121df44113f (patch)
tree44a76d6f75e02f3ac8013c109ccb9524b631bc4e /tools
parent26d36ab0ccaad16044f40dc44650ede2d78adf4f (diff)
downloadllvm-274264ce2ba93d26702f7ebfe6aea121df44113f.tar.gz
llvm-274264ce2ba93d26702f7ebfe6aea121df44113f.tar.bz2
llvm-274264ce2ba93d26702f7ebfe6aea121df44113f.tar.xz
[yaml2obj] Initial ELF section support.
The current functionality is extremely basic and a bit rough around the edges, but it will flesh out in future commits. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183953 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/yaml2obj/yaml2elf.cpp122
1 files changed, 115 insertions, 7 deletions
diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp
index 45ccb629e7..235327bd05 100644
--- a/tools/yaml2obj/yaml2elf.cpp
+++ b/tools/yaml2obj/yaml2elf.cpp
@@ -22,13 +22,71 @@
using namespace llvm;
+// There is similar code in yaml2coff, but with some slight COFF-specific
+// variations like different initial state. Might be able to deduplicate
+// some day, but also want to make sure that the Mach-O use case is served.
+//
+// This class has a deliberately small interface, since a lot of
+// implementation variation is possible.
+//
+// TODO: Use an ordered container with a suffix-based comparison in order
+// to deduplicate suffixes. std::map<> with a custom comparator is likely
+// to be the simplest implementation, but a suffix trie could be more
+// suitable for the job.
+class StringTableBuilder {
+ /// \brief Indices of strings currently present in `Buf`.
+ StringMap<unsigned> StringIndices;
+ /// \brief The contents of the string table as we build it.
+ std::string Buf;
+public:
+ StringTableBuilder() {
+ Buf.push_back('\0');
+ }
+ /// \returns Index of string in string table.
+ unsigned addString(StringRef S) {
+ StringMapEntry<unsigned> &Entry = StringIndices.GetOrCreateValue(S);
+ unsigned &I = Entry.getValue();
+ if (I != 0)
+ return I;
+ I = Buf.size();
+ Buf.append(S.begin(), S.end());
+ Buf.push_back('\0');
+ return I;
+ }
+ size_t size() const {
+ return Buf.size();
+ }
+ void writeToStream(raw_ostream &OS) {
+ OS.write(Buf.data(), Buf.size());
+ }
+};
+
+template <class T>
+static size_t vectorDataSize(const std::vector<T> &Vec) {
+ return Vec.size() * sizeof(T);
+}
+
+template <class T>
+static void writeVectorData(raw_ostream &OS, const std::vector<T> &Vec) {
+ OS.write((const char *)Vec.data(), vectorDataSize(Vec));
+}
+
+template <class T>
+static void zero(T &Obj) {
+ memset(&Obj, 0, sizeof(Obj));
+}
+
template <class ELFT>
static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
- const ELFYAML::FileHeader &Hdr = Doc.Header;
using namespace llvm::ELF;
using namespace llvm::object;
- typename ELFObjectFile<ELFT>::Elf_Ehdr Header;
- memset(&Header, 0, sizeof(Header));
+ typedef typename ELFObjectFile<ELFT>::Elf_Ehdr Elf_Ehdr;
+ typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
+
+ const ELFYAML::FileHeader &Hdr = Doc.Header;
+
+ Elf_Ehdr Header;
+ zero(Header);
Header.e_ident[EI_MAG0] = 0x7f;
Header.e_ident[EI_MAG1] = 'E';
Header.e_ident[EI_MAG2] = 'L';
@@ -36,9 +94,7 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
bool IsLittleEndian = ELFT::TargetEndianness == support::little;
Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
-
Header.e_ident[EI_VERSION] = EV_CURRENT;
-
// TODO: Implement ELF_ELFOSABI enum.
Header.e_ident[EI_OSABI] = ELFOSABI_NONE;
// TODO: Implement ELF_ABIVERSION enum.
@@ -47,11 +103,63 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Header.e_machine = Hdr.Machine;
Header.e_version = EV_CURRENT;
Header.e_entry = Hdr.Entry;
- Header.e_ehsize = sizeof(Header);
+ Header.e_ehsize = sizeof(Elf_Ehdr);
+
+ // TODO: Flesh out section header support.
+ // TODO: Program headers.
+
+ Header.e_shentsize = sizeof(Elf_Shdr);
+ // Immediately following the ELF header.
+ Header.e_shoff = sizeof(Header);
+ std::vector<ELFYAML::Section> Sections = Doc.Sections;
+ if (Sections.empty() || Sections.front().Type != SHT_NULL) {
+ ELFYAML::Section S;
+ S.Type = SHT_NULL;
+ zero(S.Flags);
+ Sections.insert(Sections.begin(), S);
+ }
+ // "+ 1" for string table.
+ Header.e_shnum = Sections.size() + 1;
+ // Place section header string table last.
+ Header.e_shstrndx = Sections.size();
+
+ StringTableBuilder StrTab;
+ std::vector<Elf_Shdr> SHeaders;
+ for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
+ const ELFYAML::Section &Sec = Sections[i];
+ Elf_Shdr SHeader;
+ zero(SHeader);
+ SHeader.sh_name = StrTab.addString(Sec.Name);
+ SHeader.sh_type = Sec.Type;
+ SHeader.sh_flags = Sec.Flags;
+ SHeader.sh_addr = 0;
+ SHeader.sh_offset = 0;
+ SHeader.sh_size = 0;
+ SHeader.sh_link = 0;
+ SHeader.sh_info = 0;
+ SHeader.sh_addralign = 1;
+ SHeader.sh_entsize = 0;
+ SHeaders.push_back(SHeader);
+ }
- // TODO: Section headers and program headers.
+ // String table header.
+ Elf_Shdr StrTabSHeader;
+ zero(StrTabSHeader);
+ StrTabSHeader.sh_name = 0;
+ StrTabSHeader.sh_type = SHT_STRTAB;
+ StrTabSHeader.sh_flags = 0;
+ StrTabSHeader.sh_addr = 0;
+ StrTabSHeader.sh_offset = Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
+ StrTabSHeader.sh_size = StrTab.size();
+ StrTabSHeader.sh_link = 0;
+ StrTabSHeader.sh_info = 0;
+ StrTabSHeader.sh_addralign = 1;
+ StrTabSHeader.sh_entsize = 0;
OS.write((const char *)&Header, sizeof(Header));
+ writeVectorData(OS, SHeaders);
+ OS.write((const char *)&StrTabSHeader, sizeof(StrTabSHeader));
+ StrTab.writeToStream(OS);
}
int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {