From 2a7e79a30f87be4103963e6049a2f1cf171f502c Mon Sep 17 00:00:00 2001 From: Sean Silva Date: Thu, 13 Jun 2013 22:20:01 +0000 Subject: [PATCH] [yaml2obj] Add support for specifying raw section content. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183955 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELFYAML.h | 1 + lib/Object/ELFYAML.cpp | 1 + test/Object/yaml2obj-elf-section-basic.yaml | 7 ++++- tools/yaml2obj/yaml2elf.cpp | 33 ++++++++++++++++++--- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index 401e4db7330..1de58af5477 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -54,6 +54,7 @@ struct Section { ELF_SHT Type; ELF_SHF Flags; llvm::yaml::Hex64 Address; + object::yaml::BinaryRef Content; }; struct Object { FileHeader Header; diff --git a/lib/Object/ELFYAML.cpp b/lib/Object/ELFYAML.cpp index 9ce2b9baadc..21ca0350b55 100644 --- a/lib/Object/ELFYAML.cpp +++ b/lib/Object/ELFYAML.cpp @@ -266,6 +266,7 @@ void MappingTraits::mapping(IO &IO, IO.mapRequired("Type", Section.Type); IO.mapOptional("Flags", Section.Flags, ELFYAML::ELF_SHF(0)); IO.mapOptional("Address", Section.Address, Hex64(0)); + IO.mapOptional("Content", Section.Content); } void MappingTraits::mapping(IO &IO, ELFYAML::Object &Object) { diff --git a/test/Object/yaml2obj-elf-section-basic.yaml b/test/Object/yaml2obj-elf-section-basic.yaml index e59b450be06..71090c5de3e 100644 --- a/test/Object/yaml2obj-elf-section-basic.yaml +++ b/test/Object/yaml2obj-elf-section-basic.yaml @@ -1,4 +1,4 @@ -# RUN: yaml2obj -format=elf %s | llvm-readobj -sections - | FileCheck %s +# RUN: yaml2obj -format=elf %s | llvm-readobj -sections -section-data - | FileCheck %s !ELF FileHeader: Class: ELFCLASS64 @@ -10,6 +10,7 @@ Sections: Type: SHT_PROGBITS Flags: [ SHF_ALLOC, SHF_EXECINSTR ] Address: 0xDEADBEEF + Content: EBFE # CHECK: Section { # CHECK: Index: 0 @@ -23,3 +24,7 @@ Sections: # CHECK-NEXT: SHF_EXECINSTR (0x4) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0xDEADBEEF +# CHECK: Size: 2 +# CHECK: SectionData ( +# CHECK-NEXT: 0000: EBFE +# CHECK-NEXT: ) diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index 1809bb5b2f7..66e1732192a 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -61,6 +61,21 @@ public: } }; +// This class is used to build up a contiguous binary blob while keeping +// track of an offset in the output (which notionally begins at +// `InitialOffset`). +class ContiguousBlobAccumulator { + const uint64_t InitialOffset; + raw_svector_ostream OS; + +public: + ContiguousBlobAccumulator(uint64_t InitialOffset_, SmallVectorImpl &Buf) + : InitialOffset(InitialOffset_), OS(Buf) {} + raw_ostream &getOS() { return OS; } + uint64_t currentOffset() const { return InitialOffset + OS.tell(); } + void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); } +}; + template static size_t vectorDataSize(const std::vector &Vec) { return Vec.size() * sizeof(T); @@ -124,6 +139,12 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { Header.e_shstrndx = Sections.size(); StringTableBuilder StrTab; + SmallVector Buf; + // XXX: This offset is tightly coupled with the order that we write + // things to `OS`. + const size_t SectionContentBeginOffset = + Header.e_ehsize + Header.e_shentsize * Header.e_shnum; + ContiguousBlobAccumulator CBA(SectionContentBeginOffset, Buf); std::vector SHeaders; for (unsigned i = 0, e = Sections.size(); i != e; ++i) { const ELFYAML::Section &Sec = Sections[i]; @@ -133,8 +154,11 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { SHeader.sh_type = Sec.Type; SHeader.sh_flags = Sec.Flags; SHeader.sh_addr = Sec.Address; - SHeader.sh_offset = 0; - SHeader.sh_size = 0; + + SHeader.sh_offset = CBA.currentOffset(); + SHeader.sh_size = Sec.Content.binary_size(); + Sec.Content.writeAsBinary(CBA.getOS()); + SHeader.sh_link = 0; SHeader.sh_info = 0; SHeader.sh_addralign = 1; @@ -149,8 +173,9 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { 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_offset = CBA.currentOffset(); StrTabSHeader.sh_size = StrTab.size(); + StrTab.writeToStream(CBA.getOS()); StrTabSHeader.sh_link = 0; StrTabSHeader.sh_info = 0; StrTabSHeader.sh_addralign = 1; @@ -159,7 +184,7 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { OS.write((const char *)&Header, sizeof(Header)); writeVectorData(OS, SHeaders); OS.write((const char *)&StrTabSHeader, sizeof(StrTabSHeader)); - StrTab.writeToStream(OS); + CBA.writeBlobToStream(OS); } int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {