Add support for the ARM_THREAD_STATE64 and

in llvm-objdump for Mach-O files add the printing of the
ARM_THREAD_STATE64 in the same format as
otool-classic(1) on darwin.

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

rdar://28985800

llvm-svn: 285967
This commit is contained in:
Kevin Enderby 2016-11-03 20:51:28 +00:00
parent 8e232573a8
commit 7747cb55dc
5 changed files with 144 additions and 0 deletions

View File

@ -1742,6 +1742,25 @@ namespace llvm {
sys::swapByteOrder(x.cpsr);
}
struct arm_thread_state64_t {
uint64_t x[29];
uint64_t fp;
uint64_t lr;
uint64_t sp;
uint64_t pc;
uint32_t cpsr;
};
inline void swapStruct(arm_thread_state64_t &x) {
for (int i = 0; i < 29; i++)
sys::swapByteOrder(x.x[i]);
sys::swapByteOrder(x.fp);
sys::swapByteOrder(x.lr);
sys::swapByteOrder(x.sp);
sys::swapByteOrder(x.pc);
sys::swapByteOrder(x.cpsr);
}
struct arm_state_hdr_t {
uint32_t flavor;
uint32_t count;
@ -1778,6 +1797,9 @@ namespace llvm {
const uint32_t ARM_THREAD_STATE_COUNT =
sizeof(arm_thread_state32_t) / sizeof(uint32_t);
const uint32_t ARM_THREAD_STATE64_COUNT =
sizeof(arm_thread_state64_t) / sizeof(uint32_t);
struct ppc_thread_state32_t {
uint32_t srr0;
uint32_t srr1;

View File

@ -970,6 +970,25 @@ static Error checkThreadCommand(const MachOObjectFile *Obj,
"flavor number " + Twine(nflavor) + " in " +
CmdName + " command");
}
} else if (cputype == MachO::CPU_TYPE_ARM64) {
if (flavor == MachO::ARM_THREAD_STATE64) {
if (count != MachO::ARM_THREAD_STATE64_COUNT)
return malformedError("load command " + Twine(LoadCommandIndex) +
" count not ARM_THREAD_STATE64_COUNT for "
"flavor number " + Twine(nflavor) + " which is "
"a ARM_THREAD_STATE64 flavor in " + CmdName +
" command");
if (state + sizeof(MachO::arm_thread_state64_t) > end)
return malformedError("load command " + Twine(LoadCommandIndex) +
" ARM_THREAD_STATE64 extends past end of "
"command in " + CmdName + " command");
state += sizeof(MachO::arm_thread_state64_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_POWERPC) {
if (flavor == MachO::PPC_THREAD_STATE) {
if (count != MachO::PPC_THREAD_STATE_COUNT)

View File

@ -0,0 +1,19 @@
RUN: llvm-objdump -macho -private-headers %p/Inputs/thread.macho-aarch64 | FileCheck %s
CHECK: Load command 0
CHECK: cmd LC_THREAD
CHECK: cmdsize 288
CHECK: flavor ARM_THREAD_STATE64
CHECK: count ARM_THREAD_STATE64_COUNT
CHECK: x0 0x0000000000000000 x1 0x0000000000000000 x2 0x0000000000000000
CHECK: x3 0x0000000000000000 x4 0x0000000000000000 x5 0x0000000000000000
CHECK: x6 0x0000000000000000 x7 0x0000000000000000 x8 0x0000000000000000
CHECK: x9 0x0000000000000000 x10 0x0000000000000000 x11 0x0000000000000000
CHECK: x12 0x0000000000000000 x13 0x0000000000000000 x14 0x0000000000000000
CHECK: x15 0x0000000000000000 x16 0x0000000000000000 x17 0x0000000000000000
CHECK: x18 0x0000000000000000 x19 0x0000000000000000 x20 0x0000000000000000
CHECK: x21 0x0000000000000000 x22 0x0000000000000000 x23 0x0000000000000000
CHECK: x24 0x0000000000000000 x25 0x0000000000000000 x26 0x0000000000000000
CHECK: x27 0x0000000000000000 x28 0x0000000000000000 fp 0x0000000000000000
CHECK: lr 0x0000000000000000 sp 0x0000000000000000 pc 0x0000000000000000
CHECK: cpsr 0x00000000

View File

@ -8656,6 +8656,43 @@ static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
}
static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]);
outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]);
outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]);
outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]);
outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]);
outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]);
outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]);
outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]);
outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]);
outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]);
outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]);
outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]);
outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]);
outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]);
outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]);
outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]);
outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]);
outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]);
outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]);
outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]);
outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n";
outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr);
outs() << " sp " << format("0x%016" PRIx64, cpu64.sp);
outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n";
outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n";
}
static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
bool isLittleEndian, uint32_t cputype) {
if (t.cmd == MachO::LC_THREAD)
@ -8859,6 +8896,53 @@ static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
begin += count * sizeof(uint32_t);
}
}
} else if (cputype == MachO::CPU_TYPE_ARM64) {
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::ARM_THREAD_STATE64) {
outs() << " flavor ARM_THREAD_STATE64\n";
if (count == MachO::ARM_THREAD_STATE64_COUNT)
outs() << " count ARM_THREAD_STATE64_COUNT\n";
else
outs() << " count " << count
<< " (not ARM_THREAD_STATE64_COUNT)\n";
MachO::arm_thread_state64_t cpu64;
left = end - begin;
if (left >= sizeof(MachO::arm_thread_state64_t)) {
memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
begin += sizeof(MachO::arm_thread_state64_t);
} else {
memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
memcpy(&cpu64, begin, left);
begin += left;
}
if (isLittleEndian != sys::IsLittleEndianHost)
swapStruct(cpu64);
Print_arm_thread_state64_t(cpu64);
} else {
outs() << " flavor " << flavor << " (unknown)\n";
outs() << " count " << count << "\n";
outs() << " state (unknown)\n";
begin += count * sizeof(uint32_t);
}
}
} else {
while (begin < end) {
if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {