[llvm] r312585 - obj2yaml: Print unique section names.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 5 15:30:00 PDT 2017


Author: rafael
Date: Tue Sep  5 15:30:00 2017
New Revision: 312585

URL: http://llvm.org/viewvc/llvm-project?rev=312585&view=rev
Log:
obj2yaml: Print unique section names.

Without this patch passing a .o file with multiple sections with the
same name to obj2yaml produces a yaml file that yaml2obj cannot
handle. This is pr34162.

The problem is that when specifying, for example, the section of a
symbol, we get only

Section: foo

and don't know which of the sections whose name is foo we have to use.

One alternative would be to use section numbers. This would work, but
the output from obj2yaml would be very inconvenient to edit as
deleting a section would invalidate all indexes.

Another alternative would be to invent a unique section id that would
exist only on yaml. This would work, but seems a bit heavy handed. We
could make the id optional and default it to the section name.

Since in the last alternative the id is basically what this patch uses
as a name, it can be implemented as a followup patch if needed.

Added:
    llvm/trunk/test/Object/X86/obj2yaml-dup-section-name.s
Modified:
    llvm/trunk/tools/obj2yaml/elf2yaml.cpp

Added: llvm/trunk/test/Object/X86/obj2yaml-dup-section-name.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/X86/obj2yaml-dup-section-name.s?rev=312585&view=auto
==============================================================================
--- llvm/trunk/test/Object/X86/obj2yaml-dup-section-name.s (added)
+++ llvm/trunk/test/Object/X86/obj2yaml-dup-section-name.s Tue Sep  5 15:30:00 2017
@@ -0,0 +1,28 @@
+# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+# RUN: obj2yaml %t.o | FileCheck %s
+
+# CHECK: Sections:
+# CHECK: - Name:            .group{{$}}
+# CHECK:   Members:
+# CHECK:     - SectionOrType:   .text.foo{{$}}
+# CHECK:     - SectionOrType:   .rela.text.foo{{$}}
+# CHECK: - Name:            .text.foo{{$}}
+# CHECK: - Name:            .rela.text.foo{{$}}
+# CHECK:   Info:            .text.foo{{$}}
+# CHECK: - Name:            .group1{{$}}
+# CHECK:   Members:
+# CHECK:     - SectionOrType:   .text.foo2{{$}}
+# CHECK:     - SectionOrType:   .rela.text.foo3{{$}}
+# CHECK: - Name:            .text.foo2{{$}}
+# CHECK: - Name:            .rela.text.foo3{{$}}
+# CHECK:   Info:            .text.foo2{{$}}
+# CHECK: Symbols:
+# CHECK:   Section:         .group{{$}}
+# CHECK:   Section:         .group1{{$}}
+
+
+        .section        .text.foo,"axG", at progbits,sym1,comdat
+        .quad undef
+
+        .section        .text.foo,"axG", at progbits,sym2,comdat
+        .quad undef

Modified: llvm/trunk/tools/obj2yaml/elf2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/elf2yaml.cpp?rev=312585&r1=312584&r2=312585&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/elf2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/elf2yaml.cpp Tue Sep  5 15:30:00 2017
@@ -9,6 +9,7 @@
 
 #include "Error.h"
 #include "obj2yaml.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/ObjectYAML/ELFYAML.h"
@@ -27,6 +28,15 @@ class ELFDumper {
   typedef typename object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
   typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
 
+  ArrayRef<Elf_Shdr> Sections;
+
+  // If the file has multiple sections with the same name, we add a
+  // suffix to make them unique.
+  unsigned Suffix = 0;
+  DenseSet<StringRef> UsedSectionNames;
+  std::vector<std::string> SectionNames;
+  Expected<StringRef> getUniquedSectionName(const Elf_Shdr *Sec);
+
   const object::ELFFile<ELFT> &Obj;
   ArrayRef<Elf_Word> ShndxTable;
 
@@ -59,7 +69,25 @@ ELFDumper<ELFT>::ELFDumper(const object:
     : Obj(O) {}
 
 template <class ELFT>
-ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
+Expected<StringRef>
+ELFDumper<ELFT>::getUniquedSectionName(const Elf_Shdr *Sec) {
+  unsigned SecIndex = Sec - &Sections[0];
+  assert(&Sections[SecIndex] == Sec);
+  if (!SectionNames[SecIndex].empty())
+    return SectionNames[SecIndex];
+
+  auto NameOrErr = Obj.getSectionName(Sec);
+  if (!NameOrErr)
+    return NameOrErr;
+  StringRef Name = *NameOrErr;
+  std::string Ret = Name;
+  while (!UsedSectionNames.insert(Ret).second)
+    Ret = (Name + to_string(++Suffix)).str();
+  SectionNames[SecIndex] = Ret;
+  return SectionNames[SecIndex];
+}
+
+template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
   auto Y = make_unique<ELFYAML::Object>();
 
   // Dump header
@@ -77,7 +105,9 @@ ErrorOr<ELFYAML::Object *> ELFDumper<ELF
   auto SectionsOrErr = Obj.sections();
   if (!SectionsOrErr)
     return errorToErrorCode(SectionsOrErr.takeError());
-  for (const Elf_Shdr &Sec : *SectionsOrErr) {
+  Sections = *SectionsOrErr;
+  SectionNames.resize(Sections.size());
+  for (const Elf_Shdr &Sec : Sections) {
     switch (Sec.sh_type) {
     case ELF::SHT_NULL:
     case ELF::SHT_DYNSYM:
@@ -199,7 +229,7 @@ ELFDumper<ELFT>::dumpSymbol(const Elf_Sy
   if (!Shdr)
     return obj2yaml_error::success;
 
-  auto NameOrErr = Obj.getSectionName(Shdr);
+  auto NameOrErr = getUniquedSectionName(Shdr);
   if (!NameOrErr)
     return errorToErrorCode(NameOrErr.takeError());
   S.Section = NameOrErr.get();
@@ -252,7 +282,7 @@ std::error_code ELFDumper<ELFT>::dumpCom
   S.Address = Shdr->sh_addr;
   S.AddressAlign = Shdr->sh_addralign;
 
-  auto NameOrErr = Obj.getSectionName(Shdr);
+  auto NameOrErr = getUniquedSectionName(Shdr);
   if (!NameOrErr)
     return errorToErrorCode(NameOrErr.takeError());
   S.Name = NameOrErr.get();
@@ -261,7 +291,7 @@ std::error_code ELFDumper<ELFT>::dumpCom
     auto LinkSection = Obj.getSection(Shdr->sh_link);
     if (LinkSection.takeError())
       return errorToErrorCode(LinkSection.takeError());
-    NameOrErr = Obj.getSectionName(*LinkSection);
+    NameOrErr = getUniquedSectionName(*LinkSection);
     if (!NameOrErr)
       return errorToErrorCode(NameOrErr.takeError());
     S.Link = NameOrErr.get();
@@ -281,7 +311,7 @@ ELFDumper<ELFT>::dumpCommonRelocationSec
   if (!InfoSection)
     return errorToErrorCode(InfoSection.takeError());
 
-  auto NameOrErr = Obj.getSectionName(*InfoSection);
+  auto NameOrErr = getUniquedSectionName(*InfoSection);
   if (!NameOrErr)
     return errorToErrorCode(NameOrErr.takeError());
   S.Info = NameOrErr.get();
@@ -410,7 +440,7 @@ ErrorOr<ELFYAML::Group *> ELFDumper<ELFT
       auto sHdr = Obj.getSection(groupMembers[i]);
       if (!sHdr)
         return errorToErrorCode(sHdr.takeError());
-      auto sectionName = Obj.getSectionName(*sHdr);
+      auto sectionName = getUniquedSectionName(*sHdr);
       if (!sectionName)
         return errorToErrorCode(sectionName.takeError());
       s.sectionNameOrType = *sectionName;




More information about the llvm-commits mailing list