From 00b62fb861abbe47854cb9257b31455f4b2286ab Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Thu, 3 Nov 2016 20:51:28 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285967 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/MachO.h | 22 +++++ lib/Object/MachOObjectFile.cpp | 19 ++++ .../AArch64/Inputs/thread.macho-aarch64 | Bin 0 -> 320 bytes .../AArch64/macho-print-thread.test | 19 ++++ tools/llvm-objdump/MachODump.cpp | 84 ++++++++++++++++++ 5 files changed, 144 insertions(+) create mode 100644 test/tools/llvm-objdump/AArch64/Inputs/thread.macho-aarch64 create mode 100644 test/tools/llvm-objdump/AArch64/macho-print-thread.test diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index d7729755d69..80106a8c1e3 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -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; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 3aec182c0c6..ad52235a50d 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -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) diff --git a/test/tools/llvm-objdump/AArch64/Inputs/thread.macho-aarch64 b/test/tools/llvm-objdump/AArch64/Inputs/thread.macho-aarch64 new file mode 100644 index 0000000000000000000000000000000000000000..ed587e3ce6ffb44055687ecea6719d06adbf2352 GIT binary patch literal 320 qcmX^A>+L@t1_nk3AYcMw5JLgX1Boy&umCZL&jzGjKmwxxB?JIa1O!z8 literal 0 HcmV?d00001 diff --git a/test/tools/llvm-objdump/AArch64/macho-print-thread.test b/test/tools/llvm-objdump/AArch64/macho-print-thread.test new file mode 100644 index 00000000000..86f5569a03b --- /dev/null +++ b/test/tools/llvm-objdump/AArch64/macho-print-thread.test @@ -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 diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 854f465fdd5..4ef6f2838c9 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -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)) { -- 2.40.0