Skip to content

Commit

Permalink
Add an implementation for llvm-nm’s -print-file-name option (aka -o a…
Browse files Browse the repository at this point in the history
…nd -A).

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
  • Loading branch information
enderby committed Jul 24, 2014
1 parent 51a4c94 commit fb0326c
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 49 deletions.
9 changes: 9 additions & 0 deletions test/Object/nm-archive.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions test/Object/nm-trivial-object.test
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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 \
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions test/Object/nm-universal-binary.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
151 changes: 102 additions & 49 deletions tools/llvm-nm/llvm-nm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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);
}
}
}
Expand All @@ -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);
Expand All @@ -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);
}
}
}
Expand All @@ -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) {
Expand All @@ -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);
}
}
}
Expand Down

0 comments on commit fb0326c

Please sign in to comment.