[yaml2obj] Add support for sh_link via `Link` key.
authorSean Silva <silvas@purdue.edu>
Sat, 15 Jun 2013 00:25:26 +0000 (00:25 +0000)
committerSean Silva <silvas@purdue.edu>
Sat, 15 Jun 2013 00:25:26 +0000 (00:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184022 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 124af7a936f6ad7e0ff01f0de7e28d121330d999..04ba0a66225ef69b5e3ce22bbbadabc002b070a3 100644 (file)
@@ -55,6 +55,7 @@ struct Section {
   ELF_SHF Flags;
   llvm::yaml::Hex64 Address;
   object::yaml::BinaryRef Content;
+  StringRef Link;
   llvm::yaml::Hex64 AddressAlign;
 };
 struct Object {
index 6e99767f87f8c79c8f613d480f015cf1671b3504..e0e95bee9347b4912b771e19c9af3aa163b51121 100644 (file)
@@ -267,6 +267,7 @@ void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
   IO.mapOptional("Flags", Section.Flags, ELFYAML::ELF_SHF(0));
   IO.mapOptional("Address", Section.Address, Hex64(0));
   IO.mapOptional("Content", Section.Content);
+  IO.mapOptional("Link", Section.Link);
   IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0));
 }
 
index e37498680530edeeb87dd483e350c48cea26e121..34be11d3658ccbad96f82a001d321c2cca3c4483 100644 (file)
@@ -10,6 +10,7 @@ Sections:
     Type: SHT_PROGBITS
     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
     Address: 0xCAFEBABE
+    Link: .text # Doesn't make sense for SHT_PROGBITS, but good enough for test.
     Content: EBFE
     AddressAlign: 2
 
@@ -26,6 +27,8 @@ Sections:
 # CHECK-NEXT:     ]
 # CHECK-NEXT:     Address: 0xCAFEBABE
 # CHECK:          Size: 2
+# Check that Link != 0.
+# CHECK:          Link: {{[1-9][0-9]*}}
 # CHECK:          AddressAlignment: 2
 # CHECK:          SectionData (
 # CHECK-NEXT:       0000: EBFE
index e5988be3293185aaba5083a2349a030a8e475869..e6a157cfd8878e2dc6e5e9d95ab45cbffa567e1a 100644 (file)
@@ -76,6 +76,29 @@ public:
   void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
 };
 
+// Used to keep track of section names, so that in the YAML file sections
+// can be referenced by name instead of by index.
+class SectionNameToIdxMap {
+  StringMap<int> Map;
+public:
+  /// \returns true if name is already present in the map.
+  bool addName(StringRef SecName, unsigned i) {
+    StringMapEntry<int> &Entry = Map.GetOrCreateValue(SecName, -1);
+    if (Entry.getValue() != -1)
+      return true;
+    Entry.setValue((int)i);
+    return false;
+  }
+  /// \returns true if name is not present in the map
+  bool lookupSection(StringRef SecName, unsigned &Idx) const {
+    StringMap<int>::const_iterator I = Map.find(SecName);
+    if (I == Map.end())
+      return true;
+    Idx = I->getValue();
+    return false;
+  }
+};
+
 template <class T>
 static size_t vectorDataSize(const std::vector<T> &Vec) {
   return Vec.size() * sizeof(T);
@@ -138,6 +161,18 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
   // Place section header string table last.
   Header.e_shstrndx = Sections.size();
 
+  SectionNameToIdxMap SN2I;
+  for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
+    StringRef Name = Sections[i].Name;
+    if (Name.empty())
+      continue;
+    if (SN2I.addName(Name, i)) {
+      errs() << "error: Repeated section name: '" << Name
+             << "' at YAML section number " << i << ".\n";
+      return;
+    }
+  }
+
   StringTableBuilder StrTab;
   SmallVector<char, 128> Buf;
   // XXX: This offset is tightly coupled with the order that we write
@@ -159,7 +194,15 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
     SHeader.sh_size = Sec.Content.binary_size();
     Sec.Content.writeAsBinary(CBA.getOS());
 
-    SHeader.sh_link = 0;
+    if (!Sec.Link.empty()) {
+      unsigned Index;
+      if (SN2I.lookupSection(Sec.Link, Index)) {
+        errs() << "error: Unknown section referenced: '" << Sec.Link
+               << "' at YAML section number " << i << ".\n";
+        return;
+      }
+      SHeader.sh_link = Index;
+    }
     SHeader.sh_info = 0;
     SHeader.sh_addralign = Sec.AddressAlign;
     SHeader.sh_entsize = 0;