Merge pull request #51 from microsoft/fix/ptrauth

Strip pointer authentication codes on arm64e
This commit is contained in:
Clement Polet 2020-03-03 07:48:43 -08:00 коммит произвёл GitHub
Родитель 3764f20d3c 04b50cb80b
Коммит 76c6ca7460
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 265 добавлений и 502 удалений

Просмотреть файл

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