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@plt +# CHECK-NEXT: 0000000000000610 T __gmon_start__@plt +# CHECK-NEXT: 00000000000005f0 T __libc_start_main@plt +# CHECK-NEXT: 0000000000000620 T abort@plt +# CHECK-NEXT: 0000000000000630 T puts@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 &SymbolList) { + const auto *ELFObj = dyn_cast(&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 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 &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);