[llvm] c56b4cf - [llvm-objdump] -T: print symbol versions
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 17 09:10:54 PDT 2021
Author: Fangrui Song
Date: 2021-08-17T09:10:50-07:00
New Revision: c56b4cfd4b2d74ce3b54fe0b1c5fb557b7c60200
URL: https://github.com/llvm/llvm-project/commit/c56b4cfd4b2d74ce3b54fe0b1c5fb557b7c60200
DIFF: https://github.com/llvm/llvm-project/commit/c56b4cfd4b2d74ce3b54fe0b1c5fb557b7c60200.diff
LOG: [llvm-objdump] -T: print symbol versions
Similar to D94907 (llvm-nm -D).
The output will match GNU objdump 2.37.
Older versions don't use ` (version)` for undefined symbols.
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D108097
Added:
llvm/test/tools/llvm-objdump/ELF/dynsym-version.test
Modified:
llvm/tools/llvm-objdump/llvm-objdump.cpp
llvm/tools/llvm-objdump/llvm-objdump.h
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-objdump/ELF/dynsym-version.test b/llvm/test/tools/llvm-objdump/ELF/dynsym-version.test
new file mode 100644
index 0000000000000..e21b3544be854
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/dynsym-version.test
@@ -0,0 +1,155 @@
+## Check we print symbol versions, when they are available.
+
+## Test undefined symbols.
+# RUN: yaml2obj %s -o %t-undef.o
+# RUN: llvm-objdump -T %t-undef.o 2>&1 | tr '\t' '|' | FileCheck %s \
+# RUN: -DFILE=%t-undef.o --check-prefix=UNDEF --match-full-lines --strict-whitespace
+
+## version2sym and version3sym are invalid: undefined symbols cannot refer to .gnu.version_d.
+## We still check their behaviors.
+# UNDEF:DYNAMIC SYMBOL TABLE:
+# UNDEF-NEXT:0000000000000000 D *UND*|0000000000000000 localversym
+# UNDEF-NEXT:0000000000000000 D *UND*|0000000000000000 globalversym
+# UNDEF-NEXT:0000000000000000 D *UND*|0000000000000000 (v2) version2sym
+# UNDEF-NEXT:0000000000000000 D *UND*|0000000000000000 (v3hidden) version3sym
+# UNDEF-NEXT:0000000000000000 D *UND*|0000000000000000 (v4) version4sym
+# UNDEF-NEXT:0000000000000000 D *UND*|0000000000000000 (v5hidden) .hidden version5sym
+
+## Test defined symbols.
+# RUN: yaml2obj -DINDEX=0x1 %s -o %t-def.o
+# RUN: llvm-objdump -T %t-def.o 2>&1 | tr '\t' '|' | FileCheck %s \
+# RUN: -DFILE=%t-def.o --check-prefix=DEF --match-full-lines --strict-whitespace
+
+# DEF:DYNAMIC SYMBOL TABLE:
+# DEF-NEXT:0000000000000000 g D .gnu.version|0000000000000000 localversym
+# DEF-NEXT:0000000000000000 g D .gnu.version|0000000000000000 globalversym
+# DEF-NEXT:0000000000000000 g D .gnu.version|0000000000000000 v2 version2sym
+# DEF-NEXT:0000000000000000 g D .gnu.version|0000000000000000 (v3hidden) version3sym
+# DEF-NEXT:0000000000000000 g D .gnu.version|0000000000000000 (v4) version4sym
+# DEF-NEXT:0000000000000000 g D .gnu.version|0000000000000000 (v5hidden) .hidden version5sym
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+Sections:
+ - Name: .gnu.version
+ Type: SHT_GNU_versym
+ Flags: [ SHF_ALLOC ]
+## 0x8000 is a special VERSYM_HIDDEN bit.
+ Entries: [ 0, 0, 1, 2, 0x8003, 4, 0x8005 ]
+ ShSize: [[VERSYMSIZE=<none>]]
+ - Name: .gnu.version_d
+ Type: SHT_GNU_verdef
+ Flags: [ SHF_ALLOC ]
+ Link: .dynstr
+ AddressAlign: 0x4
+ Info: 0x2
+ ShOffset: [[VERDEFOFFSET=<none>]]
+ Entries:
+ - VersionNdx: 2
+ Names:
+ - v2
+ - VersionNdx: 3
+ Names:
+ - v3hidden
+ - Name: .gnu.version_r
+ Type: SHT_GNU_verneed
+ Flags: [ SHF_ALLOC ]
+ Link: .dynstr
+ Info: 0x2
+ Dependencies:
+ - Version: 1
+ File: file1.so
+ Entries:
+ - Name: v4
+ Hash: 0
+ Flags: 0
+ Other: 4
+ - Version: 1
+ File: file2.0
+ Entries:
+ - Name: v5hidden
+ Hash: 0
+ Flags: 0
+ Other: 5
+ - Name: .dynsym
+ Type: SHT_DYNSYM
+ EntSize: [[ENTSIZE=<none>]]
+DynamicSymbols:
+ - Name: localversym
+ Index: [[INDEX=<none>]]
+ Binding: STB_GLOBAL
+ - Name: globalversym
+ Index: [[INDEX=<none>]]
+ Binding: STB_GLOBAL
+ - Name: version2sym
+ Index: [[INDEX=<none>]]
+ Binding: STB_GLOBAL
+ - Name: version3sym
+ Index: [[INDEX=<none>]]
+ Binding: STB_GLOBAL
+ - Name: version4sym
+ Index: [[INDEX=<none>]]
+ Binding: STB_GLOBAL
+ - Name: version5sym
+ Index: [[INDEX=<none>]]
+ Other: [ STV_HIDDEN ]
+ Binding: STB_GLOBAL
+
+## Test the output with a long version name.
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-objdump -T %t2 2>&1 | tr '\t' '|' | FileCheck %s \
+# RUN: --check-prefix=LONGNAME --match-full-lines --strict-whitespace
+
+# LONGNAME:DYNAMIC SYMBOL TABLE:
+# LONGNAME-NEXT:0000000000000000 g D .gnu.version|0000000000000000 v2 sym1
+# LONGNAME-NEXT:0000000000000000 g D .gnu.version|0000000000000000 v3withverylongname sym2
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+Sections:
+ - Name: .gnu.version
+ Type: SHT_GNU_versym
+ Flags: [ SHF_ALLOC ]
+ Entries: [ 1, 2, 3 ]
+ - Name: .gnu.version_d
+ Type: SHT_GNU_verdef
+ Flags: [ SHF_ALLOC ]
+ Link: .dynstr
+ AddressAlign: 0x4
+ Info: 0x2
+ Entries:
+ - VersionNdx: 2
+ Names:
+ - v2
+ - VersionNdx: 3
+ Names:
+ - v3withverylongname
+ - Name: .dynsym
+ Type: SHT_DYNSYM
+DynamicSymbols:
+ - Name: sym1
+ Index: 1
+ Binding: STB_GLOBAL
+ - Name: sym2
+ Index: 1
+ Binding: STB_GLOBAL
+
+## Check we report a warning when we are unable to read a SHT_GNU_versym section entry.
+## In this case, the section has a size that is not a multiple of its sh_entsize.
+
+# RUN: yaml2obj -DVERSYMSIZE=0xff %s -o %t2-broken-versym.o
+# RUN: llvm-objdump -T %t2-broken-versym.o 2>&1 | FileCheck %s --check-prefixes=VERSION-ERR1,NOVER
+
+# VERSION-ERR1:warning: {{.*}}: unable to read an entry with index 1 from SHT_GNU_versym section
+# NOVER-NEXT:0000000000000000 D *UND* 0000000000000000 localversym
+# NOVER-NEXT:0000000000000000 D *UND* 0000000000000000 globalversym
+# NOVER-NEXT:0000000000000000 D *UND* 0000000000000000 version2sym
+# NOVER-NEXT:0000000000000000 D *UND* 0000000000000000 version3sym
+# NOVER-NEXT:0000000000000000 D *UND* 0000000000000000 version4sym
+# NOVER-NEXT:0000000000000000 D *UND* 0000000000000000 .hidden version5sym
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index a062957cc7430..330597d04f0e5 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -1921,7 +1921,8 @@ void objdump::printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
if (!DumpDynamic) {
outs() << "\nSYMBOL TABLE:\n";
for (auto I = O->symbol_begin(); I != O->symbol_end(); ++I)
- printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
+ printSymbol(O, *I, {}, FileName, ArchiveName, ArchitectureName,
+ DumpDynamic);
return;
}
@@ -1934,12 +1935,21 @@ void objdump::printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
}
const ELFObjectFileBase *ELF = cast<const ELFObjectFileBase>(O);
- for (auto I = ELF->getDynamicSymbolIterators().begin();
- I != ELF->getDynamicSymbolIterators().end(); ++I)
- printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
+ auto Symbols = ELF->getDynamicSymbolIterators();
+ Expected<std::vector<VersionEntry>> SymbolVersionsOrErr =
+ ELF->readDynsymVersions();
+ if (!SymbolVersionsOrErr) {
+ reportWarning(toString(SymbolVersionsOrErr.takeError()), FileName);
+ SymbolVersionsOrErr = std::vector<VersionEntry>();
+ (void)!SymbolVersionsOrErr;
+ }
+ for (auto &Sym : Symbols)
+ printSymbol(O, Sym, *SymbolVersionsOrErr, FileName, ArchiveName,
+ ArchitectureName, DumpDynamic);
}
void objdump::printSymbol(const ObjectFile *O, const SymbolRef &Symbol,
+ ArrayRef<VersionEntry> SymbolVersions,
StringRef FileName, StringRef ArchiveName,
StringRef ArchitectureName, bool DumpDynamic) {
const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(O);
@@ -2044,6 +2054,15 @@ void objdump::printSymbol(const ObjectFile *O, const SymbolRef &Symbol,
}
if (O->isELF()) {
+ if (!SymbolVersions.empty()) {
+ const VersionEntry &Ver =
+ SymbolVersions[Symbol.getRawDataRefImpl().d.b - 1];
+ std::string Str;
+ if (!Ver.Name.empty())
+ Str = Ver.IsVerDef ? ' ' + Ver.Name : '(' + Ver.Name + ')';
+ outs() << ' ' << left_justify(Str, 12);
+ }
+
uint8_t Other = ELFSymbolRef(Symbol).getOther();
switch (Other) {
case ELF::STV_DEFAULT:
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index 3796878558dec..d9fc3bfe66a5d 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -26,6 +26,7 @@ class ELFSectionRef;
class MachOObjectFile;
class MachOUniversalBinary;
class RelocationRef;
+struct VersionEntry;
} // namespace object
namespace objdump {
@@ -137,6 +138,7 @@ void printSymbolTable(const object::ObjectFile *O, StringRef ArchiveName,
StringRef ArchitectureName = StringRef(),
bool DumpDynamic = false);
void printSymbol(const object::ObjectFile *O, const object::SymbolRef &Symbol,
+ ArrayRef<object::VersionEntry> SymbolVersions,
StringRef FileName, StringRef ArchiveName,
StringRef ArchitectureName, bool DumpDynamic);
[[noreturn]] void reportError(StringRef File, const Twine &Message);
More information about the llvm-commits
mailing list