llvm-nm.cpp revision 820428711f651a6ae6b9caf78ae170a4434d1670
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//===----------------------------------------------------------------------===// 9972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// 10972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// This program is a utility that works like traditional Unix "nm", 11972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// that is, it prints out the names of symbols in a bytecode file, 12972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// along with some information about each symbol. 13972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// 14972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// This "nm" does not print symbols' addresses. It supports many of 15972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// the features of GNU "nm", including its different output formats. 16972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke// 17972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke//===----------------------------------------------------------------------===// 18972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 19972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include "llvm/Module.h" 2008020c13d026c6b61ca68e3f9da127a4d8be36baChris Lattner#include "llvm/Bytecode/Reader.h" 2108020c13d026c6b61ca68e3f9da127a4d8be36baChris Lattner#include "Support/CommandLine.h" 221c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke#include "Support/FileUtilities.h" 23972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include <cctype> 2408d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke#include <cstring> 25972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 26d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekeusing namespace llvm; 27d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 28972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekenamespace { 29972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke enum OutputFormatTy { bsd, sysv, posix }; 30972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<OutputFormatTy> 31972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke OutputFormat("format", 32972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Specify output format"), 33972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::values(clEnumVal(bsd, "BSD format"), 34972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke clEnumVal(sysv, "System V format"), 35972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke clEnumVal(posix, "POSIX.2 format"), 0), cl::init(bsd)); 36972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias OutputFormat2("f", cl::desc("Alias for --format"), 37972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(OutputFormat)); 38972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 39972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::list<std::string> 40972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke InputFilenames(cl::Positional, cl::desc("<input bytecode files>"), 41fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner cl::ZeroOrMore); 42972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 43972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> UndefinedOnly("undefined-only", 44972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only undefined symbols")); 45972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), 46972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(UndefinedOnly)); 47972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 48972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> DefinedOnly("defined-only", 49972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only defined symbols")); 50972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 51972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> ExternalOnly("extern-only", 52972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only external symbols")); 53972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), 54972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(ExternalOnly)); 55972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 56972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd")); 57972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix")); 58972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 59972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke bool MultipleFiles = false; 60972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 61972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string ToolName; 62972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke}; 63972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 64972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekechar TypeCharForSymbol (GlobalValue &GV) { 65972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.isExternal ()) return 'U'; 66972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasLinkOnceLinkage ()) return 'C'; 67972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasWeakLinkage ()) return 'W'; 68972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<Function> (GV) && GV.hasInternalLinkage ()) return 't'; 69972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<Function> (GV)) return 'T'; 70972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<GlobalVariable> (GV) && GV.hasInternalLinkage ()) return 'd'; 71972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<GlobalVariable> (GV)) return 'D'; 72972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return '?'; 73972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 74972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 75972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNameForGlobalValue (GlobalValue &GV) { 76972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke const std::string SymbolAddrStr = " "; // Not used yet... 77972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke char TypeChar = TypeCharForSymbol (GV); 78972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if ((TypeChar != 'U') && UndefinedOnly) 79972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 80972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if ((TypeChar == 'U') && DefinedOnly) 81972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 82972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasInternalLinkage () && ExternalOnly) 83972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 84972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (OutputFormat == posix) { 85972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << GV.getName () << " " << TypeCharForSymbol (GV) << " " 86972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << SymbolAddrStr << "\n"; 87972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else if (OutputFormat == bsd) { 88972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << SymbolAddrStr << " " << TypeCharForSymbol (GV) << " " 89972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << GV.getName () << "\n"; 90972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else if (OutputFormat == sysv) { 91972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string PaddedName (GV.getName ()); 92972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke while (PaddedName.length () < 20) 93972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke PaddedName += " "; 94972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << PaddedName << "|" << SymbolAddrStr << "| " 95972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << TypeCharForSymbol (GV) 96972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << " | | | |\n"; 97972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 98972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 99972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 100972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNamesFromModule (Module *M) { 1011c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke const std::string &Filename = M->getModuleIdentifier (); 1021c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke if (OutputFormat == posix && MultipleFiles) { 1031c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cout << Filename << ":\n"; 1041c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } else if (OutputFormat == bsd && MultipleFiles) { 1051c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cout << "\n" << Filename << ":\n"; 1061c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } else if (OutputFormat == sysv) { 1071c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cout << "\n\nSymbols from " << Filename << ":\n\n" 1081c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke << "Name Value Class Type" 1091c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke << " Size Line Section\n"; 1101c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } 111972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::for_each (M->begin (), M->end (), DumpSymbolNameForGlobalValue); 112972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::for_each (M->gbegin (), M->gend (), DumpSymbolNameForGlobalValue); 113972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 114972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 115972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNamesFromFile (std::string &Filename) { 116972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string ErrorMessage; 11708d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke if (!FileOpenable (Filename)) { 11808d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke std::cerr << ToolName << ": " << Filename << ": " << strerror (errno) 11908d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke << "\n"; 12008d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke return; 12108d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke } 1221c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke if (IsBytecode (Filename)) { 1231c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke Module *Result = ParseBytecodeFile(Filename, &ErrorMessage); 1241c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke if (Result) { 1251c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke DumpSymbolNamesFromModule (Result); 1261c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } else { 1271c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; 12808d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke return; 129972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 1301c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } else if (IsArchive (Filename)) { 1311c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::vector<Module *> Modules; 13208d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke if (ReadArchiveFile (Filename, Modules, &ErrorMessage)) { 1331c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cerr << ToolName << ": " << Filename << ": " 1341c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke << ErrorMessage << "\n"; 13508d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke return; 13608d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke } 1371c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke MultipleFiles = true; 1381c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::for_each (Modules.begin (), Modules.end (), DumpSymbolNamesFromModule); 139820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke } else { 140820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke std::cerr << ToolName << ": " << Filename << ": " 141820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke << "unrecognizable file type\n"; 142820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke return; 143972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 144972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 145972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 146972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekeint main(int argc, char **argv) { 147972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::ParseCommandLineOptions(argc, argv, " llvm symbol table dumper\n"); 148972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke ToolName = argv[0]; 149972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (BSDFormat) OutputFormat = bsd; 150972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (POSIXFormat) OutputFormat = posix; 151fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner 152fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner switch (InputFilenames.size()) { 153fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner case 0: InputFilenames.push_back("-"); 154fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner case 1: break; 155fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner default: MultipleFiles = true; 156fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner } 157972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 158972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::for_each (InputFilenames.begin (), InputFilenames.end (), 159972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke DumpSymbolNamesFromFile); 160972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return 0; 161972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 162