From 6e8dbc2051ab5face6278e4056eefd5aea6c329b Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Fri, 12 Sep 2008 09:44:41 -0700 Subject: [PATCH] - catch trace traps - disassemble the instructions in a trace trap to see if it's a run-time trap - if so, print relevant info - avoid double-printing traceback on panic R=ken,rsc DELTA=66 (50 added, 7 deleted, 9 changed) OCL=15199 CL=15224 --- src/runtime/rt1_amd64_darwin.c | 18 +++++++++++------- src/runtime/rt1_amd64_linux.c | 17 +++++++++++------ src/runtime/rt2_amd64.c | 30 ++++++++++++++++++++++++++++++ src/runtime/runtime.c | 4 +++- src/runtime/runtime.h | 2 ++ src/runtime/signals.h | 2 +- 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/runtime/rt1_amd64_darwin.c b/src/runtime/rt1_amd64_darwin.c index da10508a0e..49ecb3a0ca 100644 --- a/src/runtime/rt1_amd64_darwin.c +++ b/src/runtime/rt1_amd64_darwin.c @@ -130,20 +130,24 @@ typedef struct sigaction { int32 sa_flags; /* see signal options below */ } sigaction; - void sighandler(int32 sig, siginfo *info, void *context) { - if(sig < 0 || sig >= NSIG){ - prints("Signal "); - sys·printint(sig); - }else{ - prints(sigtab[sig].name); - } + if(panicking) // traceback already printed + sys·exit(2); _STRUCT_MCONTEXT64 *uc_mcontext = get_uc_mcontext(context); _STRUCT_X86_THREAD_STATE64 *ss = get___ss(uc_mcontext); + if(!inlinetrap(sig, (byte *)ss->__rip)) { + if(sig < 0 || sig >= NSIG){ + prints("Signal "); + sys·printint(sig); + }else{ + prints(sigtab[sig].name); + } + } + prints("\nFaulting address: 0x"); sys·printpointer(info->si_addr); prints("\npc: 0x"); sys·printpointer((void *)ss->__rip); prints("\n\n"); diff --git a/src/runtime/rt1_amd64_linux.c b/src/runtime/rt1_amd64_linux.c index c14b338525..403b248338 100644 --- a/src/runtime/rt1_amd64_linux.c +++ b/src/runtime/rt1_amd64_linux.c @@ -138,15 +138,20 @@ typedef struct sigaction { void sighandler(int32 sig, siginfo* info, void** context) { - if(sig < 0 || sig >= NSIG){ - prints("Signal "); - sys·printint(sig); - }else{ - prints(sigtab[sig].name); - } + if(panicking) // traceback already printed + sys·exit(2); struct sigcontext *sc = &(((struct ucontext *)context)->uc_mcontext); + if(!inlinetrap(sig, (byte *)sc->rip)) { + if(sig < 0 || sig >= NSIG){ + prints("Signal "); + sys·printint(sig); + }else{ + prints(sigtab[sig].name); + } + } + prints("\nFaulting address: 0x"); sys·printpointer(info->si_addr); prints("\npc: 0x"); sys·printpointer((void *)sc->rip); prints("\n\n"); diff --git a/src/runtime/rt2_amd64.c b/src/runtime/rt2_amd64.c index 91bef54340..2943ac0d36 100644 --- a/src/runtime/rt2_amd64.c +++ b/src/runtime/rt2_amd64.c @@ -86,3 +86,33 @@ traceback(uint8 *pc, uint8 *sp, void* r15) prints(", ...)\n"); } } + +/* + * For trace traps, disassemble instruction to see if it's INTB of known type. + */ +int32 +inlinetrap(int32 sig, byte* pc) +{ + extern void etext(); + extern void _rt0_amd64_darwin(); + + if(sig != 5) /* SIGTRAP */ + return 0; + if(pc-2 < (byte*)_rt0_amd64_darwin || pc >= (byte*)etext) + return 0; + if(pc[-2] != 0xcd) /* INTB */ + return 0; + switch(pc[-1]) { + case 5: + prints("\nTRAP: array out of bounds\n"); + break; + case 6: + prints("\nTRAP: leaving function with returning a value\n"); + break; + default: + prints("\nTRAP: unknown run-time trap "); + sys·printint(pc[-1]); + prints("\n"); + } + return 1; +} diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 973fb5bd3c..26becc52a5 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -5,6 +5,7 @@ #include "runtime.h" int32 debug = 0; +int32 panicking = 0; void sys·panicl(int32 lno) @@ -19,7 +20,8 @@ sys·panicl(int32 lno) sp = (uint8*)&lno; traceback(sys·getcallerpc(&lno), sp, g); tracebackothers(g); - sys·breakpoint(); + panicking = 1; + sys·breakpoint(); // so we can grab it in a debugger sys·exit(2); } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index c64e5b37e7..11d3fdac8e 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -207,6 +207,7 @@ M* allm; G* allg; int32 goidgen; extern int32 gomaxprocs; +extern int32 panicking; /* * common functions and data @@ -236,6 +237,7 @@ uint32 cmpstring(string, string); void initsig(void); void traceback(uint8 *pc, uint8 *sp, G* gp); void tracebackothers(G*); +int32 inlinetrap(int32 sig, byte* pc); int32 open(byte*, int32, ...); int32 read(int32, void*, int32); int32 write(int32, void*, int32); diff --git a/src/runtime/signals.h b/src/runtime/signals.h index 5b2776a438..475f6752b5 100644 --- a/src/runtime/signals.h +++ b/src/runtime/signals.h @@ -9,7 +9,7 @@ static struct SigTab sigtab[] = { /* 2 */ 0, "SIGINT: interrupt program", /* 3 */ 1, "SIGQUIT: quit program", /* 4 */ 1, "SIGILL: illegal instruction", - /* 5 */ 0, "SIGTRAP: trace trap", /* uncaught; used by panic and signal handler */ + /* 5 */ 1, "SIGTRAP: trace trap", /* used by panic and array out of bounds, etc. */ /* 6 */ 1, "SIGABRT: abort program", /* 7 */ 1, "SIGEMT: emulate instruction executed", /* 8 */ 1, "SIGFPE: floating-point exception", -- 2.48.1