move getSymbolNMTypeChar to the one program that needs it: nm.
[oota-llvm.git] / tools / llvm-nm / llvm-nm.cpp
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", that is, it
11 // prints out the names of symbols in a bitcode or object file, along with some
12 // information about each symbol.
13 //
14 // This "nm" supports many of the features of GNU "nm", including its different
15 // output formats.
16 //
17 //===----------------------------------------------------------------------===//
18
19 #include "llvm/IR/LLVMContext.h"
20 #include "llvm/Bitcode/ReaderWriter.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/Object/Archive.h"
23 #include "llvm/Object/COFF.h"
24 #include "llvm/Object/ELFObjectFile.h"
25 #include "llvm/Object/MachO.h"
26 #include "llvm/Object/MachOUniversal.h"
27 #include "llvm/Object/ObjectFile.h"
28 #include "llvm/Support/CommandLine.h"
29 #include "llvm/Support/FileSystem.h"
30 #include "llvm/Support/Format.h"
31 #include "llvm/Support/ManagedStatic.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/PrettyStackTrace.h"
34 #include "llvm/Support/Program.h"
35 #include "llvm/Support/Signals.h"
36 #include "llvm/Support/raw_ostream.h"
37 #include "llvm/Support/system_error.h"
38 #include <algorithm>
39 #include <cctype>
40 #include <cerrno>
41 #include <cstring>
42 #include <vector>
43 using namespace llvm;
44 using namespace object;
45
46 namespace {
47   enum OutputFormatTy { bsd, sysv, posix };
48   cl::opt<OutputFormatTy>
49   OutputFormat("format",
50        cl::desc("Specify output format"),
51          cl::values(clEnumVal(bsd,   "BSD format"),
52                     clEnumVal(sysv,  "System V format"),
53                     clEnumVal(posix, "POSIX.2 format"),
54                     clEnumValEnd), cl::init(bsd));
55   cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
56                           cl::aliasopt(OutputFormat));
57
58   cl::list<std::string>
59   InputFilenames(cl::Positional, cl::desc("<input bitcode files>"),
60                  cl::ZeroOrMore);
61
62   cl::opt<bool> UndefinedOnly("undefined-only",
63                               cl::desc("Show only undefined symbols"));
64   cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
65                            cl::aliasopt(UndefinedOnly));
66
67   cl::opt<bool> DynamicSyms("dynamic",
68                              cl::desc("Display the dynamic symbols instead "
69                                       "of normal symbols."));
70   cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"),
71                          cl::aliasopt(DynamicSyms));
72
73   cl::opt<bool> DefinedOnly("defined-only",
74                             cl::desc("Show only defined symbols"));
75
76   cl::opt<bool> ExternalOnly("extern-only",
77                              cl::desc("Show only external symbols"));
78   cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
79                           cl::aliasopt(ExternalOnly));
80
81   cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"));
82   cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"));
83
84   cl::opt<bool> PrintFileName("print-file-name",
85     cl::desc("Precede each symbol with the object file it came from"));
86
87   cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"),
88                                 cl::aliasopt(PrintFileName));
89   cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"),
90                                 cl::aliasopt(PrintFileName));
91
92   cl::opt<bool> DebugSyms("debug-syms",
93     cl::desc("Show all symbols, even debugger only"));
94   cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"),
95                             cl::aliasopt(DebugSyms));
96
97   cl::opt<bool> NumericSort("numeric-sort",
98     cl::desc("Sort symbols by address"));
99   cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"),
100                               cl::aliasopt(NumericSort));
101   cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"),
102                               cl::aliasopt(NumericSort));
103
104   cl::opt<bool> NoSort("no-sort",
105     cl::desc("Show symbols in order encountered"));
106   cl::alias NoSortp("p", cl::desc("Alias for --no-sort"),
107                          cl::aliasopt(NoSort));
108
109   cl::opt<bool> PrintSize("print-size",
110     cl::desc("Show symbol size instead of address"));
111   cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"),
112                             cl::aliasopt(PrintSize));
113
114   cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size"));
115
116   cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
117                                cl::desc("Exclude aliases from output"));
118
119   cl::opt<bool> ArchiveMap("print-armap",
120     cl::desc("Print the archive map"));
121   cl::alias ArchiveMaps("s", cl::desc("Alias for --print-armap"),
122                                  cl::aliasopt(ArchiveMap));
123   bool PrintAddress = true;
124
125   bool MultipleFiles = false;
126
127   bool HadError = false;
128
129   std::string ToolName;
130 }
131
132
133 static void error(Twine message, Twine path = Twine()) {
134   errs() << ToolName << ": " << path << ": " << message << ".\n";
135 }
136
137 static bool error(error_code ec, Twine path = Twine()) {
138   if (ec) {
139     error(ec.message(), path);
140     HadError = true;
141     return true;
142   }
143   return false;
144 }
145
146 namespace {
147   struct NMSymbol {
148     uint64_t  Address;
149     uint64_t  Size;
150     char      TypeChar;
151     StringRef Name;
152   };
153
154   static bool CompareSymbolAddress(const NMSymbol &a, const NMSymbol &b) {
155     if (a.Address < b.Address)
156       return true;
157     else if (a.Address == b.Address && a.Name < b.Name)
158       return true;
159     else if (a.Address == b.Address && a.Name == b.Name && a.Size < b.Size)
160       return true;
161     else
162       return false;
163
164   }
165
166   static bool CompareSymbolSize(const NMSymbol &a, const NMSymbol &b) {
167     if (a.Size < b.Size)
168       return true;
169     else if (a.Size == b.Size && a.Name < b.Name)
170       return true;
171     else if (a.Size == b.Size && a.Name == b.Name && a.Address < b.Address)
172       return true;
173     else
174       return false;
175   }
176
177   static bool CompareSymbolName(const NMSymbol &a, const NMSymbol &b) {
178     if (a.Name < b.Name)
179       return true;
180     else if (a.Name == b.Name && a.Size < b.Size)
181       return true;
182     else if (a.Name == b.Name && a.Size == b.Size && a.Address < b.Address)
183       return true;
184     else
185       return false;
186   }
187
188   StringRef CurrentFilename;
189   typedef std::vector<NMSymbol> SymbolListT;
190   SymbolListT SymbolList;
191 }
192
193 static void SortAndPrintSymbolList() {
194   if (!NoSort) {
195     if (NumericSort)
196       std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolAddress);
197     else if (SizeSort)
198       std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolSize);
199     else
200       std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolName);
201   }
202
203   if (OutputFormat == posix && MultipleFiles) {
204     outs() << '\n' << CurrentFilename << ":\n";
205   } else if (OutputFormat == bsd && MultipleFiles) {
206     outs() << "\n" << CurrentFilename << ":\n";
207   } else if (OutputFormat == sysv) {
208     outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"
209            << "Name                  Value   Class        Type"
210            << "         Size   Line  Section\n";
211   }
212
213   for (SymbolListT::iterator i = SymbolList.begin(),
214                              e = SymbolList.end(); i != e; ++i) {
215     if ((i->TypeChar != 'U') && UndefinedOnly)
216       continue;
217     if ((i->TypeChar == 'U') && DefinedOnly)
218       continue;
219     if (SizeSort && !PrintAddress && i->Size == UnknownAddressOrSize)
220       continue;
221
222     char SymbolAddrStr[10] = "";
223     char SymbolSizeStr[10] = "";
224
225     if (OutputFormat == sysv || i->Address == object::UnknownAddressOrSize)
226       strcpy(SymbolAddrStr, "        ");
227     if (OutputFormat == sysv)
228       strcpy(SymbolSizeStr, "        ");
229
230     if (i->Address != object::UnknownAddressOrSize)
231       format("%08" PRIx64, i->Address).print(SymbolAddrStr,
232                                              sizeof(SymbolAddrStr));
233     if (i->Size != object::UnknownAddressOrSize)
234       format("%08" PRIx64, i->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
235
236     if (OutputFormat == posix) {
237       outs() << i->Name << " " << i->TypeChar << " "
238              << SymbolAddrStr << SymbolSizeStr << "\n";
239     } else if (OutputFormat == bsd) {
240       if (PrintAddress)
241         outs() << SymbolAddrStr << ' ';
242       if (PrintSize) {
243         outs() << SymbolSizeStr;
244         if (i->Size != object::UnknownAddressOrSize)
245           outs() << ' ';
246       }
247       outs() << i->TypeChar << " " << i->Name  << "\n";
248     } else if (OutputFormat == sysv) {
249       std::string PaddedName (i->Name);
250       while (PaddedName.length () < 20)
251         PaddedName += " ";
252       outs() << PaddedName << "|" << SymbolAddrStr << "|   "
253              << i->TypeChar
254              << "  |                  |" << SymbolSizeStr << "|     |\n";
255     }
256   }
257
258   SymbolList.clear();
259 }
260
261 static char TypeCharForSymbol(GlobalValue &GV) {
262   if (GV.isDeclaration())                                  return 'U';
263   if (GV.hasLinkOnceLinkage())                             return 'C';
264   if (GV.hasCommonLinkage())                               return 'C';
265   if (GV.hasWeakLinkage())                                 return 'W';
266   if (isa<Function>(GV) && GV.hasInternalLinkage())        return 't';
267   if (isa<Function>(GV))                                   return 'T';
268   if (isa<GlobalVariable>(GV) && GV.hasInternalLinkage())  return 'd';
269   if (isa<GlobalVariable>(GV))                             return 'D';
270   if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(&GV)) {
271     const GlobalValue *AliasedGV = GA->getAliasedGlobal();
272     if (isa<Function>(AliasedGV))                          return 'T';
273     if (isa<GlobalVariable>(AliasedGV))                    return 'D';
274   }
275                                                            return '?';
276 }
277
278 static void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
279   // Private linkage and available_externally linkage don't exist in symtab.
280   if (GV.hasPrivateLinkage() ||
281       GV.hasLinkerPrivateLinkage() ||
282       GV.hasLinkerPrivateWeakLinkage() ||
283       GV.hasAvailableExternallyLinkage())
284     return;
285   char TypeChar = TypeCharForSymbol(GV);
286   if (GV.hasLocalLinkage () && ExternalOnly)
287     return;
288
289   NMSymbol s;
290   s.Address = object::UnknownAddressOrSize;
291   s.Size = object::UnknownAddressOrSize;
292   s.TypeChar = TypeChar;
293   s.Name     = GV.getName();
294   SymbolList.push_back(s);
295 }
296
297 static void DumpSymbolNamesFromModule(Module *M) {
298   CurrentFilename = M->getModuleIdentifier();
299   std::for_each (M->begin(), M->end(), DumpSymbolNameForGlobalValue);
300   std::for_each (M->global_begin(), M->global_end(),
301                  DumpSymbolNameForGlobalValue);
302   if (!WithoutAliases)
303     std::for_each (M->alias_begin(), M->alias_end(),
304                    DumpSymbolNameForGlobalValue);
305
306   SortAndPrintSymbolList();
307 }
308
309 template <class ELFT>
310 error_code getSymbolNMTypeChar(ELFObjectFile<ELFT> &Obj, symbol_iterator I,
311                                char &Result) {
312   typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
313   typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
314
315   DataRefImpl Symb = I->getRawDataRefImpl();
316   const Elf_Sym *ESym = Obj.getSymbol(Symb);
317   const ELFFile<ELFT> &EF = *Obj.getELFFile();
318   const Elf_Shdr *ESec = EF.getSection(ESym);
319
320   char ret = '?';
321
322   if (ESec) {
323     switch (ESec->sh_type) {
324     case ELF::SHT_PROGBITS:
325     case ELF::SHT_DYNAMIC:
326       switch (ESec->sh_flags) {
327       case(ELF::SHF_ALLOC | ELF::SHF_EXECINSTR) :
328         ret = 't';
329         break;
330       case(ELF::SHF_ALLOC | ELF::SHF_WRITE) :
331         ret = 'd';
332         break;
333       case ELF::SHF_ALLOC:
334       case(ELF::SHF_ALLOC | ELF::SHF_MERGE) :
335       case(ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS) :
336         ret = 'r';
337         break;
338       }
339       break;
340     case ELF::SHT_NOBITS:
341       ret = 'b';
342     }
343   }
344
345   switch (EF.getSymbolTableIndex(ESym)) {
346   case ELF::SHN_UNDEF:
347     if (ret == '?')
348       ret = 'U';
349     break;
350   case ELF::SHN_ABS:
351     ret = 'a';
352     break;
353   case ELF::SHN_COMMON:
354     ret = 'c';
355     break;
356   }
357
358   switch (ESym->getBinding()) {
359   case ELF::STB_GLOBAL:
360     ret = ::toupper(ret);
361     break;
362   case ELF::STB_WEAK:
363     if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF)
364       ret = 'w';
365     else if (ESym->getType() == ELF::STT_OBJECT)
366       ret = 'V';
367     else
368       ret = 'W';
369   }
370
371   if (ret == '?' && ESym->getType() == ELF::STT_SECTION) {
372     StringRef Name;
373     error_code EC = I->getName(Name);
374     if (EC)
375       return EC;
376     Result = StringSwitch<char>(Name)
377                  .StartsWith(".debug", 'N')
378                  .StartsWith(".note", 'n')
379                  .Default('?');
380     return object_error::success;
381   }
382
383   Result = ret;
384   return object_error::success;
385 }
386
387 static error_code getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I,
388                                       char &Result) {
389   const coff_symbol *symb = Obj.getCOFFSymbol(I);
390   StringRef name;
391   if (error_code ec = I->getName(name))
392     return ec;
393   char ret = StringSwitch<char>(name)
394                  .StartsWith(".debug", 'N')
395                  .StartsWith(".sxdata", 'N')
396                  .Default('?');
397
398   if (ret != '?') {
399     Result = ret;
400     return object_error::success;
401   }
402
403   uint32_t Characteristics = 0;
404   if (symb->SectionNumber > 0) {
405     section_iterator SecI = Obj.end_sections();
406     if (error_code ec = I->getSection(SecI))
407       return ec;
408     const coff_section *Section = Obj.getCOFFSection(SecI);
409     Characteristics = Section->Characteristics;
410   }
411
412   switch (symb->SectionNumber) {
413   case COFF::IMAGE_SYM_UNDEFINED:
414     // Check storage classes.
415     if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
416       Result = 'w';
417       return object_error::success; // Don't do ::toupper.
418     } else if (symb->Value != 0)    // Check for common symbols.
419       ret = 'c';
420     else
421       ret = 'u';
422     break;
423   case COFF::IMAGE_SYM_ABSOLUTE:
424     ret = 'a';
425     break;
426   case COFF::IMAGE_SYM_DEBUG:
427     ret = 'n';
428     break;
429   default:
430     // Check section type.
431     if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
432       ret = 't';
433     else if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
434              ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
435       ret = 'r';
436     else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
437       ret = 'd';
438     else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
439       ret = 'b';
440     else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
441       ret = 'i';
442
443     // Check for section symbol.
444     else if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC &&
445              symb->Value == 0)
446       ret = 's';
447   }
448
449   if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
450     ret = ::toupper(static_cast<unsigned char>(ret));
451
452   Result = ret;
453   return object_error::success;
454 }
455
456 static uint8_t getNType(MachOObjectFile &Obj, DataRefImpl Symb) {
457   if (Obj.is64Bit()) {
458     MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);
459     return STE.n_type;
460   }
461   MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
462   return STE.n_type;
463 }
464
465 static error_code getSymbolNMTypeChar(MachOObjectFile &Obj, symbol_iterator I,
466                                       char &Res) {
467   DataRefImpl Symb = I->getRawDataRefImpl();
468   uint8_t NType = getNType(Obj, Symb);
469
470   char Char;
471   switch (NType & MachO::N_TYPE) {
472   case MachO::N_UNDF:
473     Char = 'u';
474     break;
475   case MachO::N_ABS:
476     Char = 's';
477     break;
478   case MachO::N_SECT: {
479     section_iterator Sec = Obj.end_sections();
480     Obj.getSymbolSection(Symb, Sec);
481     DataRefImpl Ref = Sec->getRawDataRefImpl();
482     StringRef SectionName;
483     Obj.getSectionName(Ref, SectionName);
484     StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
485     if (SegmentName == "__TEXT" && SectionName == "__text")
486       Char = 't';
487     else
488       Char = 's';
489   } break;
490   default:
491     Char = '?';
492     break;
493   }
494
495   if (NType & (MachO::N_EXT | MachO::N_PEXT))
496     Char = toupper(static_cast<unsigned char>(Char));
497   Res = Char;
498   return object_error::success;
499 }
500
501 static char getNMTypeChar(ObjectFile *Obj, symbol_iterator I) {
502   char Res = '?';
503   if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(Obj)) {
504     error(getSymbolNMTypeChar(*COFF, I, Res));
505     return Res;
506   }
507   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj)) {
508     error(getSymbolNMTypeChar(*MachO, I, Res));
509     return Res;
510   }
511
512   if (ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj)) {
513     error(getSymbolNMTypeChar(*ELF, I, Res));
514     return Res;
515   }
516   if (ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj)) {
517     error(getSymbolNMTypeChar(*ELF, I, Res));
518     return Res;
519   }
520   if (ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj)) {
521     error(getSymbolNMTypeChar(*ELF, I, Res));
522     return Res;
523   }
524   ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj);
525   error(getSymbolNMTypeChar(*ELF, I, Res));
526   return Res;
527 }
528
529 static void DumpSymbolNamesFromObject(ObjectFile *obj) {
530   error_code ec;
531   symbol_iterator ibegin = obj->begin_symbols();
532   symbol_iterator iend = obj->end_symbols();
533   if (DynamicSyms) {
534     ibegin = obj->begin_dynamic_symbols();
535     iend = obj->end_dynamic_symbols();
536   }
537   for (symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
538     if (error(ec)) break;
539     uint32_t symflags;
540     if (error(i->getFlags(symflags))) break;
541     if (!DebugSyms && (symflags & SymbolRef::SF_FormatSpecific))
542       continue;
543     NMSymbol s;
544     s.Size = object::UnknownAddressOrSize;
545     s.Address = object::UnknownAddressOrSize;
546     if (PrintSize || SizeSort) {
547       if (error(i->getSize(s.Size))) break;
548     }
549     if (PrintAddress)
550       if (error(i->getAddress(s.Address))) break;
551     s.TypeChar = getNMTypeChar(obj, i);
552     if (error(i->getName(s.Name))) break;
553     SymbolList.push_back(s);
554   }
555
556   CurrentFilename = obj->getFileName();
557   SortAndPrintSymbolList();
558 }
559
560 static void DumpSymbolNamesFromFile(std::string &Filename) {
561   if (Filename != "-" && !sys::fs::exists(Filename)) {
562     errs() << ToolName << ": '" << Filename << "': " << "No such file\n";
563     return;
564   }
565
566   OwningPtr<MemoryBuffer> Buffer;
567   if (error(MemoryBuffer::getFileOrSTDIN(Filename, Buffer), Filename))
568     return;
569
570   sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer());
571
572   LLVMContext &Context = getGlobalContext();
573   std::string ErrorMessage;
574   if (magic == sys::fs::file_magic::bitcode) {
575     Module *Result = 0;
576     Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage);
577     if (Result) {
578       DumpSymbolNamesFromModule(Result);
579       delete Result;
580     } else {
581       error(ErrorMessage, Filename);
582       return;
583     }
584   } else if (magic == sys::fs::file_magic::archive) {
585     OwningPtr<Binary> arch;
586     if (error(object::createBinary(Buffer.take(), arch), Filename))
587       return;
588
589     if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
590       if (ArchiveMap) {
591         object::Archive::symbol_iterator I = a->begin_symbols();
592         object::Archive::symbol_iterator E = a->end_symbols();
593         if (I !=E) {
594           outs() << "Archive map" << "\n";
595           for (; I != E; ++I) {
596             object::Archive::child_iterator c;
597             StringRef symname;
598             StringRef filename;
599             if (error(I->getMember(c)))
600               return;
601             if (error(I->getName(symname)))
602               return;
603             if (error(c->getName(filename)))
604               return;
605             outs() << symname << " in " << filename << "\n";
606           }
607           outs() << "\n";
608         }
609       }
610
611       for (object::Archive::child_iterator i = a->begin_children(),
612                                            e = a->end_children(); i != e; ++i) {
613         OwningPtr<Binary> child;
614         if (i->getAsBinary(child)) {
615           // Try opening it as a bitcode file.
616           OwningPtr<MemoryBuffer> buff;
617           if (error(i->getMemoryBuffer(buff)))
618             return;
619           Module *Result = 0;
620           if (buff)
621             Result = ParseBitcodeFile(buff.get(), Context, &ErrorMessage);
622
623           if (Result) {
624             DumpSymbolNamesFromModule(Result);
625             delete Result;
626           }
627           continue;
628         }
629         if (object::ObjectFile *o = dyn_cast<ObjectFile>(child.get())) {
630           outs() << o->getFileName() << ":\n";
631           DumpSymbolNamesFromObject(o);
632         }
633       }
634     }
635   } else if (magic == sys::fs::file_magic::macho_universal_binary) {
636     OwningPtr<Binary> Bin;
637     if (error(object::createBinary(Buffer.take(), Bin), Filename))
638       return;
639
640     object::MachOUniversalBinary *UB =
641         cast<object::MachOUniversalBinary>(Bin.get());
642     for (object::MachOUniversalBinary::object_iterator
643              I = UB->begin_objects(),
644              E = UB->end_objects();
645          I != E; ++I) {
646       OwningPtr<ObjectFile> Obj;
647       if (!I->getAsObjectFile(Obj)) {
648         outs() << Obj->getFileName() << ":\n";
649         DumpSymbolNamesFromObject(Obj.get());
650       }
651     }
652   } else if (magic.is_object()) {
653     OwningPtr<Binary> obj;
654     if (error(object::createBinary(Buffer.take(), obj), Filename))
655       return;
656     if (object::ObjectFile *o = dyn_cast<ObjectFile>(obj.get()))
657       DumpSymbolNamesFromObject(o);
658   } else {
659     errs() << ToolName << ": " << Filename << ": "
660            << "unrecognizable file type\n";
661     HadError = true;
662     return;
663   }
664 }
665
666 int main(int argc, char **argv) {
667   // Print a stack trace if we signal out.
668   sys::PrintStackTraceOnErrorSignal();
669   PrettyStackTraceProgram X(argc, argv);
670
671   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
672   cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
673
674   // llvm-nm only reads binary files.
675   if (error(sys::ChangeStdinToBinary()))
676     return 1;
677
678   ToolName = argv[0];
679   if (BSDFormat) OutputFormat = bsd;
680   if (POSIXFormat) OutputFormat = posix;
681
682   // The relative order of these is important. If you pass --size-sort it should
683   // only print out the size. However, if you pass -S --size-sort, it should
684   // print out both the size and address.
685   if (SizeSort && !PrintSize) PrintAddress = false;
686   if (OutputFormat == sysv || SizeSort) PrintSize = true;
687
688   switch (InputFilenames.size()) {
689   case 0: InputFilenames.push_back("-");
690   case 1: break;
691   default: MultipleFiles = true;
692   }
693
694   std::for_each(InputFilenames.begin(), InputFilenames.end(),
695                 DumpSymbolNamesFromFile);
696
697   if (HadError)
698     return 1;
699
700   return 0;
701 }