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>
43using namespace llvm;
44using namespace object;
45
46namespace {
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
133static void error(Twine message, Twine path = Twine()) {
134  errs() << ToolName << ": " << path << ": " << message << ".\n";
135}
136
137static 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
146namespace {
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
193static 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
261static 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
278static 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
297static 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
309template <class ELFT>
310error_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
387static 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
456static 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
465static 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
501static 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
529static 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
560static 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
666int 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}
702