Skip to content

Commit 42b07ca

Browse files
committed
[llvm-nm] Introduce synthetic flag
Compatible with GNU nm --syntethic option is used to show special symbols created by the linker. Current implementation is limited to show plt entries in the form of symbol@plt and plt entry address. Currently it would be used for BOLT testing purposes (#135867) in order to eliminate external GNU nm dependency.
1 parent c617466 commit 42b07ca

File tree

4 files changed

+154
-0
lines changed

4 files changed

+154
-0
lines changed

llvm/docs/CommandGuide/llvm-nm.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ OPTIONS
257257

258258
Do not filter special symbols from the output.
259259

260+
.. option:: --synthetic
261+
Include synthetic symbols in the output. Synthetic symbols are not present in
262+
the original object file but are generated by the tool to represent relevant
263+
runtime or linking information.
264+
260265
.. option:: --undefined-only, -u
261266

262267
Print only undefined symbols.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
## Test --synthetic flag.
2+
3+
# RUN: yaml2obj %s -o %t
4+
5+
# RUN: llvm-nm %t | count 0
6+
# RUN: llvm-nm %t --synthetic | FileCheck %s
7+
8+
--- !ELF
9+
FileHeader:
10+
Class: ELFCLASS64
11+
Data: ELFDATA2LSB
12+
Type: ET_DYN
13+
Machine: EM_AARCH64
14+
Sections:
15+
- Name: .rela.plt
16+
Type: SHT_RELA
17+
Flags: [ SHF_ALLOC, SHF_INFO_LINK ]
18+
Address: 0x540
19+
Link: .dynsym
20+
AddressAlign: 0x8
21+
Info: .got
22+
Relocations:
23+
- Offset: 0x10FA8
24+
Symbol: __libc_start_main
25+
Type: R_AARCH64_JUMP_SLOT
26+
- Offset: 0x10FB0
27+
Symbol: __cxa_finalize
28+
Type: R_AARCH64_JUMP_SLOT
29+
- Offset: 0x10FB8
30+
Symbol: __gmon_start__
31+
Type: R_AARCH64_JUMP_SLOT
32+
- Offset: 0x10FC0
33+
Symbol: abort
34+
Type: R_AARCH64_JUMP_SLOT
35+
- Offset: 0x10FC8
36+
Symbol: puts
37+
Type: R_AARCH64_JUMP_SLOT
38+
- Name: .plt
39+
Type: SHT_PROGBITS
40+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
41+
Address: 0x5D0
42+
AddressAlign: 0x10
43+
Content: F07BBFA99000009011D247F910823E9120021FD61F2003D51F2003D51F2003D59000009011D647F910A23E9120021FD69000009011DA47F910C23E9120021FD69000009011DE47F910E23E9120021FD69000009011E247F910023F9120021FD69000009011E647F910223F9120021FD6
44+
- Name: .text
45+
Type: SHT_PROGBITS
46+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
47+
Address: 0x640
48+
- Name: .dynamic
49+
Type: SHT_DYNAMIC
50+
Flags: [ SHF_WRITE, SHF_ALLOC ]
51+
Address: 0x10DA0
52+
Link: .dynstr
53+
AddressAlign: 0x8
54+
Entries:
55+
- Tag: DT_JMPREL
56+
Value: 0x540
57+
- Tag: DT_PLTRELSZ
58+
Value: 0x78
59+
- Tag: DT_PLTGOT
60+
Value: 0x10F90
61+
- Tag: DT_NULL
62+
Value: 0x0
63+
- Name: .got
64+
Type: SHT_PROGBITS
65+
Flags: [ SHF_WRITE, SHF_ALLOC ]
66+
Address: 0x10F90
67+
AddressAlign: 0x8
68+
EntSize: 0x8
69+
Content: 000000000000000000000000000000000000000000000000D005000000000000D005000000000000D005000000000000D005000000000000D005000000000000A00D01000000000000000000000000000000000000000000000000000000000054070000000000000000000000000000
70+
DynamicSymbols:
71+
- Name: __libc_start_main
72+
Type: STT_FUNC
73+
Binding: STB_GLOBAL
74+
- Name: __cxa_finalize
75+
Type: STT_FUNC
76+
Binding: STB_WEAK
77+
- Name: __gmon_start__
78+
Binding: STB_WEAK
79+
- Name: abort
80+
Type: STT_FUNC
81+
Binding: STB_GLOBAL
82+
- Name: puts
83+
Type: STT_FUNC
84+
Binding: STB_GLOBAL
85+
86+
# CHECK: 0000000000000600 T __cxa_finalize@plt
87+
# CHECK-NEXT: 0000000000000610 T __gmon_start__@plt
88+
# CHECK-NEXT: 00000000000005f0 T __libc_start_main@plt
89+
# CHECK-NEXT: 0000000000000620 T abort@plt
90+
# CHECK-NEXT: 0000000000000630 T puts@plt

llvm/tools/llvm-nm/Opts.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ defm radix : Eq<"radix", "Radix (o/d/x) for printing symbol Values">, MetaVarNam
3535
def reverse_sort : FF<"reverse-sort", "Sort in reverse order">;
3636
def size_sort : FF<"size-sort", "Sort symbols by size">;
3737
def special_syms : FF<"special-syms", "Do not filter special symbols from the output">;
38+
def synthetic_syms : FF<"synthetic", "Include synthetic symbols in the output. These are special symbols created by the linker for various purposes">;
3839
def undefined_only : FF<"undefined-only", "Show only undefined symbols">;
3940
def version : FF<"version", "Display the version">;
4041
def without_aliases : FF<"without-aliases", "Exclude aliases from output">, Flags<[HelpHidden]>;

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/Demangle/Demangle.h"
2424
#include "llvm/IR/Function.h"
2525
#include "llvm/IR/LLVMContext.h"
26+
#include "llvm/MC/TargetRegistry.h"
2627
#include "llvm/Object/Archive.h"
2728
#include "llvm/Object/COFF.h"
2829
#include "llvm/Object/COFFImportFile.h"
@@ -110,6 +111,7 @@ static bool PrintSize;
110111
static bool Quiet;
111112
static bool ReverseSort;
112113
static bool SpecialSyms;
114+
static bool SyntheticSyms;
113115
static bool SizeSort;
114116
static bool UndefinedOnly;
115117
static bool WithoutAliases;
@@ -1783,6 +1785,55 @@ getDynamicSyms(SymbolicFile &Obj) {
17831785
return E->getDynamicSymbolIterators();
17841786
}
17851787

1788+
// Returns false if there is error found or true otherwise.
1789+
static bool getPltSyms(SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList) {
1790+
const auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);
1791+
if (!ELFObj)
1792+
return true;
1793+
1794+
std::string Err;
1795+
Triple TT;
1796+
TT.setArch(ELFObj->getArch());
1797+
TT.setOS(ELFObj->getOS());
1798+
const Target *TheTarget = TargetRegistry::lookupTarget(TT, Err);
1799+
if (!TheTarget) {
1800+
error("unable to find target for " + Obj.getFileName() + ": " + Err);
1801+
return false;
1802+
}
1803+
1804+
std::unique_ptr<const MCSubtargetInfo> STI;
1805+
STI.reset(TheTarget->createMCSubtargetInfo(
1806+
TT.getTriple(), ELFObj->tryGetCPUName().value_or("").str(), ""));
1807+
if (!STI) {
1808+
error("unable to create subtarget info for " + Obj.getFileName());
1809+
return false;
1810+
}
1811+
1812+
for (auto Plt : ELFObj->getPltEntries(*STI)) {
1813+
if (Plt.Symbol) {
1814+
SymbolRef Symbol(*Plt.Symbol, ELFObj);
1815+
if (Expected<StringRef> NameOrErr = Symbol.getName()) {
1816+
if (!NameOrErr->empty()) {
1817+
NMSymbol S = {};
1818+
S.Address = Plt.Address;
1819+
S.Name = NameOrErr->str() + "@plt";
1820+
S.TypeChar = 'T';
1821+
S.SectionName = Plt.Section;
1822+
SymbolList.push_back(S);
1823+
}
1824+
} else {
1825+
consumeError(NameOrErr.takeError());
1826+
}
1827+
} else {
1828+
WithColor::warning(errs(), ToolName)
1829+
<< "PLT entry at 0x" + Twine::utohexstr(Plt.Address)
1830+
<< " references an invalid symbol";
1831+
}
1832+
}
1833+
1834+
return true;
1835+
}
1836+
17861837
// Returns false if there is error found or true otherwise.
17871838
static bool getSymbolNamesFromObject(SymbolicFile &Obj,
17881839
std::vector<NMSymbol> &SymbolList) {
@@ -1807,6 +1858,12 @@ static bool getSymbolNamesFromObject(SymbolicFile &Obj,
18071858
<< toString(VersionsOrErr.takeError()) << "\n";
18081859
}
18091860
}
1861+
1862+
if (SyntheticSyms) {
1863+
if (!getPltSyms(Obj, SymbolList))
1864+
return false;
1865+
}
1866+
18101867
// If a "-s segname sectname" option was specified and this is a Mach-O
18111868
// file get the section number for that section in this object file.
18121869
unsigned int Nsect = 0;
@@ -2474,6 +2531,7 @@ int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
24742531
"(hexadecimal)");
24752532
SizeSort = Args.hasArg(OPT_size_sort);
24762533
SpecialSyms = Args.hasArg(OPT_special_syms);
2534+
SyntheticSyms = Args.hasArg(OPT_synthetic_syms);
24772535
UndefinedOnly = Args.hasArg(OPT_undefined_only);
24782536
WithoutAliases = Args.hasArg(OPT_without_aliases);
24792537

0 commit comments

Comments
 (0)