]> granicus.if.org Git - llvm/commitdiff
Update llvm-objdump’s Mach-O symbolizer code to print the name of symbol stubs.
authorKevin Enderby <enderby@apple.com>
Fri, 26 Sep 2014 22:20:44 +0000 (22:20 +0000)
committerKevin Enderby <enderby@apple.com>
Fri, 26 Sep 2014 22:20:44 +0000 (22:20 +0000)
So in fully linked images when a call is made through a stub it now gets a
comment like the following in the disassembly:

    callq 0x100000f6c             ## symbol stub for: _printf

indicating the call is to a symbol stub and which symbol it is for.  This is
done for branch reference types and seeing if the branch target is in a stub
section and if so using the indirect symbol table entry for that stub and
using that symbol table entries symbol name.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218546 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-objdump/X86/macho-symbolized-disassembly.test
tools/llvm-objdump/MachODump.cpp

index 01105fbf3fde7660e34e7b4be76976d70f6de0d0..651531614499bc745ac36fc5a3d6fe00a4b1ef33 100644 (file)
@@ -5,3 +5,4 @@ OBJ: 0000000000000008   leaq    L_.str(%rip), %rax      ## literal pool for: "Hello w
 OBJ: 0000000000000026  callq   _printf
 
 EXE: 0000000100000f38  leaq    0x4f(%rip), %rax        ## literal pool for: "Hello world\n"
+EXE: 0000000100000f56  callq   0x100000f6c             ## symbol stub for: _printf
index 414a867ebca0306929b46a5b77dd3134b772276c..43f0661a05a4406af60f66fdc3557ff0a0817547 100644 (file)
@@ -413,6 +413,94 @@ const char *GuessCstringPointer(uint64_t ReferenceValue,
   return nullptr;
 }
 
+// GuessIndirectSymbol returns the name of the indirect symbol for the
+// ReferenceValue passed in or nullptr.  This is used when ReferenceValue maybe
+// an address of a symbol stub or a lazy or non-lazy pointer to associate the
+// symbol name being referenced by the stub or pointer.
+static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
+                                       struct DisassembleInfo *info) {
+  uint32_t LoadCommandCount = info->O->getHeader().ncmds;
+  MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
+  MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
+  MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
+  for (unsigned I = 0;; ++I) {
+    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
+      MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section_64 Sec = info->O->getSection64(Load, J);
+        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+        if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
+             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
+             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
+             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
+             section_type == MachO::S_SYMBOL_STUBS) &&
+            ReferenceValue >= Sec.addr &&
+            ReferenceValue < Sec.addr + Sec.size) {
+          uint32_t stride;
+          if (section_type == MachO::S_SYMBOL_STUBS)
+            stride = Sec.reserved2;
+          else
+            stride = 8;
+          if (stride == 0)
+            return nullptr;
+          uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
+          if (index < Dysymtab.nindirectsyms) {
+            uint32_t indirect_symbol =
+              info->O->getIndirectSymbolTableEntry(Dysymtab, index);
+            if (indirect_symbol < Symtab.nsyms) {
+              symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
+              SymbolRef Symbol = *Sym;
+              StringRef SymName;
+              Symbol.getName(SymName);
+              const char *name = SymName.data();
+              return name;
+            }
+          }
+        }
+      }
+    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
+      MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section Sec = info->O->getSection(Load, J);
+        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+        if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
+             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
+             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
+             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
+             section_type == MachO::S_SYMBOL_STUBS) &&
+            ReferenceValue >= Sec.addr &&
+            ReferenceValue < Sec.addr + Sec.size) {
+          uint32_t stride;
+          if (section_type == MachO::S_SYMBOL_STUBS)
+            stride = Sec.reserved2;
+          else
+            stride = 4;
+          if (stride == 0)
+            return nullptr;
+          uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
+          if (index < Dysymtab.nindirectsyms) {
+            uint32_t indirect_symbol =
+              info->O->getIndirectSymbolTableEntry(Dysymtab, index);
+            if (indirect_symbol < Symtab.nsyms) {
+              symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
+              SymbolRef Symbol = *Sym;
+              StringRef SymName;
+              Symbol.getName(SymName);
+              const char *name = SymName.data();
+              return name;
+            }
+          }
+        }
+      }
+    }
+    if (I == LoadCommandCount - 1)
+      break;
+    else
+      Load = info->O->getNextLoadCommandInfo(Load);
+  }
+  return nullptr;
+}
+
 // GuessLiteralPointer returns a string which for the item in the Mach-O file
 // for the address passed in as ReferenceValue for printing as a comment with
 // the instruction and also returns the corresponding type of that item
@@ -531,7 +619,14 @@ const char *SymbolizerSymbolLookUp(void *DisInfo, uint64_t ReferenceValue,
   if (!name.empty())
     SymbolName = name.data();
 
-  if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
+  if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
+    *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
+    if (*ReferenceName)
+      *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
+    else
+      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+  }
+  else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
     *ReferenceName = GuessLiteralPointer(ReferenceValue, ReferencePC,
                                          ReferenceType, info);
     if (*ReferenceName == nullptr)