[llvm] r292829 - Add support for the x86_thread_state32_t and

Kevin Enderby via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 23 13:13:29 PST 2017


Author: enderby
Date: Mon Jan 23 15:13:29 2017
New Revision: 292829

URL: http://llvm.org/viewvc/llvm-project?rev=292829&view=rev
Log:
Add support for the x86_thread_state32_t and
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

Added:
    llvm/trunk/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386   (with props)
    llvm/trunk/test/tools/llvm-objdump/X86/macho-print-thread.test
Modified:
    llvm/trunk/include/llvm/Support/MachO.h
    llvm/trunk/lib/Object/MachOObjectFile.cpp
    llvm/trunk/tools/llvm-objdump/MachODump.cpp

Modified: llvm/trunk/include/llvm/Support/MachO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MachO.h?rev=292829&r1=292828&r2=292829&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/MachO.h (original)
+++ llvm/trunk/include/llvm/Support/MachO.h Mon Jan 23 15:13:29 2017
@@ -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 =

Modified: llvm/trunk/lib/Object/MachOObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=292829&r1=292828&r2=292829&view=diff
==============================================================================
--- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/MachOObjectFile.cpp Mon Jan 23 15:13:29 2017
@@ -977,7 +977,26 @@ static Error checkThreadCommand(const Ma
       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) +

Added: llvm/trunk/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386?rev=292829&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386
------------------------------------------------------------------------------
    svn:executable = *

Propchange: llvm/trunk/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-objdump/X86/macho-print-thread.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/X86/macho-print-thread.test?rev=292829&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/X86/macho-print-thread.test (added)
+++ llvm/trunk/test/tools/llvm-objdump/X86/macho-print-thread.test Mon Jan 23 15:13:29 2017
@@ -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

Modified: llvm/trunk/tools/llvm-objdump/MachODump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/MachODump.cpp?rev=292829&r1=292828&r2=292829&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/MachODump.cpp (original)
+++ llvm/trunk/tools/llvm-objdump/MachODump.cpp Mon Jan 23 15:13:29 2017
@@ -8419,6 +8419,25 @@ static void PrintRoutinesCommand64(MachO
   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::th
   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));




More information about the llvm-commits mailing list