diff --git a/test/Object/nm-archive.test b/test/Object/nm-archive.test index 7dbc22a1e8c..b2a196ef44f 100644 --- a/test/Object/nm-archive.test +++ b/test/Object/nm-archive.test @@ -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 diff --git a/test/Object/nm-trivial-object.test b/test/Object/nm-trivial-object.test index 49c7683c80d..a7bb7caad1d 100644 --- a/test/Object/nm-trivial-object.test +++ b/test/Object/nm-trivial-object.test @@ -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 diff --git a/test/Object/nm-universal-binary.test b/test/Object/nm-universal-binary.test index 889377b5b35..732445e778b 100644 --- a/test/Object/nm-universal-binary.test +++ b/test/Object/nm-universal-binary.test @@ -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 diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 15304c40b88..38c945cb94f 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -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(&*ChildOrErr.get())) { if (!checkMachOAndArchFlags(O, Filename)) return; - outs() << "\n"; - if (isa(O)) { - outs() << Filename << "(" << O->getFileName() << ")"; - } else - outs() << O->getFileName(); - outs() << ":\n"; - dumpSymbolNamesFromObject(O, false); + if (!PrintFileName) { + outs() << "\n"; + if (isa(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> ObjOrErr = I->getAsObjectFile(); std::unique_ptr A; + std::string ArchiveName; + std::string ArchitectureName; + ArchiveName.clear(); + ArchitectureName.clear(); if (ObjOrErr) { std::unique_ptr 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(&*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> ObjOrErr = I->getAsObjectFile(); std::unique_ptr A; + std::string ArchiveName; + ArchiveName.clear(); if (ObjOrErr) { std::unique_ptr 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(&*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> ObjOrErr = I->getAsObjectFile(); std::unique_ptr A; + std::string ArchiveName; + std::string ArchitectureName; + ArchiveName.clear(); + ArchitectureName.clear(); if (ObjOrErr) { std::unique_ptr Obj = std::move(ObjOrErr.get()); - if (moreThanOneArch) - outs() << "\n"; - outs() << Obj->getFileName(); - if (isa(Obj.get()) && moreThanOneArch) - outs() << " (for architecture " << I->getArchTypeName() << ")"; - outs() << ":\n"; - dumpSymbolNamesFromObject(Obj.get(), false); + if (PrintFileName) { + if (isa(Obj.get()) && moreThanOneArch) + ArchitectureName = I->getArchTypeName(); + } else { + if (moreThanOneArch) + outs() << "\n"; + outs() << Obj->getFileName(); + if (isa(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(&*ChildOrErr.get())) { - outs() << "\n" << A->getFileName(); - if (isa(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(O) && moreThanOneArch) + ArchitectureName = I->getArchTypeName(); + } else { + outs() << "\n" << A->getFileName(); + if (isa(O)) { + outs() << "(" << O->getFileName() << ")"; + if (moreThanOneArch) + outs() << " (for architecture " << I->getArchTypeName() + << ")"; + } else + outs() << ":" << O->getFileName(); + outs() << ":\n"; + } + dumpSymbolNamesFromObject(O, false, ArchiveName, ArchitectureName); } } }