summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Enderby <enderby@apple.com>2017-01-23 21:13:29 +0000
committerKevin Enderby <enderby@apple.com>2017-01-23 21:13:29 +0000
commitc3a035d86f91a380bd001eb6ad4cf4faf6bd5e84 (patch)
treece9d221635aec359a32197eb6b1cd58d3ade2120
parentb6137063ebda8a99f6b6f7c0c94b1cd3ad1c67d4 (diff)
downloadbcm5719-llvm-c3a035d86f91a380bd001eb6ad4cf4faf6bd5e84.tar.gz
bcm5719-llvm-c3a035d86f91a380bd001eb6ad4cf4faf6bd5e84.zip
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 llvm-svn: 292829
-rw-r--r--llvm/include/llvm/Support/MachO.h42
-rw-r--r--llvm/lib/Object/MachOObjectFile.cpp21
-rwxr-xr-xllvm/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386bin0 -> 9204 bytes
-rw-r--r--llvm/test/tools/llvm-objdump/X86/macho-print-thread.test11
-rw-r--r--llvm/tools/llvm-objdump/MachODump.cpp99
5 files changed, 171 insertions, 2 deletions
diff --git a/llvm/include/llvm/Support/MachO.h b/llvm/include/llvm/Support/MachO.h
index 88483aafb4e..3d704292c26 100644
--- a/llvm/include/llvm/Support/MachO.h
+++ b/llvm/include/llvm/Support/MachO.h
@@ -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 =
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index f35a3e3ba2f..ae1ac097169 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -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/llvm/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386 b/llvm/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386
new file mode 100755
index 00000000000..f4b805d9b03
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/Inputs/thread.macho-i386
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/X86/macho-print-thread.test b/llvm/test/tools/llvm-objdump/X86/macho-print-thread.test
new file mode 100644
index 00000000000..12f71de1db2
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/macho-print-thread.test
@@ -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
diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp
index faace1dfb62..53517c58cea 100644
--- a/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/llvm/tools/llvm-objdump/MachODump.cpp
@@ -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));
OpenPOWER on IntegriCloud