- Add sigsegv stacktrace in test and regular errors for Darwin Arm64. #1105

This commit is contained in:
Christoffer Lerno
2025-11-20 20:36:33 +01:00
committed by Christoffer Lerno
parent a50de26c5d
commit 5b83108dd1
5 changed files with 131 additions and 38 deletions

View File

@@ -0,0 +1,44 @@
module std::os::darwin @if(env::DARWIN);
alias __Darwin_sigset_t = uint;
alias __Darwin_size_t = usz;
struct __Darwin_arm_exception_state64
{
ulong __far; /* Virtual Fault Address */
uint __esr; /* Exception syndrome */
uint __exception; /* number of arm exception taken */
}
struct __Darwin_arm_thread_state64
{
ulong[29] __x; /* General purpose registers x0-x28 */
ulong __fp; /* Frame pointer x29 */
ulong __lr; /* Link register x30 */
ulong __sp; /* Stack pointer x31 */
ulong __pc; /* Program counter */
ulong __cpsr; /* Current program status register */
ulong __pad; /* Same size for 32-bit or 64-bit clients */
}
struct __Darwin_arm_neon_state64
{
uint128[32] __v;
uint __fpsr;
uint __fpcr;
}
struct __Darwin_mcontext64
{
__Darwin_arm_exception_state64 __es;
__Darwin_arm_thread_state64 __ss;
__Darwin_arm_neon_state64 __ns;
}
struct __Darwin_sigaltstack
{
void* ss_sp; /* signal stack base */
__Darwin_size_t ss_size; /* signal stack length */
int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */
}

View File

@@ -1,5 +1,5 @@
module std::os::posix @if(env::POSIX);
import libc;
import libc, std::os::darwin;
struct Posix_spawn_file_actions_t
{
@@ -60,6 +60,15 @@ alias BacktraceFn = fn CInt(void** buffer, CInt size);
extern fn CInt backtrace(void** buffer, CInt size) @if(env::OPENBSD);
fn void install_signal_handler(CInt signal, SigActionFunction func)
{
Sigaction action = {
.sa_sigaction = func,
};
Sigaction old;
libc::sigaction(signal, &action, &old);
}
fn CInt backtrace(void** buffer, CInt size) @if(!env::OPENBSD)
{
if (size < 1) return 0;
@@ -75,12 +84,13 @@ fn CInt backtrace(void** buffer, CInt size) @if(!env::OPENBSD)
}
// Loop through the return addresses until we hit a signal.
// This avoids using the frame address.
SignalFunction restore_backtrace = fn void(CInt) {
libc::longjmp(&backtrace_jmpbuf, 1);
};
SignalFunction sig_bus = libc::signal(libc::SIGBUS, restore_backtrace);
SignalFunction sig_segv = libc::signal(libc::SIGSEGV, restore_backtrace);
SignalFunction sig_ill = libc::signal(libc::SIGILL, restore_backtrace);
Sigaction restore_backtrace = {
.sa_sigaction = fn void(CInt, void*, void*) { libc::longjmp(&backtrace_jmpbuf, 1); },
};
Sigaction sig_bus, sig_segv, sig_ill;
libc::sigaction(libc::SIGBUS, &restore_backtrace, &sig_bus);
libc::sigaction(libc::SIGSEGV, &restore_backtrace, &sig_segv);
libc::sigaction(libc::SIGILL, &restore_backtrace, &sig_ill);
void*[128] buffer_first;
int i = 0;
@@ -90,8 +100,47 @@ fn CInt backtrace(void** buffer, CInt size) @if(!env::OPENBSD)
buffer[i] = builtin::get_returnaddress(i);
if (!buffer[i]) break;
}
libc::signal(libc::SIGBUS, sig_bus);
libc::signal(libc::SIGSEGV, sig_segv);
libc::signal(libc::SIGILL, sig_ill);
Sigaction old;
libc::sigaction(libc::SIGBUS, &sig_bus, &old);
libc::sigaction(libc::SIGSEGV, &sig_segv, &old);
libc::sigaction(libc::SIGILL, &sig_ill, &old);
return i;
}
struct PosixUContext_t @if(env::DARWIN)
{
int uc_onstack;
__Darwin_sigset_t uc_sigmask; /* signal mask used by this context */
__Darwin_sigaltstack uc_stack; /* stack used by this context */
PosixUContext_t* uc_link; /* pointer to resuming context */
__Darwin_size_t uc_mcsize; /* size of the machine context passed in */
__Darwin_mcontext64* uc_mcontext; /* pointer to machine specific context */
}
alias PosixUContext_t @if(!env::DARWIN) = void;
macro void* stack_instruction(PosixUContext_t* uc)
{
$switch:
$case env::DARWIN && env::AARCH64:
return (void*)uc.uc_mcontext.__ss.__pc + 1;
/* $case env::DARWIN && env::X86_64:
return uc.uc_mcontext.__ss.__rip;
$case env::LINUX && env::X86:
return uc.uc_mcontext.gregs[REG_EIP];
$case env::LINUX && env::X86_64:
return uc.uc_mcontext.gregs[REG_RIP];
$case env::LINUX && env::AARCH64:
return uc.uc_mcontext.pc;
$case env::FREEBSD && env::X86_64:
return uc.uc_mcontext.mc_rip;
$case env::OPENBSD && env::X86_64:
return uc.sc_rip;
$case env::NETBSD:
uc.uc_mcontext.__gregs[_REG_RIP];*/
$default:
return null;
$endswitch
}