[yaml2obj] Add support for specifying raw section content.
authorSean Silva <silvas@purdue.edu>
Thu, 13 Jun 2013 22:20:01 +0000 (22:20 +0000)
committerSean Silva <silvas@purdue.edu>
Thu, 13 Jun 2013 22:20:01 +0000 (22:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183955 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/ELFYAML.h
lib/Object/ELFYAML.cpp
test/Object/yaml2obj-elf-section-basic.yaml
tools/yaml2obj/yaml2elf.cpp

index 401e4db7330fa93bf2139ed2cc60bbae15bd3e63..1de58af54776832b37be6a4c304334efe2480f80 100644 (file)
@@ -54,6 +54,7 @@ struct Section {
   ELF_SHT Type;
   ELF_SHF Flags;
   llvm::yaml::Hex64 Address;
+  object::yaml::BinaryRef Content;
 };
 struct Object {
   FileHeader Header;
index 9ce2b9baadc09e849523d7598e6a3084c8b0457b..21ca0350b55fc99c8a8cc56eede539f8a40e679d 100644 (file)
@@ -266,6 +266,7 @@ void MappingTraits<ELFYAML::Section>::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<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
index e59b450be0690bad0c2cce6a84b4640fb4377ccc..71090c5de3e9fbdc413bbe5ca9e28701dfed82f1 100644 (file)
@@ -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:     )
index 1809bb5b2f70c84fc6fd17c2a861d6cfd8fcdad1..66e1732192aa6ac65f91ccf82ae1546d70a9015f 100644 (file)
@@ -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<char> &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 <class T>
 static size_t vectorDataSize(const std::vector<T> &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<char, 128> 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<Elf_Shdr> 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) {