summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Enderby <enderby@apple.com>2018-03-22 23:59:35 +0000
committerKevin Enderby <enderby@apple.com>2018-03-22 23:59:35 +0000
commitd3cf76ba25446fc3e76a8540d97b775fbe7c9fb0 (patch)
treef07ab8e795b95492cc07fb525fe1679acb77afa3
parentf4ec686bf7a1af2ce3362da35ea983b0cda9ff70 (diff)
downloadbcm5719-llvm-d3cf76ba25446fc3e76a8540d97b775fbe7c9fb0.tar.gz
bcm5719-llvm-d3cf76ba25446fc3e76a8540d97b775fbe7c9fb0.zip
For llvm-nm and Mach-O files also use function starts info in some
cases when printing symbols. As an improvement to: r305733 - Change llvm-nm for Mach-O files to use dyld info in some cases when printing symbols it could be made a bit better if it also read the function starts and faked up nlist entries to those address not already faked up by the other dyld info. This would help with stripped static functions. rdar://38761029 llvm-svn: 328274
-rwxr-xr-xllvm/test/tools/llvm-nm/X86/Inputs/Strip-N.hello.exe.macho-x86_64bin0 -> 8320 bytes
-rw-r--r--llvm/test/tools/llvm-nm/X86/dyldinfo.test8
-rw-r--r--llvm/tools/llvm-nm/llvm-nm.cpp92
3 files changed, 98 insertions, 2 deletions
diff --git a/llvm/test/tools/llvm-nm/X86/Inputs/Strip-N.hello.exe.macho-x86_64 b/llvm/test/tools/llvm-nm/X86/Inputs/Strip-N.hello.exe.macho-x86_64
new file mode 100755
index 00000000000..8aee1a5170c
--- /dev/null
+++ b/llvm/test/tools/llvm-nm/X86/Inputs/Strip-N.hello.exe.macho-x86_64
Binary files differ
diff --git a/llvm/test/tools/llvm-nm/X86/dyldinfo.test b/llvm/test/tools/llvm-nm/X86/dyldinfo.test
index 3a632c57737..483dd2104aa 100644
--- a/llvm/test/tools/llvm-nm/X86/dyldinfo.test
+++ b/llvm/test/tools/llvm-nm/X86/dyldinfo.test
@@ -1,6 +1,7 @@
# RUN: llvm-nm %p/Inputs/Strip-ST.dylib.macho-x86_64 | FileCheck --check-prefix=DEFAULT %s
# RUN: llvm-nm -no-dyldinfo %p/Inputs/Strip-ST.dylib.macho-x86_64 | FileCheck --check-prefix=NO-DYLDINFO %s
# RUN: llvm-nm -dyldinfo-only %p/Inputs/Strip-ST.dylib.macho-x86_64 | FileCheck --check-prefix=DYLDINFO-ONLY %s
+# RUN: llvm-nm %p/Inputs/Strip-N.hello.exe.macho-x86_64 | FileCheck --check-prefix=FUNC-STARTS %s
# DEFAULT: 0000000000000f90 T __Bob_is_slow
# DEFAULT: 0000000000001008 D __T0ims_data
@@ -16,3 +17,10 @@
# DYLDINFO-ONLY: 0000000000001008 D __T0ims_data
# DYLDINFO-ONLY: 0000000000000f80 T __T0om_is_not_swift
# DYLDINFO-ONLY-NOT: U dyld_stub_binder
+
+# FUNC-STARTS: 0000000100000f70 t <redacted function 1>
+# FUNC-STARTS: 0000000100000f80 t <redacted function 2>
+# FUNC-STARTS: 0000000100000000 T __mh_execute_header
+# FUNC-STARTS: 0000000100000f30 T _main
+# FUNC-STARTS: U _printf
+# FUNC-STARTS: U dyld_stub_binder
diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index 2b18a3ce8c3..e494920018d 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -270,8 +270,16 @@ struct NMSymbol {
} // anonymous namespace
static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) {
- bool ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined);
- bool BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined);
+ bool ADefined;
+ if (A.Sym.getRawDataRefImpl().p)
+ ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined);
+ else
+ ADefined = A.TypeChar != 'U';
+ bool BDefined;
+ if (B.Sym.getRawDataRefImpl().p)
+ BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined);
+ else
+ BDefined = B.TypeChar != 'U';
return std::make_tuple(ADefined, A.Address, A.Name, A.Size) <
std::make_tuple(BDefined, B.Address, B.Name, B.Size);
}
@@ -1207,6 +1215,8 @@ dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
raw_string_ostream LOS(LazysNameBuffer);
std::string WeaksNameBuffer;
raw_string_ostream WOS(WeaksNameBuffer);
+ std::string FunctionStartsNameBuffer;
+ raw_string_ostream FOS(FunctionStartsNameBuffer);
if (MachO && !NoDyldInfo) {
MachO::mach_header H;
MachO::mach_header_64 H_64;
@@ -1577,6 +1587,84 @@ dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
I++;
}
}
+
+ // Trying adding symbol from the function starts table.
+ SmallVector<uint64_t, 8> FoundFns;
+ for (const auto &Command : MachO->load_commands()) {
+ if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
+ // We found a function starts segment, parse the addresses for
+ // consumption.
+ MachO::linkedit_data_command LLC =
+ MachO->getLinkeditDataLoadCommand(Command);
+
+ MachO->ReadULEB128s(LLC.dataoff, FoundFns);
+ }
+ }
+ // See if these addresses are already in the symbol table.
+ unsigned FunctionStartsAdded = 0;
+ for (uint64_t f = 0; f < FoundFns.size(); f++) {
+ bool found = false;
+ for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
+ if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress)
+ found = true;
+ }
+ // See this address is not already in the symbol table fake up an
+ // nlist for it.
+ if (!found) {
+ NMSymbol F;
+ memset(&F, '\0', sizeof(NMSymbol));
+ F.Name = "<redacted function X>";
+ F.Address = FoundFns[f] + BaseSegmentAddress;
+ F.Size = 0;
+ // There is no symbol in the nlist symbol table for this so we set
+ // Sym effectivly to null and the rest of code in here must test for
+ // it and not do things like Sym.getFlags() for it.
+ F.Sym = BasicSymbolRef();
+ F.SymFlags = 0;
+ F.NType = MachO::N_SECT;
+ F.NSect = 0;
+ StringRef SegmentName = StringRef();
+ StringRef SectionName = StringRef();
+ for (const SectionRef &Section : MachO->sections()) {
+ Section.getName(SectionName);
+ SegmentName = MachO->getSectionFinalSegmentName(
+ Section.getRawDataRefImpl());
+ F.NSect++;
+ if (F.Address >= Section.getAddress() &&
+ F.Address < Section.getAddress() + Section.getSize()) {
+ F.Section = Section;
+ break;
+ }
+ }
+ if (SegmentName == "__TEXT" && SectionName == "__text")
+ F.TypeChar = 't';
+ else if (SegmentName == "__DATA" && SectionName == "__data")
+ F.TypeChar = 'd';
+ else if (SegmentName == "__DATA" && SectionName == "__bss")
+ F.TypeChar = 'b';
+ else
+ F.TypeChar = 's';
+ F.NDesc = 0;
+ F.IndirectName = StringRef();
+ SymbolList.push_back(F);
+ FOS << "<redacted function " << f << ">";
+ FOS << '\0';
+ FunctionStartsAdded++;
+ }
+ }
+ if (FunctionStartsAdded) {
+ FOS.flush();
+ const char *Q = FunctionStartsNameBuffer.c_str();
+ for (unsigned K = 0; K < FunctionStartsAdded; K++) {
+ SymbolList[I].Name = Q;
+ Q += strlen(Q) + 1;
+ if (SymbolList[I].TypeChar == 'I') {
+ SymbolList[I].IndirectName = Q;
+ Q += strlen(Q) + 1;
+ }
+ I++;
+ }
+ }
}
}
OpenPOWER on IntegriCloud