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