blob: 0a1491b846755f59ce73ef9dfb12d59667e8e850 [file] [log] [blame]
Brian Gaeke0af759d2003-10-16 04:43:15 +00001//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===//
Misha Brukman650ba8e2005-04-22 00:00:37 +00002//
John Criswell09344dc2003-10-20 17:47:21 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattner345353d2007-12-29 20:44:31 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Misha Brukman650ba8e2005-04-22 00:00:37 +00007//
John Criswell09344dc2003-10-20 17:47:21 +00008//===----------------------------------------------------------------------===//
Brian Gaeke0af759d2003-10-16 04:43:15 +00009//
Michael J. Spencer838e5ad2012-06-06 23:34:10 +000010// This program is a utility that works like traditional Unix "nm", that is, it
11// prints out the names of symbols in a bitcode or object file, along with some
12// information about each symbol.
Misha Brukman650ba8e2005-04-22 00:00:37 +000013//
Michael J. Spencer838e5ad2012-06-06 23:34:10 +000014// This "nm" supports many of the features of GNU "nm", including its different
15// output formats.
Brian Gaeke0af759d2003-10-16 04:43:15 +000016//
17//===----------------------------------------------------------------------===//
18
Rafael Espindolaf12b8282014-02-21 20:10:59 +000019#include "llvm/IR/Function.h"
20#include "llvm/IR/GlobalAlias.h"
21#include "llvm/IR/GlobalVariable.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000022#include "llvm/IR/LLVMContext.h"
Michael J. Spencer2bc774a2011-09-27 19:37:18 +000023#include "llvm/Object/Archive.h"
Rafael Espindola586af97a2013-11-02 21:16:09 +000024#include "llvm/Object/COFF.h"
25#include "llvm/Object/ELFObjectFile.h"
Chandler Carruth442f7842014-03-04 10:07:28 +000026#include "llvm/Object/IRObjectFile.h"
Rafael Espindola586af97a2013-11-02 21:16:09 +000027#include "llvm/Object/MachO.h"
Alexey Samsonove6388e62013-06-18 15:03:28 +000028#include "llvm/Object/MachOUniversal.h"
Michael J. Spencerb8672a52011-01-20 06:38:57 +000029#include "llvm/Object/ObjectFile.h"
Rui Ueyamaf078eff2014-03-18 23:37:53 +000030#include "llvm/Support/COFF.h"
Reid Spencer7c16caa2004-09-01 22:55:40 +000031#include "llvm/Support/CommandLine.h"
Michael J. Spencerb8672a52011-01-20 06:38:57 +000032#include "llvm/Support/FileSystem.h"
Chandler Carruth4d88a1c2012-12-04 10:44:52 +000033#include "llvm/Support/Format.h"
Chris Lattner76d46322006-12-06 01:18:01 +000034#include "llvm/Support/ManagedStatic.h"
Chris Lattneref8f3892007-05-06 05:36:18 +000035#include "llvm/Support/MemoryBuffer.h"
Chris Lattnere3fc2d12009-03-06 05:34:10 +000036#include "llvm/Support/PrettyStackTrace.h"
Michael J. Spencerbc96f372011-12-13 23:17:29 +000037#include "llvm/Support/Program.h"
Michael J. Spencer447762d2010-11-29 18:16:10 +000038#include "llvm/Support/Signals.h"
Chandler Carruth4d88a1c2012-12-04 10:44:52 +000039#include "llvm/Support/raw_ostream.h"
Michael J. Spencer7b6fef82010-12-09 17:36:48 +000040#include "llvm/Support/system_error.h"
Jeff Cohenb622c112007-03-05 00:00:42 +000041#include <algorithm>
Brian Gaeke0af759d2003-10-16 04:43:15 +000042#include <cctype>
Alkis Evlogimenosf68f40e2004-04-21 16:11:40 +000043#include <cerrno>
Brian Gaeke55447b42003-11-19 21:52:09 +000044#include <cstring>
Michael J. Spencerb8672a52011-01-20 06:38:57 +000045#include <vector>
Brian Gaeke960707c2003-11-11 22:41:34 +000046using namespace llvm;
Michael J. Spencerb8672a52011-01-20 06:38:57 +000047using namespace object;
Brian Gaeke960707c2003-11-11 22:41:34 +000048
Brian Gaeke0af759d2003-10-16 04:43:15 +000049namespace {
Rafael Espindolace82a072014-01-30 19:24:00 +000050enum OutputFormatTy { bsd, sysv, posix };
Rafael Espindola619581c2014-01-29 04:56:19 +000051cl::opt<OutputFormatTy> OutputFormat(
52 "format", cl::desc("Specify output format"),
53 cl::values(clEnumVal(bsd, "BSD format"), clEnumVal(sysv, "System V format"),
54 clEnumVal(posix, "POSIX.2 format"), clEnumValEnd),
55 cl::init(bsd));
56cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
57 cl::aliasopt(OutputFormat));
Brian Gaeke0af759d2003-10-16 04:43:15 +000058
Rafael Espindolaf12b8282014-02-21 20:10:59 +000059cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
Rafael Espindola619581c2014-01-29 04:56:19 +000060 cl::ZeroOrMore);
Brian Gaeke0af759d2003-10-16 04:43:15 +000061
Rafael Espindola619581c2014-01-29 04:56:19 +000062cl::opt<bool> UndefinedOnly("undefined-only",
63 cl::desc("Show only undefined symbols"));
64cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
65 cl::aliasopt(UndefinedOnly));
Brian Gaeke0af759d2003-10-16 04:43:15 +000066
Rafael Espindola619581c2014-01-29 04:56:19 +000067cl::opt<bool> DynamicSyms("dynamic",
68 cl::desc("Display the dynamic symbols instead "
69 "of normal symbols."));
70cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"),
71 cl::aliasopt(DynamicSyms));
Michael J. Spencer8c4729f2012-02-28 00:40:37 +000072
Rafael Espindola619581c2014-01-29 04:56:19 +000073cl::opt<bool> DefinedOnly("defined-only",
74 cl::desc("Show only defined symbols"));
Brian Gaeke0af759d2003-10-16 04:43:15 +000075
Rafael Espindola619581c2014-01-29 04:56:19 +000076cl::opt<bool> ExternalOnly("extern-only",
77 cl::desc("Show only external symbols"));
78cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
79 cl::aliasopt(ExternalOnly));
Brian Gaeke0af759d2003-10-16 04:43:15 +000080
Rafael Espindola619581c2014-01-29 04:56:19 +000081cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"));
82cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"));
Brian Gaeke0af759d2003-10-16 04:43:15 +000083
Rafael Espindola619581c2014-01-29 04:56:19 +000084cl::opt<bool> PrintFileName(
85 "print-file-name",
Michael J. Spencerb8672a52011-01-20 06:38:57 +000086 cl::desc("Precede each symbol with the object file it came from"));
87
Rafael Espindola619581c2014-01-29 04:56:19 +000088cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"),
89 cl::aliasopt(PrintFileName));
90cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"),
91 cl::aliasopt(PrintFileName));
Michael J. Spencerb8672a52011-01-20 06:38:57 +000092
Rafael Espindola619581c2014-01-29 04:56:19 +000093cl::opt<bool> DebugSyms("debug-syms",
94 cl::desc("Show all symbols, even debugger only"));
95cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"),
96 cl::aliasopt(DebugSyms));
Michael J. Spencerb8672a52011-01-20 06:38:57 +000097
Rafael Espindolab4865d62014-04-03 00:19:35 +000098cl::opt<bool> NumericSort("numeric-sort", cl::desc("Sort symbols by address"));
Rafael Espindola619581c2014-01-29 04:56:19 +000099cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"),
100 cl::aliasopt(NumericSort));
101cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"),
102 cl::aliasopt(NumericSort));
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000103
Rafael Espindola619581c2014-01-29 04:56:19 +0000104cl::opt<bool> NoSort("no-sort", cl::desc("Show symbols in order encountered"));
105cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort));
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000106
Rafael Espindola619581c2014-01-29 04:56:19 +0000107cl::opt<bool> PrintSize("print-size",
Rafael Espindolab4865d62014-04-03 00:19:35 +0000108 cl::desc("Show symbol size instead of address"));
Rafael Espindola619581c2014-01-29 04:56:19 +0000109cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"),
110 cl::aliasopt(PrintSize));
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000111
Rafael Espindola619581c2014-01-29 04:56:19 +0000112cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size"));
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000113
Rafael Espindola619581c2014-01-29 04:56:19 +0000114cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
115 cl::desc("Exclude aliases from output"));
Jan Sjödin4d0c2992012-09-18 18:47:58 +0000116
Rafael Espindola619581c2014-01-29 04:56:19 +0000117cl::opt<bool> ArchiveMap("print-armap", cl::desc("Print the archive map"));
118cl::alias ArchiveMaps("s", cl::desc("Alias for --print-armap"),
119 cl::aliasopt(ArchiveMap));
Rafael Espindolab4865d62014-04-03 00:19:35 +0000120bool PrintAddress = true;
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000121
Rafael Espindola619581c2014-01-29 04:56:19 +0000122bool MultipleFiles = false;
Brian Gaeke0af759d2003-10-16 04:43:15 +0000123
Rafael Espindola619581c2014-01-29 04:56:19 +0000124bool HadError = false;
Rafael Espindola8b82a4d2013-07-03 15:46:03 +0000125
Rafael Espindola619581c2014-01-29 04:56:19 +0000126std::string ToolName;
Chris Lattneraa2372562006-05-24 17:04:05 +0000127}
Brian Gaeke0af759d2003-10-16 04:43:15 +0000128
Rafael Espindola619581c2014-01-29 04:56:19 +0000129static void error(Twine Message, Twine Path = Twine()) {
130 HadError = true;
131 errs() << ToolName << ": " << Path << ": " << Message << ".\n";
Michael J. Spencerbc96f372011-12-13 23:17:29 +0000132}
133
Rafael Espindola619581c2014-01-29 04:56:19 +0000134static bool error(error_code EC, Twine Path = Twine()) {
135 if (EC) {
136 error(EC.message(), Path);
Michael J. Spencerbc96f372011-12-13 23:17:29 +0000137 return true;
138 }
139 return false;
140}
141
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000142namespace {
Rafael Espindola619581c2014-01-29 04:56:19 +0000143struct NMSymbol {
Rafael Espindolab4865d62014-04-03 00:19:35 +0000144 uint64_t Address;
Rafael Espindola619581c2014-01-29 04:56:19 +0000145 uint64_t Size;
146 char TypeChar;
147 StringRef Name;
148};
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000149}
150
Rafael Espindolab4865d62014-04-03 00:19:35 +0000151static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) {
152 if (A.Address < B.Address)
Rafael Espindola619581c2014-01-29 04:56:19 +0000153 return true;
Rafael Espindolab4865d62014-04-03 00:19:35 +0000154 else if (A.Address == B.Address && A.Name < B.Name)
Rafael Espindola619581c2014-01-29 04:56:19 +0000155 return true;
Rafael Espindolab4865d62014-04-03 00:19:35 +0000156 else if (A.Address == B.Address && A.Name == B.Name && A.Size < B.Size)
Rafael Espindola619581c2014-01-29 04:56:19 +0000157 return true;
158 else
159 return false;
160}
161
162static bool compareSymbolSize(const NMSymbol &A, const NMSymbol &B) {
163 if (A.Size < B.Size)
164 return true;
165 else if (A.Size == B.Size && A.Name < B.Name)
166 return true;
Rafael Espindolab4865d62014-04-03 00:19:35 +0000167 else if (A.Size == B.Size && A.Name == B.Name && A.Address < B.Address)
Rafael Espindola619581c2014-01-29 04:56:19 +0000168 return true;
169 else
170 return false;
171}
172
173static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) {
174 if (A.Name < B.Name)
175 return true;
176 else if (A.Name == B.Name && A.Size < B.Size)
177 return true;
Rafael Espindolab4865d62014-04-03 00:19:35 +0000178 else if (A.Name == B.Name && A.Size == B.Size && A.Address < B.Address)
Rafael Espindola619581c2014-01-29 04:56:19 +0000179 return true;
180 else
181 return false;
182}
183
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000184static char isSymbolList64Bit(SymbolicFile *Obj) {
Kevin Enderby15e24712014-05-12 20:45:00 +0000185 if (isa<IRObjectFile>(Obj))
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000186 return false;
Kevin Enderby15e24712014-05-12 20:45:00 +0000187 else if (isa<COFFObjectFile>(Obj))
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000188 return false;
189 else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj))
190 return MachO->is64Bit();
Kevin Enderby15e24712014-05-12 20:45:00 +0000191 else if (isa<ELF32LEObjectFile>(Obj))
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000192 return false;
Kevin Enderby15e24712014-05-12 20:45:00 +0000193 else if (isa<ELF64LEObjectFile>(Obj))
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000194 return true;
Kevin Enderby15e24712014-05-12 20:45:00 +0000195 else if (isa<ELF32BEObjectFile>(Obj))
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000196 return false;
Kevin Enderby15e24712014-05-12 20:45:00 +0000197 else if(isa<ELF64BEObjectFile>(Obj))
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000198 return true;
199 else
200 return false;
201}
202
Rafael Espindola619581c2014-01-29 04:56:19 +0000203static StringRef CurrentFilename;
204typedef std::vector<NMSymbol> SymbolListT;
205static SymbolListT SymbolList;
206
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000207static void sortAndPrintSymbolList(SymbolicFile *Obj) {
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000208 if (!NoSort) {
209 if (NumericSort)
Rafael Espindolab4865d62014-04-03 00:19:35 +0000210 std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolAddress);
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000211 else if (SizeSort)
Rafael Espindola619581c2014-01-29 04:56:19 +0000212 std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolSize);
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000213 else
Rafael Espindola619581c2014-01-29 04:56:19 +0000214 std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolName);
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000215 }
216
217 if (OutputFormat == posix && MultipleFiles) {
218 outs() << '\n' << CurrentFilename << ":\n";
219 } else if (OutputFormat == bsd && MultipleFiles) {
220 outs() << "\n" << CurrentFilename << ":\n";
221 } else if (OutputFormat == sysv) {
222 outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"
223 << "Name Value Class Type"
224 << " Size Line Section\n";
225 }
226
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000227 const char *printBlanks, *printFormat;
228 if (isSymbolList64Bit(Obj)) {
229 printBlanks = " ";
230 printFormat = "%016" PRIx64;
231 } else {
232 printBlanks = " ";
233 printFormat = "%08" PRIx64;
234 }
235
Rafael Espindola619581c2014-01-29 04:56:19 +0000236 for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end();
237 I != E; ++I) {
238 if ((I->TypeChar != 'U') && UndefinedOnly)
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000239 continue;
Rafael Espindola619581c2014-01-29 04:56:19 +0000240 if ((I->TypeChar == 'U') && DefinedOnly)
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000241 continue;
Rafael Espindolab4865d62014-04-03 00:19:35 +0000242 if (SizeSort && !PrintAddress && I->Size == UnknownAddressOrSize)
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000243 continue;
244
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000245 char SymbolAddrStr[18] = "";
246 char SymbolSizeStr[18] = "";
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000247
Rafael Espindolab4865d62014-04-03 00:19:35 +0000248 if (OutputFormat == sysv || I->Address == UnknownAddressOrSize)
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000249 strcpy(SymbolAddrStr, printBlanks);
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000250 if (OutputFormat == sysv)
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000251 strcpy(SymbolSizeStr, printBlanks);
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000252
Rafael Espindolab4865d62014-04-03 00:19:35 +0000253 if (I->Address != UnknownAddressOrSize)
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000254 format(printFormat, I->Address)
Rafael Espindolab4865d62014-04-03 00:19:35 +0000255 .print(SymbolAddrStr, sizeof(SymbolAddrStr));
Rafael Espindola0115b082014-01-30 21:51:42 +0000256 if (I->Size != UnknownAddressOrSize)
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000257 format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000258
259 if (OutputFormat == posix) {
Rafael Espindolab4865d62014-04-03 00:19:35 +0000260 outs() << I->Name << " " << I->TypeChar << " " << SymbolAddrStr
Rafael Espindola619581c2014-01-29 04:56:19 +0000261 << SymbolSizeStr << "\n";
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000262 } else if (OutputFormat == bsd) {
Rafael Espindolab4865d62014-04-03 00:19:35 +0000263 if (PrintAddress)
264 outs() << SymbolAddrStr << ' ';
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000265 if (PrintSize) {
266 outs() << SymbolSizeStr;
Rafael Espindola0115b082014-01-30 21:51:42 +0000267 if (I->Size != UnknownAddressOrSize)
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000268 outs() << ' ';
269 }
Rafael Espindola619581c2014-01-29 04:56:19 +0000270 outs() << I->TypeChar << " " << I->Name << "\n";
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000271 } else if (OutputFormat == sysv) {
Rafael Espindola619581c2014-01-29 04:56:19 +0000272 std::string PaddedName(I->Name);
273 while (PaddedName.length() < 20)
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000274 PaddedName += " ";
Rafael Espindolab4865d62014-04-03 00:19:35 +0000275 outs() << PaddedName << "|" << SymbolAddrStr << "| " << I->TypeChar
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000276 << " | |" << SymbolSizeStr << "| |\n";
277 }
278 }
279
280 SymbolList.clear();
281}
282
Rafael Espindola586af97a2013-11-02 21:16:09 +0000283template <class ELFT>
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000284static char getSymbolNMTypeChar(ELFObjectFile<ELFT> &Obj,
285 basic_symbol_iterator I) {
Rafael Espindola586af97a2013-11-02 21:16:09 +0000286 typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
287 typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
288
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000289 // OK, this is ELF
290 symbol_iterator SymI(I);
291
Rafael Espindola586af97a2013-11-02 21:16:09 +0000292 DataRefImpl Symb = I->getRawDataRefImpl();
293 const Elf_Sym *ESym = Obj.getSymbol(Symb);
294 const ELFFile<ELFT> &EF = *Obj.getELFFile();
295 const Elf_Shdr *ESec = EF.getSection(ESym);
296
Rafael Espindola586af97a2013-11-02 21:16:09 +0000297 if (ESec) {
298 switch (ESec->sh_type) {
299 case ELF::SHT_PROGBITS:
300 case ELF::SHT_DYNAMIC:
301 switch (ESec->sh_flags) {
302 case(ELF::SHF_ALLOC | ELF::SHF_EXECINSTR) :
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000303 return 't';
Rafael Espindola9fa52152014-01-30 00:42:30 +0000304 case(ELF::SHF_TLS | ELF::SHF_ALLOC | ELF::SHF_WRITE) :
Rafael Espindola586af97a2013-11-02 21:16:09 +0000305 case(ELF::SHF_ALLOC | ELF::SHF_WRITE) :
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000306 return 'd';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000307 case ELF::SHF_ALLOC:
308 case(ELF::SHF_ALLOC | ELF::SHF_MERGE) :
309 case(ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS) :
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000310 return 'r';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000311 }
312 break;
313 case ELF::SHT_NOBITS:
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000314 return 'b';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000315 }
316 }
317
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000318 if (ESym->getType() == ELF::STT_SECTION) {
Rafael Espindola586af97a2013-11-02 21:16:09 +0000319 StringRef Name;
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000320 if (error(SymI->getName(Name)))
Rafael Espindola74375892014-02-04 00:21:18 +0000321 return '?';
322 return StringSwitch<char>(Name)
323 .StartsWith(".debug", 'N')
324 .StartsWith(".note", 'n')
325 .Default('?');
Rafael Espindola586af97a2013-11-02 21:16:09 +0000326 }
327
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000328 return '?';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000329}
330
Rafael Espindola74375892014-02-04 00:21:18 +0000331static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
Alexey Samsonov27dc8392014-03-18 06:53:02 +0000332 const coff_symbol *Symb = Obj.getCOFFSymbol(*I);
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000333 // OK, this is COFF.
334 symbol_iterator SymI(I);
335
Rafael Espindola619581c2014-01-29 04:56:19 +0000336 StringRef Name;
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000337 if (error(SymI->getName(Name)))
Rafael Espindola74375892014-02-04 00:21:18 +0000338 return '?';
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000339
Rafael Espindola619581c2014-01-29 04:56:19 +0000340 char Ret = StringSwitch<char>(Name)
Rafael Espindola586af97a2013-11-02 21:16:09 +0000341 .StartsWith(".debug", 'N')
342 .StartsWith(".sxdata", 'N')
343 .Default('?');
344
Rafael Espindola74375892014-02-04 00:21:18 +0000345 if (Ret != '?')
346 return Ret;
Rafael Espindola586af97a2013-11-02 21:16:09 +0000347
348 uint32_t Characteristics = 0;
Rui Ueyamaf078eff2014-03-18 23:37:53 +0000349 if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000350 section_iterator SecI = Obj.section_end();
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000351 if (error(SymI->getSection(SecI)))
Rafael Espindola74375892014-02-04 00:21:18 +0000352 return '?';
Alexey Samsonov27dc8392014-03-18 06:53:02 +0000353 const coff_section *Section = Obj.getCOFFSection(*SecI);
Rafael Espindola586af97a2013-11-02 21:16:09 +0000354 Characteristics = Section->Characteristics;
355 }
356
Rafael Espindola619581c2014-01-29 04:56:19 +0000357 switch (Symb->SectionNumber) {
Rafael Espindola586af97a2013-11-02 21:16:09 +0000358 case COFF::IMAGE_SYM_DEBUG:
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000359 return 'n';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000360 default:
361 // Check section type.
362 if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000363 return 't';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000364 else if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
365 ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000366 return 'r';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000367 else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000368 return 'd';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000369 else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000370 return 'b';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000371 else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000372 return 'i';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000373
374 // Check for section symbol.
David Majnemerddf28f22014-03-19 04:47:47 +0000375 else if (Symb->isSectionDefinition())
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000376 return 's';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000377 }
378
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000379 return '?';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000380}
381
382static uint8_t getNType(MachOObjectFile &Obj, DataRefImpl Symb) {
383 if (Obj.is64Bit()) {
384 MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);
385 return STE.n_type;
386 }
387 MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
388 return STE.n_type;
389}
390
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000391static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
Rafael Espindola586af97a2013-11-02 21:16:09 +0000392 DataRefImpl Symb = I->getRawDataRefImpl();
393 uint8_t NType = getNType(Obj, Symb);
394
Rafael Espindola586af97a2013-11-02 21:16:09 +0000395 switch (NType & MachO::N_TYPE) {
Rafael Espindola586af97a2013-11-02 21:16:09 +0000396 case MachO::N_ABS:
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000397 return 's';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000398 case MachO::N_SECT: {
Rafael Espindolab5155a52014-02-10 20:24:04 +0000399 section_iterator Sec = Obj.section_end();
Rafael Espindola586af97a2013-11-02 21:16:09 +0000400 Obj.getSymbolSection(Symb, Sec);
401 DataRefImpl Ref = Sec->getRawDataRefImpl();
402 StringRef SectionName;
403 Obj.getSectionName(Ref, SectionName);
404 StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
405 if (SegmentName == "__TEXT" && SectionName == "__text")
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000406 return 't';
Rafael Espindola586af97a2013-11-02 21:16:09 +0000407 else
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000408 return 's';
409 }
Rafael Espindola586af97a2013-11-02 21:16:09 +0000410 }
411
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000412 return '?';
413}
414
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000415static char getSymbolNMTypeChar(const GlobalValue &GV) {
416 if (isa<Function>(GV))
417 return 't';
418 // FIXME: should we print 'b'? At the IR level we cannot be sure if this
419 // will be in bss or not, but we could approximate.
420 if (isa<GlobalVariable>(GV))
421 return 'd';
422 const GlobalAlias *GA = cast<GlobalAlias>(&GV);
423 const GlobalValue *AliasedGV = GA->getAliasedGlobal();
424 return getSymbolNMTypeChar(*AliasedGV);
425}
426
427static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) {
428 const GlobalValue &GV = Obj.getSymbolGV(I->getRawDataRefImpl());
429 return getSymbolNMTypeChar(GV);
430}
431
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000432template <class ELFT>
433static bool isObject(ELFObjectFile<ELFT> &Obj, symbol_iterator I) {
434 typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
435
436 DataRefImpl Symb = I->getRawDataRefImpl();
437 const Elf_Sym *ESym = Obj.getSymbol(Symb);
438
439 return ESym->getType() == ELF::STT_OBJECT;
440}
441
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000442static bool isObject(SymbolicFile *Obj, basic_symbol_iterator I) {
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000443 if (ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj))
444 return isObject(*ELF, I);
445 if (ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj))
446 return isObject(*ELF, I);
447 if (ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj))
448 return isObject(*ELF, I);
449 if (ELF64BEObjectFile *ELF = dyn_cast<ELF64BEObjectFile>(Obj))
450 return isObject(*ELF, I);
451 return false;
Rafael Espindola586af97a2013-11-02 21:16:09 +0000452}
453
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000454static char getNMTypeChar(SymbolicFile *Obj, basic_symbol_iterator I) {
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000455 uint32_t Symflags = I->getFlags();
456 if ((Symflags & object::SymbolRef::SF_Weak) && !isa<MachOObjectFile>(Obj)) {
457 char Ret = isObject(Obj, I) ? 'v' : 'w';
458 if (!(Symflags & object::SymbolRef::SF_Undefined))
459 Ret = toupper(Ret);
460 return Ret;
461 }
462
463 if (Symflags & object::SymbolRef::SF_Undefined)
464 return 'U';
465
466 if (Symflags & object::SymbolRef::SF_Common)
467 return 'C';
468
469 char Ret = '?';
470 if (Symflags & object::SymbolRef::SF_Absolute)
471 Ret = 'a';
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000472 else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(Obj))
473 Ret = getSymbolNMTypeChar(*IR, I);
Rafael Espindola22fe9c12014-02-05 05:19:19 +0000474 else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(Obj))
475 Ret = getSymbolNMTypeChar(*COFF, I);
476 else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj))
477 Ret = getSymbolNMTypeChar(*MachO, I);
478 else if (ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj))
479 Ret = getSymbolNMTypeChar(*ELF, I);
480 else if (ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj))
481 Ret = getSymbolNMTypeChar(*ELF, I);
482 else if (ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj))
483 Ret = getSymbolNMTypeChar(*ELF, I);
484 else
485 Ret = getSymbolNMTypeChar(*cast<ELF64BEObjectFile>(Obj), I);
486
487 if (Symflags & object::SymbolRef::SF_Global)
488 Ret = toupper(Ret);
489
490 return Ret;
Rafael Espindola586af97a2013-11-02 21:16:09 +0000491}
492
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000493static void dumpSymbolNamesFromObject(SymbolicFile *Obj) {
494 basic_symbol_iterator IBegin = Obj->symbol_begin();
495 basic_symbol_iterator IEnd = Obj->symbol_end();
Michael J. Spencer8c4729f2012-02-28 00:40:37 +0000496 if (DynamicSyms) {
Rafael Espindola196666c2014-01-30 20:45:33 +0000497 if (!Obj->isELF()) {
498 error("File format has no dynamic symbol table", Obj->getFileName());
499 return;
500 }
Alexey Samsonov65056a32014-02-26 12:51:19 +0000501 std::pair<symbol_iterator, symbol_iterator> IDyn =
502 getELFDynamicSymbolIterators(Obj);
503 IBegin = IDyn.first;
504 IEnd = IDyn.second;
Michael J. Spencer8c4729f2012-02-28 00:40:37 +0000505 }
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000506 std::string NameBuffer;
507 raw_string_ostream OS(NameBuffer);
508 for (basic_symbol_iterator I = IBegin; I != IEnd; ++I) {
Rafael Espindola20122a42014-01-31 20:57:12 +0000509 uint32_t SymFlags = I->getFlags();
Rafael Espindola619581c2014-01-29 04:56:19 +0000510 if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific))
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000511 continue;
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000512 if (WithoutAliases) {
513 if (IRObjectFile *IR = dyn_cast<IRObjectFile>(Obj)) {
514 const GlobalValue &GV = IR->getSymbolGV(I->getRawDataRefImpl());
515 if(isa<GlobalAlias>(GV))
516 continue;
517 }
518 }
Rafael Espindola619581c2014-01-29 04:56:19 +0000519 NMSymbol S;
Rafael Espindola0115b082014-01-30 21:51:42 +0000520 S.Size = UnknownAddressOrSize;
Rafael Espindolab4865d62014-04-03 00:19:35 +0000521 S.Address = UnknownAddressOrSize;
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000522 if ((PrintSize || SizeSort) && isa<ObjectFile>(Obj)) {
523 symbol_iterator SymI = I;
524 if (error(SymI->getSize(S.Size)))
Rafael Espindola619581c2014-01-29 04:56:19 +0000525 break;
Michael J. Spencer1d6167f2011-06-25 17:55:23 +0000526 }
Rafael Espindolab4865d62014-04-03 00:19:35 +0000527 if (PrintAddress && isa<ObjectFile>(Obj))
528 if (error(symbol_iterator(I)->getAddress(S.Address)))
Rafael Espindola619581c2014-01-29 04:56:19 +0000529 break;
530 S.TypeChar = getNMTypeChar(Obj, I);
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000531 if (error(I->printName(OS)))
Rafael Espindola619581c2014-01-29 04:56:19 +0000532 break;
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000533 OS << '\0';
Rafael Espindola619581c2014-01-29 04:56:19 +0000534 SymbolList.push_back(S);
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000535 }
536
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000537 OS.flush();
538 const char *P = NameBuffer.c_str();
539 for (unsigned I = 0; I < SymbolList.size(); ++I) {
540 SymbolList[I].Name = P;
541 P += strlen(P) + 1;
542 }
543
Rafael Espindola619581c2014-01-29 04:56:19 +0000544 CurrentFilename = Obj->getFileName();
Kevin Enderby6abc2e52014-05-09 23:57:49 +0000545 sortAndPrintSymbolList(Obj);
Brian Gaeke0af759d2003-10-16 04:43:15 +0000546}
547
Rafael Espindola619581c2014-01-29 04:56:19 +0000548static void dumpSymbolNamesFromFile(std::string &Filename) {
Ahmed Charles56440fd2014-03-06 05:51:42 +0000549 std::unique_ptr<MemoryBuffer> Buffer;
Michael J. Spencerbc96f372011-12-13 23:17:29 +0000550 if (error(MemoryBuffer::getFileOrSTDIN(Filename, Buffer), Filename))
551 return;
552
Owen Anderson19251ec2009-07-15 22:16:10 +0000553 LLVMContext &Context = getGlobalContext();
Ahmed Charles96c9d952014-03-05 10:19:29 +0000554 ErrorOr<Binary *> BinaryOrErr = createBinary(Buffer.release(), &Context);
Rafael Espindolace82a072014-01-30 19:24:00 +0000555 if (error(BinaryOrErr.getError(), Filename))
556 return;
Ahmed Charles56440fd2014-03-06 05:51:42 +0000557 std::unique_ptr<Binary> Bin(BinaryOrErr.get());
Shankar Easwaran15b28be2012-11-13 18:38:42 +0000558
Rafael Espindola0115b082014-01-30 21:51:42 +0000559 if (Archive *A = dyn_cast<Archive>(Bin.get())) {
Rafael Espindolace82a072014-01-30 19:24:00 +0000560 if (ArchiveMap) {
Rafael Espindola0115b082014-01-30 21:51:42 +0000561 Archive::symbol_iterator I = A->symbol_begin();
562 Archive::symbol_iterator E = A->symbol_end();
Rafael Espindolace82a072014-01-30 19:24:00 +0000563 if (I != E) {
Rafael Espindola0115b082014-01-30 21:51:42 +0000564 outs() << "Archive map\n";
Rafael Espindolace82a072014-01-30 19:24:00 +0000565 for (; I != E; ++I) {
Rafael Espindola0115b082014-01-30 21:51:42 +0000566 Archive::child_iterator C;
Rafael Espindolace82a072014-01-30 19:24:00 +0000567 StringRef SymName;
568 StringRef FileName;
569 if (error(I->getMember(C)))
Michael J. Spencer9718f452013-02-03 10:48:50 +0000570 return;
Rafael Espindolace82a072014-01-30 19:24:00 +0000571 if (error(I->getName(SymName)))
572 return;
573 if (error(C->getName(FileName)))
574 return;
575 outs() << SymName << " in " << FileName << "\n";
Michael J. Spencer2bc774a2011-09-27 19:37:18 +0000576 }
Rafael Espindolace82a072014-01-30 19:24:00 +0000577 outs() << "\n";
Michael J. Spencer2bc774a2011-09-27 19:37:18 +0000578 }
579 }
Alexey Samsonove6388e62013-06-18 15:03:28 +0000580
Rafael Espindola0115b082014-01-30 21:51:42 +0000581 for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
Rafael Espindolace82a072014-01-30 19:24:00 +0000582 I != E; ++I) {
Ahmed Charles56440fd2014-03-06 05:51:42 +0000583 std::unique_ptr<Binary> Child;
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000584 if (I->getAsBinary(Child, &Context))
Rafael Espindolace82a072014-01-30 19:24:00 +0000585 continue;
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000586 if (SymbolicFile *O = dyn_cast<SymbolicFile>(Child.get())) {
Rafael Espindolace82a072014-01-30 19:24:00 +0000587 outs() << O->getFileName() << ":\n";
588 dumpSymbolNamesFromObject(O);
589 }
590 }
591 return;
592 }
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000593 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin.get())) {
Rafael Espindola0115b082014-01-30 21:51:42 +0000594 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
595 E = UB->end_objects();
Alexey Samsonove6388e62013-06-18 15:03:28 +0000596 I != E; ++I) {
Ahmed Charles56440fd2014-03-06 05:51:42 +0000597 std::unique_ptr<ObjectFile> Obj;
Alexey Samsonove6388e62013-06-18 15:03:28 +0000598 if (!I->getAsObjectFile(Obj)) {
599 outs() << Obj->getFileName() << ":\n";
Rafael Espindola619581c2014-01-29 04:56:19 +0000600 dumpSymbolNamesFromObject(Obj.get());
Alexey Samsonove6388e62013-06-18 15:03:28 +0000601 }
602 }
Brian Gaeke618026a2003-11-19 21:57:30 +0000603 return;
Brian Gaeke0af759d2003-10-16 04:43:15 +0000604 }
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000605 if (SymbolicFile *O = dyn_cast<SymbolicFile>(Bin.get())) {
Rafael Espindolace82a072014-01-30 19:24:00 +0000606 dumpSymbolNamesFromObject(O);
607 return;
608 }
609 error("unrecognizable file type", Filename);
610 return;
Brian Gaeke0af759d2003-10-16 04:43:15 +0000611}
612
613int main(int argc, char **argv) {
Chris Lattnere3fc2d12009-03-06 05:34:10 +0000614 // Print a stack trace if we signal out.
Chris Lattneref8f3892007-05-06 05:36:18 +0000615 sys::PrintStackTraceOnErrorSignal();
Chris Lattnere3fc2d12009-03-06 05:34:10 +0000616 PrettyStackTraceProgram X(argc, argv);
Michael J. Spencer618d2192010-08-31 06:36:46 +0000617
Rafael Espindola619581c2014-01-29 04:56:19 +0000618 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
Chris Lattnere3fc2d12009-03-06 05:34:10 +0000619 cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
Chris Lattner12439ff2004-02-19 20:32:12 +0000620
Michael J. Spencerbc96f372011-12-13 23:17:29 +0000621 // llvm-nm only reads binary files.
Rafael Espindolacb2eca02013-06-12 20:58:35 +0000622 if (error(sys::ChangeStdinToBinary()))
Michael J. Spencerbc96f372011-12-13 23:17:29 +0000623 return 1;
624
Chris Lattneref8f3892007-05-06 05:36:18 +0000625 ToolName = argv[0];
Rafael Espindola619581c2014-01-29 04:56:19 +0000626 if (BSDFormat)
627 OutputFormat = bsd;
628 if (POSIXFormat)
629 OutputFormat = posix;
Chris Lattner4aae1f42003-10-16 18:45:23 +0000630
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000631 // The relative order of these is important. If you pass --size-sort it should
632 // only print out the size. However, if you pass -S --size-sort, it should
Rafael Espindolab4865d62014-04-03 00:19:35 +0000633 // print out both the size and address.
Rafael Espindola619581c2014-01-29 04:56:19 +0000634 if (SizeSort && !PrintSize)
Rafael Espindolab4865d62014-04-03 00:19:35 +0000635 PrintAddress = false;
Rafael Espindola619581c2014-01-29 04:56:19 +0000636 if (OutputFormat == sysv || SizeSort)
637 PrintSize = true;
Michael J. Spencerb8672a52011-01-20 06:38:57 +0000638
Chris Lattneref8f3892007-05-06 05:36:18 +0000639 switch (InputFilenames.size()) {
Rafael Espindola619581c2014-01-29 04:56:19 +0000640 case 0:
641 InputFilenames.push_back("-");
642 case 1:
643 break;
644 default:
645 MultipleFiles = true;
Chris Lattner4aae1f42003-10-16 18:45:23 +0000646 }
Chris Lattneref8f3892007-05-06 05:36:18 +0000647
648 std::for_each(InputFilenames.begin(), InputFilenames.end(),
Rafael Espindola619581c2014-01-29 04:56:19 +0000649 dumpSymbolNamesFromFile);
Rafael Espindola8b82a4d2013-07-03 15:46:03 +0000650
651 if (HadError)
652 return 1;
653
Chris Lattneref8f3892007-05-06 05:36:18 +0000654 return 0;
Brian Gaeke0af759d2003-10-16 04:43:15 +0000655}