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