llvm-nm.cpp revision fc046d52e442324fe238e572c314f86dbc894f92
1972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===// 2972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// 3972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// This program is a utility that works like traditional Unix "nm", 4972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// that is, it prints out the names of symbols in a bytecode file, 5972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// along with some information about each symbol. 6972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// 7972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// This "nm" does not print symbols' addresses. It supports many of 8972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// the features of GNU "nm", including its different output formats. 9972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// 10972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke//===----------------------------------------------------------------------===// 11972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 12972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include "Support/CommandLine.h" 13972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include "llvm/Bytecode/Reader.h" 14972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include "llvm/GlobalValue.h" 15972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include "llvm/Module.h" 16972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include <cctype> 17972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 18972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekenamespace { 19972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke enum OutputFormatTy { bsd, sysv, posix }; 20972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<OutputFormatTy> 21972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke OutputFormat("format", 22972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Specify output format"), 23972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::values(clEnumVal(bsd, "BSD format"), 24972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke clEnumVal(sysv, "System V format"), 25972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke clEnumVal(posix, "POSIX.2 format"), 0), cl::init(bsd)); 26972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias OutputFormat2("f", cl::desc("Alias for --format"), 27972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(OutputFormat)); 28972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 29972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::list<std::string> 30972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke InputFilenames(cl::Positional, cl::desc("<input bytecode files>"), 31fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner cl::ZeroOrMore); 32972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 33972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> UndefinedOnly("undefined-only", 34972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only undefined symbols")); 35972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), 36972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(UndefinedOnly)); 37972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 38972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> DefinedOnly("defined-only", 39972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only defined symbols")); 40972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 41972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> ExternalOnly("extern-only", 42972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only external symbols")); 43972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), 44972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(ExternalOnly)); 45972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 46972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd")); 47972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix")); 48972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 49972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke bool MultipleFiles = false; 50972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 51972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string ToolName; 52972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke}; 53972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 54972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekechar TypeCharForSymbol (GlobalValue &GV) { 55972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.isExternal ()) return 'U'; 56972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasLinkOnceLinkage ()) return 'C'; 57972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasWeakLinkage ()) return 'W'; 58972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<Function> (GV) && GV.hasInternalLinkage ()) return 't'; 59972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<Function> (GV)) return 'T'; 60972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<GlobalVariable> (GV) && GV.hasInternalLinkage ()) return 'd'; 61972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<GlobalVariable> (GV)) return 'D'; 62972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return '?'; 63972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 64972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 65972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNameForGlobalValue (GlobalValue &GV) { 66972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke const std::string SymbolAddrStr = " "; // Not used yet... 67972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke char TypeChar = TypeCharForSymbol (GV); 68972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if ((TypeChar != 'U') && UndefinedOnly) 69972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 70972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if ((TypeChar == 'U') && DefinedOnly) 71972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 72972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasInternalLinkage () && ExternalOnly) 73972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 74972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (OutputFormat == posix) { 75972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << GV.getName () << " " << TypeCharForSymbol (GV) << " " 76972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << SymbolAddrStr << "\n"; 77972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else if (OutputFormat == bsd) { 78972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << SymbolAddrStr << " " << TypeCharForSymbol (GV) << " " 79972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << GV.getName () << "\n"; 80972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else if (OutputFormat == sysv) { 81972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string PaddedName (GV.getName ()); 82972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke while (PaddedName.length () < 20) 83972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke PaddedName += " "; 84972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << PaddedName << "|" << SymbolAddrStr << "| " 85972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << TypeCharForSymbol (GV) 86972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << " | | | |\n"; 87972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 88972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 89972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 90972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNamesFromModule (Module *M) { 91972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::for_each (M->begin (), M->end (), DumpSymbolNameForGlobalValue); 92972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::for_each (M->gbegin (), M->gend (), DumpSymbolNameForGlobalValue); 93972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 94972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 95972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNamesFromFile (std::string &Filename) { 96972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string ErrorMessage; 97972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke Module *Result = ParseBytecodeFile(Filename, &ErrorMessage); 98972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (Result) { 99972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (OutputFormat == posix && MultipleFiles) { 100972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << Filename << ":\n"; 101972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else if (OutputFormat == bsd && MultipleFiles) { 102972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << "\n" << Filename << ":\n"; 103972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else if (OutputFormat == sysv) { 104972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << "\n\nSymbols from " << Filename << ":\n\n" 105972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << "Name Value Class Type" 106972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << " Size Line Section\n"; 107972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 108972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke DumpSymbolNamesFromModule (Result); 109972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else { 110972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; 111972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 112972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 113972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 114972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekeint main(int argc, char **argv) { 115972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::ParseCommandLineOptions(argc, argv, " llvm symbol table dumper\n"); 116972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke ToolName = argv[0]; 117972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (BSDFormat) OutputFormat = bsd; 118972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (POSIXFormat) OutputFormat = posix; 119fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner 120fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner switch (InputFilenames.size()) { 121fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner case 0: InputFilenames.push_back("-"); 122fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner case 1: break; 123fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner default: MultipleFiles = true; 124fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner } 125972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 126972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::for_each (InputFilenames.begin (), InputFilenames.end (), 127972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke DumpSymbolNamesFromFile); 128972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return 0; 129972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 130