Skip to content

Commit aeb2d94

Browse files
jpnurmiclaude
andcommitted
feat(native): ptrace-capture registers for non-crashed threads on 32-bit ARM
ptrace_get_thread_registers had x86_64 / aarch64 / i386 branches but no __arm__ branch. On arm32 it returned false without populating the thread's ucontext, so every non-crashed thread landed in the minidump without registers or stack — multi-threaded crash reports on arm32 were effectively single-threaded. Add the arm32 branch using PTRACE_GETREGS (same mechanism the x86_64 / i386 branches use; works on arm32 too) and map the returned `struct user_regs` uregs[0..16] into the ucontext_t's arm_* fields. No VFP/NEON capture yet — matches the i386 branch's punt on FPU state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1c408c6 commit aeb2d94

1 file changed

Lines changed: 28 additions & 0 deletions

File tree

src/backends/native/minidump/sentry_minidump_linux.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,34 @@ ptrace_get_thread_registers(pid_t tid, ucontext_t *uctx)
273273
SENTRY_DEBUGF("ptrace(PTRACE_GETREGS) failed for thread %d: %s", tid,
274274
strerror(errno));
275275
}
276+
# elif defined(__arm__)
277+
struct user_regs regs;
278+
if (ptrace(PTRACE_GETREGS, tid, NULL, &regs) == 0) {
279+
// uregs[0..15] = R0..R15, uregs[16] = CPSR
280+
uctx->uc_mcontext.arm_r0 = regs.uregs[0];
281+
uctx->uc_mcontext.arm_r1 = regs.uregs[1];
282+
uctx->uc_mcontext.arm_r2 = regs.uregs[2];
283+
uctx->uc_mcontext.arm_r3 = regs.uregs[3];
284+
uctx->uc_mcontext.arm_r4 = regs.uregs[4];
285+
uctx->uc_mcontext.arm_r5 = regs.uregs[5];
286+
uctx->uc_mcontext.arm_r6 = regs.uregs[6];
287+
uctx->uc_mcontext.arm_r7 = regs.uregs[7];
288+
uctx->uc_mcontext.arm_r8 = regs.uregs[8];
289+
uctx->uc_mcontext.arm_r9 = regs.uregs[9];
290+
uctx->uc_mcontext.arm_r10 = regs.uregs[10];
291+
uctx->uc_mcontext.arm_fp = regs.uregs[11];
292+
uctx->uc_mcontext.arm_ip = regs.uregs[12];
293+
uctx->uc_mcontext.arm_sp = regs.uregs[13];
294+
uctx->uc_mcontext.arm_lr = regs.uregs[14];
295+
uctx->uc_mcontext.arm_pc = regs.uregs[15];
296+
uctx->uc_mcontext.arm_cpsr = regs.uregs[16];
297+
success = true;
298+
SENTRY_DEBUGF("Thread %d: captured registers via ptrace, SP=0x%lx", tid,
299+
(unsigned long)regs.uregs[13]);
300+
} else {
301+
SENTRY_DEBUGF("ptrace(PTRACE_GETREGS) failed for thread %d: %s", tid,
302+
strerror(errno));
303+
}
276304
# endif
277305

278306
// Detach from thread

0 commit comments

Comments
 (0)