llvm-nm.cpp revision 21c62da287237d39d0d95004881ea4baae3be6da
1//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This program is a utility that works like traditional Unix "nm", 11// that is, it prints out the names of symbols in a bitcode file, 12// along with some information about each symbol. 13// 14// This "nm" does not print symbols' addresses. It supports many of 15// the features of GNU "nm", including its different output formats. 16// 17//===----------------------------------------------------------------------===// 18 19#include "llvm/Module.h" 20#include "llvm/Bitcode/ReaderWriter.h" 21#include "llvm/Bitcode/Archive.h" 22#include "llvm/Support/CommandLine.h" 23#include "llvm/Support/ManagedStatic.h" 24#include "llvm/Support/MemoryBuffer.h" 25#include "llvm/System/Signals.h" 26#include <algorithm> 27#include <cctype> 28#include <cerrno> 29#include <cstring> 30#include <iostream> 31using namespace llvm; 32 33namespace { 34 enum OutputFormatTy { bsd, sysv, posix }; 35 cl::opt<OutputFormatTy> 36 OutputFormat("format", 37 cl::desc("Specify output format"), 38 cl::values(clEnumVal(bsd, "BSD format"), 39 clEnumVal(sysv, "System V format"), 40 clEnumVal(posix, "POSIX.2 format"), 41 clEnumValEnd), cl::init(bsd)); 42 cl::alias OutputFormat2("f", cl::desc("Alias for --format"), 43 cl::aliasopt(OutputFormat)); 44 45 cl::list<std::string> 46 InputFilenames(cl::Positional, cl::desc("<input bitcode files>"), 47 cl::ZeroOrMore); 48 49 cl::opt<bool> UndefinedOnly("undefined-only", 50 cl::desc("Show only undefined symbols")); 51 cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), 52 cl::aliasopt(UndefinedOnly)); 53 54 cl::opt<bool> DefinedOnly("defined-only", 55 cl::desc("Show only defined symbols")); 56 57 cl::opt<bool> ExternalOnly("extern-only", 58 cl::desc("Show only external symbols")); 59 cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), 60 cl::aliasopt(ExternalOnly)); 61 62 cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd")); 63 cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix")); 64 65 bool MultipleFiles = false; 66 67 std::string ToolName; 68} 69 70static char TypeCharForSymbol(GlobalValue &GV) { 71 if (GV.isDeclaration()) return 'U'; 72 if (GV.hasLinkOnceLinkage()) return 'C'; 73 if (GV.hasWeakLinkage()) return 'W'; 74 if (isa<Function>(GV) && GV.hasInternalLinkage()) return 't'; 75 if (isa<Function>(GV)) return 'T'; 76 if (isa<GlobalVariable>(GV) && GV.hasInternalLinkage()) return 'd'; 77 if (isa<GlobalVariable>(GV)) return 'D'; 78 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(&GV)) { 79 const GlobalValue *AliasedGV = GA->getAliasedGlobal(); 80 if (isa<Function>(AliasedGV)) return 'T'; 81 if (isa<GlobalVariable>(AliasedGV)) return 'D'; 82 } 83 return '?'; 84} 85 86static void DumpSymbolNameForGlobalValue(GlobalValue &GV) { 87 const std::string SymbolAddrStr = " "; // Not used yet... 88 char TypeChar = TypeCharForSymbol (GV); 89 if ((TypeChar != 'U') && UndefinedOnly) 90 return; 91 if ((TypeChar == 'U') && DefinedOnly) 92 return; 93 if (GV.hasInternalLinkage () && ExternalOnly) 94 return; 95 if (OutputFormat == posix) { 96 std::cout << GV.getName () << " " << TypeCharForSymbol (GV) << " " 97 << SymbolAddrStr << "\n"; 98 } else if (OutputFormat == bsd) { 99 std::cout << SymbolAddrStr << " " << TypeCharForSymbol (GV) << " " 100 << GV.getName () << "\n"; 101 } else if (OutputFormat == sysv) { 102 std::string PaddedName (GV.getName ()); 103 while (PaddedName.length () < 20) 104 PaddedName += " "; 105 std::cout << PaddedName << "|" << SymbolAddrStr << "| " 106 << TypeCharForSymbol (GV) 107 << " | | | |\n"; 108 } 109} 110 111static void DumpSymbolNamesFromModule(Module *M) { 112 const std::string &Filename = M->getModuleIdentifier (); 113 if (OutputFormat == posix && MultipleFiles) { 114 std::cout << Filename << ":\n"; 115 } else if (OutputFormat == bsd && MultipleFiles) { 116 std::cout << "\n" << Filename << ":\n"; 117 } else if (OutputFormat == sysv) { 118 std::cout << "\n\nSymbols from " << Filename << ":\n\n" 119 << "Name Value Class Type" 120 << " Size Line Section\n"; 121 } 122 std::for_each (M->begin (), M->end (), DumpSymbolNameForGlobalValue); 123 std::for_each (M->global_begin (), M->global_end (), 124 DumpSymbolNameForGlobalValue); 125 std::for_each (M->alias_begin (), M->alias_end (), 126 DumpSymbolNameForGlobalValue); 127} 128 129static void DumpSymbolNamesFromFile(std::string &Filename) { 130 std::string ErrorMessage; 131 sys::Path aPath(Filename); 132 // Note: Currently we do not support reading an archive from stdin. 133 if (Filename == "-" || aPath.isBitcodeFile()) { 134 std::auto_ptr<MemoryBuffer> Buffer( 135 MemoryBuffer::getFileOrSTDIN(Filename, &ErrorMessage)); 136 Module *Result = 0; 137 if (Buffer.get()) 138 Result = ParseBitcodeFile(Buffer.get(), &ErrorMessage); 139 140 if (Result) 141 DumpSymbolNamesFromModule(Result); 142 else { 143 std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; 144 return; 145 } 146 147 } else if (aPath.isArchive()) { 148 std::string ErrMsg; 149 Archive* archive = Archive::OpenAndLoad(sys::Path(Filename), &ErrorMessage); 150 if (!archive) 151 std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; 152 std::vector<Module *> Modules; 153 if (archive->getAllModules(Modules, &ErrorMessage)) { 154 std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; 155 return; 156 } 157 MultipleFiles = true; 158 std::for_each (Modules.begin(), Modules.end(), DumpSymbolNamesFromModule); 159 } else { 160 std::cerr << ToolName << ": " << Filename << ": " 161 << "unrecognizable file type\n"; 162 return; 163 } 164} 165 166int main(int argc, char **argv) { 167 llvm_shutdown_obj X; // Call llvm_shutdown() on exit. 168 cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n"); 169 sys::PrintStackTraceOnErrorSignal(); 170 171 ToolName = argv[0]; 172 if (BSDFormat) OutputFormat = bsd; 173 if (POSIXFormat) OutputFormat = posix; 174 175 switch (InputFilenames.size()) { 176 case 0: InputFilenames.push_back("-"); 177 case 1: break; 178 default: MultipleFiles = true; 179 } 180 181 std::for_each(InputFilenames.begin(), InputFilenames.end(), 182 DumpSymbolNamesFromFile); 183 return 0; 184} 185