From 972d3d7fff89c50612e86dfc8222da51bb23f387 Mon Sep 17 00:00:00 2001 From: Brian Gaeke Date: Thu, 16 Oct 2003 04:43:15 +0000 Subject: [PATCH] Okay, this is a little hack that "scratches an itch" of mine. I dislike having to examine the output of "dis" to see what symbols are in a bytecode file. So, here is a first cut at a "nm" utility for llvm. Flame away.... :-) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9153 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-nm/Makefile | 5 ++ tools/llvm-nm/llvm-nm.cpp | 127 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 tools/llvm-nm/Makefile create mode 100644 tools/llvm-nm/llvm-nm.cpp diff --git a/tools/llvm-nm/Makefile b/tools/llvm-nm/Makefile new file mode 100644 index 00000000000..eef5a0e2de4 --- /dev/null +++ b/tools/llvm-nm/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../.. + +TOOLNAME = llvm-nm +USEDLIBS = bcreader vmcore support.a +include $(LEVEL)/Makefile.common diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp new file mode 100644 index 00000000000..c819bb9307a --- /dev/null +++ b/tools/llvm-nm/llvm-nm.cpp @@ -0,0 +1,127 @@ +//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===// +// +// This program is a utility that works like traditional Unix "nm", +// that is, it prints out the names of symbols in a bytecode file, +// along with some information about each symbol. +// +// This "nm" does not print symbols' addresses. It supports many of +// the features of GNU "nm", including its different output formats. +// +//===----------------------------------------------------------------------===// + +#include "Support/CommandLine.h" +#include "llvm/Bytecode/Reader.h" +#include "llvm/GlobalValue.h" +#include "llvm/Module.h" +#include + +namespace { + enum OutputFormatTy { bsd, sysv, posix }; + 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"), 0), cl::init(bsd)); + cl::alias OutputFormat2("f", cl::desc("Alias for --format"), + cl::aliasopt(OutputFormat)); + + cl::list + InputFilenames(cl::Positional, cl::desc(""), + cl::OneOrMore); + + cl::opt UndefinedOnly("undefined-only", + cl::desc("Show only undefined symbols")); + cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), + cl::aliasopt(UndefinedOnly)); + + cl::opt DefinedOnly("defined-only", + cl::desc("Show only defined symbols")); + + cl::opt ExternalOnly("extern-only", + cl::desc("Show only external symbols")); + cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), + cl::aliasopt(ExternalOnly)); + + cl::opt BSDFormat("B", cl::desc("Alias for --format=bsd")); + cl::opt POSIXFormat("P", cl::desc("Alias for --format=posix")); + + bool MultipleFiles = false; + + std::string ToolName; +}; + +char TypeCharForSymbol (GlobalValue &GV) { + if (GV.isExternal ()) return 'U'; + if (GV.hasLinkOnceLinkage ()) return 'C'; +#ifdef WEAK_LINKAGE_EVENTUALLY_IMPLEMENTED + if (GV.hasWeakLinkage ()) return 'W'; +#endif + if (isa (GV) && GV.hasInternalLinkage ()) return 't'; + if (isa (GV)) return 'T'; + if (isa (GV) && GV.hasInternalLinkage ()) return 'd'; + if (isa (GV)) return 'D'; + return '?'; +} + +void DumpSymbolNameForGlobalValue (GlobalValue &GV) { + const std::string SymbolAddrStr = " "; // Not used yet... + char TypeChar = TypeCharForSymbol (GV); + if ((TypeChar != 'U') && UndefinedOnly) + return; + if ((TypeChar == 'U') && DefinedOnly) + return; + if (GV.hasInternalLinkage () && ExternalOnly) + return; + if (OutputFormat == posix) { + std::cout << GV.getName () << " " << TypeCharForSymbol (GV) << " " + << SymbolAddrStr << "\n"; + } else if (OutputFormat == bsd) { + std::cout << SymbolAddrStr << " " << TypeCharForSymbol (GV) << " " + << GV.getName () << "\n"; + } else if (OutputFormat == sysv) { + std::string PaddedName (GV.getName ()); + while (PaddedName.length () < 20) + PaddedName += " "; + std::cout << PaddedName << "|" << SymbolAddrStr << "| " + << TypeCharForSymbol (GV) + << " | | | |\n"; + } +} + +void DumpSymbolNamesFromModule (Module *M) { + std::for_each (M->begin (), M->end (), DumpSymbolNameForGlobalValue); + std::for_each (M->gbegin (), M->gend (), DumpSymbolNameForGlobalValue); +} + +void DumpSymbolNamesFromFile (std::string &Filename) { + std::string ErrorMessage; + Module *Result = ParseBytecodeFile(Filename, &ErrorMessage); + if (Result) { + if (OutputFormat == posix && MultipleFiles) { + std::cout << Filename << ":\n"; + } else if (OutputFormat == bsd && MultipleFiles) { + std::cout << "\n" << Filename << ":\n"; + } else if (OutputFormat == sysv) { + std::cout << "\n\nSymbols from " << Filename << ":\n\n" + << "Name Value Class Type" + << " Size Line Section\n"; + } + DumpSymbolNamesFromModule (Result); + } else { + std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; + } +} + +int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv, " llvm symbol table dumper\n"); + ToolName = argv[0]; + if (BSDFormat) OutputFormat = bsd; + if (POSIXFormat) OutputFormat = posix; + if (InputFilenames.size () != 1) + MultipleFiles = true; + + std::for_each (InputFilenames.begin (), InputFilenames.end (), + DumpSymbolNamesFromFile); + return 0; +} -- 2.34.1