[llvm] [llvm-nm] Introduce synthetic flag (PR #138232)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 1 22:28:44 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-binary-utilities
Author: Vladislav Khmelevsky (yota9)
<details>
<summary>Changes</summary>
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
(https://github.com/llvm/llvm-project/pull/135867)
in order to eliminate external GNU nm dependency.
---
Full diff: https://github.com/llvm/llvm-project/pull/138232.diff
3 Files Affected:
- (added) llvm/test/tools/llvm-nm/AArch64/synthetic.test (+90)
- (modified) llvm/tools/llvm-nm/Opts.td (+1)
- (modified) llvm/tools/llvm-nm/llvm-nm.cpp (+58)
``````````diff
diff --git a/llvm/test/tools/llvm-nm/AArch64/synthetic.test b/llvm/test/tools/llvm-nm/AArch64/synthetic.test
new file mode 100644
index 0000000000000..c98770db6ab8a
--- /dev/null
+++ b/llvm/test/tools/llvm-nm/AArch64/synthetic.test
@@ -0,0 +1,90 @@
+## Test --synthetic flag.
+
+# RUN: yaml2obj %s -o %t
+
+# RUN: llvm-nm %t | count 0
+# RUN: llvm-nm %t --synthetic | FileCheck %s
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_AARCH64
+Sections:
+ - Name: .rela.plt
+ Type: SHT_RELA
+ Flags: [ SHF_ALLOC, SHF_INFO_LINK ]
+ Address: 0x540
+ Link: .dynsym
+ AddressAlign: 0x8
+ Info: .got
+ Relocations:
+ - Offset: 0x10FA8
+ Symbol: __libc_start_main
+ Type: R_AARCH64_JUMP_SLOT
+ - Offset: 0x10FB0
+ Symbol: __cxa_finalize
+ Type: R_AARCH64_JUMP_SLOT
+ - Offset: 0x10FB8
+ Symbol: __gmon_start__
+ Type: R_AARCH64_JUMP_SLOT
+ - Offset: 0x10FC0
+ Symbol: abort
+ Type: R_AARCH64_JUMP_SLOT
+ - Offset: 0x10FC8
+ Symbol: puts
+ Type: R_AARCH64_JUMP_SLOT
+ - Name: .plt
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x5D0
+ AddressAlign: 0x10
+ Content: F07BBFA99000009011D247F910823E9120021FD61F2003D51F2003D51F2003D59000009011D647F910A23E9120021FD69000009011DA47F910C23E9120021FD69000009011DE47F910E23E9120021FD69000009011E247F910023F9120021FD69000009011E647F910223F9120021FD6
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x640
+ - Name: .dynamic
+ Type: SHT_DYNAMIC
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x10DA0
+ Link: .dynstr
+ AddressAlign: 0x8
+ Entries:
+ - Tag: DT_JMPREL
+ Value: 0x540
+ - Tag: DT_PLTRELSZ
+ Value: 0x78
+ - Tag: DT_PLTGOT
+ Value: 0x10F90
+ - Tag: DT_NULL
+ Value: 0x0
+ - Name: .got
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x10F90
+ AddressAlign: 0x8
+ EntSize: 0x8
+ Content: 000000000000000000000000000000000000000000000000D005000000000000D005000000000000D005000000000000D005000000000000D005000000000000A00D01000000000000000000000000000000000000000000000000000000000054070000000000000000000000000000
+DynamicSymbols:
+ - Name: __libc_start_main
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+ - Name: __cxa_finalize
+ Type: STT_FUNC
+ Binding: STB_WEAK
+ - Name: __gmon_start__
+ Binding: STB_WEAK
+ - Name: abort
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+ - Name: puts
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+
+# CHECK: 0000000000000600 T __cxa_finalize at plt
+# CHECK-NEXT: 0000000000000610 T __gmon_start__ at plt
+# CHECK-NEXT: 00000000000005f0 T __libc_start_main at plt
+# CHECK-NEXT: 0000000000000620 T abort at plt
+# CHECK-NEXT: 0000000000000630 T puts at plt
diff --git a/llvm/tools/llvm-nm/Opts.td b/llvm/tools/llvm-nm/Opts.td
index 04d9f5db5cf85..b534c3a26a8f8 100644
--- a/llvm/tools/llvm-nm/Opts.td
+++ b/llvm/tools/llvm-nm/Opts.td
@@ -35,6 +35,7 @@ defm radix : Eq<"radix", "Radix (o/d/x) for printing symbol Values">, MetaVarNam
def reverse_sort : FF<"reverse-sort", "Sort in reverse order">;
def size_sort : FF<"size-sort", "Sort symbols by size">;
def special_syms : FF<"special-syms", "Do not filter special symbols from the output">;
+def synthetic_syms : FF<"synthetic", "Include synthetic symbols in the output. These are special symbols created by the linker for various purposes">;
def undefined_only : FF<"undefined-only", "Show only undefined symbols">;
def version : FF<"version", "Display the version">;
def without_aliases : FF<"without-aliases", "Exclude aliases from output">, Flags<[HelpHidden]>;
diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index ff07fbbaa5351..16db73c47f027 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -23,6 +23,7 @@
#include "llvm/Demangle/Demangle.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/COFFImportFile.h"
@@ -110,6 +111,7 @@ static bool PrintSize;
static bool Quiet;
static bool ReverseSort;
static bool SpecialSyms;
+static bool SyntheticSyms;
static bool SizeSort;
static bool UndefinedOnly;
static bool WithoutAliases;
@@ -1783,6 +1785,55 @@ getDynamicSyms(SymbolicFile &Obj) {
return E->getDynamicSymbolIterators();
}
+// Returns false if there is error found or true otherwise.
+static bool getPltSyms(SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList) {
+ const auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);
+ if (!ELFObj)
+ return true;
+
+ std::string Err;
+ Triple TT;
+ TT.setArch(ELFObj->getArch());
+ TT.setOS(ELFObj->getOS());
+ const Target *TheTarget = TargetRegistry::lookupTarget(TT, Err);
+ if (!TheTarget) {
+ error("unable to find target for " + Obj.getFileName() + ": " + Err);
+ return false;
+ }
+
+ MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(
+ TT.getTriple(), ELFObj->tryGetCPUName().value_or("").str(), "");
+ if (!STI) {
+ error("unable to create subtarget info for " + Obj.getFileName() + ": " +
+ Err);
+ return false;
+ }
+
+ for (auto Plt : ELFObj->getPltEntries(*STI)) {
+ if (Plt.Symbol) {
+ SymbolRef Symbol(*Plt.Symbol, ELFObj);
+ if (Expected<StringRef> NameOrErr = Symbol.getName()) {
+ if (!NameOrErr->empty()) {
+ NMSymbol S = {};
+ S.Address = Plt.Address;
+ S.Name = NameOrErr->str() + "@plt";
+ S.TypeChar = 'T';
+ S.SectionName = Plt.Section;
+ SymbolList.push_back(S);
+ }
+ } else {
+ consumeError(NameOrErr.takeError());
+ }
+ } else {
+ WithColor::warning(errs(), ToolName)
+ << "PLT entry at 0x" + Twine::utohexstr(Plt.Address)
+ << " references an invalid symbol";
+ }
+ }
+
+ return true;
+}
+
// Returns false if there is error found or true otherwise.
static bool getSymbolNamesFromObject(SymbolicFile &Obj,
std::vector<NMSymbol> &SymbolList) {
@@ -1807,6 +1858,12 @@ static bool getSymbolNamesFromObject(SymbolicFile &Obj,
<< toString(VersionsOrErr.takeError()) << "\n";
}
}
+
+ if (SyntheticSyms) {
+ if (!getPltSyms(Obj, SymbolList))
+ return false;
+ }
+
// If a "-s segname sectname" option was specified and this is a Mach-O
// file get the section number for that section in this object file.
unsigned int Nsect = 0;
@@ -2474,6 +2531,7 @@ int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
"(hexadecimal)");
SizeSort = Args.hasArg(OPT_size_sort);
SpecialSyms = Args.hasArg(OPT_special_syms);
+ SyntheticSyms = Args.hasArg(OPT_synthetic_syms);
UndefinedOnly = Args.hasArg(OPT_undefined_only);
WithoutAliases = Args.hasArg(OPT_without_aliases);
``````````
</details>
https://github.com/llvm/llvm-project/pull/138232
More information about the llvm-commits
mailing list