Add the code and test cases for 32-bit Intel to llvm-objdump’s Mach-O symbolizer.
authorKevin Enderby <enderby@apple.com>
Tue, 4 Nov 2014 00:43:16 +0000 (00:43 +0000)
committerKevin Enderby <enderby@apple.com>
Tue, 4 Nov 2014 00:43:16 +0000 (00:43 +0000)
llvm-svn: 221211

llvm/include/llvm/Object/MachO.h
llvm/lib/Object/MachOObjectFile.cpp
llvm/test/tools/llvm-objdump/X86/Inputs/hello.exe.macho-i386 [new file with mode: 0755]
llvm/test/tools/llvm-objdump/X86/Inputs/hello.obj.macho-i386 [new file with mode: 0644]
llvm/test/tools/llvm-objdump/X86/macho-symbolized-disassembly.test
llvm/test/tools/llvm-objdump/X86/macho-symbolized-subtractor-i386.test [new file with mode: 0644]
llvm/tools/llvm-objdump/MachODump.cpp

index 2497b7a..768cda6 100644 (file)
@@ -322,6 +322,8 @@ public:
                                     const MachO::any_relocation_info &RE) const;
   uint32_t getScatteredRelocationValue(
                                     const MachO::any_relocation_info &RE) const;
+  uint32_t getScatteredRelocationType(
+                                    const MachO::any_relocation_info &RE) const;
   unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const;
   unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
   unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
index 75e39fd..678728e 100644 (file)
@@ -2150,6 +2150,11 @@ uint32_t MachOObjectFile::getScatteredRelocationValue(
   return RE.r_word1;
 }
 
+uint32_t MachOObjectFile::getScatteredRelocationType(
+    const MachO::any_relocation_info &RE) const {
+  return (RE.r_word0 >> 24) & 0xf;
+}
+
 unsigned MachOObjectFile::getAnyRelocationAddress(
     const MachO::any_relocation_info &RE) const {
   if (isRelocationScattered(RE))
diff --git a/llvm/test/tools/llvm-objdump/X86/Inputs/hello.exe.macho-i386 b/llvm/test/tools/llvm-objdump/X86/Inputs/hello.exe.macho-i386
new file mode 100755 (executable)
index 0000000..b1f7bd8
Binary files /dev/null and b/llvm/test/tools/llvm-objdump/X86/Inputs/hello.exe.macho-i386 differ
diff --git a/llvm/test/tools/llvm-objdump/X86/Inputs/hello.obj.macho-i386 b/llvm/test/tools/llvm-objdump/X86/Inputs/hello.obj.macho-i386
new file mode 100644 (file)
index 0000000..b69d4be
Binary files /dev/null and b/llvm/test/tools/llvm-objdump/X86/Inputs/hello.obj.macho-i386 differ
index cb9b8b2..1e1080a 100644 (file)
@@ -4,6 +4,9 @@
 // RUN: llvm-objdump -d -m -no-show-raw-insn -full-leading-addr -print-imm-hex %p/Inputs/ObjC.exe.macho-x86_64 | FileCheck %s -check-prefix=ObjC-EXE
 // RUN: llvm-objdump -d -m -no-show-raw-insn -full-leading-addr -print-imm-hex %p/Inputs/hello_cpp.exe.macho-x86_64 | FileCheck %s -check-prefix=CXX-EXE
 
+// RUN: llvm-objdump -d -m -no-show-raw-insn -full-leading-addr -print-imm-hex %p/Inputs/hello.obj.macho-i386 | FileCheck %s -check-prefix=i386-OBJ
+// RUN: llvm-objdump -d -m -no-show-raw-insn -full-leading-addr -print-imm-hex %p/Inputs/hello.exe.macho-i386 | FileCheck %s -check-prefix=i386-EXE
+
 OBJ: 0000000000000008  leaq    L_.str(%rip), %rax      ## literal pool for: "Hello world\n"
 OBJ: 0000000000000026  callq   _printf
 
@@ -29,3 +32,7 @@ CXX-EXE: 00000001000014cb     callq   __ZNSt3__116__pad_and_outputIcNS_11char_traitsIc
 
 // FIXME: Demangler depends on host's <cxxabi.h>.
 // std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > std::__1::__pad_and_output<char, std::__1::char_traits<char> >(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, char const*, char const*, char const*, std::__1::ios_base&, char)
+
+i386-OBJ: 0000002f     calll   _printf
+
+i386-EXE: 00001f6f     calll   0x1f84                  ## symbol stub for: _printf
diff --git a/llvm/test/tools/llvm-objdump/X86/macho-symbolized-subtractor-i386.test b/llvm/test/tools/llvm-objdump/X86/macho-symbolized-subtractor-i386.test
new file mode 100644 (file)
index 0000000..a0f753b
--- /dev/null
@@ -0,0 +1,10 @@
+# RUN: llvm-mc < %s -triple x86_64-apple-darwin -filetype=obj | llvm-objdump -m -d - | FileCheck %s
+
+nop
+x:
+leal   x-y(%eax), %ebx
+.data
+y:
+.quad 0
+
+# CHECK: leal  x-y(%eax), %ebx
index c62a92e..50afab7 100644 (file)
@@ -248,6 +248,21 @@ struct DisassembleInfo {
   BindTable *bindtable;
 };
 
+// GuessSymbolName is passed the address of what might be a symbol and a
+// pointer to the DisassembleInfo struct.  It returns the name of a symbol
+// with that address or nullptr if no symbol is found with that address.
+static const char *GuessSymbolName(uint64_t value,
+                                   struct DisassembleInfo *info) {
+  const char *SymbolName = nullptr;
+  // A DenseMap can't lookup up some values.
+  if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
+    StringRef name = info->AddrMap->lookup(value);
+    if (!name.empty())
+      SymbolName = name.data();
+  }
+  return SymbolName;
+}
+
 // SymbolizerGetOpInfo() is the operand information call back function.
 // This is called to get the symbolic information for operand(s) of an
 // instruction when it is being done.  This routine does this from
@@ -281,6 +296,83 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
 
   unsigned int Arch = info->O->getArch();
   if (Arch == Triple::x86) {
+    if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
+      return 0;
+    // First search the section's relocation entries (if any) for an entry
+    // for this section offset.
+    uint32_t sect_addr = info->S.getAddress();
+    uint32_t sect_offset = (Pc + Offset) - sect_addr;
+    bool reloc_found = false;
+    DataRefImpl Rel;
+    MachO::any_relocation_info RE;
+    bool isExtern = false;
+    SymbolRef Symbol;
+    bool r_scattered = false;
+    uint32_t r_value, pair_r_value, r_type;
+    for (const RelocationRef &Reloc : info->S.relocations()) {
+      uint64_t RelocOffset;
+      Reloc.getOffset(RelocOffset);
+      if (RelocOffset == sect_offset) {
+        Rel = Reloc.getRawDataRefImpl();
+        RE = info->O->getRelocation(Rel);
+        r_scattered = info->O->isRelocationScattered(RE);
+        if (r_scattered) {
+          r_value = info->O->getScatteredRelocationValue(RE);
+          r_type = info->O->getScatteredRelocationType(RE);
+          if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
+              r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
+            DataRefImpl RelNext = Rel;
+            info->O->moveRelocationNext(RelNext);
+            MachO::any_relocation_info RENext;
+            RENext = info->O->getRelocation(RelNext);
+            if (info->O->isRelocationScattered(RENext))
+              pair_r_value = info->O->getPlainRelocationSymbolNum(RENext);
+            else
+              return 0;
+          }
+        } else {
+          isExtern = info->O->getPlainRelocationExternal(RE);
+          if (isExtern) {
+            symbol_iterator RelocSym = Reloc.getSymbol();
+            Symbol = *RelocSym;
+          }
+        }
+        reloc_found = true;
+        break;
+      }
+    }
+    if (reloc_found && isExtern) {
+      StringRef SymName;
+      Symbol.getName(SymName);
+      const char *name = SymName.data();
+      op_info->AddSymbol.Present = 1;
+      op_info->AddSymbol.Name = name;
+      // For i386 extern relocation entries the value in the instruction is
+      // the offset from the symbol, and value is already set in op_info->Value.
+      return 1;
+    }
+    if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
+                        r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
+      const char *add = GuessSymbolName(r_value, info);
+      const char *sub = GuessSymbolName(pair_r_value, info);
+      uint32_t offset = value - (r_value - pair_r_value);
+      op_info->AddSymbol.Present = 1;
+      if (add != nullptr)
+        op_info->AddSymbol.Name = add;
+      else
+        op_info->AddSymbol.Value = r_value;
+      op_info->SubtractSymbol.Present = 1;
+      if (sub != nullptr)
+        op_info->SubtractSymbol.Name = sub;
+      else
+        op_info->SubtractSymbol.Value = pair_r_value;
+      op_info->Value = offset;
+      return 1;
+    }
+    // TODO:
+    // Second search the external relocation entries of a fully linked image
+    // (if any) for an entry that matches this segment offset.
+    // uint32_t seg_offset = (Pc + Offset);
     return 0;
   } else if (Arch == Triple::x86_64) {
     if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
@@ -716,13 +808,7 @@ const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
   //
   // NOTE: need add passing the ReferenceValue to this routine.  Then that code
   // would simply be this:
-  //
-  // if (ReferenceValue != 0xffffffffffffffffLLU &&
-  //     ReferenceValue != 0xfffffffffffffffeLLU) {
-  //   StringRef name = info->AddrMap->lookup(ReferenceValue);
-  //   if (!name.empty())
-  //     SymbolName = name.data();
-  // }
+  // SymbolName = GuessSymbolName(ReferenceValue, info);
 
   return SymbolName;
 }
@@ -1071,13 +1157,7 @@ const char *SymbolizerSymbolLookUp(void *DisInfo, uint64_t ReferenceValue,
     return nullptr;
   }
 
-  const char *SymbolName = nullptr;
-  if (ReferenceValue != 0xffffffffffffffffULL &&
-      ReferenceValue != 0xfffffffffffffffeULL) {
-    StringRef name = info->AddrMap->lookup(ReferenceValue);
-    if (!name.empty())
-      SymbolName = name.data();
-  }
+  const char *SymbolName = GuessSymbolName(ReferenceValue, info);
 
   if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
     *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);