forked from OSchip/llvm-project
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:
parent
b6137063eb
commit
c3a035d86f
|
@ -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 =
|
||||
|
|
|
@ -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.
|
@ -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
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue