Skip to content

Commit

Permalink
feat: Capture registers with inproc backend (FEEDBACK-1413) (#714)
Browse files Browse the repository at this point in the history
  • Loading branch information
Swatinem authored Jun 14, 2022
1 parent 939dff3 commit 2d53a5a
Showing 1 changed file with 274 additions and 2 deletions.
276 changes: 274 additions & 2 deletions src/backends/sentry_backend_inproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 2d53a5a

Please sign in to comment.