diff options
Diffstat (limited to 'src/runtime/linux/signal.c')
-rw-r--r-- | src/runtime/linux/signal.c | 193 |
1 files changed, 45 insertions, 148 deletions
diff --git a/src/runtime/linux/signal.c b/src/runtime/linux/signal.c index 5805f35ab..87bea263a 100644 --- a/src/runtime/linux/signal.c +++ b/src/runtime/linux/signal.c @@ -5,102 +5,34 @@ #include "runtime.h" #include "defs.h" #include "signals.h" - -/* From /usr/include/asm-x86_64/sigcontext.h */ -struct _fpstate { - uint16 cwd; - uint16 swd; - uint16 twd; /* Note this is not the same as the 32bit/x87/FSAVE twd */ - uint16 fop; - uint64 rip; - uint32 rdp; - uint32 mxcsr; - uint32 mxcsr_mask; - uint32 st_space[32]; /* 8*16 bytes for each FP-reg */ - uint32 xmm_space[64]; /* 16*16 bytes for each XMM-reg */ - uint32 reserved2[24]; -}; - -struct sigcontext { - uint64 r8; - uint64 r9; - uint64 r10; - uint64 r11; - uint64 r12; - uint64 r13; - uint64 r14; - uint64 r15; - uint64 rdi; - uint64 rsi; - uint64 rbp; - uint64 rbx; - uint64 rdx; - uint64 rax; - uint64 rcx; - uint64 rsp; - uint64 rip; - uint64 eflags; /* RFLAGS */ - uint16 cs; - uint16 gs; - uint16 fs; - uint16 __pad0; - uint64 err; - uint64 trapno; - uint64 oldmask; - uint64 cr2; - struct _fpstate *fpstate; /* zero when no FPU context */ - uint64 reserved1[8]; -}; - - -/* From /usr/include/asm-x86_64/signal.h */ -typedef struct sigaltstack { - void /*__user*/ *ss_sp; - int32 ss_flags; - uint64 ss_size; -} stack_t; - -typedef uint64 sigset_t; - - -/* From /usr/include/asm-x86_64/ucontext.h */ -struct ucontext { - uint64 uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; /* mask last for extensibility */ -}; - +#include "os.h" void -print_sigcontext(struct sigcontext *sc) +dumpregs(Sigcontext *r) { - prints("\nrax "); sys·printhex(sc->rax); - prints("\nrbx "); sys·printhex(sc->rbx); - prints("\nrcx "); sys·printhex(sc->rcx); - prints("\nrdx "); sys·printhex(sc->rdx); - prints("\nrdi "); sys·printhex(sc->rdi); - prints("\nrsi "); sys·printhex(sc->rsi); - prints("\nrbp "); sys·printhex(sc->rbp); - prints("\nrsp "); sys·printhex(sc->rsp); - prints("\nr8 "); sys·printhex(sc->r8 ); - prints("\nr9 "); sys·printhex(sc->r9 ); - prints("\nr10 "); sys·printhex(sc->r10); - prints("\nr11 "); sys·printhex(sc->r11); - prints("\nr12 "); sys·printhex(sc->r12); - prints("\nr13 "); sys·printhex(sc->r13); - prints("\nr14 "); sys·printhex(sc->r14); - prints("\nr15 "); sys·printhex(sc->r15); - prints("\nrip "); sys·printhex(sc->rip); - prints("\nrflags "); sys·printhex(sc->eflags); - prints("\ncs "); sys·printhex(sc->cs); - prints("\nfs "); sys·printhex(sc->fs); - prints("\ngs "); sys·printhex(sc->gs); - prints("\n"); + printf("rax %X\n", r->rax); + printf("rbx %X\n", r->rbx); + printf("rcx %X\n", r->rcx); + printf("rdx %X\n", r->rdx); + printf("rdi %X\n", r->rdi); + printf("rsi %X\n", r->rsi); + printf("rbp %X\n", r->rbp); + printf("rsp %X\n", r->rsp); + printf("r8 %X\n", r->r8 ); + printf("r9 %X\n", r->r9 ); + printf("r10 %X\n", r->r10); + printf("r11 %X\n", r->r11); + printf("r12 %X\n", r->r12); + printf("r13 %X\n", r->r13); + printf("r14 %X\n", r->r14); + printf("r15 %X\n", r->r15); + printf("rip %X\n", r->rip); + printf("rflags %X\n", r->eflags); + printf("cs %X\n", (uint64)r->cs); + printf("fs %X\n", (uint64)r->fs); + printf("gs %X\n", (uint64)r->gs); } - /* * This assembler routine takes the args from registers, puts them on the stack, * and calls sighandler(). @@ -109,89 +41,54 @@ extern void sigtramp(void); extern void sigignore(void); // just returns extern void sigreturn(void); // calls sigreturn -/* - * Rudimentary reverse-engineered definition of signal interface. - * You'd think it would be documented. - */ -/* From /usr/include/bits/siginfo.h */ -struct siginfo { - int32 si_signo; /* signal number */ - int32 si_errno; /* errno association */ - int32 si_code; /* signal code */ - int32 si_status; /* exit value */ - void *si_addr; /* faulting address */ - /* more stuff here */ -}; - -// This is a struct sigaction from /usr/include/asm/signal.h -struct sigaction { - void (*sa_handler)(int32, struct siginfo*, void*); - uint64 sa_flags; - void (*sa_restorer)(void); - uint64 sa_mask; -}; - void -sighandler(int32 sig, struct siginfo* info, void** context) +sighandler(int32 sig, Siginfo* info, void* context) { + Ucontext *uc; + Mcontext *mc; + Sigcontext *sc; + if(panicking) // traceback already printed sys_Exit(2); - struct sigcontext *sc = &(((struct ucontext *)context)->uc_mcontext); + uc = context; + mc = &uc->uc_mcontext; + sc = (Sigcontext*)mc; // same layout, more conveient names - if(sig < 0 || sig >= NSIG){ - prints("Signal "); - sys·printint(sig); - }else{ - prints(sigtab[sig].name); - } + if(sig < 0 || sig >= NSIG) + printf("Signal %d\n", sig); + else + printf("%s\n", sigtab[sig].name); - prints("\nFaulting address: "); sys·printpointer(info->si_addr); - prints("\npc: "); sys·printhex(sc->rip); - prints("\n\n"); + printf("Faulting address: %p\n", *(void**)info->_sifields); + printf("PC=%X\n", sc->rip); + printf("\n"); if(gotraceback()){ - traceback((void *)sc->rip, (void *)sc->rsp, (void *)sc->r15); + traceback((void*)sc->rip, (void*)sc->rsp, (void*)sc->r15); tracebackothers((void*)sc->r15); - print_sigcontext(sc); + dumpregs(sc); } sys·Breakpoint(); sys_Exit(2); } -struct stack_t { - void *sp; - int32 flags; - int32 pad; - int64 size; -}; - void signalstack(byte *p, int32 n) { - struct stack_t st; + Sigaltstack st; - st.sp = p; - st.size = n; - st.pad = 0; - st.flags = 0; + st.ss_sp = p; + st.ss_size = n; + st.ss_flags = 0; sigaltstack(&st, nil); } -void rt_sigaction(int64, void*, void*, uint64); - -enum { - SA_RESTART = 0x10000000, - SA_ONSTACK = 0x08000000, - SA_RESTORER = 0x04000000, - SA_SIGINFO = 0x00000004, -}; - void initsig(void) { - static struct sigaction sa; + static Sigaction sa; int32 i; sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER; |