From ee0c4c2b8ebbbaafbfe9a7f8ddec1d436a36c2ab Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Thu, 23 Mar 2006 23:21:27 +0000 Subject: [PATCH] Workaround brokenness of __builtin_frame_address(0) on gcc 4.1 (as shipped with FC5, at least). b=331436 r=brendan git-svn-id: svn://10.0.0.236/trunk@192881 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/gc/boehm/os_dep.c | 9 ++++++ mozilla/js/src/jsutil.c | 31 ++++++++++++------- mozilla/tools/jprof/stub/libmalloc.cpp | 19 +++++++++--- .../tools/trace-malloc/lib/nsTraceMalloc.c | 29 +++++++++++------ mozilla/xpcom/base/nsStackFrameUnix.cpp | 12 ++++++- 5 files changed, 74 insertions(+), 26 deletions(-) diff --git a/mozilla/gc/boehm/os_dep.c b/mozilla/gc/boehm/os_dep.c index ce4780b2857..196c4cb01b7 100644 --- a/mozilla/gc/boehm/os_dep.c +++ b/mozilla/gc/boehm/os_dep.c @@ -2442,7 +2442,16 @@ struct stack_frame { static stack_frame* getStackFrame() { stack_frame* currentFrame; +#if defined(__i386) + __asm__( "movl %%ebp, %0" : "=g"(currentFrame)); +#elif defined(__x86_64__) + __asm__( "movq %%rbp, %0" : "=g"(currentFrame)); +#else + // It would be nice if this worked uniformly, but at least on i386 and + // x86_64, it stopped working with gcc 4.1, because it points to the + // end of the saved registers instead of the start. currentFrame = (stack_frame*)__builtin_frame_address(0); +#endif currentFrame = currentFrame->next; return currentFrame; } diff --git a/mozilla/js/src/jsutil.c b/mozilla/js/src/jsutil.c index 02ba56a021d..be5f5c44275 100644 --- a/mozilla/js/src/jsutil.c +++ b/mozilla/js/src/jsutil.c @@ -73,9 +73,9 @@ JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln) JSCallsite js_calltree_root = {0, NULL, NULL, 0, NULL, NULL, NULL, NULL}; static JSCallsite * -CallTree(uint32 *bp) +CallTree(void **bp) { - uint32 *bpup, *bpdown, pc; + void **bpup, **bpdown, *pc; JSCallsite *parent, *site, **csp; Dl_info info; int ok, offset; @@ -85,9 +85,9 @@ CallTree(uint32 *bp) /* Reverse the stack frame list to avoid recursion. */ bpup = NULL; for (;;) { - bpdown = (uint32*) bp[0]; - bp[0] = (uint32) bpup; - if ((uint32*) bpdown[0] < bpdown) + bpdown = (void**) bp[0]; + bp[0] = (void*) bpup; + if ((void**) bpdown[0] < bpdown) break; bpup = bp; bp = bpdown; @@ -96,8 +96,8 @@ CallTree(uint32 *bp) /* Reverse the stack again, finding and building a path in the tree. */ parent = &js_calltree_root; do { - bpup = (uint32*) bp[0]; - bp[0] = (uint32) bpdown; + bpup = (void**) bp[0]; + bp[0] = (void*) bpdown; pc = bp[1]; csp = &parent->kids; @@ -125,7 +125,7 @@ CallTree(uint32 *bp) * XXX static syms are masked by nearest lower global */ info.dli_fname = info.dli_sname = NULL; - ok = dladdr((void*) pc, &info); + ok = dladdr(pc, &info); if (ok < 0) { fprintf(stderr, "dladdr failed!\n"); return NULL; @@ -169,12 +169,21 @@ CallTree(uint32 *bp) JSCallsite * JS_Backtrace(int skip) { - uint32 *bp, *bpdown; + void **bp, **bpdown; /* Stack walking code adapted from Kipp's "leaky". */ - bp = (uint32*) __builtin_frame_address(0); +#if defined(__i386) + __asm__( "movl %%ebp, %0" : "=g"(bp)); +#elif defined(__x86_64__) + __asm__( "movq %%rbp, %0" : "=g"(bp)); +#else + // It would be nice if this worked uniformly, but at least on i386 and + // x86_64, it stopped working with gcc 4.1, because it points to the + // end of the saved registers instead of the start. + bp = (void**) __builtin_frame_address(0); +#endif while (--skip >= 0) { - bpdown = (uint32*) *bp++; + bpdown = (void**) *bp++; if (bpdown < bp) break; bp = bpdown; diff --git a/mozilla/tools/jprof/stub/libmalloc.cpp b/mozilla/tools/jprof/stub/libmalloc.cpp index 274dd3332db..70edb190ae8 100644 --- a/mozilla/tools/jprof/stub/libmalloc.cpp +++ b/mozilla/tools/jprof/stub/libmalloc.cpp @@ -93,7 +93,7 @@ static int enableRTCSignals(bool enable); #if defined(i386) || defined(_i386) static void CrawlStack(malloc_log_entry* me, void* frame_ptr, char* first) { - u_long* bp = (u_long*)frame_ptr; + void** bp = (void**)frame_ptr; u_long numpcs = 0; #ifdef JPROF_PTHREAD_HACK @@ -106,8 +106,8 @@ static void CrawlStack(malloc_log_entry* me, void* frame_ptr, char* first) int skip = 2; #endif while (numpcs < MAX_STACK_CRAWL) { - u_long* nextbp = (u_long*) *bp++; - u_long pc = *bp; + void** nextbp = (void**) *bp++; + void* pc = *bp; #ifdef JPROF_PTHREAD_HACK if ((pc < 0x08000000) || ((pc > 0x7fffffff) && (skip <= 0)) || (nextbp < bp)) { #else @@ -180,7 +180,18 @@ Log(u_long aTime, char *first) me.delTime = aTime; - CrawlStack(&me, __builtin_frame_address(0), first); + void *bp; +#if defined(__i386) + __asm__( "movl %%ebp, %0" : "=g"(bp)); +#elif defined(__x86_64__) + __asm__( "movq %%rbp, %0" : "=g"(bp)); +#else + // It would be nice if this worked uniformly, but at least on i386 and + // x86_64, it stopped working with gcc 4.1, because it points to the + // end of the saved registers instead of the start. + bp = __builtin_frame_address(0); +#endif + CrawlStack(&me, bp, first); #ifndef NTO write(gLogFD, &me, offsetof(malloc_log_entry, pcs) + me.numpcs*sizeof(char*)); diff --git a/mozilla/tools/trace-malloc/lib/nsTraceMalloc.c b/mozilla/tools/trace-malloc/lib/nsTraceMalloc.c index 283f5feaca9..2cf929853de 100644 --- a/mozilla/tools/trace-malloc/lib/nsTraceMalloc.c +++ b/mozilla/tools/trace-malloc/lib/nsTraceMalloc.c @@ -1005,10 +1005,10 @@ static callsite *calltree(int skip) #else /*XP_UNIX*/ -static callsite *calltree(uint32 *bp) +static callsite *calltree(void **bp) { logfile *fp = logfp; - uint32 *bpup, *bpdown, pc; + void **bpup, **bpdown, *pc; uint32 depth, nkids; callsite *parent, *site, **csp, *tmp; Dl_info info; @@ -1026,9 +1026,9 @@ static callsite *calltree(uint32 *bp) /* Reverse the stack frame list to avoid recursion. */ bpup = NULL; for (depth = 0; ; depth++) { - bpdown = (uint32*) bp[0]; - bp[0] = (uint32) bpup; - if ((uint32*) bpdown[0] < bpdown) + bpdown = (void**) bp[0]; + bp[0] = (void*) bpup; + if ((void**) bpdown[0] < bpdown) break; bpup = bp; bp = bpdown; @@ -1040,8 +1040,8 @@ static callsite *calltree(uint32 *bp) /* Reverse the stack again, finding and building a path in the tree. */ parent = &calltree_root; do { - bpup = (uint32*) bp[0]; - bp[0] = (uint32) bpdown; + bpup = (void**) bp[0]; + bp[0] = (void*) bpdown; pc = bp[1]; csp = &parent->kids; @@ -1338,7 +1338,7 @@ backtrace(int skip) callsite * backtrace(int skip) { - uint32 *bp, *bpdown; + void **bp, **bpdown; callsite *site, **key; PLHashNumber hash; PLHashEntry **hep, *he; @@ -1348,9 +1348,18 @@ backtrace(int skip) suppress_tracing++; /* Stack walking code adapted from Kipp's "leaky". */ - bp = (uint32*) __builtin_frame_address(0); +#if defined(__i386) + __asm__( "movl %%ebp, %0" : "=g"(bp)); +#elif defined(__x86_64__) + __asm__( "movq %%rbp, %0" : "=g"(bp)); +#else + // It would be nice if this worked uniformly, but at least on i386 and + // x86_64, it stopped working with gcc 4.1, because it points to the + // end of the saved registers instead of the start. + bp = (void**) __builtin_frame_address(0); +#endif while (--skip >= 0) { - bpdown = (uint32*) *bp++; + bpdown = (void**) *bp++; if (bpdown < bp) break; bp = bpdown; diff --git a/mozilla/xpcom/base/nsStackFrameUnix.cpp b/mozilla/xpcom/base/nsStackFrameUnix.cpp index b568ddfaeb2..c896302cf92 100644 --- a/mozilla/xpcom/base/nsStackFrameUnix.cpp +++ b/mozilla/xpcom/base/nsStackFrameUnix.cpp @@ -91,7 +91,17 @@ void DumpStackToFile(FILE* aStream) // Stack walking code courtesy Kipp's "leaky". // Get the frame pointer - void **bp = (void**) __builtin_frame_address(0); + void **bp; +#if defined(__i386) + __asm__( "movl %%ebp, %0" : "=g"(bp)); +#elif defined(__x86_64__) + __asm__( "movq %%rbp, %0" : "=g"(bp)); +#else + // It would be nice if this worked uniformly, but at least on i386 and + // x86_64, it stopped working with gcc 4.1, because it points to the + // end of the saved registers instead of the start. + bp = (void**) __builtin_frame_address(0); +#endif int skip = 2; for ( ; (void**)*bp > bp; bp = (void**)*bp) {