diff options
Diffstat (limited to 'llvm')
| -rwxr-xr-x | llvm/test/tools/llvm-nm/X86/Inputs/Strip-N.hello.exe.macho-x86_64 | bin | 0 -> 8320 bytes | |||
| -rw-r--r-- | llvm/test/tools/llvm-nm/X86/dyldinfo.test | 8 | ||||
| -rw-r--r-- | llvm/tools/llvm-nm/llvm-nm.cpp | 92 |
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 Binary files differnew file mode 100755 index 00000000000..8aee1a5170c --- /dev/null +++ b/llvm/test/tools/llvm-nm/X86/Inputs/Strip-N.hello.exe.macho-x86_64 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++; + } + } } } |

