diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-01-30 22:24:40 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-01-30 22:24:40 +0000 |
commit | 051dc824954265bd097b1abeeef4c0c9b29bffbd (patch) | |
tree | 1764d8d318ba67622aefbf3e311749a6744bfa02 | |
parent | 53486a83200dcd6ef17ca09e1d77db3664acbe2b (diff) | |
download | gcc-051dc824954265bd097b1abeeef4c0c9b29bffbd.tar.gz |
runtime: In backtraces, get inline functions, skip split-stack fns.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@195591 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libgo/runtime/go-caller.c | 10 | ||||
-rw-r--r-- | libgo/runtime/go-callers.c | 50 | ||||
-rw-r--r-- | libgo/runtime/go-traceback.c | 20 | ||||
-rw-r--r-- | libgo/runtime/mprof.goc | 48 | ||||
-rw-r--r-- | libgo/runtime/proc.c | 15 | ||||
-rw-r--r-- | libgo/runtime/runtime.h | 19 | ||||
-rw-r--r-- | libgo/runtime/string.goc | 34 |
7 files changed, 143 insertions, 53 deletions
diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c index 63b45f368c2..d84580fa594 100644 --- a/libgo/runtime/go-caller.c +++ b/libgo/runtime/go-caller.c @@ -166,16 +166,16 @@ struct caller_ret Caller (int skip) { struct caller_ret ret; - uintptr pc; + Location loc; int32 n; - String fn; runtime_memclr (&ret, sizeof ret); - n = runtime_callers (skip + 1, &pc, 1); + n = runtime_callers (skip + 1, &loc, 1); if (n < 1) return ret; - ret.pc = pc; - __go_file_line (pc, &fn, &ret.file, &ret.line); + ret.pc = loc.pc; + ret.file = loc.filename; + ret.line = loc.lineno; ret.ok = 1; return ret; } diff --git a/libgo/runtime/go-callers.c b/libgo/runtime/go-callers.c index a19e79f053b..ea6b5db1bcb 100644 --- a/libgo/runtime/go-callers.c +++ b/libgo/runtime/go-callers.c @@ -15,20 +15,37 @@ struct callers_data { - uintptr *pcbuf; + Location *locbuf; int index; int max; }; -/* Callback function for backtrace_simple. Just collect the PC - values. Return zero to continue, non-zero to stop. */ +/* Callback function for backtrace_full. Just collect the locations. + Return zero to continue, non-zero to stop. */ static int -callback (void *data, uintptr_t pc) +callback (void *data, uintptr_t pc, const char *filename, int lineno, + const char *function) { struct callers_data *arg = (struct callers_data *) data; - - arg->pcbuf[arg->index] = pc; + Location *loc; + + /* Skip split stack functions. */ + if (function != NULL) + { + const char *p = function; + + if (__builtin_strncmp (p, "___", 3) == 0) + ++p; + if (__builtin_strncmp (p, "__morestack_", 12) == 0) + return 0; + } + + loc = &arg->locbuf[arg->index]; + loc->pc = pc; + loc->filename = runtime_gostring ((const byte *) filename); + loc->function = runtime_gostring ((const byte *) function); + loc->lineno = lineno; ++arg->index; return arg->index >= arg->max; } @@ -47,15 +64,15 @@ error_callback (void *data __attribute__ ((unused)), /* Gather caller PC's. */ int32 -runtime_callers (int32 skip, uintptr *pcbuf, int32 m) +runtime_callers (int32 skip, Location *locbuf, int32 m) { struct callers_data data; - data.pcbuf = pcbuf; + data.locbuf = locbuf; data.index = 0; data.max = m; - backtrace_simple (__go_get_backtrace_state (), skip + 1, callback, - error_callback, &data); + backtrace_full (__go_get_backtrace_state (), skip + 1, callback, + error_callback, &data); return data.index; } @@ -65,8 +82,19 @@ int Callers (int, struct __go_open_array) int Callers (int skip, struct __go_open_array pc) { + Location *locbuf; + int ret; + int i; + + locbuf = (Location *) runtime_mal (pc.__count * sizeof (Location)); + /* In the Go 1 release runtime.Callers has an off-by-one error, which we can not correct because it would break backward compatibility. Adjust SKIP here to be compatible. */ - return runtime_callers (skip - 1, (uintptr *) pc.__values, pc.__count); + ret = runtime_callers (skip - 1, locbuf, pc.__count); + + for (i = 0; i < ret; i++) + ((uintptr *) pc.__values)[i] = locbuf[i].pc; + + return ret; } diff --git a/libgo/runtime/go-traceback.c b/libgo/runtime/go-traceback.c index 30a5ed91c44..f397f075231 100644 --- a/libgo/runtime/go-traceback.c +++ b/libgo/runtime/go-traceback.c @@ -13,29 +13,25 @@ void runtime_traceback () { - uintptr pcbuf[100]; + Location locbuf[100]; int32 c; - c = runtime_callers (1, pcbuf, sizeof pcbuf / sizeof pcbuf[0]); - runtime_printtrace (pcbuf, c, true); + c = runtime_callers (1, locbuf, nelem (locbuf)); + runtime_printtrace (locbuf, c, true); } void -runtime_printtrace (uintptr *pcbuf, int32 c, bool current) +runtime_printtrace (Location *locbuf, int32 c, bool current) { int32 i; for (i = 0; i < c; ++i) { - String fn; - String file; - intgo line; - - if (__go_file_line (pcbuf[i], &fn, &file, &line) - && runtime_showframe (fn, current)) + if (runtime_showframe (locbuf[i].function, current)) { - runtime_printf ("%S\n", fn); - runtime_printf ("\t%S:%D\n", file, (int64) line); + runtime_printf ("%S\n", locbuf[i].function); + runtime_printf ("\t%S:%D\n", locbuf[i].filename, + (int64) locbuf[i].lineno); } } } diff --git a/libgo/runtime/mprof.goc b/libgo/runtime/mprof.goc index 2cf2afba433..c1b09bea7f5 100644 --- a/libgo/runtime/mprof.goc +++ b/libgo/runtime/mprof.goc @@ -11,6 +11,7 @@ package runtime #include "malloc.h" #include "defs.h" #include "go-type.h" +#include "go-string.h" // NOTE(rsc): Everything here could use cas if contention became an issue. static Lock proflock; @@ -46,7 +47,7 @@ struct Bucket }; uintptr hash; uintptr nstk; - uintptr stk[1]; + Location stk[1]; }; enum { BuckHashSize = 179999, @@ -58,9 +59,9 @@ static uintptr bucketmem; // Return the bucket for stk[0:nstk], allocating new bucket if needed. static Bucket* -stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc) +stkbucket(int32 typ, Location *stk, int32 nstk, bool alloc) { - int32 i; + int32 i, j; uintptr h; Bucket *b; @@ -72,7 +73,7 @@ stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc) // Hash stack. h = 0; for(i=0; i<nstk; i++) { - h += stk[i]; + h += stk[i].pc; h += h<<10; h ^= h>>6; } @@ -80,10 +81,18 @@ stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc) h ^= h>>11; i = h%BuckHashSize; - for(b = buckhash[i]; b; b=b->next) - if(b->typ == typ && b->hash == h && b->nstk == (uintptr)nstk && - runtime_mcmp((byte*)b->stk, (byte*)stk, nstk*sizeof stk[0]) == 0) - return b; + for(b = buckhash[i]; b; b=b->next) { + if(b->typ == typ && b->hash == h && b->nstk == (uintptr)nstk) { + for(j = 0; j < nstk; j++) { + if(b->stk[j].pc != stk[j].pc || + b->stk[j].lineno != stk[j].lineno || + !__go_strings_equal(b->stk[j].filename, stk[j].filename)) + break; + } + if (j == nstk) + return b; + } + } if(!alloc) return nil; @@ -241,7 +250,7 @@ runtime_MProf_Malloc(void *p, uintptr size) { M *m; int32 nstk; - uintptr stk[32]; + Location stk[32]; Bucket *b; m = runtime_m(); @@ -298,7 +307,7 @@ runtime_blockevent(int64 cycles, int32 skip) { int32 nstk; int64 rate; - uintptr stk[32]; + Location stk[32]; Bucket *b; if(cycles <= 0) @@ -336,7 +345,7 @@ record(Record *r, Bucket *b) r->alloc_objects = b->allocs; r->free_objects = b->frees; for(i=0; i<b->nstk && i<nelem(r->stk); i++) - r->stk[i] = b->stk[i]; + r->stk[i] = b->stk[i].pc; for(; i<nelem(r->stk); i++) r->stk[i] = 0; } @@ -396,7 +405,7 @@ func BlockProfile(p Slice) (n int, ok bool) { r->count = b->count; r->cycles = b->cycles; for(i=0; (uintptr)i<b->nstk && (uintptr)i<nelem(r->stk); i++) - r->stk[i] = b->stk[i]; + r->stk[i] = b->stk[i].pc; for(; (uintptr)i<nelem(r->stk); i++) r->stk[i] = 0; } @@ -413,6 +422,7 @@ struct TRecord { func ThreadCreateProfile(p Slice) (n int, ok bool) { TRecord *r; M *first, *mp; + int32 i; first = runtime_atomicloadp(&runtime_allm); n = 0; @@ -423,7 +433,9 @@ func ThreadCreateProfile(p Slice) (n int, ok bool) { ok = true; r = (TRecord*)p.__values; for(mp=first; mp; mp=mp->alllink) { - runtime_memmove(r->stk, mp->createstack, sizeof r->stk); + for(i = 0; (uintptr)i < nelem(r->stk); i++) { + r->stk[i] = mp->createstack[i].pc; + } r++; } } @@ -473,10 +485,14 @@ func Stack(b Slice, all bool) (n int) { static void saveg(G *gp, TRecord *r) { - int32 n; + int32 n, i; + Location locstk[nelem(r->stk)]; - if(gp == runtime_g()) - n = runtime_callers(0, r->stk, nelem(r->stk)); + if(gp == runtime_g()) { + n = runtime_callers(0, locstk, nelem(r->stk)); + for(i = 0; i < n; i++) + r->stk[i] = locstk[i].pc; + } else { // FIXME: Not implemented. n = 0; diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index b2e37f39150..6d9007614b9 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -631,7 +631,7 @@ runtime_goroutinetrailer(G *g) struct Traceback { G* gp; - uintptr pcbuf[100]; + Location locbuf[100]; int32 c; }; @@ -677,7 +677,7 @@ runtime_tracebackothers(G * volatile me) runtime_gogo(gp); } - runtime_printtrace(tb.pcbuf, tb.c, false); + runtime_printtrace(tb.locbuf, tb.c, false); runtime_goroutinetrailer(gp); } } @@ -692,8 +692,8 @@ gtraceback(G* gp) traceback = gp->traceback; gp->traceback = nil; - traceback->c = runtime_callers(1, traceback->pcbuf, - sizeof traceback->pcbuf / sizeof traceback->pcbuf[0]); + traceback->c = runtime_callers(1, traceback->locbuf, + sizeof traceback->locbuf / sizeof traceback->locbuf[0]); runtime_gogo(traceback->gp); } @@ -1742,13 +1742,14 @@ static struct { void (*fn)(uintptr*, int32); int32 hz; uintptr pcbuf[100]; + Location locbuf[100]; } prof; // Called if we receive a SIGPROF signal. void runtime_sigprof() { - int32 n; + int32 n, i; if(prof.fn == nil || prof.hz == 0) return; @@ -1758,7 +1759,9 @@ runtime_sigprof() runtime_unlock(&prof); return; } - n = runtime_callers(0, prof.pcbuf, nelem(prof.pcbuf)); + n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf)); + for(i = 0; i < n; i++) + prof.pcbuf[i] = prof.locbuf[i].pc; if(n > 0) prof.fn(prof.pcbuf, n); runtime_unlock(&prof); diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index de72f42bc55..9392df162bf 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -83,6 +83,8 @@ typedef struct __go_map_type MapType; typedef struct Traceback Traceback; +typedef struct Location Location; + /* * Per-CPU declaration. */ @@ -155,6 +157,16 @@ struct GCStats uint64 nosyield; uint64 nsleep; }; + +// A location in the program, used for backtraces. +struct Location +{ + uintptr pc; + String filename; + String function; + intgo lineno; +}; + struct G { Defer* defer; @@ -226,7 +238,7 @@ struct M MCache *mcache; G* lockedg; G* idleg; - uintptr createstack[32]; // Stack that created this thread. + Location createstack[32]; // Stack that created this thread. M* nextwaitm; // next M waiting for lock uintptr waitsema; // semaphore for parking on locks uint32 waitsemacount; @@ -391,7 +403,8 @@ void runtime_goroutineheader(G*); void runtime_goroutinetrailer(G*); void runtime_traceback(); void runtime_tracebackothers(G*); -void runtime_printtrace(uintptr*, int32, bool); +void runtime_printtrace(Location*, int32, bool); +String runtime_gostring(const byte*); String runtime_gostringnocopy(const byte*); void* runtime_mstart(void*); G* runtime_malg(int32, byte**, size_t*); @@ -406,7 +419,7 @@ void runtime_entersyscall(void) __asm__ (GOSYM_PREFIX "syscall.Entersyscall"); void runtime_exitsyscall(void) __asm__ (GOSYM_PREFIX "syscall.Exitsyscall"); void siginit(void); bool __go_sigsend(int32 sig); -int32 runtime_callers(int32, uintptr*, int32); +int32 runtime_callers(int32, Location*, int32); int64 runtime_nanotime(void); int64 runtime_cputicks(void); int64 runtime_tickspersecond(void); diff --git a/libgo/runtime/string.goc b/libgo/runtime/string.goc index 240ab0ba5e4..04ecbe6f73a 100644 --- a/libgo/runtime/string.goc +++ b/libgo/runtime/string.goc @@ -10,6 +10,8 @@ package runtime #define charntorune(pv, str, len) __go_get_rune(str, len, pv) +const String runtime_emptystring; + intgo runtime_findnull(const byte *s) { @@ -18,6 +20,38 @@ runtime_findnull(const byte *s) return __builtin_strlen((const char*) s); } +static String +gostringsize(intgo l, byte** pmem) +{ + String s; + byte *mem; + + if(l == 0) { + *pmem = nil; + return runtime_emptystring; + } + // leave room for NUL for C runtime (e.g., callers of getenv) + mem = runtime_mallocgc(l+1, FlagNoPointers, 1, 0); + s.str = mem; + s.len = l; + mem[l] = 0; + *pmem = mem; + return s; +} + +String +runtime_gostring(const byte *str) +{ + intgo l; + String s; + byte *mem; + + l = runtime_findnull(str); + s = gostringsize(l, &mem); + runtime_memmove(mem, str, l); + return s; +} + String runtime_gostringnocopy(const byte *str) { |