]> granicus.if.org Git - llvm/commitdiff
Add support for the x86_thread_state32_t and
authorKevin Enderby <enderby@apple.com>
Mon, 23 Jan 2017 21:13:29 +0000 (21:13 +0000)
committerKevin Enderby <enderby@apple.com>
Mon, 23 Jan 2017 21:13:29 +0000 (21:13 +0000)
in llvm-objdump for Mach-O files add the printing of the
x86_thread_state32_t in the same format as
otool-classic(1) on darwin.

To do this the 32-bit x86 general tread state
needed to be defined in include/llvm/Support/MachO.h .

rdar://30110111

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

include/llvm/Support/MachO.h
lib/Object/MachOObjectFile.cpp
test/tools/llvm-objdump/X86/Inputs/thread.macho-i386 [new file with mode: 0755]
test/tools/llvm-objdump/X86/macho-print-thread.test [new file with mode: 0644]
tools/llvm-objdump/MachODump.cpp

index 88483aafb4efb4df6da416a7c09bfc2b950c88f3..3d704292c260a13335abb11971e3b23da95a9e75 100644 (file)
@@ -1530,6 +1530,25 @@ namespace llvm {
       CPU_SUBTYPE_MC98601       = CPU_SUBTYPE_POWERPC_601
     };
 
+    struct x86_thread_state32_t {
+      uint32_t eax;
+      uint32_t ebx;
+      uint32_t ecx;
+      uint32_t edx;
+      uint32_t edi;
+      uint32_t esi;
+      uint32_t ebp;
+      uint32_t esp;
+      uint32_t ss;
+      uint32_t eflags;
+      uint32_t eip;
+      uint32_t cs;
+      uint32_t ds;
+      uint32_t es;
+      uint32_t fs;
+      uint32_t gs;
+    };
+
     struct x86_thread_state64_t {
       uint64_t rax;
       uint64_t rbx;
@@ -1659,6 +1678,25 @@ namespace llvm {
       uint64_t faultvaddr;
     };
 
+    inline void swapStruct(x86_thread_state32_t &x) {
+      sys::swapByteOrder(x.eax);
+      sys::swapByteOrder(x.ebx);
+      sys::swapByteOrder(x.ecx);
+      sys::swapByteOrder(x.edx);
+      sys::swapByteOrder(x.edi);
+      sys::swapByteOrder(x.esi);
+      sys::swapByteOrder(x.ebp);
+      sys::swapByteOrder(x.esp);
+      sys::swapByteOrder(x.ss);
+      sys::swapByteOrder(x.eflags);
+      sys::swapByteOrder(x.eip);
+      sys::swapByteOrder(x.cs);
+      sys::swapByteOrder(x.ds);
+      sys::swapByteOrder(x.es);
+      sys::swapByteOrder(x.fs);
+      sys::swapByteOrder(x.gs);
+    }
+
     inline void swapStruct(x86_thread_state64_t &x) {
       sys::swapByteOrder(x.rax);
       sys::swapByteOrder(x.rbx);
@@ -1716,6 +1754,7 @@ namespace llvm {
       x86_state_hdr_t tsh;
       union {
         x86_thread_state64_t ts64;
+        x86_thread_state32_t ts32;
       } uts;
     };
 
@@ -1771,6 +1810,9 @@ namespace llvm {
         swapStruct(x.ues.es64);
     }
 
+    const uint32_t x86_THREAD_STATE32_COUNT =
+      sizeof(x86_thread_state32_t) / sizeof(uint32_t);
+
     const uint32_t x86_THREAD_STATE64_COUNT =
       sizeof(x86_thread_state64_t) / sizeof(uint32_t);
     const uint32_t x86_FLOAT_STATE64_COUNT =
index f35a3e3ba2f1222446eadc1ce7dfb20b45d052fa..ae1ac09716981cdc4460be035aecbf6445b583e4 100644 (file)
@@ -977,7 +977,26 @@ static Error checkThreadCommand(const MachOObjectFile &Obj,
       sys::swapByteOrder(count);
     state += sizeof(uint32_t);
 
-    if (cputype == MachO::CPU_TYPE_X86_64) {
+    if (cputype == MachO::CPU_TYPE_I386) {
+      if (flavor == MachO::x86_THREAD_STATE32) {
+        if (count != MachO::x86_THREAD_STATE32_COUNT)
+          return malformedError("load command " + Twine(LoadCommandIndex) +
+                                " count not x86_THREAD_STATE32_COUNT for "
+                                "flavor number " + Twine(nflavor) + " which is "
+                                "a x86_THREAD_STATE32 flavor in " + CmdName +
+                                " command");
+        if (state + sizeof(MachO::x86_thread_state32_t) > end)
+          return malformedError("load command " + Twine(LoadCommandIndex) +
+                                " x86_THREAD_STATE32 extends past end of "
+                                "command in " + CmdName + " command");
+        state += sizeof(MachO::x86_thread_state32_t);
+      } else {
+        return malformedError("load command " + Twine(LoadCommandIndex) +
+                              " unknown flavor (" + Twine(flavor) + ") for "
+                              "flavor number " + Twine(nflavor) + " in " +
+                              CmdName + " command");
+      }
+    } else if (cputype == MachO::CPU_TYPE_X86_64) {
       if (flavor == MachO::x86_THREAD_STATE64) {
         if (count != MachO::x86_THREAD_STATE64_COUNT)
           return malformedError("load command " + Twine(LoadCommandIndex) +
diff --git a/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386 b/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386
new file mode 100755 (executable)
index 0000000..f4b805d
Binary files /dev/null and b/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386 differ
diff --git a/test/tools/llvm-objdump/X86/macho-print-thread.test b/test/tools/llvm-objdump/X86/macho-print-thread.test
new file mode 100644 (file)
index 0000000..12f71de
--- /dev/null
@@ -0,0 +1,11 @@
+RUN: llvm-objdump -macho -private-headers %p/Inputs/thread.macho-i386 | FileCheck %s
+
+CHECK: Load command 9
+CHECK:         cmd LC_UNIXTHREAD
+CHECK:     cmdsize 80
+CHECK:      flavor i386_THREAD_STATE
+CHECK:       count i386_THREAD_STATE_COUNT
+CHECK:             eax 0x00000000 ebx    0x00000000 ecx 0x00000000 edx 0x00000000
+CHECK:             edi 0x00000000 esi    0x00000000 ebp 0x00000000 esp 0x00000000
+CHECK:             ss  0x00000000 eflags 0x00000000 eip 0x00001db0 cs  0x00000000
+CHECK:             ds  0x00000000 es     0x00000000 fs  0x00000000 gs  0x00000000
index faace1dfb629edf9207f73f0259e71982c493347..53517c58ceaa653ce81d59b3bc46c7f77f49b9ae 100644 (file)
@@ -8419,6 +8419,25 @@ static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
   outs() << "    reserved6 " << r.reserved6 << "\n";
 }
 
+static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
+  outs() << "\t    eax " << format("0x%08" PRIx32, cpu32.eax);
+  outs() << " ebx    " << format("0x%08" PRIx32, cpu32.ebx);
+  outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx);
+  outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n";
+  outs() << "\t    edi " << format("0x%08" PRIx32, cpu32.edi);
+  outs() << " esi    " << format("0x%08" PRIx32, cpu32.esi);
+  outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp);
+  outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n";
+  outs() << "\t    ss  " << format("0x%08" PRIx32, cpu32.ss);
+  outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags);
+  outs() << " eip " << format("0x%08" PRIx32, cpu32.eip);
+  outs() << " cs  " << format("0x%08" PRIx32, cpu32.cs) << "\n";
+  outs() << "\t    ds  " << format("0x%08" PRIx32, cpu32.ds);
+  outs() << " es     " << format("0x%08" PRIx32, cpu32.es);
+  outs() << " fs  " << format("0x%08" PRIx32, cpu32.fs);
+  outs() << " gs  " << format("0x%08" PRIx32, cpu32.gs) << "\n";
+}
+
 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
   outs() << "   rax  " << format("0x%016" PRIx64, cpu64.rax);
   outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
@@ -8656,7 +8675,85 @@ static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
   const char *begin = Ptr + sizeof(struct MachO::thread_command);
   const char *end = Ptr + t.cmdsize;
   uint32_t flavor, count, left;
-  if (cputype == MachO::CPU_TYPE_X86_64) {
+  if (cputype == MachO::CPU_TYPE_I386) {
+    while (begin < end) {
+      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
+        memcpy((char *)&flavor, begin, sizeof(uint32_t));
+        begin += sizeof(uint32_t);
+      } else {
+        flavor = 0;
+        begin = end;
+      }
+      if (isLittleEndian != sys::IsLittleEndianHost)
+        sys::swapByteOrder(flavor);
+      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
+        memcpy((char *)&count, begin, sizeof(uint32_t));
+        begin += sizeof(uint32_t);
+      } else {
+        count = 0;
+        begin = end;
+      }
+      if (isLittleEndian != sys::IsLittleEndianHost)
+        sys::swapByteOrder(count);
+      if (flavor == MachO::x86_THREAD_STATE32) {
+        outs() << "     flavor i386_THREAD_STATE\n";
+        if (count == MachO::x86_THREAD_STATE32_COUNT)
+          outs() << "      count i386_THREAD_STATE_COUNT\n";
+        else
+          outs() << "      count " << count
+                 << " (not x86_THREAD_STATE32_COUNT)\n";
+        MachO::x86_thread_state32_t cpu32;
+        left = end - begin;
+        if (left >= sizeof(MachO::x86_thread_state32_t)) {
+          memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
+          begin += sizeof(MachO::x86_thread_state32_t);
+        } else {
+          memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
+          memcpy(&cpu32, begin, left);
+          begin += left;
+        }
+        if (isLittleEndian != sys::IsLittleEndianHost)
+          swapStruct(cpu32);
+        Print_x86_thread_state32_t(cpu32);
+      } else if (flavor == MachO::x86_THREAD_STATE) {
+        outs() << "     flavor x86_THREAD_STATE\n";
+        if (count == MachO::x86_THREAD_STATE_COUNT)
+          outs() << "      count x86_THREAD_STATE_COUNT\n";
+        else
+          outs() << "      count " << count
+                 << " (not x86_THREAD_STATE_COUNT)\n";
+        struct MachO::x86_thread_state_t ts;
+        left = end - begin;
+        if (left >= sizeof(MachO::x86_thread_state_t)) {
+          memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
+          begin += sizeof(MachO::x86_thread_state_t);
+        } else {
+          memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
+          memcpy(&ts, begin, left);
+          begin += left;
+        }
+        if (isLittleEndian != sys::IsLittleEndianHost)
+          swapStruct(ts);
+        if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
+          outs() << "\t    tsh.flavor x86_THREAD_STATE32 ";
+          if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
+            outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
+          else
+            outs() << "tsh.count " << ts.tsh.count
+                   << " (not x86_THREAD_STATE32_COUNT\n";
+          Print_x86_thread_state32_t(ts.uts.ts32);
+        } else {
+          outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
+                 << ts.tsh.count << "\n";
+        }
+      } else {
+        outs() << "     flavor " << flavor << " (unknown)\n";
+        outs() << "      count " << count << "\n";
+        outs() << "      state (unknown)\n";
+        begin += count * sizeof(uint32_t);
+      }
+    }
+  } else if (cputype == MachO::CPU_TYPE_X86_64) {
     while (begin < end) {
       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
         memcpy((char *)&flavor, begin, sizeof(uint32_t));