From 274264ce2ba93d26702f7ebfe6aea121df44113f Mon Sep 17 00:00:00 2001 From: Sean Silva Date: Thu, 13 Jun 2013 22:19:48 +0000 Subject: [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 --- tools/yaml2obj/yaml2elf.cpp | 122 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 7 deletions(-) (limited to 'tools') 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 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 &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 +static size_t vectorDataSize(const std::vector &Vec) { + return Vec.size() * sizeof(T); +} + +template +static void writeVectorData(raw_ostream &OS, const std::vector &Vec) { + OS.write((const char *)Vec.data(), vectorDataSize(Vec)); +} + +template +static void zero(T &Obj) { + memset(&Obj, 0, sizeof(Obj)); +} + template 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::Elf_Ehdr Header; - memset(&Header, 0, sizeof(Header)); + typedef typename ELFObjectFile::Elf_Ehdr Elf_Ehdr; + typedef typename ELFObjectFile::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 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 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) { -- cgit v1.2.3