Merge pull request #51 from microsoft/fix/ptrauth
Strip pointer authentication codes on arm64e
This commit is contained in:
Коммит
76c6ca7460
|
@ -7,6 +7,7 @@
|
|||
* Fix arm64e crash report text formatting.
|
||||
* Fix possible crash `plcrash_log_writer_set_exception` method when `NSException` instances have a `nil` reason.
|
||||
* Apply bit mask for non-pointer isa values on macOS x64 (used in runtime symbolication).
|
||||
* Strip pointer authentication codes on arm64e.
|
||||
|
||||
___
|
||||
|
||||
|
|
|
@ -33,44 +33,79 @@
|
|||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <mach/thread_status.h>
|
||||
|
||||
#if defined(__arm__) || defined(__arm64__)
|
||||
|
||||
#define RETGEN(name, type, ts) {\
|
||||
return (ts->arm_state. type . __ ## name); \
|
||||
}
|
||||
|
||||
#define SETGEN(name, type, ts, regnum, value) {\
|
||||
ts->valid_regs |= 1ULL<<regnum; \
|
||||
#define THREAD_STATE_GET(name, type, ts) (ts->arm_state. type . __ ## name)
|
||||
#define THREAD_STATE_SET(name, type, ts, regnum, value) { \
|
||||
ts->valid_regs |= 1ULL << regnum; \
|
||||
(ts->arm_state. type . __ ## name) = value; \
|
||||
break; \
|
||||
}
|
||||
|
||||
/* Access thread status via macro when defined (will be for arch arm64 and arm64e on Xcode 10 and newer),
|
||||
if macros are not available fall back to the old ones */
|
||||
#if defined(arm_thread_state64_get_pc)
|
||||
#define RETGENM(name, type, ts) {\
|
||||
return arm_thread_state64_get_ ## name (((plcrash_async_thread_state_t *)ts)->arm_state. type );\
|
||||
#if defined(__LP64__)
|
||||
|
||||
/*
|
||||
* Pointer authentication codes (on arm64e for example) must be stripped out.
|
||||
* See https://developer.apple.com/documentation/security/preparing_your_app_to_work_with_pointer_authentication
|
||||
*/
|
||||
#if __has_feature(ptrauth_calls)
|
||||
|
||||
#include <ptrauth.h>
|
||||
|
||||
#define THREAD_STATE_GET_PTR(name, type, ts) ({ \
|
||||
plcrash_greg_t ptr = arm_thread_state64_get_ ## name (ts->arm_state. type); \
|
||||
ptrauth_strip((void *) ptr, ptrauth_key_frame_pointer); \
|
||||
})
|
||||
#define THREAD_STATE_GET_FPTR(name, type, ts) ({ \
|
||||
plcrash_greg_t ptr = arm_thread_state64_get_ ## name ## _fptr (ts->arm_state. type); \
|
||||
ptrauth_strip((void *) ptr, ptrauth_key_function_pointer); \
|
||||
})
|
||||
|
||||
#define THREAD_STATE_SET_PTR(name, type, ts, regnum, value) { \
|
||||
void *ptr = ptrauth_strip((void *)value, ptrauth_key_frame_pointer); \
|
||||
ptr = ptrauth_sign_unauthenticated(ptr, ptrauth_key_frame_pointer, 0); \
|
||||
ts->valid_regs |= 1ULL << regnum; \
|
||||
arm_thread_state64_set_ ## name (ts->arm_state. type, ptr); \
|
||||
}
|
||||
#define THREAD_STATE_SET_FPTR(name, type, ts, regnum, value) { \
|
||||
void *ptr = ptrauth_strip((void *)value, ptrauth_key_function_pointer); \
|
||||
ptr = ptrauth_sign_unauthenticated(ptr, ptrauth_key_function_pointer, 0); \
|
||||
ts->valid_regs |= 1ULL << regnum; \
|
||||
arm_thread_state64_set_ ## name ## _fptr (ts->arm_state. type, ptr); \
|
||||
}
|
||||
|
||||
#define SETGENM(name, type, ts, regnum, value) {\
|
||||
ts->valid_regs |= 1ULL<<regnum; \
|
||||
arm_thread_state64_set_ ## name (ts->arm_state. type, value) ;\
|
||||
break; \
|
||||
#else // __has_feature(ptrauth_calls)
|
||||
|
||||
/*
|
||||
* Even if pointer authentication is not available at the compile time, the binary still can be used in an environment with PAC.
|
||||
* In this case, we can apply bitmask as a workaround.
|
||||
*/
|
||||
#define ARM64_PTR_MASK 0x0000000FFFFFFFFF
|
||||
|
||||
#define THREAD_STATE_GET_PTR(name, type, ts) ({ \
|
||||
plcrash_greg_t ptr = arm_thread_state64_get_ ## name (ts->arm_state. type); \
|
||||
(ptr & ARM64_PTR_MASK); \
|
||||
})
|
||||
#define THREAD_STATE_GET_FPTR(name, type, ts) THREAD_STATE_GET_PTR(name ## _fptr, type, ts)
|
||||
|
||||
#define THREAD_STATE_SET_PTR(name, type, ts, regnum, value) { \
|
||||
ts->valid_regs |= 1ULL << regnum; \
|
||||
arm_thread_state64_set_ ## name (ts->arm_state. type, (void *)value); \
|
||||
}
|
||||
#define THREAD_STATE_SET_FPTR(name, type, ts, regnum, value) THREAD_STATE_SET_PTR(name ## _fptr, type, ts, regnum, value)
|
||||
|
||||
#define SETGENMF(name, type, ts, regnum, value) {\
|
||||
ts->valid_regs |= 1ULL<<regnum; \
|
||||
arm_thread_state64_set_ ## name ## _fptr(ts->arm_state. type, (void *)value) ;\
|
||||
break; \
|
||||
}
|
||||
#endif // __has_feature(ptrauth_calls)
|
||||
|
||||
#else /* defined(arm_thread_state64_get_pc) */
|
||||
#define RETGENM(name, type, ts) RETGEN(name, type, ts)
|
||||
#define SETGENM(name, type, ts, regnum, value) SETGEN(name, type, ts, regnum, value)
|
||||
#define SETGENMF(name, type, ts, regnum, value) SETGEN(name, type, ts, regnum, value)
|
||||
#endif /* defined(arm_thread_state64_get_pc) */
|
||||
#else // __LP64__
|
||||
|
||||
#define THREAD_STATE_GET_PTR THREAD_STATE_GET
|
||||
#define THREAD_STATE_GET_FPTR THREAD_STATE_GET
|
||||
|
||||
#define THREAD_STATE_SET_PTR THREAD_STATE_SET
|
||||
#define THREAD_STATE_SET_FPTR THREAD_STATE_SET
|
||||
|
||||
#endif // __LP64__
|
||||
|
||||
/* Mapping of DWARF register numbers to PLCrashReporter register numbers. */
|
||||
struct dwarf_register_table {
|
||||
|
@ -202,344 +237,147 @@ static const struct dwarf_register_table arm64_dwarf_table [] = {
|
|||
{ PLCRASH_ARM64_SP, 31 },
|
||||
};
|
||||
|
||||
static inline plcrash_greg_t plcrash_async_thread_state_get_reg_32 (const plcrash_async_thread_state_t *ts, plcrash_regnum_t regnum) {
|
||||
switch (regnum) {
|
||||
case PLCRASH_ARM_R0: return THREAD_STATE_GET(r[0], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R1: return THREAD_STATE_GET(r[1], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R2: return THREAD_STATE_GET(r[2], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R3: return THREAD_STATE_GET(r[3], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R4: return THREAD_STATE_GET(r[4], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R5: return THREAD_STATE_GET(r[5], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R6: return THREAD_STATE_GET(r[6], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R7: return THREAD_STATE_GET(r[7], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R8: return THREAD_STATE_GET(r[8], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R9: return THREAD_STATE_GET(r[9], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R10: return THREAD_STATE_GET(r[10], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R11: return THREAD_STATE_GET(r[11], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_R12: return THREAD_STATE_GET(r[12], thread.ts_32, ts);
|
||||
case PLCRASH_ARM_SP: return THREAD_STATE_GET(sp, thread.ts_32, ts);
|
||||
case PLCRASH_ARM_LR: return THREAD_STATE_GET(lr, thread.ts_32, ts);
|
||||
case PLCRASH_ARM_PC: return THREAD_STATE_GET(pc, thread.ts_32, ts);
|
||||
case PLCRASH_ARM_CPSR: return THREAD_STATE_GET(cpsr, thread.ts_32, ts);
|
||||
default: __builtin_trap();
|
||||
}
|
||||
}
|
||||
|
||||
static inline plcrash_greg_t plcrash_async_thread_state_get_reg_64 (const plcrash_async_thread_state_t *ts, plcrash_regnum_t regnum) {
|
||||
switch (regnum) {
|
||||
case PLCRASH_ARM64_X0: return THREAD_STATE_GET(x[0], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X1: return THREAD_STATE_GET(x[1], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X2: return THREAD_STATE_GET(x[2], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X3: return THREAD_STATE_GET(x[3], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X4: return THREAD_STATE_GET(x[4], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X5: return THREAD_STATE_GET(x[5], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X6: return THREAD_STATE_GET(x[6], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X7: return THREAD_STATE_GET(x[7], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X8: return THREAD_STATE_GET(x[8], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X9: return THREAD_STATE_GET(x[9], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X10: return THREAD_STATE_GET(x[10], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X11: return THREAD_STATE_GET(x[11], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X12: return THREAD_STATE_GET(x[12], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X13: return THREAD_STATE_GET(x[13], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X14: return THREAD_STATE_GET(x[14], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X15: return THREAD_STATE_GET(x[15], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X16: return THREAD_STATE_GET(x[16], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X17: return THREAD_STATE_GET(x[17], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X18: return THREAD_STATE_GET(x[18], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X19: return THREAD_STATE_GET(x[19], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X20: return THREAD_STATE_GET(x[20], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X21: return THREAD_STATE_GET(x[21], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X22: return THREAD_STATE_GET(x[22], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X23: return THREAD_STATE_GET(x[23], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X24: return THREAD_STATE_GET(x[24], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X25: return THREAD_STATE_GET(x[25], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X26: return THREAD_STATE_GET(x[26], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X27: return THREAD_STATE_GET(x[27], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_X28: return THREAD_STATE_GET(x[28], thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_FP: return THREAD_STATE_GET_PTR(fp, thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_SP: return THREAD_STATE_GET_PTR(sp, thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_LR: return THREAD_STATE_GET_FPTR(lr, thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_PC: return THREAD_STATE_GET_FPTR(pc, thread.ts_64, ts);
|
||||
case PLCRASH_ARM64_CPSR: return THREAD_STATE_GET(cpsr, thread.ts_64, ts);
|
||||
default: __builtin_trap();
|
||||
}
|
||||
}
|
||||
|
||||
// PLCrashAsyncThread API
|
||||
plcrash_greg_t plcrash_async_thread_state_get_reg (const plcrash_async_thread_state_t *ts, plcrash_regnum_t regnum) {
|
||||
if (ts->arm_state.thread.ash.flavor == ARM_THREAD_STATE32) {
|
||||
switch (regnum) {
|
||||
case PLCRASH_ARM_R0:
|
||||
RETGEN(r[0], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R1:
|
||||
RETGEN(r[1], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R2:
|
||||
RETGEN(r[2], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R3:
|
||||
RETGEN(r[3], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R4:
|
||||
RETGEN(r[4], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R5:
|
||||
RETGEN(r[5], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R6:
|
||||
RETGEN(r[6], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R7:
|
||||
RETGEN(r[7], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R8:
|
||||
RETGEN(r[8], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R9:
|
||||
RETGEN(r[9], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R10:
|
||||
RETGEN(r[10], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R11:
|
||||
RETGEN(r[11], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_R12:
|
||||
RETGEN(r[12], thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_SP:
|
||||
RETGEN(sp, thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_LR:
|
||||
RETGEN(lr, thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_PC:
|
||||
RETGEN(pc, thread.ts_32, ts);
|
||||
|
||||
case PLCRASH_ARM_CPSR:
|
||||
RETGEN(cpsr, thread.ts_32, ts);
|
||||
|
||||
default:
|
||||
__builtin_trap();
|
||||
}
|
||||
return plcrash_async_thread_state_get_reg_32(ts, regnum);
|
||||
} else {
|
||||
switch (regnum) {
|
||||
case PLCRASH_ARM64_X0:
|
||||
RETGEN(x[0], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X1:
|
||||
RETGEN(x[1], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X2:
|
||||
RETGEN(x[2], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X3:
|
||||
RETGEN(x[3], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X4:
|
||||
RETGEN(x[4], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X5:
|
||||
RETGEN(x[5], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X6:
|
||||
RETGEN(x[6], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X7:
|
||||
RETGEN(x[7], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X8:
|
||||
RETGEN(x[8], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X9:
|
||||
RETGEN(x[9], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X10:
|
||||
RETGEN(x[10], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X11:
|
||||
RETGEN(x[11], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X12:
|
||||
RETGEN(x[12], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X13:
|
||||
RETGEN(x[13], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X14:
|
||||
RETGEN(x[14], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X15:
|
||||
RETGEN(x[15], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X16:
|
||||
RETGEN(x[16], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X17:
|
||||
RETGEN(x[17], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X18:
|
||||
RETGEN(x[18], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X19:
|
||||
RETGEN(x[19], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X20:
|
||||
RETGEN(x[20], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X21:
|
||||
RETGEN(x[21], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X22:
|
||||
RETGEN(x[22], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X23:
|
||||
RETGEN(x[23], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X24:
|
||||
RETGEN(x[24], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X25:
|
||||
RETGEN(x[25], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X26:
|
||||
RETGEN(x[26], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X27:
|
||||
RETGEN(x[27], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_X28:
|
||||
RETGEN(x[28], thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_FP:
|
||||
RETGENM(fp, thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_SP:
|
||||
RETGENM(sp, thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_LR:
|
||||
RETGENM(lr, thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_PC:
|
||||
RETGENM(pc, thread.ts_64, ts);
|
||||
|
||||
case PLCRASH_ARM64_CPSR:
|
||||
RETGEN(cpsr, thread.ts_64, ts);
|
||||
|
||||
default:
|
||||
__builtin_trap();
|
||||
}
|
||||
return plcrash_async_thread_state_get_reg_64(ts, regnum);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void plcrash_async_thread_state_set_reg_32 (plcrash_async_thread_state_t *ts, plcrash_regnum_t regnum, plcrash_greg_t reg) {
|
||||
switch (regnum) {
|
||||
case PLCRASH_ARM_R0: THREAD_STATE_SET(r[0], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R1: THREAD_STATE_SET(r[1], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R2: THREAD_STATE_SET(r[2], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R3: THREAD_STATE_SET(r[3], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R4: THREAD_STATE_SET(r[4], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R5: THREAD_STATE_SET(r[5], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R6: THREAD_STATE_SET(r[6], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R7: THREAD_STATE_SET(r[7], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R8: THREAD_STATE_SET(r[8], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R9: THREAD_STATE_SET(r[9], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R10: THREAD_STATE_SET(r[10], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R11: THREAD_STATE_SET(r[11], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_R12: THREAD_STATE_SET(r[12], thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_SP: THREAD_STATE_SET(sp, thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_LR: THREAD_STATE_SET(lr, thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_PC: THREAD_STATE_SET(pc, thread.ts_32, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM_CPSR: THREAD_STATE_SET(cpsr, thread.ts_32, ts, regnum, reg); break;
|
||||
default: __builtin_trap(); // Unsupported register
|
||||
}
|
||||
}
|
||||
|
||||
static inline void plcrash_async_thread_state_set_reg_64 (plcrash_async_thread_state_t *ts, plcrash_regnum_t regnum, plcrash_greg_t reg) {
|
||||
switch (regnum) {
|
||||
case PLCRASH_ARM64_X0: THREAD_STATE_SET(x[0], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X1: THREAD_STATE_SET(x[1], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X2: THREAD_STATE_SET(x[2], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X3: THREAD_STATE_SET(x[3], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X4: THREAD_STATE_SET(x[4], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X5: THREAD_STATE_SET(x[5], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X6: THREAD_STATE_SET(x[6], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X7: THREAD_STATE_SET(x[7], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X8: THREAD_STATE_SET(x[8], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X9: THREAD_STATE_SET(x[9], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X10: THREAD_STATE_SET(x[10], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X11: THREAD_STATE_SET(x[11], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X12: THREAD_STATE_SET(x[12], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X13: THREAD_STATE_SET(x[13], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X14: THREAD_STATE_SET(x[14], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X15: THREAD_STATE_SET(x[15], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X16: THREAD_STATE_SET(x[16], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X17: THREAD_STATE_SET(x[17], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X18: THREAD_STATE_SET(x[18], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X19: THREAD_STATE_SET(x[19], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X20: THREAD_STATE_SET(x[20], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X21: THREAD_STATE_SET(x[21], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X22: THREAD_STATE_SET(x[22], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X23: THREAD_STATE_SET(x[23], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X24: THREAD_STATE_SET(x[24], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X25: THREAD_STATE_SET(x[25], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X26: THREAD_STATE_SET(x[26], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X27: THREAD_STATE_SET(x[27], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_X28: THREAD_STATE_SET(x[28], thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_FP: THREAD_STATE_SET_PTR(fp, thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_SP: THREAD_STATE_SET_PTR(sp, thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_LR: THREAD_STATE_SET_FPTR(lr, thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_PC: THREAD_STATE_SET_FPTR(pc, thread.ts_64, ts, regnum, reg); break;
|
||||
case PLCRASH_ARM64_CPSR: THREAD_STATE_SET(cpsr, thread.ts_64, ts, regnum, reg); break;
|
||||
default: __builtin_trap();
|
||||
}
|
||||
/* Should not be reachable */
|
||||
return 0;
|
||||
}
|
||||
|
||||
// PLCrashAsyncThread API
|
||||
void plcrash_async_thread_state_set_reg (plcrash_async_thread_state_t *thread_state, plcrash_regnum_t regnum, plcrash_greg_t reg) {
|
||||
plcrash_async_thread_state_t *ts = thread_state;
|
||||
|
||||
if (ts->arm_state.thread.ash.flavor == ARM_THREAD_STATE32) {
|
||||
switch (regnum) {
|
||||
case PLCRASH_ARM_R0:
|
||||
SETGEN(r[0], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R1:
|
||||
SETGEN(r[1], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R2:
|
||||
SETGEN(r[2], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R3:
|
||||
SETGEN(r[3], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R4:
|
||||
SETGEN(r[4], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R5:
|
||||
SETGEN(r[5], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R6:
|
||||
SETGEN(r[6], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R7:
|
||||
SETGEN(r[7], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R8:
|
||||
SETGEN(r[8], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R9:
|
||||
SETGEN(r[9], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R10:
|
||||
SETGEN(r[10], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R11:
|
||||
SETGEN(r[11], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_R12:
|
||||
SETGEN(r[12], thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_SP:
|
||||
SETGEN(sp, thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_LR:
|
||||
SETGEN(lr, thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_PC:
|
||||
SETGEN(pc, thread.ts_32, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM_CPSR:
|
||||
SETGEN(cpsr, thread.ts_32, ts, regnum, reg);
|
||||
|
||||
default:
|
||||
// Unsupported register
|
||||
__builtin_trap();
|
||||
}
|
||||
if (thread_state->arm_state.thread.ash.flavor == ARM_THREAD_STATE32) {
|
||||
plcrash_async_thread_state_set_reg_32(thread_state, regnum, reg);
|
||||
} else {
|
||||
switch (regnum) {
|
||||
case PLCRASH_ARM64_X0:
|
||||
SETGEN(x[0], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X1:
|
||||
SETGEN(x[1], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X2:
|
||||
SETGEN(x[2], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X3:
|
||||
SETGEN(x[3], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X4:
|
||||
SETGEN(x[4], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X5:
|
||||
SETGEN(x[5], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X6:
|
||||
SETGEN(x[6], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X7:
|
||||
SETGEN(x[7], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X8:
|
||||
SETGEN(x[8], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X9:
|
||||
SETGEN(x[9], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X10:
|
||||
SETGEN(x[10], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X11:
|
||||
SETGEN(x[11], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X12:
|
||||
SETGEN(x[12], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X13:
|
||||
SETGEN(x[13], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X14:
|
||||
SETGEN(x[14], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X15:
|
||||
SETGEN(x[15], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X16:
|
||||
SETGEN(x[16], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X17:
|
||||
SETGEN(x[17], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X18:
|
||||
SETGEN(x[18], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X19:
|
||||
SETGEN(x[19], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X20:
|
||||
SETGEN(x[20], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X21:
|
||||
SETGEN(x[21], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X22:
|
||||
SETGEN(x[22], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X23:
|
||||
SETGEN(x[23], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X24:
|
||||
SETGEN(x[24], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X25:
|
||||
SETGEN(x[25], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X26:
|
||||
SETGEN(x[26], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X27:
|
||||
SETGEN(x[27], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_X28:
|
||||
SETGEN(x[28], thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_FP:
|
||||
SETGENM(fp, thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_SP:
|
||||
SETGENM(sp, thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_LR:
|
||||
SETGENMF(lr, thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_PC:
|
||||
SETGENMF(pc, thread.ts_64, ts, regnum, reg);
|
||||
|
||||
case PLCRASH_ARM64_CPSR:
|
||||
SETGEN(cpsr, thread.ts_64, ts, regnum, reg);
|
||||
|
||||
default:
|
||||
__builtin_trap();
|
||||
}
|
||||
plcrash_async_thread_state_set_reg_64(thread_state, regnum, reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,160 +391,84 @@ size_t plcrash_async_thread_state_get_reg_count (const plcrash_async_thread_stat
|
|||
}
|
||||
}
|
||||
|
||||
// PLCrashAsyncThread API
|
||||
char const *plcrash_async_thread_state_get_reg_name (const plcrash_async_thread_state_t *thread_state, plcrash_regnum_t regnum) {
|
||||
if (thread_state->arm_state.thread.ash.flavor == ARM_THREAD_STATE32) {
|
||||
switch ((plcrash_arm_regnum_t) regnum) {
|
||||
case PLCRASH_ARM_R0:
|
||||
return "r0";
|
||||
case PLCRASH_ARM_R1:
|
||||
return "r1";
|
||||
case PLCRASH_ARM_R2:
|
||||
return "r2";
|
||||
case PLCRASH_ARM_R3:
|
||||
return "r3";
|
||||
case PLCRASH_ARM_R4:
|
||||
return "r4";
|
||||
case PLCRASH_ARM_R5:
|
||||
return "r5";
|
||||
case PLCRASH_ARM_R6:
|
||||
return "r6";
|
||||
case PLCRASH_ARM_R7:
|
||||
return "r7";
|
||||
case PLCRASH_ARM_R8:
|
||||
return "r8";
|
||||
case PLCRASH_ARM_R9:
|
||||
return "r9";
|
||||
case PLCRASH_ARM_R10:
|
||||
return "r10";
|
||||
case PLCRASH_ARM_R11:
|
||||
return "r11";
|
||||
case PLCRASH_ARM_R12:
|
||||
return "r12";
|
||||
|
||||
case PLCRASH_ARM_SP:
|
||||
return "sp";
|
||||
|
||||
case PLCRASH_ARM_LR:
|
||||
return "lr";
|
||||
|
||||
case PLCRASH_ARM_PC:
|
||||
return "pc";
|
||||
|
||||
case PLCRASH_ARM_CPSR:
|
||||
return "cpsr";
|
||||
}
|
||||
} else {
|
||||
switch ((plcrash_arm64_regnum_t) regnum) {
|
||||
case PLCRASH_ARM64_X0:
|
||||
return "x0";
|
||||
|
||||
case PLCRASH_ARM64_X1:
|
||||
return "x1";
|
||||
|
||||
case PLCRASH_ARM64_X2:
|
||||
return "x2";
|
||||
|
||||
case PLCRASH_ARM64_X3:
|
||||
return "x3";
|
||||
|
||||
case PLCRASH_ARM64_X4:
|
||||
return "x4";
|
||||
|
||||
case PLCRASH_ARM64_X5:
|
||||
return "x5";
|
||||
|
||||
case PLCRASH_ARM64_X6:
|
||||
return "x6";
|
||||
|
||||
case PLCRASH_ARM64_X7:
|
||||
return "x7";
|
||||
|
||||
case PLCRASH_ARM64_X8:
|
||||
return "x8";
|
||||
|
||||
case PLCRASH_ARM64_X9:
|
||||
return "x9";
|
||||
|
||||
case PLCRASH_ARM64_X10:
|
||||
return "x10";
|
||||
|
||||
case PLCRASH_ARM64_X11:
|
||||
return "x11";
|
||||
|
||||
case PLCRASH_ARM64_X12:
|
||||
return "x12";
|
||||
|
||||
case PLCRASH_ARM64_X13:
|
||||
return "x13";
|
||||
|
||||
case PLCRASH_ARM64_X14:
|
||||
return "x14";
|
||||
|
||||
case PLCRASH_ARM64_X15:
|
||||
return "x15";
|
||||
|
||||
case PLCRASH_ARM64_X16:
|
||||
return "x16";
|
||||
|
||||
case PLCRASH_ARM64_X17:
|
||||
return "x17";
|
||||
|
||||
case PLCRASH_ARM64_X18:
|
||||
return "x18";
|
||||
|
||||
case PLCRASH_ARM64_X19:
|
||||
return "x19";
|
||||
|
||||
case PLCRASH_ARM64_X20:
|
||||
return "x20";
|
||||
|
||||
case PLCRASH_ARM64_X21:
|
||||
return "x21";
|
||||
|
||||
case PLCRASH_ARM64_X22:
|
||||
return "x22";
|
||||
|
||||
case PLCRASH_ARM64_X23:
|
||||
return "x23";
|
||||
|
||||
case PLCRASH_ARM64_X24:
|
||||
return "x24";
|
||||
|
||||
case PLCRASH_ARM64_X25:
|
||||
return "x25";
|
||||
|
||||
case PLCRASH_ARM64_X26:
|
||||
return "x26";
|
||||
|
||||
case PLCRASH_ARM64_X27:
|
||||
return "x27";
|
||||
|
||||
case PLCRASH_ARM64_X28:
|
||||
return "x28";
|
||||
|
||||
case PLCRASH_ARM64_FP:
|
||||
return "fp";
|
||||
|
||||
case PLCRASH_ARM64_SP:
|
||||
return "sp";
|
||||
|
||||
case PLCRASH_ARM64_LR:
|
||||
return "lr";
|
||||
|
||||
case PLCRASH_ARM64_PC:
|
||||
return "pc";
|
||||
|
||||
case PLCRASH_ARM64_CPSR:
|
||||
return "cpsr";
|
||||
}
|
||||
static inline char const *plcrash_async_thread_state_get_reg_name_32 (const plcrash_async_thread_state_t *thread_state, plcrash_regnum_t regnum) {
|
||||
switch ((plcrash_arm_regnum_t) regnum) {
|
||||
case PLCRASH_ARM_R0: return "r0";
|
||||
case PLCRASH_ARM_R1: return "r1";
|
||||
case PLCRASH_ARM_R2: return "r2";
|
||||
case PLCRASH_ARM_R3: return "r3";
|
||||
case PLCRASH_ARM_R4: return "r4";
|
||||
case PLCRASH_ARM_R5: return "r5";
|
||||
case PLCRASH_ARM_R6: return "r6";
|
||||
case PLCRASH_ARM_R7: return "r7";
|
||||
case PLCRASH_ARM_R8: return "r8";
|
||||
case PLCRASH_ARM_R9: return "r9";
|
||||
case PLCRASH_ARM_R10: return "r10";
|
||||
case PLCRASH_ARM_R11: return "r11";
|
||||
case PLCRASH_ARM_R12: return "r12";
|
||||
case PLCRASH_ARM_SP: return "sp";
|
||||
case PLCRASH_ARM_LR: return "lr";
|
||||
case PLCRASH_ARM_PC: return "pc";
|
||||
case PLCRASH_ARM_CPSR: return "cpsr";
|
||||
}
|
||||
|
||||
|
||||
/* Unsupported register is an implementation error (checked in unit tests) */
|
||||
PLCF_DEBUG("Missing register name for register id: %d", regnum);
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline char const *plcrash_async_thread_state_get_reg_name_64 (const plcrash_async_thread_state_t *thread_state, plcrash_regnum_t regnum) {
|
||||
switch ((plcrash_arm64_regnum_t) regnum) {
|
||||
case PLCRASH_ARM64_X0: return "x0";
|
||||
case PLCRASH_ARM64_X1: return "x1";
|
||||
case PLCRASH_ARM64_X2: return "x2";
|
||||
case PLCRASH_ARM64_X3: return "x3";
|
||||
case PLCRASH_ARM64_X4: return "x4";
|
||||
case PLCRASH_ARM64_X5: return "x5";
|
||||
case PLCRASH_ARM64_X6: return "x6";
|
||||
case PLCRASH_ARM64_X7: return "x7";
|
||||
case PLCRASH_ARM64_X8: return "x8";
|
||||
case PLCRASH_ARM64_X9: return "x9";
|
||||
case PLCRASH_ARM64_X10: return "x10";
|
||||
case PLCRASH_ARM64_X11: return "x11";
|
||||
case PLCRASH_ARM64_X12: return "x12";
|
||||
case PLCRASH_ARM64_X13: return "x13";
|
||||
case PLCRASH_ARM64_X14: return "x14";
|
||||
case PLCRASH_ARM64_X15: return "x15";
|
||||
case PLCRASH_ARM64_X16: return "x16";
|
||||
case PLCRASH_ARM64_X17: return "x17";
|
||||
case PLCRASH_ARM64_X18: return "x18";
|
||||
case PLCRASH_ARM64_X19: return "x19";
|
||||
case PLCRASH_ARM64_X20: return "x20";
|
||||
case PLCRASH_ARM64_X21: return "x21";
|
||||
case PLCRASH_ARM64_X22: return "x22";
|
||||
case PLCRASH_ARM64_X23: return "x23";
|
||||
case PLCRASH_ARM64_X24: return "x24";
|
||||
case PLCRASH_ARM64_X25: return "x25";
|
||||
case PLCRASH_ARM64_X26: return "x26";
|
||||
case PLCRASH_ARM64_X27: return "x27";
|
||||
case PLCRASH_ARM64_X28: return "x28";
|
||||
case PLCRASH_ARM64_FP: return "fp";
|
||||
case PLCRASH_ARM64_SP: return "sp";
|
||||
case PLCRASH_ARM64_LR: return "lr";
|
||||
case PLCRASH_ARM64_PC: return "pc";
|
||||
case PLCRASH_ARM64_CPSR: return "cpsr";
|
||||
}
|
||||
|
||||
/* Unsupported register is an implementation error (checked in unit tests) */
|
||||
PLCF_DEBUG("Missing register name for register id: %d", regnum);
|
||||
abort();
|
||||
}
|
||||
|
||||
// PLCrashAsyncThread API
|
||||
char const *plcrash_async_thread_state_get_reg_name (const plcrash_async_thread_state_t *thread_state, plcrash_regnum_t regnum) {
|
||||
if (thread_state->arm_state.thread.ash.flavor == ARM_THREAD_STATE32) {
|
||||
return plcrash_async_thread_state_get_reg_name_32(thread_state, regnum);
|
||||
} else {
|
||||
return plcrash_async_thread_state_get_reg_name_64(thread_state, regnum);
|
||||
}
|
||||
}
|
||||
|
||||
// PLCrashAsyncThread API
|
||||
void plcrash_async_thread_state_clear_volatile_regs (plcrash_async_thread_state_t *thread_state) {
|
||||
const plcrash_regnum_t *table;
|
||||
|
|
Загрузка…
Ссылка в новой задаче