llvm-nm.cpp revision 266c7bbbbcc4b326dea82e577de1a415d6acc23e
1972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===//
23da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman//
37c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell//                     The LLVM Compiler Infrastructure
47c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell//
521c62da287237d39d0d95004881ea4baae3be6daChris Lattner// This file is distributed under the University of Illinois Open Source
621c62da287237d39d0d95004881ea4baae3be6daChris Lattner// 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",
11a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif// that is, it prints out the names of symbols in a bitcode 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"
204d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner#include "llvm/Bitcode/ReaderWriter.h"
2144dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner#include "llvm/Bitcode/Archive.h"
22551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h"
23c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner#include "llvm/Support/ManagedStatic.h"
244d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner#include "llvm/Support/MemoryBuffer.h"
25cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner#include "llvm/Support/PrettyStackTrace.h"
26bed85ff010b95923646ed4e187a5d432cedf67daChris Lattner#include "llvm/System/Signals.h"
27ca5183d445954a9b2a570d6bbba1bc2b00ad6442Jeff Cohen#include <algorithm>
28972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke#include <cctype>
2909233fb86e237715d138db5dc5b72ada386089f2Alkis Evlogimenos#include <cerrno>
3008d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke#include <cstring>
3186f42bdad93677fa0ca33b27afb0f493028376cbReid Spencer#include <iostream>
32d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekeusing namespace llvm;
33d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
34972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekenamespace {
35972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  enum OutputFormatTy { bsd, sysv, posix };
36972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::opt<OutputFormatTy>
37972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  OutputFormat("format",
38972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke       cl::desc("Specify output format"),
39972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke         cl::values(clEnumVal(bsd,   "BSD format"),
40972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke                    clEnumVal(sysv,  "System V format"),
413da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman                    clEnumVal(posix, "POSIX.2 format"),
424d143ee01988e1b52e106ffccbb313937ca5e886Chris Lattner                    clEnumValEnd), cl::init(bsd));
43972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
44972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke                          cl::aliasopt(OutputFormat));
45972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
463da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman  cl::list<std::string>
47a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif  InputFilenames(cl::Positional, cl::desc("<input bitcode files>"),
48fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner                 cl::ZeroOrMore);
49972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
50972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::opt<bool> UndefinedOnly("undefined-only",
51972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke                              cl::desc("Show only undefined symbols"));
52972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
53972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke                           cl::aliasopt(UndefinedOnly));
54972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
55972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::opt<bool> DefinedOnly("defined-only",
56972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke                            cl::desc("Show only defined symbols"));
57972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
58972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::opt<bool> ExternalOnly("extern-only",
59972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke                             cl::desc("Show only external symbols"));
60972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
61972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke                          cl::aliasopt(ExternalOnly));
62972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
63972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"));
64972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"));
65972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
66972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  bool MultipleFiles = false;
67972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
68972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  std::string ToolName;
69d74ea2bbd8bb630331f35ead42d385249bd42af8Chris Lattner}
70972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
71c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattnerstatic char TypeCharForSymbol(GlobalValue &GV) {
724a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio  if (GV.isDeclaration())                                  return 'U';
73c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner  if (GV.hasLinkOnceLinkage())                             return 'C';
747d5633e9074db9eaf796e677451f6642c0174facDale Johannesen  if (GV.hasCommonLinkage())                               return 'C';
75c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner  if (GV.hasWeakLinkage())                                 return 'W';
764a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio  if (isa<Function>(GV) && GV.hasInternalLinkage())        return 't';
77c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner  if (isa<Function>(GV))                                   return 'T';
784a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio  if (isa<GlobalVariable>(GV) && GV.hasInternalLinkage())  return 'd';
79c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner  if (isa<GlobalVariable>(GV))                             return 'D';
804a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio  if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(&GV)) {
814a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio    const GlobalValue *AliasedGV = GA->getAliasedGlobal();
824a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio    if (isa<Function>(AliasedGV))                          return 'T';
834a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio    if (isa<GlobalVariable>(AliasedGV))                    return 'D';
844a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio  }
854a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio                                                           return '?';
86972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke}
87972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
88c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattnerstatic void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
89266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner  // Private linkage and available_externally linkage don't exist in symtab.
90266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner  if (GV.hasPrivateLinkage() || GV.hasAvailableExternallyLinkage()) return;
91266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner
92972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  const std::string SymbolAddrStr = "        "; // Not used yet...
93266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner  char TypeChar = TypeCharForSymbol(GV);
94972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  if ((TypeChar != 'U') && UndefinedOnly)
95972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke    return;
96972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  if ((TypeChar == 'U') && DefinedOnly)
97972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke    return;
98bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola  if (GV.hasLocalLinkage () && ExternalOnly)
99972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke    return;
100972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  if (OutputFormat == posix) {
101266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner    std::cout << GV.getName () << " " << TypeCharForSymbol(GV) << " "
102972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke              << SymbolAddrStr << "\n";
103972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  } else if (OutputFormat == bsd) {
104266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner    std::cout << SymbolAddrStr << " " << TypeCharForSymbol(GV) << " "
105972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke              << GV.getName () << "\n";
106972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  } else if (OutputFormat == sysv) {
107972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke    std::string PaddedName (GV.getName ());
108972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke    while (PaddedName.length () < 20)
109972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke      PaddedName += " ";
110972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke    std::cout << PaddedName << "|" << SymbolAddrStr << "|   "
111266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner              << TypeCharForSymbol(GV)
112972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke              << "  |                  |      |     |\n";
113972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  }
114972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke}
115972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
116c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattnerstatic void DumpSymbolNamesFromModule(Module *M) {
1171c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke  const std::string &Filename = M->getModuleIdentifier ();
1181c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke  if (OutputFormat == posix && MultipleFiles) {
1191c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke    std::cout << Filename << ":\n";
1201c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke  } else if (OutputFormat == bsd && MultipleFiles) {
1211c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke    std::cout << "\n" << Filename << ":\n";
1221c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke  } else if (OutputFormat == sysv) {
1231c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke    std::cout << "\n\nSymbols from " << Filename << ":\n\n"
1241c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke              << "Name                  Value   Class        Type"
1251c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke              << "         Size   Line  Section\n";
1261c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke  }
127266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner  std::for_each (M->begin(), M->end(), DumpSymbolNameForGlobalValue);
128266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner  std::for_each (M->global_begin(), M->global_end(),
1294a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio                 DumpSymbolNameForGlobalValue);
130266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner  std::for_each (M->alias_begin(), M->alias_end(),
1314a828eeed33a6f11698b625190bc7eafceee3100Lauro Ramos Venancio                 DumpSymbolNameForGlobalValue);
132972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke}
133972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
134c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattnerstatic void DumpSymbolNamesFromFile(std::string &Filename) {
135972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  std::string ErrorMessage;
13611db4b8084270cb91446485b9534864ce52a95efReid Spencer  sys::Path aPath(Filename);
1378b1daa3e71109b8ae6a057a1def35ae0ab87ce37Brian Gaeke  // Note: Currently we do not support reading an archive from stdin.
13844dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner  if (Filename == "-" || aPath.isBitcodeFile()) {
1394d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner    std::auto_ptr<MemoryBuffer> Buffer(
140065344dfd5a7b3502098810b981eb0077e5d81f3Chris Lattner                   MemoryBuffer::getFileOrSTDIN(Filename, &ErrorMessage));
1414d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner    Module *Result = 0;
1424d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner    if (Buffer.get())
1434d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner      Result = ParseBitcodeFile(Buffer.get(), &ErrorMessage);
1444d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner
1454d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner    if (Result)
1464d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner      DumpSymbolNamesFromModule(Result);
1474d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner    else {
1484d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner      std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
1494d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner      return;
1504d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner    }
1514d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner
15211db4b8084270cb91446485b9534864ce52a95efReid Spencer  } else if (aPath.isArchive()) {
1538d8a7ffe580c622e7e43f1426bca64e517de0d06Reid Spencer    std::string ErrMsg;
154c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner    Archive* archive = Archive::OpenAndLoad(sys::Path(Filename), &ErrorMessage);
15563efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer    if (!archive)
15663efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer      std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
1571c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke    std::vector<Module *> Modules;
158c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner    if (archive->getAllModules(Modules, &ErrorMessage)) {
15963efb7798051f2634167eee1e807f0dc7c3f13cfReid Spencer      std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
16008d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke      return;
16108d03c79a238dba0ea7b59b38304c431bd392432Brian Gaeke    }
1621c0b6982d28c910e7555d2c7a98f745f5d701827Brian Gaeke    MultipleFiles = true;
163c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner    std::for_each (Modules.begin(), Modules.end(), DumpSymbolNamesFromModule);
164820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke  } else {
165820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke    std::cerr << ToolName << ": " << Filename << ": "
166820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke              << "unrecognizable file type\n";
167820428711f651a6ae6b9caf78ae170a4434d1670Brian Gaeke    return;
168972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke  }
169972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke}
170972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke
171972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaekeint main(int argc, char **argv) {
172cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner  // Print a stack trace if we signal out.
1734d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  sys::PrintStackTraceOnErrorSignal();
174cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner  PrettyStackTraceProgram X(argc, argv);
175cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner
176cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
177cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner  cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
178fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner
1794d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  ToolName = argv[0];
1804d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  if (BSDFormat) OutputFormat = bsd;
1814d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  if (POSIXFormat) OutputFormat = posix;
1824d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner
1834d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  switch (InputFilenames.size()) {
1844d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  case 0: InputFilenames.push_back("-");
1854d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  case 1: break;
1864d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  default: MultipleFiles = true;
187fc046d52e442324fe238e572c314f86dbc894f92Chris Lattner  }
1884d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner
1894d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  std::for_each(InputFilenames.begin(), InputFilenames.end(),
1904d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner                DumpSymbolNamesFromFile);
1914d5aad2d99233fdee38cbbf844f65b7a74073954Chris Lattner  return 0;
192972d3d7fff89c50612e86dfc8222da51bb23f387Brian Gaeke}
193