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