Skip to content

Commit 08e1bbd

Browse files
committed
Add an implementation for llvm-nm’s -print-file-name option (aka -o and -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. llvm-svn: 213906
1 parent ab131e8 commit 08e1bbd

File tree

4 files changed

+136
-49
lines changed

4 files changed

+136
-49
lines changed

llvm/test/Object/nm-archive.test

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ COFF-NEXT: U _SomeOtherFunction
99
COFF-NEXT: 00000000 T _main
1010
COFF-NEXT: U _puts
1111

12+
RUN: llvm-nm -o %p/Inputs/archive-test.a-coff-i386 \
13+
RUN: | FileCheck %s -check-prefix COFF-o
14+
15+
COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 d .data
16+
COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 t .text
17+
COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 d L_.str
18+
COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: U _SomeOtherFunction
19+
COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 T _main
20+
COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: U _puts
1221

1322
RUN: llvm-as %p/Inputs/trivial.ll -o=%t1
1423
RUN: rm -f %t2

llvm/test/Object/nm-trivial-object.test

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ RUN: yaml2obj %p/Inputs/COFF/x86-64.yaml | llvm-nm - \
44
RUN: | FileCheck %s -check-prefix COFF
55
RUN: llvm-nm %p/Inputs/trivial-object-test.elf-i386 \
66
RUN: | FileCheck %s -check-prefix ELF
7+
RUN: llvm-nm -o %p/Inputs/trivial-object-test.elf-i386 \
8+
RUN: | FileCheck %s -check-prefix ELF-o
79
RUN: llvm-nm %p/Inputs/trivial-object-test.elf-x86-64 \
810
RUN: | FileCheck %s -check-prefix ELF64
911
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 \
2628
RUN: | FileCheck %s -check-prefix macho-s
2729
RUN: llvm-nm -x %p/Inputs/macho-text-data-bss.macho-x86_64 \
2830
RUN: | FileCheck %s -check-prefix macho-x
31+
RUN: llvm-nm -o %p/Inputs/macho-text-data-bss.macho-x86_64 \
32+
RUN: | FileCheck %s -check-prefix macho-o
2933
RUN: llvm-nm -p -a %p/Inputs/macho-hello-g.macho-x86_64 \
3034
RUN: | FileCheck %s -check-prefix macho-pa
3135
RUN: llvm-nm %p/Inputs/common.coff-i386 \
@@ -62,6 +66,10 @@ ELF: U SomeOtherFunction
6266
ELF: 00000000 T main
6367
ELF: U puts
6468

69+
ELF-o: {{.*}}/trivial-object-test.elf-i386: U SomeOtherFunction
70+
ELF-o: {{.*}}/trivial-object-test.elf-i386: 00000000 T main
71+
ELF-o: {{.*}}/trivial-object-test.elf-i386: U puts
72+
6573
ELF64: U SomeOtherFunction
6674
ELF64: 0000000000000000 T main
6775
ELF64: U puts
@@ -117,6 +125,13 @@ macho-x: 000000000000000c 0f 02 0000 00000004 _d
117125
macho-x: 0000000000000000 0f 01 0000 00000001 _t
118126
macho-x: 0000000000000048 0f 05 0000 00000007 _t.eh
119127

128+
129+
macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000030 s EH_frame0
130+
macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000070 b _b
131+
macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 000000000000000c D _d
132+
macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000000 T _t
133+
macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000048 S _t.eh
134+
120135
macho-pa: 0000000000000000 - 00 0000 SO /Volumes/SandBox/
121136
macho-pa: 0000000000000000 - 00 0000 SO hello.c
122137
macho-pa: 0000000053c8408d - 03 0001 OSO /Volumes/SandBox/hello.o

llvm/test/Object/nm-universal-binary.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ RUN: llvm-nm -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
66
RUN: | FileCheck %s -check-prefix CHECK-AR
77
RUN: llvm-nm -arch i386 %p/Inputs/macho-universal-archive.x86_64.i386 \
88
RUN: | FileCheck %s -check-prefix CHECK-AR-i386
9+
RUN: llvm-nm -o -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
10+
RUN: | FileCheck %s -check-prefix CHECK-AR-o
911

1012
CHECK-OBJ: macho-universal.x86_64.i386 (for architecture x86_64):
1113
CHECK-OBJ: 0000000100000f60 T _main
@@ -29,3 +31,11 @@ CHECK-AR: 00000000 T _foo
2931
CHECK-AR-i386: macho-universal-archive.x86_64.i386(foo.o):
3032
CHECK-AR-i386: 00000008 D _bar
3133
CHECK-AR-i386: 00000000 T _foo
34+
35+
CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000068 s EH_frame0
36+
CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 000000000000003b s L_.str
37+
CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000000 T _main
38+
CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000080 S _main.eh
39+
CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: U _printf
40+
CHECK-AR-o: (for architecture i386):{{.*}}/macho-universal-archive.x86_64.i386:foo.o: 00000008 D _bar
41+
CHECK-AR-o: (for architecture i386):{{.*}}/macho-universal-archive.x86_64.i386:foo.o: 00000000 T _foo

llvm/tools/llvm-nm/llvm-nm.cpp

Lines changed: 102 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,9 @@ static void darwinPrintStab(MachOObjectFile *MachO, SymbolListT::iterator I) {
535535
outs() << Str;
536536
}
537537

538-
static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) {
538+
static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName,
539+
std::string ArchiveName,
540+
std::string ArchitectureName) {
539541
if (!NoSort) {
540542
if (NumericSort)
541543
std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolAddress);
@@ -545,14 +547,16 @@ static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) {
545547
std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolName);
546548
}
547549

548-
if (OutputFormat == posix && MultipleFiles && printName) {
549-
outs() << '\n' << CurrentFilename << ":\n";
550-
} else if (OutputFormat == bsd && MultipleFiles && printName) {
551-
outs() << "\n" << CurrentFilename << ":\n";
552-
} else if (OutputFormat == sysv) {
553-
outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"
554-
<< "Name Value Class Type"
555-
<< " Size Line Section\n";
550+
if (!PrintFileName) {
551+
if (OutputFormat == posix && MultipleFiles && printName) {
552+
outs() << '\n' << CurrentFilename << ":\n";
553+
} else if (OutputFormat == bsd && MultipleFiles && printName) {
554+
outs() << "\n" << CurrentFilename << ":\n";
555+
} else if (OutputFormat == sysv) {
556+
outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"
557+
<< "Name Value Class Type"
558+
<< " Size Line Section\n";
559+
}
556560
}
557561

558562
const char *printBlanks, *printFormat;
@@ -572,6 +576,13 @@ static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) {
572576
continue;
573577
if (SizeSort && !PrintAddress && I->Size == UnknownAddressOrSize)
574578
continue;
579+
if (PrintFileName) {
580+
if (!ArchitectureName.empty())
581+
outs() << "(for architecture " << ArchitectureName << "):";
582+
if (!ArchiveName.empty())
583+
outs() << ArchiveName << ":";
584+
outs() << CurrentFilename << ": ";
585+
}
575586
if (JustSymbolName) {
576587
outs() << I->Name << "\n";
577588
continue;
@@ -883,7 +894,10 @@ static unsigned getNsectInMachO(MachOObjectFile &Obj, basic_symbol_iterator I) {
883894
return 0;
884895
}
885896

886-
static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) {
897+
static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName,
898+
std::string ArchiveName = std::string(),
899+
std::string ArchitectureName =
900+
std::string()) {
887901
basic_symbol_iterator IBegin = Obj->symbol_begin();
888902
basic_symbol_iterator IEnd = Obj->symbol_end();
889903
if (DynamicSyms) {
@@ -951,7 +965,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) {
951965
}
952966

953967
CurrentFilename = Obj->getFileName();
954-
sortAndPrintSymbolList(Obj, printName);
968+
sortAndPrintSymbolList(Obj, printName, ArchiveName, ArchitectureName);
955969
}
956970

957971
// checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
@@ -1029,13 +1043,15 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
10291043
if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
10301044
if (!checkMachOAndArchFlags(O, Filename))
10311045
return;
1032-
outs() << "\n";
1033-
if (isa<MachOObjectFile>(O)) {
1034-
outs() << Filename << "(" << O->getFileName() << ")";
1035-
} else
1036-
outs() << O->getFileName();
1037-
outs() << ":\n";
1038-
dumpSymbolNamesFromObject(O, false);
1046+
if (!PrintFileName) {
1047+
outs() << "\n";
1048+
if (isa<MachOObjectFile>(O)) {
1049+
outs() << Filename << "(" << O->getFileName() << ")";
1050+
} else
1051+
outs() << O->getFileName();
1052+
outs() << ":\n";
1053+
}
1054+
dumpSymbolNamesFromObject(O, false, Filename);
10391055
}
10401056
}
10411057
return;
@@ -1055,14 +1071,22 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
10551071
ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
10561072
I->getAsObjectFile();
10571073
std::unique_ptr<Archive> A;
1074+
std::string ArchiveName;
1075+
std::string ArchitectureName;
1076+
ArchiveName.clear();
1077+
ArchitectureName.clear();
10581078
if (ObjOrErr) {
10591079
std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
10601080
if (ArchFlags.size() > 1) {
1061-
outs() << "\n" << Obj->getFileName() << " (for architecture "
1062-
<< I->getArchTypeName() << ")"
1063-
<< ":\n";
1081+
if (PrintFileName)
1082+
ArchitectureName = I->getArchTypeName();
1083+
else
1084+
outs() << "\n" << Obj->getFileName() << " (for architecture "
1085+
<< I->getArchTypeName() << ")"
1086+
<< ":\n";
10641087
}
1065-
dumpSymbolNamesFromObject(Obj.get(), false);
1088+
dumpSymbolNamesFromObject(Obj.get(), false, ArchiveName,
1089+
ArchitectureName);
10661090
} else if (!I->getAsArchive(A)) {
10671091
for (Archive::child_iterator AI = A->child_begin(),
10681092
AE = A->child_end();
@@ -1073,14 +1097,21 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
10731097
continue;
10741098
if (SymbolicFile *O =
10751099
dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
1076-
outs() << "\n" << A->getFileName();
1077-
outs() << "(" << O->getFileName() << ")";
1078-
if (ArchFlags.size() > 1) {
1079-
outs() << " (for architecture " << I->getArchTypeName()
1080-
<< ")";
1100+
if (PrintFileName) {
1101+
ArchiveName = A->getFileName();
1102+
if (ArchFlags.size() > 1)
1103+
ArchitectureName = I->getArchTypeName();
1104+
} else {
1105+
outs() << "\n" << A->getFileName();
1106+
outs() << "(" << O->getFileName() << ")";
1107+
if (ArchFlags.size() > 1) {
1108+
outs() << " (for architecture " << I->getArchTypeName()
1109+
<< ")";
1110+
}
1111+
outs() << ":\n";
10811112
}
1082-
outs() << ":\n";
1083-
dumpSymbolNamesFromObject(O, false);
1113+
dumpSymbolNamesFromObject(O, false, ArchiveName,
1114+
ArchitectureName);
10841115
}
10851116
}
10861117
}
@@ -1104,6 +1135,8 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
11041135
if (HostArchName == I->getArchTypeName()) {
11051136
ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
11061137
std::unique_ptr<Archive> A;
1138+
std::string ArchiveName;
1139+
ArchiveName.clear();
11071140
if (ObjOrErr) {
11081141
std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
11091142
dumpSymbolNamesFromObject(Obj.get(), false);
@@ -1117,10 +1150,13 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
11171150
continue;
11181151
if (SymbolicFile *O =
11191152
dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
1120-
outs() << "\n" << A->getFileName() << "(" << O->getFileName()
1121-
<< ")"
1122-
<< ":\n";
1123-
dumpSymbolNamesFromObject(O, false);
1153+
if (PrintFileName)
1154+
ArchiveName = A->getFileName();
1155+
else
1156+
outs() << "\n" << A->getFileName() << "(" << O->getFileName()
1157+
<< ")"
1158+
<< ":\n";
1159+
dumpSymbolNamesFromObject(O, false, ArchiveName);
11241160
}
11251161
}
11261162
}
@@ -1136,15 +1172,25 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
11361172
I != E; ++I) {
11371173
ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
11381174
std::unique_ptr<Archive> A;
1175+
std::string ArchiveName;
1176+
std::string ArchitectureName;
1177+
ArchiveName.clear();
1178+
ArchitectureName.clear();
11391179
if (ObjOrErr) {
11401180
std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
1141-
if (moreThanOneArch)
1142-
outs() << "\n";
1143-
outs() << Obj->getFileName();
1144-
if (isa<MachOObjectFile>(Obj.get()) && moreThanOneArch)
1145-
outs() << " (for architecture " << I->getArchTypeName() << ")";
1146-
outs() << ":\n";
1147-
dumpSymbolNamesFromObject(Obj.get(), false);
1181+
if (PrintFileName) {
1182+
if (isa<MachOObjectFile>(Obj.get()) && moreThanOneArch)
1183+
ArchitectureName = I->getArchTypeName();
1184+
} else {
1185+
if (moreThanOneArch)
1186+
outs() << "\n";
1187+
outs() << Obj->getFileName();
1188+
if (isa<MachOObjectFile>(Obj.get()) && moreThanOneArch)
1189+
outs() << " (for architecture " << I->getArchTypeName() << ")";
1190+
outs() << ":\n";
1191+
}
1192+
dumpSymbolNamesFromObject(Obj.get(), false, ArchiveName,
1193+
ArchitectureName);
11481194
} else if (!I->getAsArchive(A)) {
11491195
for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
11501196
AI != AE; ++AI) {
@@ -1153,15 +1199,22 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
11531199
if (ChildOrErr.getError())
11541200
continue;
11551201
if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
1156-
outs() << "\n" << A->getFileName();
1157-
if (isa<MachOObjectFile>(O)) {
1158-
outs() << "(" << O->getFileName() << ")";
1159-
if (moreThanOneArch)
1160-
outs() << " (for architecture " << I->getArchTypeName() << ")";
1161-
} else
1162-
outs() << ":" << O->getFileName();
1163-
outs() << ":\n";
1164-
dumpSymbolNamesFromObject(O, false);
1202+
if (PrintFileName) {
1203+
ArchiveName = A->getFileName();
1204+
if (isa<MachOObjectFile>(O) && moreThanOneArch)
1205+
ArchitectureName = I->getArchTypeName();
1206+
} else {
1207+
outs() << "\n" << A->getFileName();
1208+
if (isa<MachOObjectFile>(O)) {
1209+
outs() << "(" << O->getFileName() << ")";
1210+
if (moreThanOneArch)
1211+
outs() << " (for architecture " << I->getArchTypeName()
1212+
<< ")";
1213+
} else
1214+
outs() << ":" << O->getFileName();
1215+
outs() << ":\n";
1216+
}
1217+
dumpSymbolNamesFromObject(O, false, ArchiveName, ArchitectureName);
11651218
}
11661219
}
11671220
}

0 commit comments

Comments
 (0)