From 2d53a5a69dfa59b22484e9cef92c847ef9ac5e9f Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Tue, 14 Jun 2022 14:51:26 +0200 Subject: [PATCH] feat: Capture registers with inproc backend (FEEDBACK-1413) (#714) --- src/backends/sentry_backend_inproc.c | 276 ++++++++++++++++++++++++++- 1 file changed, 274 insertions(+), 2 deletions(-) diff --git a/src/backends/sentry_backend_inproc.c b/src/backends/sentry_backend_inproc.c index 9e1a4b8b9..0c5297b32 100644 --- a/src/backends/sentry_backend_inproc.c +++ b/src/backends/sentry_backend_inproc.c @@ -114,7 +114,8 @@ shutdown_inproc_backend(sentry_backend_t *UNUSED(backend)) reset_signal_handlers(); } -#elif defined SENTRY_PLATFORM_WINDOWS +#elif defined(SENTRY_PLATFORM_WINDOWS) + struct signal_slot { DWORD signum; const char *signame; @@ -168,8 +169,273 @@ shutdown_inproc_backend(sentry_backend_t *UNUSED(backend)) SetUnhandledExceptionFilter(current_handler); } } + #endif +sentry_value_t +sentry__registers_from_uctx(const sentry_ucontext_t *uctx) +{ + sentry_value_t registers = sentry_value_new_object(); + +#if defined(SENTRY_PLATFORM_LINUX) + + // just assume the ctx is a bunch of uintpr_t, and index that directly + uintptr_t *ctx = (uintptr_t *)&uctx->user_context->uc_mcontext; + +# define SET_REG(name, num) \ + sentry_value_set_by_key(registers, name, \ + sentry__value_new_addr((uint64_t)(size_t)ctx[num])); + +# if defined(__x86_64__) + + SET_REG("r8", 0); + SET_REG("r9", 1); + SET_REG("r10", 2); + SET_REG("r11", 3); + SET_REG("r12", 4); + SET_REG("r13", 5); + SET_REG("r14", 6); + SET_REG("r15", 7); + SET_REG("rdi", 8); + SET_REG("rsi", 9); + SET_REG("rbp", 10); + SET_REG("rbx", 11); + SET_REG("rdx", 12); + SET_REG("rax", 13); + SET_REG("rcx", 14); + SET_REG("rsp", 15); + SET_REG("rip", 16); + +# elif defined(__i386__) + + // gs, fs, es, ds + SET_REG("edi", 4); + SET_REG("esi", 5); + SET_REG("ebp", 6); + SET_REG("esp", 7); + SET_REG("ebx", 8); + SET_REG("edx", 9); + SET_REG("ecx", 10); + SET_REG("eax", 11); + SET_REG("eip", 14); + SET_REG("eflags", 16); + +# elif defined(__aarch64__) + + // 0 is `fault_address` + SET_REG("x0", 1); + SET_REG("x1", 2); + SET_REG("x2", 3); + SET_REG("x3", 4); + SET_REG("x4", 5); + SET_REG("x5", 6); + SET_REG("x6", 7); + SET_REG("x7", 8); + SET_REG("x8", 9); + SET_REG("x9", 10); + SET_REG("x10", 11); + SET_REG("x11", 12); + SET_REG("x12", 13); + SET_REG("x13", 14); + SET_REG("x14", 15); + SET_REG("x15", 16); + SET_REG("x16", 17); + SET_REG("x17", 18); + SET_REG("x18", 19); + SET_REG("x19", 20); + SET_REG("x20", 21); + SET_REG("x21", 22); + SET_REG("x22", 23); + SET_REG("x23", 24); + SET_REG("x24", 25); + SET_REG("x25", 26); + SET_REG("x26", 27); + SET_REG("x27", 28); + SET_REG("x28", 29); + SET_REG("fp", 30); + SET_REG("lr", 31); + SET_REG("sp", 32); + SET_REG("pc", 33); + +# elif defined(__arm__) + + // trap_no, _error_code, oldmask + SET_REG("r0", 3); + SET_REG("r1", 4); + SET_REG("r2", 5); + SET_REG("r3", 6); + SET_REG("r4", 7); + SET_REG("r5", 8); + SET_REG("r6", 9); + SET_REG("r7", 10); + SET_REG("r8", 11); + SET_REG("r9", 12); + SET_REG("r10", 13); + SET_REG("fp", 14); + SET_REG("ip", 15); + SET_REG("sp", 16); + SET_REG("lr", 17); + SET_REG("pc", 18); + +# endif + +# undef SET_REG + +#elif defined(SENTRY_PLATFORM_DARWIN) + +# define SET_REG(name, prop) \ + sentry_value_set_by_key(registers, name, \ + sentry__value_new_addr((uint64_t)(size_t)thread_state->prop)); + +# if defined(__x86_64__) + + _STRUCT_X86_THREAD_STATE64 *thread_state + = &uctx->user_context->uc_mcontext->__ss; + + SET_REG("rax", __rax); + SET_REG("rbx", __rbx); + SET_REG("rcx", __rcx); + SET_REG("rdx", __rdx); + SET_REG("rdi", __rdi); + SET_REG("rsi", __rsi); + SET_REG("rbp", __rbp); + SET_REG("rsp", __rsp); + SET_REG("r8", __r8); + SET_REG("r9", __r9); + SET_REG("r10", __r10); + SET_REG("r11", __r11); + SET_REG("r12", __r12); + SET_REG("r13", __r13); + SET_REG("r14", __r14); + SET_REG("r15", __r15); + SET_REG("rip", __rip); + +# elif defined(__arm64__) + + _STRUCT_ARM_THREAD_STATE64 *thread_state + = &uctx->user_context->uc_mcontext->__ss; + + SET_REG("x0", __x[0]); + SET_REG("x1", __x[1]); + SET_REG("x2", __x[2]); + SET_REG("x3", __x[3]); + SET_REG("x4", __x[4]); + SET_REG("x5", __x[5]); + SET_REG("x6", __x[6]); + SET_REG("x7", __x[7]); + SET_REG("x8", __x[8]); + SET_REG("x9", __x[9]); + SET_REG("x10", __x[10]); + SET_REG("x11", __x[11]); + SET_REG("x12", __x[12]); + SET_REG("x13", __x[13]); + SET_REG("x14", __x[14]); + SET_REG("x15", __x[15]); + SET_REG("x16", __x[16]); + SET_REG("x17", __x[17]); + SET_REG("x18", __x[18]); + SET_REG("x19", __x[19]); + SET_REG("x20", __x[20]); + SET_REG("x21", __x[21]); + SET_REG("x22", __x[22]); + SET_REG("x23", __x[23]); + SET_REG("x24", __x[24]); + SET_REG("x25", __x[25]); + SET_REG("x26", __x[26]); + SET_REG("x27", __x[27]); + SET_REG("x28", __x[28]); + SET_REG("fp", __fp); + SET_REG("lr", __lr); + SET_REG("sp", __sp); + SET_REG("pc", __pc); + +# elif defined(__arm__) + + _STRUCT_ARM_THREAD_STATE *thread_state + = &uctx->user_context->uc_mcontext->__ss; + + SET_REG("r0", __r[0]); + SET_REG("r1", __r[1]); + SET_REG("r2", __r[2]); + SET_REG("r3", __r[3]); + SET_REG("r4", __r[4]); + SET_REG("r5", __r[5]); + SET_REG("r6", __r[6]); + SET_REG("r7", __r[7]); + SET_REG("r8", __r[8]); + SET_REG("r9", __r[9]); + SET_REG("r10", __r[10]); + SET_REG("fp", __r[11]); + SET_REG("ip", __r[12]); + SET_REG("sp", __sp); + SET_REG("lr", __lr); + SET_REG("pc", __pc); + +# endif + +# undef SET_REG + +#elif defined(SENTRY_PLATFORM_WINDOWS) + PCONTEXT ctx = uctx->exception_ptrs.ContextRecord; + +# define SET_REG(name, prop) \ + sentry_value_set_by_key(registers, name, \ + sentry__value_new_addr((uint64_t)(size_t)ctx->prop)); + +# if defined(_M_AMD64) + + if (ctx->ContextFlags & CONTEXT_INTEGER) { + SET_REG("rax", Rax); + SET_REG("rcx", Rcx); + SET_REG("rdx", Rdx); + SET_REG("rbx", Rbx); + SET_REG("rbp", Rbp); + SET_REG("rsi", Rsi); + SET_REG("rdi", Rdi); + SET_REG("r8", R8); + SET_REG("r9", R9); + SET_REG("r10", R10); + SET_REG("r11", R11); + SET_REG("r12", R12); + SET_REG("r13", R13); + SET_REG("r14", R14); + SET_REG("r15", R15); + } + + if (ctx->ContextFlags & CONTEXT_CONTROL) { + SET_REG("rsp", Rsp); + SET_REG("rip", Rip); + } + +# elif defined(_M_IX86) + + if (ctx->ContextFlags & CONTEXT_INTEGER) { + SET_REG("edi", Edi); + SET_REG("esi", Esi); + SET_REG("ebx", Ebx); + SET_REG("edx", Edx); + SET_REG("ecx", Ecx); + SET_REG("eax", Eax); + } + + if (ctx->ContextFlags & CONTEXT_CONTROL) { + SET_REG("ebp", Ebp); + SET_REG("eip", Eip); + SET_REG("eflags", EFlags); + SET_REG("esp", Esp); + } + +# else + // _ARM64_ +# endif + +# undef SET_REG + +#endif + + return registers; +} + static sentry_value_t make_signal_event( const struct signal_slot *sig_slot, const sentry_ucontext_t *uctx) @@ -214,7 +480,13 @@ make_signal_event( } SENTRY_TRACEF("captured backtrace with %lu frames", frame_count); - sentry_value_set_stacktrace(exc, &backtrace[0], frame_count); + sentry_value_t stacktrace + = sentry_value_new_stacktrace(&backtrace[0], frame_count); + + sentry_value_t registers = sentry__registers_from_uctx(uctx); + sentry_value_set_by_key(stacktrace, "registers", registers); + + sentry_value_set_by_key(exc, "stacktrace", stacktrace); sentry_event_add_exception(event, exc); return event;