Add an implementation for llvm-nm’s -print-file-name option (aka -o and -A).
authorKevin Enderby <enderby@apple.com>
Thu, 24 Jul 2014 23:31:52 +0000 (23:31 +0000)
committerKevin Enderby <enderby@apple.com>
Thu, 24 Jul 2014 23:31:52 +0000 (23:31 +0000)
The -print-file-name option in llvm-nm is to precede each symbol
with the object file it came from.  While code for the parsing of this
option and its aliases existed there was no code to implement it.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213906 91177308-0d34-0410-b5e6-96231b3b80d8

test/Object/nm-archive.test
test/Object/nm-trivial-object.test
test/Object/nm-universal-binary.test
tools/llvm-nm/llvm-nm.cpp

index 7dbc22a1e8cf5202a29034fddfb0f57a298ce9fa..b2a196ef44fa3655ad89416976170bc8a861b9d2 100644 (file)
@@ -9,6 +9,15 @@ COFF-NEXT:          U _SomeOtherFunction
 COFF-NEXT: 00000000 T _main
 COFF-NEXT:          U _puts
 
+RUN: llvm-nm -o %p/Inputs/archive-test.a-coff-i386 \
+RUN:         | FileCheck %s -check-prefix COFF-o
+
+COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 d .data
+COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 t .text
+COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 d L_.str
+COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386:          U _SomeOtherFunction
+COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 T _main
+COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386:          U _puts
 
 RUN: llvm-as %p/Inputs/trivial.ll -o=%t1
 RUN: rm -f %t2
index 49c7683c80d4178619dc6770a514f5261ac3d2b6..a7bb7caad1d8004a8b3ace23d3b097305bcb3163 100644 (file)
@@ -4,6 +4,8 @@ RUN: yaml2obj %p/Inputs/COFF/x86-64.yaml | llvm-nm - \
 RUN:         | FileCheck %s -check-prefix COFF
 RUN: llvm-nm %p/Inputs/trivial-object-test.elf-i386 \
 RUN:         | FileCheck %s -check-prefix ELF
+RUN: llvm-nm -o %p/Inputs/trivial-object-test.elf-i386 \
+RUN:         | FileCheck %s -check-prefix ELF-o
 RUN: llvm-nm %p/Inputs/trivial-object-test.elf-x86-64 \
 RUN:         | FileCheck %s -check-prefix ELF64
 RUN: llvm-nm %p/Inputs/weak.elf-x86-64 \
@@ -26,6 +28,8 @@ RUN: llvm-nm %p/Inputs/macho-text-data-bss.macho-x86_64 -s __DATA __data \
 RUN:         | FileCheck %s -check-prefix macho-s
 RUN: llvm-nm -x %p/Inputs/macho-text-data-bss.macho-x86_64 \
 RUN:         | FileCheck %s -check-prefix macho-x
+RUN: llvm-nm -o %p/Inputs/macho-text-data-bss.macho-x86_64 \
+RUN:         | FileCheck %s -check-prefix macho-o
 RUN: llvm-nm -p -a %p/Inputs/macho-hello-g.macho-x86_64 \
 RUN:         | FileCheck %s -check-prefix macho-pa
 RUN: llvm-nm %p/Inputs/common.coff-i386 \
@@ -62,6 +66,10 @@ ELF:          U SomeOtherFunction
 ELF: 00000000 T main
 ELF:          U puts
 
+ELF-o: {{.*}}/trivial-object-test.elf-i386:          U SomeOtherFunction
+ELF-o: {{.*}}/trivial-object-test.elf-i386: 00000000 T main
+ELF-o: {{.*}}/trivial-object-test.elf-i386:          U puts
+
 ELF64:                  U SomeOtherFunction
 ELF64: 0000000000000000 T main
 ELF64:                  U puts
@@ -117,6 +125,13 @@ macho-x: 000000000000000c 0f 02 0000 00000004 _d
 macho-x: 0000000000000000 0f 01 0000 00000001 _t
 macho-x: 0000000000000048 0f 05 0000 00000007 _t.eh
 
+
+macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000030 s EH_frame0
+macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000070 b _b
+macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 000000000000000c D _d
+macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000000 T _t
+macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000048 S _t.eh
+
 macho-pa: 0000000000000000 - 00 0000    SO /Volumes/SandBox/
 macho-pa: 0000000000000000 - 00 0000    SO hello.c
 macho-pa: 0000000053c8408d - 03 0001   OSO /Volumes/SandBox/hello.o
index 889377b5b35b41daa77901bd6515f40e3ccf61ad..732445e778bbf4d5a58d41e7741722aeef4cb7e2 100644 (file)
@@ -6,6 +6,8 @@ RUN: llvm-nm -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
 RUN:         | FileCheck %s -check-prefix CHECK-AR
 RUN: llvm-nm -arch i386 %p/Inputs/macho-universal-archive.x86_64.i386 \
 RUN:         | FileCheck %s -check-prefix CHECK-AR-i386
+RUN: llvm-nm -o -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
+RUN:         | FileCheck %s -check-prefix CHECK-AR-o
 
 CHECK-OBJ: macho-universal.x86_64.i386 (for architecture x86_64):
 CHECK-OBJ: 0000000100000f60 T _main
@@ -29,3 +31,11 @@ CHECK-AR: 00000000 T _foo
 CHECK-AR-i386: macho-universal-archive.x86_64.i386(foo.o):
 CHECK-AR-i386: 00000008 D _bar
 CHECK-AR-i386: 00000000 T _foo
+
+CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000068 s EH_frame0
+CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 000000000000003b s L_.str
+CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000000 T _main
+CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000080 S _main.eh
+CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o:                  U _printf
+CHECK-AR-o: (for architecture i386):{{.*}}/macho-universal-archive.x86_64.i386:foo.o: 00000008 D _bar
+CHECK-AR-o: (for architecture i386):{{.*}}/macho-universal-archive.x86_64.i386:foo.o: 00000000 T _foo
index 15304c40b887d036858d78d9d1202c8f526ab113..38c945cb94f2eb8e612254aca990a948bf35b8b2 100644 (file)
@@ -535,7 +535,9 @@ static void darwinPrintStab(MachOObjectFile *MachO, SymbolListT::iterator I) {
   outs() << Str;
 }
 
-static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) {
+static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName,
+                                   std::string ArchiveName,
+                                   std::string ArchitectureName) {
   if (!NoSort) {
     if (NumericSort)
       std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolAddress);
@@ -545,14 +547,16 @@ static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) {
       std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolName);
   }
 
-  if (OutputFormat == posix && MultipleFiles && printName) {
-    outs() << '\n' << CurrentFilename << ":\n";
-  } else if (OutputFormat == bsd && MultipleFiles && printName) {
-    outs() << "\n" << CurrentFilename << ":\n";
-  } else if (OutputFormat == sysv) {
-    outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"
-           << "Name                  Value   Class        Type"
-           << "         Size   Line  Section\n";
+  if (!PrintFileName) {
+    if (OutputFormat == posix && MultipleFiles && printName) {
+      outs() << '\n' << CurrentFilename << ":\n";
+    } else if (OutputFormat == bsd && MultipleFiles && printName) {
+      outs() << "\n" << CurrentFilename << ":\n";
+    } else if (OutputFormat == sysv) {
+      outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"
+             << "Name                  Value   Class        Type"
+             << "         Size   Line  Section\n";
+    }
   }
 
   const char *printBlanks, *printFormat;
@@ -572,6 +576,13 @@ static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) {
       continue;
     if (SizeSort && !PrintAddress && I->Size == UnknownAddressOrSize)
       continue;
+    if (PrintFileName) {
+      if (!ArchitectureName.empty())
+        outs() << "(for architecture " << ArchitectureName << "):";
+      if (!ArchiveName.empty())
+        outs() << ArchiveName << ":";
+      outs() << CurrentFilename << ": ";
+    }
     if (JustSymbolName) {
       outs() << I->Name << "\n";
       continue;
@@ -883,7 +894,10 @@ static unsigned getNsectInMachO(MachOObjectFile &Obj, basic_symbol_iterator I) {
   return 0;
 }
 
-static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) {
+static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName,
+                                      std::string ArchiveName = std::string(),
+                                      std::string ArchitectureName =
+                                        std::string()) {
   basic_symbol_iterator IBegin = Obj->symbol_begin();
   basic_symbol_iterator IEnd = Obj->symbol_end();
   if (DynamicSyms) {
@@ -951,7 +965,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) {
   }
 
   CurrentFilename = Obj->getFileName();
-  sortAndPrintSymbolList(Obj, printName);
+  sortAndPrintSymbolList(Obj, printName, ArchiveName, ArchitectureName);
 }
 
 // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
@@ -1029,13 +1043,15 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
       if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
         if (!checkMachOAndArchFlags(O, Filename))
           return;
-        outs() << "\n";
-        if (isa<MachOObjectFile>(O)) {
-          outs() << Filename << "(" << O->getFileName() << ")";
-        } else
-          outs() << O->getFileName();
-        outs() << ":\n";
-        dumpSymbolNamesFromObject(O, false);
+        if (!PrintFileName) {
+          outs() << "\n";
+          if (isa<MachOObjectFile>(O)) {
+            outs() << Filename << "(" << O->getFileName() << ")";
+          } else
+            outs() << O->getFileName();
+          outs() << ":\n";
+        }
+        dumpSymbolNamesFromObject(O, false, Filename);
       }
     }
     return;
@@ -1055,14 +1071,22 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
             ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
                 I->getAsObjectFile();
             std::unique_ptr<Archive> A;
+            std::string ArchiveName;
+            std::string ArchitectureName;
+            ArchiveName.clear();
+            ArchitectureName.clear();
             if (ObjOrErr) {
               std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
               if (ArchFlags.size() > 1) {
-                outs() << "\n" << Obj->getFileName() << " (for architecture "
-                       << I->getArchTypeName() << ")"
-                       << ":\n";
+                if (PrintFileName)
+                  ArchitectureName = I->getArchTypeName();
+                else
+                  outs() << "\n" << Obj->getFileName() << " (for architecture "
+                         << I->getArchTypeName() << ")"
+                         << ":\n";
               }
-              dumpSymbolNamesFromObject(Obj.get(), false);
+              dumpSymbolNamesFromObject(Obj.get(), false, ArchiveName,
+                                        ArchitectureName);
             } else if (!I->getAsArchive(A)) {
               for (Archive::child_iterator AI = A->child_begin(),
                                            AE = A->child_end();
@@ -1073,14 +1097,21 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
                   continue;
                 if (SymbolicFile *O =
                         dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
-                  outs() << "\n" << A->getFileName();
-                  outs() << "(" << O->getFileName() << ")";
-                  if (ArchFlags.size() > 1) {
-                    outs() << " (for architecture " << I->getArchTypeName()
-                           << ")";
+                  if (PrintFileName) {
+                    ArchiveName = A->getFileName();
+                    if (ArchFlags.size() > 1)
+                      ArchitectureName = I->getArchTypeName();
+                  } else {
+                    outs() << "\n" << A->getFileName();
+                    outs() << "(" << O->getFileName() << ")";
+                    if (ArchFlags.size() > 1) {
+                      outs() << " (for architecture " << I->getArchTypeName()
+                             << ")";
+                    }
+                    outs() << ":\n";
                   }
-                  outs() << ":\n";
-                  dumpSymbolNamesFromObject(O, false);
+                  dumpSymbolNamesFromObject(O, false, ArchiveName,
+                                            ArchitectureName);
                 }
               }
             }
@@ -1104,6 +1135,8 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
         if (HostArchName == I->getArchTypeName()) {
           ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
           std::unique_ptr<Archive> A;
+          std::string ArchiveName;
+          ArchiveName.clear();
           if (ObjOrErr) {
             std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
             dumpSymbolNamesFromObject(Obj.get(), false);
@@ -1117,10 +1150,13 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
                 continue;
               if (SymbolicFile *O =
                       dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
-                outs() << "\n" << A->getFileName() << "(" << O->getFileName()
-                       << ")"
-                       << ":\n";
-                dumpSymbolNamesFromObject(O, false);
+                if (PrintFileName)
+                  ArchiveName = A->getFileName();
+                else
+                  outs() << "\n" << A->getFileName() << "(" << O->getFileName()
+                         << ")"
+                         << ":\n";
+                dumpSymbolNamesFromObject(O, false, ArchiveName);
               }
             }
           }
@@ -1136,15 +1172,25 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
          I != E; ++I) {
       ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
       std::unique_ptr<Archive> A;
+      std::string ArchiveName;
+      std::string ArchitectureName;
+      ArchiveName.clear();
+      ArchitectureName.clear();
       if (ObjOrErr) {
         std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
-        if (moreThanOneArch)
-          outs() << "\n";
-        outs() << Obj->getFileName();
-        if (isa<MachOObjectFile>(Obj.get()) && moreThanOneArch)
-          outs() << " (for architecture " << I->getArchTypeName() << ")";
-        outs() << ":\n";
-        dumpSymbolNamesFromObject(Obj.get(), false);
+        if (PrintFileName) {
+          if (isa<MachOObjectFile>(Obj.get()) && moreThanOneArch)
+            ArchitectureName = I->getArchTypeName();
+        } else {
+          if (moreThanOneArch)
+            outs() << "\n";
+          outs() << Obj->getFileName();
+          if (isa<MachOObjectFile>(Obj.get()) && moreThanOneArch)
+            outs() << " (for architecture " << I->getArchTypeName() << ")";
+          outs() << ":\n";
+        }
+        dumpSymbolNamesFromObject(Obj.get(), false, ArchiveName,
+                                  ArchitectureName);
       } else if (!I->getAsArchive(A)) {
         for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
              AI != AE; ++AI) {
@@ -1153,15 +1199,22 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
           if (ChildOrErr.getError())
             continue;
           if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
-            outs() << "\n" << A->getFileName();
-            if (isa<MachOObjectFile>(O)) {
-              outs() << "(" << O->getFileName() << ")";
-              if (moreThanOneArch)
-                outs() << " (for architecture " << I->getArchTypeName() << ")";
-            } else
-              outs() << ":" << O->getFileName();
-            outs() << ":\n";
-            dumpSymbolNamesFromObject(O, false);
+            if (PrintFileName) {
+              ArchiveName = A->getFileName();
+              if (isa<MachOObjectFile>(O) && moreThanOneArch)
+                ArchitectureName = I->getArchTypeName();
+            } else {
+              outs() << "\n" << A->getFileName();
+              if (isa<MachOObjectFile>(O)) {
+                outs() << "(" << O->getFileName() << ")";
+                if (moreThanOneArch)
+                  outs() << " (for architecture " << I->getArchTypeName()
+                         << ")";
+              } else
+                outs() << ":" << O->getFileName();
+              outs() << ":\n";
+            }
+            dumpSymbolNamesFromObject(O, false, ArchiveName, ArchitectureName);
           }
         }
       }