[llvm-nm] Fix Bug 41353 - unique symbols printed as D instead of u
authorJordan Rupprecht <rupprecht@google.com>
Fri, 24 May 2019 04:02:05 +0000 (04:02 +0000)
committerJordan Rupprecht <rupprecht@google.com>
Fri, 24 May 2019 04:02:05 +0000 (04:02 +0000)
Summary:
https://bugs.llvm.org/show_bug.cgi?id=41353

I'm new to LLVM and C++ so please do not hesitate to iterate with me on this fix.

Patch by Mike Pozulp!

Reviewers: rupprecht, zbrid, grimar, jhenderson

Reviewed By: rupprecht, jhenderson

Subscribers: jhenderson, chrisjackson, MaskRay, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D61117

llvm-svn: 361595

llvm/include/llvm/Object/ELFObjectFile.h
llvm/test/tools/llvm-nm/X86/unique.test [new file with mode: 0644]
llvm/tools/llvm-nm/llvm-nm.cpp

index ed54ad02ccff7af7dc0fc4065e994b4eff986c26..d5e9d3638dc3cf1aadbbf7f6010c880097aaa640 100644 (file)
@@ -56,6 +56,7 @@ protected:
 
   virtual uint16_t getEMachine() const = 0;
   virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0;
+  virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0;
   virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0;
   virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0;
 
@@ -145,6 +146,10 @@ public:
     return getObject()->getSymbolSize(getRawDataRefImpl());
   }
 
+  uint8_t getBinding() const {
+    return getObject()->getSymbolBinding(getRawDataRefImpl());
+  }
+
   uint8_t getOther() const {
     return getObject()->getSymbolOther(getRawDataRefImpl());
   }
@@ -252,6 +257,7 @@ protected:
   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
   uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+  uint8_t getSymbolBinding(DataRefImpl Symb) const override;
   uint8_t getSymbolOther(DataRefImpl Symb) const override;
   uint8_t getSymbolELFType(DataRefImpl Symb) const override;
   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
@@ -553,6 +559,11 @@ uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
   return getSymbol(Symb)->st_size;
 }
 
+template <class ELFT>
+uint8_t ELFObjectFile<ELFT>::getSymbolBinding(DataRefImpl Symb) const {
+  return getSymbol(Symb)->getBinding();
+}
+
 template <class ELFT>
 uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const {
   return getSymbol(Symb)->st_other;
diff --git a/llvm/test/tools/llvm-nm/X86/unique.test b/llvm/test/tools/llvm-nm/X86/unique.test
new file mode 100644 (file)
index 0000000..a8879d7
--- /dev/null
@@ -0,0 +1,50 @@
+## Check that we print 'u' for unique symbols
+## and 'U' for a unique symbol without a section.
+# RUN: yaml2obj %s | llvm-nm - | FileCheck %s
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:  .nobits
+    Type:  SHT_NOBITS
+  - Name:  .progbits
+    Type:  SHT_PROGBITS
+  - Name:  .progbits_alloc
+    Type:  SHT_PROGBITS
+    Flags: [SHF_ALLOC]
+  - Name:  .progbits_alloc_write
+    Type:  SHT_PROGBITS
+    Flags: [SHF_ALLOC, SHF_WRITE]
+  - Name:  .progbits_execinstr
+    Type:  SHT_PROGBITS
+    Flags: [SHF_EXECINSTR]
+Symbols:
+  - Name:    nosection
+    Binding: STB_GNU_UNIQUE
+  - Name:    nobits
+    Section: .nobits
+    Binding: STB_GNU_UNIQUE
+  - Name:    progbits
+    Section: .progbits
+    Binding: STB_GNU_UNIQUE
+  - Name:    progbits_alloc
+    Section: .progbits_alloc
+    Binding: STB_GNU_UNIQUE
+  - Name:    progbits_alloc_write
+    Section: .progbits_alloc_write
+    Binding: STB_GNU_UNIQUE
+  - Name:    progbits_execinstr
+    Section: .progbits_execinstr
+    Binding: STB_GNU_UNIQUE
+...
+
+# CHECK: 0000000000000000 u nobits
+# CHECK:                  U nosection
+# CHECK: 0000000000000000 u progbits
+# CHECK: 0000000000000000 u progbits_alloc
+# CHECK: 0000000000000000 u progbits_alloc_write
+# CHECK: 0000000000000000 u progbits_execinstr
index f21978d50cc12d855d957ba46a5fdcb235d85bb1..871ca638d9d75862d368ecb623ddf49cd40b82eb 100644 (file)
@@ -894,6 +894,9 @@ static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,
     return '?';
   }
 
+  if (SymI->getBinding() == ELF::STB_GNU_UNIQUE)
+    return 'u';
+
   elf_section_iterator SecI = *SecIOrErr;
   if (SecI != Obj.section_end()) {
     uint32_t Type = SecI->getType();
@@ -1119,10 +1122,13 @@ static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
   else
     Ret = getSymbolNMTypeChar(cast<ELFObjectFileBase>(Obj), I);
 
-  if (Symflags & object::SymbolRef::SF_Global)
-    Ret = toupper(Ret);
+  if (!(Symflags & object::SymbolRef::SF_Global))
+    return Ret;
+
+  if (Obj.isELF() && ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
+    return Ret;
 
-  return Ret;
+  return toupper(Ret);
 }
 
 // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"