aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2008-09-12 09:44:41 -0700
committerRob Pike <r@golang.org>2008-09-12 09:44:41 -0700
commit6e8dbc2051ab5face6278e4056eefd5aea6c329b (patch)
tree93eeb9ec4ccb53ef9685d3f689f7fb97c3654050 /src/runtime
parent96b906498abad3eea2d6ea7e401917ec431bef83 (diff)
downloadgo-6e8dbc2051ab5face6278e4056eefd5aea6c329b.tar.xz
- 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
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/rt1_amd64_darwin.c18
-rw-r--r--src/runtime/rt1_amd64_linux.c17
-rw-r--r--src/runtime/rt2_amd64.c30
-rw-r--r--src/runtime/runtime.c4
-rw-r--r--src/runtime/runtime.h2
-rw-r--r--src/runtime/signals.h2
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",