llvm-nm.cpp revision d74ea2bbd8bb630331f35ead42d385249bd42af8
1972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===// 23da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 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. 73da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 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. 133da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 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" 2163efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer#include "llvm/Bytecode/Archive.h" 22551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h" 23bed85ff010b95923646ed4e187a5d432cedf67daChris Lattner#include "llvm/System/Signals.h" 24972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include <cctype> 2509233fb86e237715d138db5dc5b72ada386089f2Alkis Evlogimenos#include <cerrno> 2608d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke#include <cstring> 2786f42bdad93677fa0ca33b27afb0f493028376cbReid Spencer#include <iostream> 28972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 29d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekeusing namespace llvm; 30d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 31972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekenamespace { 32972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke enum OutputFormatTy { bsd, sysv, posix }; 33972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<OutputFormatTy> 34972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke OutputFormat("format", 35972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Specify output format"), 36972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::values(clEnumVal(bsd, "BSD format"), 37972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke clEnumVal(sysv, "System V format"), 383da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman clEnumVal(posix, "POSIX.2 format"), 394d143ee01988e1b52e106ffccbb313937ca5e886Chris Lattner clEnumValEnd), cl::init(bsd)); 40972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias OutputFormat2("f", cl::desc("Alias for --format"), 41972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(OutputFormat)); 42972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 433da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman cl::list<std::string> 44972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke InputFilenames(cl::Positional, cl::desc("<input bytecode files>"), 45fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner cl::ZeroOrMore); 46972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 47972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> UndefinedOnly("undefined-only", 48972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only undefined symbols")); 49972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), 50972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(UndefinedOnly)); 51972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 52972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> DefinedOnly("defined-only", 53972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only defined symbols")); 54972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 55972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> ExternalOnly("extern-only", 56972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::desc("Show only external symbols")); 57972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), 58972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::aliasopt(ExternalOnly)); 59972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 60972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd")); 61972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix")); 62972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 63972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke bool MultipleFiles = false; 64972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 65972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string ToolName; 66d74ea2bbd8bb630331f35ead42d385249bd42af8Chris Lattner} 67972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 68972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekechar TypeCharForSymbol (GlobalValue &GV) { 69972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.isExternal ()) return 'U'; 70972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasLinkOnceLinkage ()) return 'C'; 71972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasWeakLinkage ()) return 'W'; 72972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<Function> (GV) && GV.hasInternalLinkage ()) return 't'; 73972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<Function> (GV)) return 'T'; 74972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<GlobalVariable> (GV) && GV.hasInternalLinkage ()) return 'd'; 75972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (isa<GlobalVariable> (GV)) return 'D'; 76972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return '?'; 77972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 78972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 79972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNameForGlobalValue (GlobalValue &GV) { 80972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke const std::string SymbolAddrStr = " "; // Not used yet... 81972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke char TypeChar = TypeCharForSymbol (GV); 82972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if ((TypeChar != 'U') && UndefinedOnly) 83972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 84972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if ((TypeChar == 'U') && DefinedOnly) 85972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 86972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (GV.hasInternalLinkage () && ExternalOnly) 87972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke return; 88972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke if (OutputFormat == posix) { 89972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << GV.getName () << " " << TypeCharForSymbol (GV) << " " 90972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << SymbolAddrStr << "\n"; 91972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else if (OutputFormat == bsd) { 92972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << SymbolAddrStr << " " << TypeCharForSymbol (GV) << " " 93972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << GV.getName () << "\n"; 94972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } else if (OutputFormat == sysv) { 95972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string PaddedName (GV.getName ()); 96972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke while (PaddedName.length () < 20) 97972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke PaddedName += " "; 98972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::cout << PaddedName << "|" << SymbolAddrStr << "| " 99972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << TypeCharForSymbol (GV) 100972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke << " | | | |\n"; 101972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 102972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 103972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 104972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNamesFromModule (Module *M) { 1051c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke const std::string &Filename = M->getModuleIdentifier (); 1061c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke if (OutputFormat == posix && MultipleFiles) { 1071c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cout << Filename << ":\n"; 1081c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } else if (OutputFormat == bsd && MultipleFiles) { 1091c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cout << "\n" << Filename << ":\n"; 1101c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } else if (OutputFormat == sysv) { 1111c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cout << "\n\nSymbols from " << Filename << ":\n\n" 1121c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke << "Name Value Class Type" 1131c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke << " Size Line Section\n"; 1141c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } 115972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::for_each (M->begin (), M->end (), DumpSymbolNameForGlobalValue); 116a3fcfff63300e1fb8be99bcb0581dff580d9b291Chris Lattner std::for_each (M->global_begin (), M->global_end (), DumpSymbolNameForGlobalValue); 117972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 118972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 119972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekevoid DumpSymbolNamesFromFile (std::string &Filename) { 120972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke std::string ErrorMessage; 12111db4b8084270cb91446485b9534864ce52a95efReid Spencer sys::Path aPath(Filename); 122c7f083297cd796c2fadb534307e4ef406fd68945Reid Spencer if (Filename != "-" && !aPath.canRead()) { 12308d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke std::cerr << ToolName << ": " << Filename << ": " << strerror (errno) 12408d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke << "\n"; 12508d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke return; 12608d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke } 1278b1daa3e71109b8ae6a057a1def35ae0ab87ce37Brian Gaeke // Note: Currently we do not support reading an archive from stdin. 12811db4b8084270cb91446485b9534864ce52a95efReid Spencer if (Filename == "-" || aPath.isBytecodeFile()) { 1291c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke Module *Result = ParseBytecodeFile(Filename, &ErrorMessage); 1301c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke if (Result) { 1311c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke DumpSymbolNamesFromModule (Result); 1321c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke } else { 1331c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; 13408d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke return; 135972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 13611db4b8084270cb91446485b9534864ce52a95efReid Spencer } else if (aPath.isArchive()) { 13763efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer Archive* archive = Archive::OpenAndLoad(sys::Path(Filename)); 13863efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer if (!archive) 13963efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; 1401c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::vector<Module *> Modules; 14163efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer if (archive->getAllModules(Modules,&ErrorMessage)) { 14263efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; 14308d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke return; 14408d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke } 1451c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke MultipleFiles = true; 1461c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke std::for_each (Modules.begin (), Modules.end (), DumpSymbolNamesFromModule); 147820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke } else { 148820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke std::cerr << ToolName << ": " << Filename << ": " 149820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke << "unrecognizable file type\n"; 150820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke return; 151972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke } 152972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 153972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke 154972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekeint main(int argc, char **argv) { 1551ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer try { 1561ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer cl::ParseCommandLineOptions(argc, argv, " llvm symbol table dumper\n"); 1571ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer sys::PrintStackTraceOnErrorSignal(); 1581ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer 1591ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer ToolName = argv[0]; 1601ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer if (BSDFormat) OutputFormat = bsd; 1611ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer if (POSIXFormat) OutputFormat = posix; 1621ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer 1631ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer switch (InputFilenames.size()) { 1641ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer case 0: InputFilenames.push_back("-"); 1651ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer case 1: break; 1661ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer default: MultipleFiles = true; 1671ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer } 168fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner 1691ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer std::for_each (InputFilenames.begin (), InputFilenames.end (), 1701ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer DumpSymbolNamesFromFile); 1711ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer return 0; 1721ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer } catch (const std::string& msg) { 1731ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer std::cerr << argv[0] << ": " << msg << "\n"; 1741ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer } catch (...) { 1751ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n"; 176fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner } 1771ef8bdaedbd98bee35a573b8bc87149f2182cb5eReid Spencer return 1; 178972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke} 179