summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-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