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
This commit is contained in:
Kevin Enderby 2017-01-23 21:13:29 +00:00
parent b6137063eb
commit c3a035d86f
5 changed files with 171 additions and 2 deletions

View 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 =

View 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) +

Binary file not shown.

View File

@ -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

View 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));