Skip to content

Commit db92d47

Browse files
author
Georgii Rymar
committed
[llvm-nm][ELF] - Use @@ prefix when printing default versions.
llvm-readelf prints default versions with `@@` prefix. This patch does the same for llvm-nm. Differential revision: https://reviews.llvm.org/D94912
1 parent 68dbd1a commit db92d47

File tree

2 files changed

+73
-31
lines changed

2 files changed

+73
-31
lines changed

llvm/test/tools/llvm-nm/dynamic.test

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,26 @@ Sections:
6262
Size: 0
6363

6464
## Check we print symbol versions, when they are available.
65-
66-
# RUN: yaml2obj --docnum=4 %s -o %t4.o
67-
# RUN: llvm-nm --dynamic %t4.o 2>&1 | \
68-
# RUN: FileCheck %s -DFILE=%t4.o --check-prefix=VERSIONED-SYMS
69-
70-
# VERSIONED-SYMS: U globalversym
71-
# VERSIONED-SYMS-NEXT: U localversym
72-
# VERSIONED-SYMS-NEXT: U version2sym@v2
73-
# VERSIONED-SYMS-NEXT: U version3sym@v3hidden
74-
# VERSIONED-SYMS-NEXT: U version4sym@v4
75-
# VERSIONED-SYMS-NEXT: U version5sym@v5hidden
65+
## A default version is one that is contained in the version table (SHT_GNU_versym)
66+
## and only available for defined symbols. Check we use the "@@" prefix to print it.
67+
68+
# RUN: yaml2obj --docnum=4 %s -o %t4-undef.o
69+
# RUN: llvm-nm --dynamic %t4-undef.o 2>&1 | \
70+
# RUN: FileCheck %s -DFILE=%t4-undef.o -DTYPE=U \
71+
# RUN: --check-prefixes=VERSIONED-SYMS,VERSIONED-UNDEF-SYMS
72+
73+
# RUN: yaml2obj --docnum=4 -DINDEX=0x1 %s -o %t4-def.o
74+
# RUN: llvm-nm --dynamic %t4-def.o 2>&1 | \
75+
# RUN: FileCheck %s -DFILE=%t4-def.o -DTYPE=r \
76+
# RUN: --check-prefixes=VERSIONED-SYMS,VERSIONED-DEF-SYMS
77+
78+
# VERSIONED-SYMS: [[TYPE]] globalversym
79+
# VERSIONED-SYMS-NEXT: [[TYPE]] localversym
80+
# VERSIONED-UNDEF-SYMS-NEXT: [[TYPE]] version2sym@v2
81+
# VERSIONED-DEF-SYMS-NEXT: [[TYPE]] version2sym@@v2
82+
# VERSIONED-SYMS-NEXT: [[TYPE]] version3sym@v3hidden
83+
# VERSIONED-SYMS-NEXT: [[TYPE]] version4sym@v4
84+
# VERSIONED-SYMS-NEXT: [[TYPE]] version5sym@v5hidden
7685

7786
--- !ELF
7887
FileHeader:
@@ -120,13 +129,22 @@ Sections:
120129
Hash: 0
121130
Flags: 0
122131
Other: 5
132+
- Name: .dynsym
133+
Type: SHT_DYNSYM
134+
EntSize: [[ENTSIZE=<none>]]
123135
DynamicSymbols:
124-
- Name: localversym
125-
- Name: globalversym
126-
- Name: version2sym
127-
- Name: version3sym
128-
- Name: version4sym
129-
- Name: version5sym
136+
- Name: localversym
137+
Index: [[INDEX=<none>]]
138+
- Name: globalversym
139+
Index: [[INDEX=<none>]]
140+
- Name: version2sym
141+
Index: [[INDEX=<none>]]
142+
- Name: version3sym
143+
Index: [[INDEX=<none>]]
144+
- Name: version4sym
145+
Index: [[INDEX=<none>]]
146+
- Name: version5sym
147+
Index: [[INDEX=<none>]]
130148

131149
## In the following cases we check we report warnings when unable to read symbol version.
132150
## Check that we still print unversioned symbol names.
@@ -137,7 +155,7 @@ DynamicSymbols:
137155

138156
# RUN: yaml2obj --docnum=4 -DVERDEFOFFSET=0xffffffff %s -o %t4-broken-verdef.o
139157
# RUN: llvm-nm --dynamic %t4-broken-verdef.o 2>&1 | \
140-
# RUN: FileCheck %s -DFILE=%t4-broken-verdef.o --check-prefixes=VERSION-ERR,VERSION-ERR1
158+
# RUN: FileCheck %s --check-prefixes=VERSION-ERR,VERSION-ERR1
141159

142160
# VERSION-ERR1: warning: unable to read symbol versions: cannot read content of SHT_GNU_verdef section with index 2: section [index 2] has a sh_offset (0xffffffff) + sh_size (0x38) that is greater than the file size (0x438)
143161
# VERSION-ERR2: warning: unable to read symbol versions: unable to read an entry with index 1 from SHT_GNU_versym section with index 1: section [index 1] has an invalid sh_size (255) which is not a multiple of its sh_entsize (2)
@@ -155,11 +173,21 @@ DynamicSymbols:
155173

156174
# RUN: yaml2obj --docnum=4 -DVERSYMSIZE=0xff %s -o %t4-broken-versym.o
157175
# RUN: llvm-nm --dynamic %t4-broken-versym.o 2>&1 | \
158-
# RUN: FileCheck %s -DFILE=%t4-broken-versym.o --check-prefixes=VERSION-ERR,VERSION-ERR2
176+
# RUN: FileCheck %s --check-prefixes=VERSION-ERR,VERSION-ERR2
159177

160-
## Case 3: check we report a warning when we are unable to get a vesrion for a SHT_GNU_versym section entry.
178+
## Case 3: check we report a warning when we are unable to get a version for a SHT_GNU_versym section entry.
161179
## In this case the SHT_GNU_versym section refers to a version index 255 which is missing.
162180

163181
# RUN: yaml2obj --docnum=4 -DVERSYMENTRY=0xff %s -o %t4-broken-index.o
164182
# RUN: llvm-nm --dynamic %t4-broken-index.o 2>&1 | \
165-
# RUN: FileCheck %s -DFILE=%t4-broken-index.o --check-prefixes=VERSION-ERR,VERSION-ERR3
183+
# RUN: FileCheck %s --check-prefixes=VERSION-ERR,VERSION-ERR3
184+
185+
## Case 4: check we report a warning when we are unable to get symbol flags.
186+
## In this case the dynamic symbol table has a wrong sh_entsize and we can't read a symbol.
187+
188+
# RUN: yaml2obj --docnum=4 -DENTSIZE=0xff %s -o %t4-broken-dynsym.o
189+
# RUN: not llvm-nm --dynamic %t4-broken-dynsym.o 2>&1 | \
190+
# RUN: FileCheck %s -DFILE=%t4-broken-dynsym.o --check-prefix=VERSION-ERR4
191+
192+
# VERSION-ERR4: warning: unable to read symbol versions: unable to read flags for symbol with index 1: section [index 4] has invalid sh_entsize: expected 24, but got 255
193+
# VERSION-ERR4: error: [[FILE]] section [index 4] has invalid sh_entsize: expected 24, but got 255

llvm/tools/llvm-nm/llvm-nm.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,8 +1686,15 @@ static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO) {
16861686
}
16871687
}
16881688

1689+
namespace {
1690+
struct SymbolVersion {
1691+
std::string Name;
1692+
bool IsDefault;
1693+
};
1694+
}; // namespace
1695+
16891696
template <class ELFT>
1690-
static Expected<std::vector<std::string>>
1697+
static Expected<std::vector<SymbolVersion>>
16911698
readSymbolVersionsELF(const ELFFile<ELFT> &Obj, StringRef FileName,
16921699
ELFObjectFileBase::elf_symbol_iterator_range Symbols) {
16931700
using Elf_Shdr = typename ELFT::Shdr;
@@ -1707,14 +1714,14 @@ readSymbolVersionsELF(const ELFFile<ELFT> &Obj, StringRef FileName,
17071714
}
17081715

17091716
if (!SymVerSec)
1710-
return std::vector<std::string>{};
1717+
return std::vector<SymbolVersion>{};
17111718

17121719
Expected<SmallVector<Optional<VersionEntry>, 0>> MapOrErr =
17131720
Obj.loadVersionMap(SymVerNeedSec, SymVerDefSec);
17141721
if (!MapOrErr)
17151722
return MapOrErr.takeError();
17161723

1717-
std::vector<std::string> Ret;
1724+
std::vector<SymbolVersion> Ret;
17181725
size_t I = 0;
17191726
for (auto It = Symbols.begin(), E = Symbols.end(); It != E; ++It) {
17201727
++I;
@@ -1725,21 +1732,27 @@ readSymbolVersionsELF(const ELFFile<ELFT> &Obj, StringRef FileName,
17251732
" from " + describe(Obj, *SymVerSec) + ": " +
17261733
toString(VerEntryOrErr.takeError()));
17271734

1735+
Expected<uint32_t> FlagsOrErr = It->getFlags();
1736+
if (!FlagsOrErr)
1737+
return createError("unable to read flags for symbol with index " +
1738+
Twine(I) + ": " + toString(FlagsOrErr.takeError()));
1739+
17281740
bool IsDefault;
17291741
Expected<StringRef> VerOrErr = Obj.getSymbolVersionByIndex(
1730-
(*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr, /*IsSymHidden=*/None);
1742+
(*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr,
1743+
(*FlagsOrErr) & SymbolRef::SF_Undefined);
17311744
if (!VerOrErr)
17321745
return createError("unable to get a version for entry " + Twine(I) +
17331746
" of " + describe(Obj, *SymVerSec) + ": " +
17341747
toString(VerOrErr.takeError()));
17351748

1736-
Ret.push_back((*VerOrErr).str());
1749+
Ret.push_back({(*VerOrErr).str(), IsDefault});
17371750
}
17381751

17391752
return Ret;
17401753
}
17411754

1742-
static Expected<std::vector<std::string>>
1755+
static Expected<std::vector<SymbolVersion>>
17431756
readSymbolVersionsELF(const ELFObjectFileBase &Obj,
17441757
ELFObjectFileBase::elf_symbol_iterator_range Symbols) {
17451758
if (const auto *ELF = dyn_cast<ELF32LEObjectFile>(&Obj))
@@ -1756,7 +1769,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
17561769
StringRef ArchiveName = {},
17571770
StringRef ArchitectureName = {}) {
17581771
auto Symbols = Obj.symbols();
1759-
std::vector<std::string> SymbolVersions;
1772+
std::vector<SymbolVersion> SymbolVersions;
17601773
if (DynamicSyms) {
17611774
const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
17621775
if (!E) {
@@ -1765,7 +1778,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
17651778
}
17661779
Symbols = E->getDynamicSymbolIterators();
17671780

1768-
if (Expected<std::vector<std::string>> VersionsOrErr =
1781+
if (Expected<std::vector<SymbolVersion>> VersionsOrErr =
17691782
readSymbolVersionsELF(*E, Symbols))
17701783
SymbolVersions = std::move(*VersionsOrErr);
17711784
else
@@ -1827,8 +1840,9 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
18271840
} else
18281841
error(std::move(E), Obj.getFileName());
18291842
}
1830-
if (!SymbolVersions.empty() && !SymbolVersions[I].empty())
1831-
S.Name += "@" + SymbolVersions[I];
1843+
if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty())
1844+
S.Name +=
1845+
(SymbolVersions[I].IsDefault ? "@@" : "@") + SymbolVersions[I].Name;
18321846

18331847
S.Sym = Sym;
18341848
SymbolList.push_back(S);

0 commit comments

Comments
 (0)