diff --git a/llvm/docs/CommandGuide/llvm-nm.rst b/llvm/docs/CommandGuide/llvm-nm.rst --- a/llvm/docs/CommandGuide/llvm-nm.rst +++ b/llvm/docs/CommandGuide/llvm-nm.rst @@ -130,7 +130,7 @@ Show all symbols, even those usually suppressed. -.. option:: --defined-only, -U +.. option:: --defined-only Print only symbols defined in this file. @@ -157,11 +157,7 @@ Print a summary of command-line options and their meanings. -.. option:: --help-list - - Print an uncategorized summary of command-line options and their meanings. - -.. option:: --just-symbol-name, -j +.. option:: -j Print just the symbol names. Alias for `--format=just-symbols``. @@ -181,7 +177,7 @@ Show symbols in the order encountered. -.. option:: --no-weak, -W +.. option:: --no-weak Don't print weak symbols. @@ -193,7 +189,7 @@ Use POSIX.2 output format. Alias for ``--format=posix``. -.. option:: --print-armap, -M +.. option:: --print-armap Print the archive symbol table, in addition to the symbols. @@ -235,10 +231,6 @@ Display the version of the :program:`llvm-nm` executable, then exit. Does not stack with other commands. -.. option:: --without-aliases - - Exclude aliases from the output. - .. option:: @ Read command-line options from response file ``. @@ -267,7 +259,7 @@ Do not add any symbols from the dyldinfo. -.. option:: -s= +.. option:: -s
Dump only symbols from this segment and section name. diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -169,6 +169,13 @@ ``--section-details`` respectively, to match llvm-readelf. (`D105055 `_) +* The llvm-nm short aliases ``-M`` (``--print-armap``), ``-U`` + (``--defined-only``), and ``-W`` (``--no-weak``) are now deprecated. + Use the long form versions instead. + The alias ``--just-symbol-name`` is now deprecated in favor of + ``--format=just-symbols`` and ``-j``. + (`D105330 `_) + Changes to LLDB --------------------------------- diff --git a/llvm/test/Object/nm-universal-binary.test b/llvm/test/Object/nm-universal-binary.test --- a/llvm/test/Object/nm-universal-binary.test +++ b/llvm/test/Object/nm-universal-binary.test @@ -5,9 +5,9 @@ RUN: llvm-nm --arch=x86_64 %p/Inputs/macho-universal.x86_64.i386 \ RUN: | FileCheck %s -check-prefix CHECK-OBJ-x86_64 RUN: not llvm-nm --arch=armv7m %p/Inputs/macho-universal.x86_64.i386 2>&1 \ -RUN: | FileCheck %s -check-prefix CHECK-OBJ-armv7m +RUN: | FileCheck %s --check-prefix=CHECK-OBJ-armv7m --implicit-check-not=error: RUN: not llvm-nm --arch=foobar %p/Inputs/macho-universal.x86_64.i386 2>&1 \ -RUN: | FileCheck %s -check-prefix CHECK-OBJ-foobar +RUN: | FileCheck %s --check-prefix=CHECK-OBJ-foobar --implicit-check-not=error: RUN: llvm-nm --arch=all %p/Inputs/macho-universal-archive.x86_64.i386 \ RUN: | FileCheck %s -check-prefix CHECK-AR RUN: llvm-nm --arch=all %p/Inputs/macho-universal64-archive.x86_64.i386 \ @@ -31,11 +31,9 @@ CHECK-OBJ-x86_64: 0000000100000f60 T _main CHECK-OBJ-x86_64: U dyld_stub_binder -CHECK-OBJ-armv7m-NOT: Unknown architecture named -CHECK-OBJ-armv7m: does not contain architecture +CHECK-OBJ-armv7m: error: file: {{.*}} does not contain architecture -CHECK-OBJ-foobar: Unknown architecture named -CHECK-OBJ-foobar: does not contain architecture +CHECK-OBJ-foobar: error: for the --arch option: Unknown architecture named 'foobar' CHECK-AR: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64): CHECK-AR: 0000000000000068 s EH_frame0 diff --git a/llvm/test/tools/llvm-nm/X86/radix.s b/llvm/test/tools/llvm-nm/X86/radix.s --- a/llvm/test/tools/llvm-nm/X86/radix.s +++ b/llvm/test/tools/llvm-nm/X86/radix.s @@ -2,7 +2,8 @@ // RUN: llvm-mc %s -filetype=obj -triple=x86_64-pc-linux -o %t.o // RUN: llvm-nm --radix=d %t.o | FileCheck %s // RUN: llvm-nm --radix=o %t.o | FileCheck --check-prefix=OCTAL %s -// RUN: llvm-nm -t=x %t.o | FileCheck --check-prefix=HEX %s +// RUN: llvm-nm -tx %t.o | FileCheck --check-prefix=HEX %s +// RUN: llvm-nm -t x %t.o | FileCheck --check-prefix=HEX %s .text .file "1.c" diff --git a/llvm/test/tools/llvm-nm/format-bsd.test b/llvm/test/tools/llvm-nm/format-bsd.test --- a/llvm/test/tools/llvm-nm/format-bsd.test +++ b/llvm/test/tools/llvm-nm/format-bsd.test @@ -3,7 +3,7 @@ # RUN: yaml2obj %s -o %t.o # RUN: llvm-nm %t.o --format=bsd > %t.formatbsd.txt -# RUN: llvm-nm %t.o -f=bsd > %t.fbsd.txt +# RUN: llvm-nm %t.o -f bsd > %t.fbsd.txt # RUN: llvm-nm %t.o -B > %t.b.txt # RUN: llvm-nm %t.o > %t.default.txt diff --git a/llvm/test/tools/llvm-nm/format-sysv-layout.test b/llvm/test/tools/llvm-nm/format-sysv-layout.test --- a/llvm/test/tools/llvm-nm/format-sysv-layout.test +++ b/llvm/test/tools/llvm-nm/format-sysv-layout.test @@ -1,6 +1,7 @@ # RUN: yaml2obj %s -o %t.o # RUN: llvm-nm %t.o --debug-syms --format=sysv | FileCheck %s -DFILE=%t.o --strict-whitespace -# RUN: llvm-nm %t.o --debug-syms -f=sysv | FileCheck %s -DFILE=%t.o --strict-whitespace +# RUN: llvm-nm %t.o --debug-syms -fsysv | FileCheck %s -DFILE=%t.o --strict-whitespace +# RUN: llvm-nm %t.o --debug-syms -f sysv | FileCheck %s -DFILE=%t.o --strict-whitespace !ELF FileHeader: diff --git a/llvm/test/tools/llvm-nm/help.test b/llvm/test/tools/llvm-nm/help.test --- a/llvm/test/tools/llvm-nm/help.test +++ b/llvm/test/tools/llvm-nm/help.test @@ -1,3 +1,10 @@ RUN: llvm-nm --help 2>&1 | FileCheck --implicit-check-not="General Options:" %s -CHECK: Generic Options: -CHECK: llvm-nm Options: +RUN: llvm-nm -h 2>&1 | FileCheck --implicit-check-not="General Options:" %s +CHECK: OPTIONS: +CHECK: --debug-syms +CHECK: --demangle +CHECK: --format= +CHECK: llvm-nm Mach-O Specific Options: +CHECK: --arch= +CHECK: -s +CHECK: Pass @FILE {{.*}} diff --git a/llvm/test/tools/llvm-nm/just-symbols.test b/llvm/test/tools/llvm-nm/just-symbols.test --- a/llvm/test/tools/llvm-nm/just-symbols.test +++ b/llvm/test/tools/llvm-nm/just-symbols.test @@ -7,7 +7,7 @@ # RUN: llvm-nm --just-symbol-name %t.o | diff %t.txt - # RUN: llvm-nm --format=just-symbols %t.o | diff %t.txt - # RUN: llvm-nm --format=sysv -j %t.o | diff %t.txt - -# RUN: llvm-nm -j --format=posix %t.o | diff %t.txt - +# RUN: llvm-nm -j --format=posix %t.o | not diff -q %t.txt %t1.txt # RUN: FileCheck %s --input-file=%t.txt --implicit-check-not={{.}} --check-prefix=COMMON diff --git a/llvm/test/tools/llvm-nm/libtool-version.test b/llvm/test/tools/llvm-nm/libtool-version.test --- a/llvm/test/tools/llvm-nm/libtool-version.test +++ b/llvm/test/tools/llvm-nm/libtool-version.test @@ -4,5 +4,5 @@ RUN: llvm-nm -V | FileCheck %s RUN: llvm-nm --version | FileCheck %s -CHECK: LLVM version CHECK: GNU +CHECK: LLVM version diff --git a/llvm/tools/llvm-nm/CMakeLists.txt b/llvm/tools/llvm-nm/CMakeLists.txt --- a/llvm/tools/llvm-nm/CMakeLists.txt +++ b/llvm/tools/llvm-nm/CMakeLists.txt @@ -6,14 +6,20 @@ Core Demangle Object + Option Support TextAPI ) +set(LLVM_TARGET_DEFINITIONS Opts.td) +tablegen(LLVM Opts.inc -gen-opt-parser-defs) +add_public_tablegen_target(NmOptsTableGen) + add_llvm_tool(llvm-nm llvm-nm.cpp DEPENDS + NmOptsTableGen intrinsics_gen ) diff --git a/llvm/tools/llvm-nm/Opts.td b/llvm/tools/llvm-nm/Opts.td new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-nm/Opts.td @@ -0,0 +1,76 @@ +include "llvm/Option/OptParser.td" + +class F : Flag<["-"], letter>, HelpText; +class FF : Flag<["--", "-"], name>, HelpText; + +multiclass BB { + def NAME: Flag<["--", "-"], name>, HelpText; + def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText; +} + +multiclass Eq { + def NAME #_EQ : Joined<["--", "-"], name #"=">, + HelpText; + def : Separate<["--", "-"], name>, Alias(NAME #_EQ)>; +} + +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">; +def dynamic : FF<"dynamic", "Display dynamic symbols instead of normal symbols">; +def extern_only : FF<"extern-only", "Show only external symbols">; +defm format : Eq<"format", "Specify output format: bsd (default), posix, sysv, darwin, just-symbols">, MetaVarName<"">; +def help : FF<"help", "Display this help">; +def no_llvm_bc : FF<"no-llvm-bc", "Disable LLVM bitcode reader">; +def no_sort : FF<"no-sort", "Show symbols in order encountered">; +def no_weak : FF<"no-weak", "Show only non-weak symbols">; +def numeric_sort : FF<"numeric-sort", "Sort symbols by address">; +def print_armap : FF<"print-armap", "Print the archive map">; +def print_file_name : FF<"print-file-name", "Precede each symbol with the object file it came from">; +def print_size : FF<"print-size", "Show symbol size as well as address">; +def quiet : FF<"quiet", "Suppress 'no symbols' diagnostic">; +defm radix : Eq<"radix", "Radix (o/d/x) for printing symbol Values">, MetaVarName<"">; +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 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]>; + +// Mach-O specific options. +def grp_mach_o : OptionGroup<"kind">, HelpText<"llvm-nm Mach-O Specific Options">; + +def add_dyldinfo : FF<"add-dyldinfo", "Add symbols from the dyldinfo not already in the symbol table">, Group; +def add_inlinedinfo : FF<"add-inlinedinfo", "Add symbols from the inlined libraries, TBD only">, Group; +defm arch : Eq<"arch", "architecture(s) from a Mach-O file to dump">, Group; +def dyldinfo_only : FF<"dyldinfo-only", "Show only symbols from the dyldinfo">, Group; +def no_dyldinfo : FF<"no-dyldinfo", "Don't add any symbols from the dyldinfo">, Group; +def s : F<"s", "Dump only symbols from this segment and section name">, Group; +def x : F<"x", "Print symbol entry in hex">, Group; + +def : FF<"just-symbol-name", "Alias for --format=just-symbols">, Alias, AliasArgs<["just-symbols"]>, Flags<[HelpHidden]>; +def : FF<"portability", "Alias for --format=posix">, Alias, AliasArgs<["posix"]>; + +def : F<"a", "Alias for --debug-syms">, Alias; +def : F<"A", "Alias for --print-file-name">, Alias; +def : F<"B", "Alias for --format=bsd">, Alias, AliasArgs<["bsd"]>; +def : F<"C", "Alias for --demangle">, Alias; +def : F<"D", "Alias for --dynamic">, Alias; +def : JoinedOrSeparate<["-"], "f">, HelpText<"Alias for --format">, Alias, MetaVarName<"">; +def : F<"h", "Alias for --help">, Alias; +def : F<"g", "Alias for --extern-only">, Alias; +def : F<"j", "Alias for --format=just-symbols">, Alias, AliasArgs<["just-symbols"]>; +def : F<"m", "Alias for --format=darwin">, Alias, AliasArgs<["darwin"]>; +def : F<"M", "Deprecated alias for --print-armap">, Alias, Flags<[HelpHidden]>; +def : F<"n", "Alias for --numeric-sort">, Alias; +def : F<"o", "Alias for --print-file-name">, Alias; +def : F<"p", "Alias for --no-sort">, Alias; +def : F<"P", "Alias for --format=posix">, Alias, AliasArgs<["posix"]>; +def : F<"r", "Alias for --reverse-sort">, Alias; +def : F<"S", "Alias for --print-size">, Alias; +def : JoinedOrSeparate<["-"], "t">, HelpText<"Alias for --radix">, Alias, MetaVarName<"">; +def : F<"u", "Alias for --undefined-only">, Alias; +def : F<"U", "Deprecated alias for --defined-only">, Alias, Flags<[HelpHidden]>; +def : F<"v", "Alias for --numeric-sort">, Alias; +def : F<"V", "Alias for --version">, Alias; +def : F<"W", "Deprecated alias for --no-weak">, Alias, Flags<[HelpHidden]>; diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -31,6 +31,9 @@ #include "llvm/Object/TapiFile.h" #include "llvm/Object/TapiUniversal.h" #include "llvm/Object/Wasm.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" @@ -47,200 +50,82 @@ using namespace object; namespace { +using namespace llvm::opt; // for HelpHidden in Opts.inc +enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + OPT_##ID, +#include "Opts.inc" +#undef OPTION +}; + +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#include "Opts.inc" +#undef PREFIX + +static const opt::OptTable::Info InfoTable[] = { +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + { \ + PREFIX, NAME, HELPTEXT, \ + METAVAR, OPT_##ID, opt::Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, \ + OPT_##ALIAS, ALIASARGS, VALUES}, +#include "Opts.inc" +#undef OPTION +}; + +class NmOptTable : public opt::OptTable { +public: + NmOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); } +}; + enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols }; +} // namespace -cl::OptionCategory NMCat("llvm-nm Options"); - -cl::opt OutputFormat( - "format", cl::desc("Specify output format"), - cl::values(clEnumVal(bsd, "BSD format"), clEnumVal(sysv, "System V format"), - clEnumVal(posix, "POSIX.2 format"), - clEnumVal(darwin, "Darwin -m format"), - cl::OptionEnumValue{"just-symbols", int(just_symbols), - "just symbol names"}), - cl::init(bsd), cl::cat(NMCat)); -cl::alias OutputFormat2("f", cl::desc("Alias for --format"), - cl::aliasopt(OutputFormat), cl::NotHidden); - -cl::list InputFilenames(cl::Positional, cl::desc(""), - cl::ZeroOrMore); - -cl::opt UndefinedOnly("undefined-only", - cl::desc("Show only undefined symbols"), - cl::cat(NMCat)); -cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), - cl::aliasopt(UndefinedOnly), cl::Grouping, - cl::NotHidden); - -cl::opt DynamicSyms("dynamic", - cl::desc("Display the dynamic symbols instead " - "of normal symbols."), - cl::cat(NMCat)); -cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"), - cl::aliasopt(DynamicSyms), cl::Grouping, cl::NotHidden); - -cl::opt DefinedOnly("defined-only", cl::desc("Show only defined symbols"), - cl::cat(NMCat)); -cl::alias DefinedOnly2("U", cl::desc("Alias for --defined-only"), - cl::aliasopt(DefinedOnly), cl::Grouping, cl::NotHidden); - -cl::opt ExternalOnly("extern-only", - cl::desc("Show only external symbols"), - cl::ZeroOrMore, cl::cat(NMCat)); -cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), - cl::aliasopt(ExternalOnly), cl::Grouping, - cl::ZeroOrMore, cl::NotHidden); - -cl::opt NoWeakSymbols("no-weak", cl::desc("Show only non-weak symbols"), - cl::cat(NMCat)); -cl::alias NoWeakSymbols2("W", cl::desc("Alias for --no-weak"), - cl::aliasopt(NoWeakSymbols), cl::Grouping, - cl::NotHidden); - -cl::opt BSDFormat("B", cl::desc("Alias for --format=bsd"), cl::Grouping, - cl::cat(NMCat)); -cl::opt POSIXFormat("P", cl::desc("Alias for --format=posix"), - cl::Grouping, cl::cat(NMCat)); -cl::alias Portability("portability", cl::desc("Alias for --format=posix"), - cl::aliasopt(POSIXFormat), cl::NotHidden); -cl::opt DarwinFormat("m", cl::desc("Alias for --format=darwin"), - cl::Grouping, cl::cat(NMCat), cl::NotHidden); - -static cl::list - ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), - cl::ZeroOrMore, cl::cat(NMCat)); -bool ArchAll = false; - -cl::opt PrintFileName( - "print-file-name", - cl::desc("Precede each symbol with the object file it came from"), - cl::cat(NMCat)); - -cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"), - cl::aliasopt(PrintFileName), cl::Grouping, - cl::NotHidden); -cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"), - cl::aliasopt(PrintFileName), cl::Grouping, - cl::NotHidden); - -cl::opt Quiet("quiet", cl::desc("Suppress 'no symbols' diagnostic"), - cl::cat(NMCat)); - -cl::opt DebugSyms("debug-syms", - cl::desc("Show all symbols, even debugger only"), - cl::cat(NMCat)); -cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"), - cl::aliasopt(DebugSyms), cl::Grouping, cl::NotHidden); - -cl::opt NumericSort("numeric-sort", cl::desc("Sort symbols by address"), - cl::cat(NMCat)); -cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"), - cl::aliasopt(NumericSort), cl::Grouping, cl::NotHidden); -cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"), - cl::aliasopt(NumericSort), cl::Grouping, cl::NotHidden); - -cl::opt NoSort("no-sort", cl::desc("Show symbols in order encountered"), - cl::cat(NMCat)); -cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort), - cl::Grouping, cl::NotHidden); - -cl::opt Demangle("demangle", cl::ZeroOrMore, - cl::desc("Demangle C++ symbol names"), cl::cat(NMCat)); -cl::alias DemangleC("C", cl::desc("Alias for --demangle"), - cl::aliasopt(Demangle), cl::Grouping, cl::NotHidden); -cl::opt NoDemangle("no-demangle", cl::init(false), cl::ZeroOrMore, - cl::desc("Don't demangle symbol names"), - cl::cat(NMCat)); - -cl::opt ReverseSort("reverse-sort", cl::desc("Sort in reverse order"), - cl::cat(NMCat)); -cl::alias ReverseSortr("r", cl::desc("Alias for --reverse-sort"), - cl::aliasopt(ReverseSort), cl::Grouping, cl::NotHidden); - -cl::opt PrintSize("print-size", - cl::desc("Show symbol size as well as address"), - cl::cat(NMCat)); -cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"), - cl::aliasopt(PrintSize), cl::Grouping, cl::NotHidden); -bool MachOPrintSizeWarning = false; - -cl::opt SizeSort("size-sort", cl::desc("Sort symbols by size"), - cl::cat(NMCat)); - -cl::opt WithoutAliases("without-aliases", cl::Hidden, - cl::desc("Exclude aliases from output"), - cl::cat(NMCat), cl::NotHidden); - -cl::opt ArchiveMap("print-armap", cl::desc("Print the archive map"), - cl::cat(NMCat)); -cl::alias ArchiveMaps("M", cl::desc("Alias for --print-armap"), - cl::aliasopt(ArchiveMap), cl::Grouping, cl::NotHidden); +static bool ArchiveMap; +static bool DebugSyms; +static bool DefinedOnly; +static bool Demangle; +static bool DynamicSyms; +static bool ExternalOnly; +static OutputFormatTy OutputFormat; +static bool NoLLVMBitcode; +static bool NoSort; +static bool NoWeakSymbols; +static bool NumericSort; +static bool PrintFileName; +static bool PrintSize; +static bool Quiet; +static bool ReverseSort; +static bool SpecialSyms; +static bool SizeSort; +static bool UndefinedOnly; +static bool WithoutAliases; +namespace { enum Radix { d, o, x }; -cl::opt - AddressRadix("radix", cl::desc("Radix (o/d/x) for printing symbol Values"), - cl::values(clEnumVal(d, "decimal"), clEnumVal(o, "octal"), - clEnumVal(x, "hexadecimal")), - cl::init(x), cl::cat(NMCat)); -cl::alias RadixAlias("t", cl::desc("Alias for --radix"), - cl::aliasopt(AddressRadix), cl::NotHidden); - -cl::opt JustSymbolName("just-symbol-name", - cl::desc("Alias for --format=just-symbols"), - cl::cat(NMCat), cl::NotHidden); -cl::alias JustSymbolNames("j", cl::desc("Alias for --format-just-symbols"), - cl::aliasopt(JustSymbolName), cl::Grouping, - cl::NotHidden); - -cl::opt - SpecialSyms("special-syms", - cl::desc("Do not filter special symbols from the output"), - cl::cat(NMCat)); - -cl::list SegSect("s", cl::multi_val(2), cl::ZeroOrMore, - cl::value_desc("segment section"), cl::Hidden, - cl::desc("Dump only symbols from this segment " - "and section name, Mach-O only"), - cl::cat(NMCat)); - -cl::opt FormatMachOasHex("x", - cl::desc("Print symbol entry in hex, " - "Mach-O only"), - cl::Grouping, cl::cat(NMCat)); -cl::opt AddDyldInfo("add-dyldinfo", - cl::desc("Add symbols from the dyldinfo not already " - "in the symbol table, Mach-O only"), - cl::cat(NMCat)); -cl::opt NoDyldInfo("no-dyldinfo", - cl::desc("Don't add any symbols from the dyldinfo, " - "Mach-O only"), - cl::cat(NMCat)); -cl::opt DyldInfoOnly("dyldinfo-only", - cl::desc("Show only symbols from the dyldinfo, " - "Mach-O only"), - cl::cat(NMCat)); - -cl::opt NoLLVMBitcode("no-llvm-bc", - cl::desc("Disable LLVM bitcode reader"), - cl::cat(NMCat)); - -cl::opt AddInlinedInfo("add-inlinedinfo", - cl::desc("Add symbols from the inlined libraries, " - "TBD(Mach-O) only"), - cl::cat(NMCat)); - -cl::opt Version("V", cl::desc("Print version info"), cl::cat(NMCat)); - -cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); - -bool PrintAddress = true; - -bool MultipleFiles = false; - -bool HadError = false; - -std::string ToolName; -} // anonymous namespace +} // namespace +static Radix AddressRadix; + +// Mach-O specific options. +static bool ArchAll = false; +static std::vector ArchFlags; +static bool AddDyldInfo; +static bool AddInlinedInfo; +static bool DyldInfoOnly; +static bool FormatMachOasHex; +static bool NoDyldInfo; +static std::vector SegSect; +static bool MachOPrintSizeWarning = false; + +// Miscellaneous states. +static bool PrintAddress = true; +static bool MultipleFiles = false; +static bool HadError = false; + +static StringRef ToolName; static void error(Twine Message, Twine Path = Twine()) { HadError = true; @@ -2237,23 +2122,83 @@ } } -static void printExtraVersionInfo(raw_ostream &Outs) { - // This needs to contain the word "GNU", libtool looks for that string. - Outs << "llvm-nm, compatible with GNU nm\n"; -} - int main(int argc, char **argv) { InitLLVM X(argc, argv); - cl::HideUnrelatedOptions(NMCat); - cl::AddExtraVersionPrinter(printExtraVersionInfo); - cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n"); - - if (Version) { + BumpPtrAllocator A; + StringSaver Saver(A); + NmOptTable Tbl; + ToolName = argv[0]; + opt::InputArgList Args = + Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { + error(Msg); + exit(1); + }); + if (Args.hasArg(OPT_help)) { + Tbl.printHelp( + outs(), + (Twine(ToolName) + " [options] ").str().c_str(), + "LLVM symbol table dumper"); + // TODO Replace this with OptTable API once it adds extrahelp support. + outs() << "\nPass @FILE as argument to read options from FILE.\n"; + return 0; + } + if (Args.hasArg(OPT_version)) { + // This needs to contain the word "GNU", libtool looks for that string. + outs() << "llvm-nm, compatible with GNU nm" << '\n'; cl::PrintVersionMessage(); - printExtraVersionInfo(outs()); return 0; } + DebugSyms = Args.hasArg(OPT_debug_syms); + DefinedOnly = Args.hasArg(OPT_defined_only); + Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false); + DynamicSyms = Args.hasArg(OPT_dynamic); + ExternalOnly = Args.hasArg(OPT_extern_only); + StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd"); + if (V == "bsd") + OutputFormat = bsd; + else if (V == "posix") + OutputFormat = posix; + else if (V == "sysv") + OutputFormat = sysv; + else if (V == "darwin") + OutputFormat = darwin; + else if (V == "just-symbols") + OutputFormat = just_symbols; + else + error("--format value should be one of: bsd, posix, sysv, darwin, " + "just-symbols"); + NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc); + NoSort = Args.hasArg(OPT_no_sort); + NoWeakSymbols = Args.hasArg(OPT_no_weak); + NumericSort = Args.hasArg(OPT_numeric_sort); + ArchiveMap = Args.hasArg(OPT_print_armap); + PrintFileName = Args.hasArg(OPT_print_file_name); + PrintSize = Args.hasArg(OPT_print_size); + ReverseSort = Args.hasArg(OPT_reverse_sort); + Quiet = Args.hasArg(OPT_quiet); + V = Args.getLastArgValue(OPT_radix_EQ, "x"); + if (V == "o") + AddressRadix = Radix::o; + else if (V == "d") + AddressRadix = Radix::d; + else if (V == "x") + AddressRadix = Radix::x; + else + error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' " + "(hexadecimal)"); + SizeSort = Args.hasArg(OPT_size_sort); + SpecialSyms = Args.hasArg(OPT_special_syms); + UndefinedOnly = Args.hasArg(OPT_undefined_only); + WithoutAliases = Args.hasArg(OPT_without_aliases); + + // Mach-O specific options. + FormatMachOasHex = Args.hasArg(OPT_x); + AddDyldInfo = Args.hasArg(OPT_add_dyldinfo); + AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo); + DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only); + NoDyldInfo = Args.hasArg(OPT_no_dyldinfo); + // llvm-nm only reads binary files. if (error(sys::ChangeStdinToBinary())) return 1; @@ -2263,16 +2208,6 @@ llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); - ToolName = argv[0]; - if (BSDFormat) - OutputFormat = bsd; - if (POSIXFormat) - OutputFormat = posix; - if (DarwinFormat) - OutputFormat = darwin; - if (JustSymbolName) - OutputFormat = just_symbols; - // The relative order of these is important. If you pass --size-sort it should // only print out the size. However, if you pass -S --size-sort, it should // print out both the size and address. @@ -2280,29 +2215,44 @@ PrintAddress = false; if (OutputFormat == sysv || SizeSort) PrintSize = true; - if (InputFilenames.empty()) - InputFilenames.push_back("a.out"); - if (InputFilenames.size() > 1) - MultipleFiles = true; - // If both --demangle and --no-demangle are specified then pick the last one. - if (NoDemangle.getPosition() > Demangle.getPosition()) - Demangle = !NoDemangle; - - for (unsigned i = 0; i < ArchFlags.size(); ++i) { - if (ArchFlags[i] == "all") { - ArchAll = true; - } else { - if (!MachOObjectFile::isValidArch(ArchFlags[i])) - error("Unknown architecture named '" + ArchFlags[i] + "'", + for (const auto *A : Args.filtered(OPT_arch_EQ)) { + SmallVector Values; + llvm::SplitString(A->getValue(), Values, ","); + for (StringRef V : Values) { + if (V == "all") + ArchAll = true; + else if (MachOObjectFile::isValidArch(V)) + ArchFlags.push_back(V); + else + error("Unknown architecture named '" + V + "'", "for the --arch option"); } } + // Mach-O takes -s to accept two arguments. We emulate this by iterating over + // both OPT_s and OPT_INPUT. + std::vector InputFilenames; + int SegSectArgs = 0; + for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) { + if (SegSectArgs > 0) { + --SegSectArgs; + SegSect.push_back(A->getValue()); + } else if (A->getOption().matches(OPT_s)) { + SegSectArgs = 2; + } else { + InputFilenames.push_back(A->getValue()); + } + } if (!SegSect.empty() && SegSect.size() != 2) error("bad number of arguments (must be two arguments)", "for the -s option"); + if (InputFilenames.empty()) + InputFilenames.push_back("a.out"); + if (InputFilenames.size() > 1) + MultipleFiles = true; + if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly)) error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only"); diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/llvm-nm/BUILD.gn @@ -1,6 +1,12 @@ import("//llvm/tools/binutils_symlinks.gni") +import("//llvm/utils/TableGen/tablegen.gni") import("//llvm/utils/gn/build/symlink_or_copy.gni") +tablegen("Opts") { + visibility = [ ":llvm-nm" ] + args = [ "-gen-opt-parser-defs" ] +} + if (llvm_install_binutils_symlinks) { symlink_or_copy("nm") { deps = [ ":llvm-nm" ] @@ -19,10 +25,12 @@ executable("llvm-nm") { deps = [ + ":Opts", "//llvm/lib/Bitcode/Reader", "//llvm/lib/Demangle", "//llvm/lib/IR", "//llvm/lib/Object", + "//llvm/lib/Option", "//llvm/lib/Support", "//llvm/lib/Target:AllTargetsAsmParsers", "//llvm/lib/Target:AllTargetsDescs", diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -3059,6 +3059,18 @@ ], ) +gentbl( + name = "NmOptsTableGen", + strip_include_prefix = "tools/llvm-nm", + tbl_outs = [( + "-gen-opt-parser-defs", + "tools/llvm-nm/Opts.inc", + )], + tblgen = ":llvm-tblgen", + td_file = "tools/llvm-nm/Opts.td", + td_srcs = ["include/llvm/Option/OptParser.td"], +) + cc_binary( name = "llvm-nm", srcs = glob([ @@ -3074,7 +3086,9 @@ ":BitReader", ":Core", ":Demangle", + ":NmOptsTableGen", ":Object", + ":Option", ":Support", ], )