From 0135aa7b988f87626fa5640c92fae68dff4e2897 Mon Sep 17 00:00:00 2001 From: zhijian Date: Tue, 15 Feb 2022 09:43:31 -0500 Subject: [PATCH] [llvm-nm] add a new option -X to specify the type of object file llvm-nm should examine Summary: Added a new option "-X" to specify, which type of object file should be examine. For example: 1. "llvm-nm -X64 archive.a" only deal with the 64bit object files in the archive.a ,ignore the all 32bit object files in the archive.a 2. "llvm-nm -X32 xcoffobj32.o xcoffobj64.o " only deal with the 32bit object file "xcoffobj32.o" , 64bit object file "xcoffobj64.o" will be ignored Reviewers: James Henderson,Fangrui Song Differential Revision: https://reviews.llvm.org/D118193 --- llvm/docs/CommandGuide/llvm-nm.rst | 14 +++ .../tools/llvm-nm/Inputs/bitcode-sym32.ll | 14 +++ .../tools/llvm-nm/Inputs/bitcode-sym64.ll | 12 ++ llvm/test/tools/llvm-nm/option-X.test | 111 ++++++++++++++++++ llvm/tools/llvm-nm/Opts.td | 1 + llvm/tools/llvm-nm/llvm-nm.cpp | 30 ++++- 6 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 llvm/test/tools/llvm-nm/Inputs/bitcode-sym32.ll create mode 100644 llvm/test/tools/llvm-nm/Inputs/bitcode-sym64.ll create mode 100644 llvm/test/tools/llvm-nm/option-X.test diff --git a/llvm/docs/CommandGuide/llvm-nm.rst b/llvm/docs/CommandGuide/llvm-nm.rst index e2d96c8220df..dd78fd0afc34 100644 --- a/llvm/docs/CommandGuide/llvm-nm.rst +++ b/llvm/docs/CommandGuide/llvm-nm.rst @@ -126,6 +126,20 @@ OPTIONS Use BSD output format. Alias for ``--format=bsd``. +.. option:: -X + + Specify the type of XCOFF object file, ELF object file, or IR object file input + from command line or from archive files that llvm-nm should examine. The + mode must be one of the following: + 32 + Process only 32-bit object files. + 64 + Process only 64-bit object files. + 32_64 + Process both 32-bit and 64-bit object files. + any + Process all the supported object files. + .. option:: --debug-syms, -a Show all symbols, even those usually suppressed. diff --git a/llvm/test/tools/llvm-nm/Inputs/bitcode-sym32.ll b/llvm/test/tools/llvm-nm/Inputs/bitcode-sym32.ll new file mode 100644 index 000000000000..0c76f09fd22b --- /dev/null +++ b/llvm/test/tools/llvm-nm/Inputs/bitcode-sym32.ll @@ -0,0 +1,14 @@ +target triple = "powerpcle-unknown-linux-gnu" + +@C32 = dso_local global i32 5, align 4 +@undef_var32 = external dso_local global i32, align 4 + +define dso_local i32 @foo32(i32 %i) #0 { +entry: + %i.addr = alloca i32, align 4 + store i32 %i, i32* %i.addr, align 4 + %0 = load i32, i32* %i.addr, align 4 + %1 = load i32, i32* @undef_var32, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} diff --git a/llvm/test/tools/llvm-nm/Inputs/bitcode-sym64.ll b/llvm/test/tools/llvm-nm/Inputs/bitcode-sym64.ll new file mode 100644 index 000000000000..cd749199fe79 --- /dev/null +++ b/llvm/test/tools/llvm-nm/Inputs/bitcode-sym64.ll @@ -0,0 +1,12 @@ +target triple = "powerpc64le-unknown-linux-gnu" + +@C64 = dso_local global i32 5, align 4 +@static_var64 = internal global i32 2, align 4 + +define dso_local signext i32 @bar64() #0 { +entry: + %0 = load i32, i32* @static_var64, align 4 + %1 = load i32, i32* @C64, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} diff --git a/llvm/test/tools/llvm-nm/option-X.test b/llvm/test/tools/llvm-nm/option-X.test new file mode 100644 index 000000000000..caa21f9d7961 --- /dev/null +++ b/llvm/test/tools/llvm-nm/option-X.test @@ -0,0 +1,111 @@ +## Test the "-X" option. +## The option specifies the type of object file to examine. + +# RUN: llvm-as -o %t32.bc %p/Inputs/bitcode-sym32.ll +# RUN: llvm-as -o %t64.bc %p/Inputs/bitcode-sym64.ll + +# RUN: llvm-nm --format=just-symbols -X32 %t32.bc %t64.bc | \ +# RUN: FileCheck %s -DFILE1=%t32.bc --check-prefixes=BITCODE32 --implicit-check-not={{.}} +# RUN: llvm-nm --format=just-symbols -X64 %t32.bc %t64.bc | \ +# RUN: FileCheck %s -DFILE2=%t64.bc --check-prefixes=BITCODE64 --implicit-check-not={{.}} +# RUN: llvm-nm --format=just-symbols %t32.bc %t64.bc | \ +# RUN: FileCheck %s -DFILE1=%t32.bc -DFILE2=%t64.bc --check-prefixes=BITCODE32,BITCODE64 +# RUN: llvm-nm --format=just-symbols -X32_64 %t32.bc %t64.bc | \ +# RUN: FileCheck %s -DFILE1=%t32.bc -DFILE2=%t64.bc --check-prefixes=BITCODE32,BITCODE64 +# RUN: llvm-nm --format=just-symbols -Xany %t32.bc %t64.bc | \ +# RUN: FileCheck %s -DFILE1=%t32.bc -DFILE2=%t64.bc --check-prefixes=BITCODE32,BITCODE64 + +# BITCODE32: [[FILE1]]: +# BITCODE32-NEXT: C32 +# BITCODE32-NEXT: foo32 +# BITCODE32-NEXT: undef_var32 + +# BITCODE64: [[FILE2]]: +# BITCODE64-NEXT: C64 +# BITCODE64-NEXT: bar64 +# BITCODE64-NEXT: static_var64 + +# RUN: yaml2obj --docnum=1 -DCLASS=ELFCLASS32 %s -o %t_elf32.o +# RUN: yaml2obj --docnum=1 -DCLASS=ELFCLASS64 %s -o %t_elf64.o + +# RUN: llvm-nm --format=just-symbols -X32 %t_elf32.o %t_elf64.o | \ +# RUN: FileCheck %s -DFILE32=%t_elf32.o --check-prefixes=ELF32 --implicit-check-not={{.}} +# RUN: llvm-nm --format=just-symbols -X64 %t_elf32.o %t_elf64.o | \ +# RUN: FileCheck %s -DFILE64=%t_elf64.o --check-prefixes=ELF64 --implicit-check-not={{.}} +# RUN: llvm-nm --format=just-symbols %t_elf32.o %t_elf64.o | \ +# RUN: FileCheck %s -DFILE32=%t_elf32.o -DFILE64=%t_elf64.o --check-prefixes=ELF32,ELF64 +# RUN: llvm-nm --format=just-symbols -X32_64 %t_elf32.o %t_elf64.o | \ +# RUN: FileCheck %s -DFILE32=%t_elf32.o -DFILE64=%t_elf64.o --check-prefixes=ELF32,ELF64 +# RUN: llvm-nm --format=just-symbols -Xany %t_elf32.o %t_elf64.o | \ +# RUN: FileCheck %s -DFILE32=%t_elf32.o -DFILE64=%t_elf64.o --check-prefixes=ELF32,ELF64 + +# ELF32: [[FILE32]]: +# ELF32-NEXT: ELFCLASS32_var + +# ELF64: [[FILE64]]: +# ELF64-NEXT: ELFCLASS64_var + +--- !ELF +FileHeader: + Class: [[CLASS]] + Data: ELFDATA2LSB + Type: ET_REL +Symbols: + - Name: [[CLASS]]_var + +# RUN: yaml2obj --docnum=2 -DFLAG=0x1DF %s -o %t_xcoff32.o +# RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o %t_xcoff64.o +# RUN: rm -f %t.a +# RUN: llvm-ar -q -c %t.a %t_xcoff32.o %t_xcoff64.o + +# RUN: llvm-nm --format=just-symbols -X32 %t_xcoff32.o | \ +# RUN: FileCheck --check-prefixes=XCOFF32 %s --implicit-check-not={{.}} +# RUN: llvm-nm --format=just-symbols -X32 %t.a | \ +# RUN: FileCheck --check-prefixes=ARC32,XCOFF32 %s -DFILE=%basename_t --implicit-check-not={{.}} +# ARC32: [[FILE]].tmp_xcoff32.o: +# XCOFF32: var_0x1DF + +# RUN: llvm-nm --format=just-symbols -X64 %t_xcoff64.o | \ +# RUN: FileCheck --check-prefixes=XCOFF64 %s --implicit-check-not={{.}} +# RUN: llvm-nm --format=just-symbols -X64 %t.a | \ +# RUN: FileCheck --check-prefixes=ARC64,XCOFF64 -DFILE=%basename_t %s --implicit-check-not={{.}} +# ARC64: [[FILE]].tmp_xcoff64.o: +# XCOFF64: var_0x1F7 + +# RUN: llvm-nm --format=just-symbols %t_xcoff32.o %t_xcoff64.o | \ +# RUN: FileCheck --check-prefixes=BOTH %s -DFILE32=%t_xcoff32.o -DFILE64=%t_xcoff64.o --match-full-lines +# RUN: llvm-nm --format=just-symbols -X32_64 %t_xcoff32.o %t_xcoff64.o | \ +# RUN: FileCheck --check-prefixes=BOTH %s -DFILE32=%t_xcoff32.o -DFILE64=%t_xcoff64.o --match-full-lines +# RUN: llvm-nm --format=just-symbols -Xany %t_xcoff32.o %t_xcoff64.o | \ +# RUN: FileCheck --check-prefixes=BOTH %s -DFILE32=%t_xcoff32.o -DFILE64=%t_xcoff64.o --match-full-lines + +# BOTH: [[FILE32]]: +# BOTH-NEXT: var_0x1DF +# BOTH-EMPTY: +# BOTH-NEXT: [[FILE64]]: +# BOTH-NEXT: var_0x1F7 + +# RUN: llvm-nm --format=just-symbols %t.a | \ +# RUN: FileCheck --check-prefixes=ARCHIVE-BOTH -DFILE=%basename_t --match-full-lines %s +# RUN: llvm-nm --format=just-symbols -X32_64 %t.a | \ +# RUN: FileCheck --check-prefixes=ARCHIVE-BOTH -DFILE=%basename_t --match-full-lines %s +# RUN: llvm-nm --format=just-symbols -Xany %t.a | \ +# RUN: FileCheck --check-prefixes=ARCHIVE-BOTH -DFILE=%basename_t --match-full-lines %s + +# ARCHIVE-BOTH: [[FILE]].tmp_xcoff32.o: +# ARCHIVE-BOTH-NEXT: var_0x1DF{{[[:space:]]}} +# ARCHIVE-BOTH-NEXT: [[FILE]].tmp_xcoff64.o: +# ARCHIVE-BOTH-NEXT: var_0x1F7 + +# RUN: llvm-nm --format=just-symbols -X64 %t_xcoff32.o | count 0 +# RUN: llvm-nm --format=just-symbols -X32 %t_xcoff64.o | count 0 + +# RUN: not llvm-nm --format=just-symbols -X33 %t_xcoff32.o 2>&1 | FileCheck %s --check-prefixes=ERR +# ERR: error: : -X value should be one of: 32, 64, 32_64, (default) any +# ERR-NEXT: var_0x1DF + +--- !XCOFF +FileHeader: + MagicNumber: [[FLAG]] +Symbols: + - Name: var_[[FLAG]] diff --git a/llvm/tools/llvm-nm/Opts.td b/llvm/tools/llvm-nm/Opts.td index 3a790890909a..434a70b1fbc9 100644 --- a/llvm/tools/llvm-nm/Opts.td +++ b/llvm/tools/llvm-nm/Opts.td @@ -13,6 +13,7 @@ multiclass Eq { def : Separate<["--"], name>, Alias(NAME #_EQ)>; } +def X : JoinedOrSeparate<["-"], "X">, HelpText<"Specifies the type of ELF, XCOFF, or IR object file to examine. The value must be one of: 32, 64, 32_64, any (default)">; def debug_syms : FF<"debug-syms", "Show all symbols, even debugger only">; def defined_only : FF<"defined-only", "Show only defined symbols">; defm demangle : BB<"demangle", "Demangle C++ symbol names", "Don't demangle symbol names">; diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index b5d78d1d8c4b..2196faf933b8 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -83,9 +83,11 @@ public: }; enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols }; +enum class BitModeTy { Bit32, Bit64, Bit32_64, Any }; } // namespace static bool ArchiveMap; +static BitModeTy BitMode; static bool DebugSyms; static bool DefinedOnly; static bool Demangle; @@ -1624,9 +1626,23 @@ static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO) { } } +static bool shouldDump(SymbolicFile &Obj) { + // The -X option is currently only implemented for XCOFF, ELF, and IR object + // files. The option isn't fundamentally impossible with other formats, just + // isn't implemented. + if (!isa(Obj) && !isa(Obj) && + !isa(Obj)) + return true; + + return isSymbolList64Bit(Obj) ? BitMode != BitModeTy::Bit32 + : BitMode != BitModeTy::Bit64; +} + static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, StringRef ArchiveName = {}, StringRef ArchitectureName = {}) { + if (!shouldDump(Obj)) + return; auto Symbols = Obj.symbols(); std::vector SymbolVersions; if (DynamicSyms) { @@ -1830,7 +1846,7 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { } if (!checkMachOAndArchFlags(O, Filename)) return; - if (!PrintFileName) { + if (!PrintFileName && shouldDump(*O)) { outs() << "\n"; if (isa(O)) { outs() << Filename << "(" << O->getFileName() << ")"; @@ -2168,6 +2184,18 @@ int main(int argc, char **argv) { UndefinedOnly = Args.hasArg(OPT_undefined_only); WithoutAliases = Args.hasArg(OPT_without_aliases); + StringRef Mode = Args.getLastArgValue(OPT_X, "any"); + if (Mode == "32") + BitMode = BitModeTy::Bit32; + else if (Mode == "64") + BitMode = BitModeTy::Bit64; + else if (Mode == "32_64") + BitMode = BitModeTy::Bit32_64; + else if (Mode == "any") + BitMode = BitModeTy::Any; + else + error("-X value should be one of: 32, 64, 32_64, (default) any"); + // Mach-O specific options. FormatMachOasHex = Args.hasArg(OPT_x); AddDyldInfo = Args.hasArg(OPT_add_dyldinfo);