зеркало из https://github.com/mozilla/pjs.git
Make jprof compile (and maybe even run in some cases) on x86_64, and make its stack walking code a little less fragile. b=349166 r=bzbarsky
This commit is contained in:
Родитель
5ebeb98ba2
Коммит
29401c0f5b
|
@ -241,11 +241,12 @@ void leaky::open()
|
|||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
static ptrdiff_t symbolOrder(void const* a, void const* b)
|
||||
static int symbolOrder(void const* a, void const* b)
|
||||
{
|
||||
Symbol const* ap = (Symbol const *)a;
|
||||
Symbol const* bp = (Symbol const *)b;
|
||||
return ap->address - bp->address;
|
||||
ptrdiff_t diff = ap->address - bp->address;
|
||||
return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1);
|
||||
}
|
||||
|
||||
void leaky::ReadSharedLibrarySymbols()
|
||||
|
|
|
@ -47,11 +47,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// Some versions of glibc (i.e., the one that comes with RedHat 6.0 rather
|
||||
// than 6.1) seem to do things a bit differently when libpthread is involved.
|
||||
// If things don't work for you, try defining this:
|
||||
//#define JPROF_PTHREAD_HACK
|
||||
|
||||
#include <errno.h>
|
||||
#if defined(linux)
|
||||
#include <linux/rtc.h>
|
||||
|
@ -66,6 +61,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include "libmalloc.h"
|
||||
#include "jprof.h"
|
||||
|
@ -90,32 +86,33 @@ static int enableRTCSignals(bool enable);
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#if defined(i386) || defined(_i386)
|
||||
static void CrawlStack(malloc_log_entry* me, void* frame_ptr, char* first)
|
||||
#if defined(i386) || defined(_i386) || defined(__x86_64__)
|
||||
static void CrawlStack(malloc_log_entry* me,
|
||||
void* stack_top, void* top_instr_ptr)
|
||||
{
|
||||
void** bp = (void**)frame_ptr;
|
||||
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
|
||||
u_long numpcs = 0;
|
||||
|
||||
#ifdef JPROF_PTHREAD_HACK
|
||||
int skip = 3;
|
||||
#else
|
||||
me->pcs[numpcs++] = first;
|
||||
me->pcs[numpcs++] = (char*) top_instr_ptr;
|
||||
|
||||
// skip 2 frames: StackHook, __restore_rt.
|
||||
// The next frame is the frame _above_ |first|.
|
||||
int skip = 2;
|
||||
#endif
|
||||
while (numpcs < MAX_STACK_CRAWL) {
|
||||
void** nextbp = (void**) *bp++;
|
||||
void* pc = *bp;
|
||||
#ifdef JPROF_PTHREAD_HACK
|
||||
if ((pc < 0x08000000) || ((pc > 0x7fffffff) && (skip <= 0)) || (nextbp < bp)) {
|
||||
#else
|
||||
if ((nextbp < bp)) {
|
||||
#endif
|
||||
if (nextbp < bp) {
|
||||
break;
|
||||
}
|
||||
if (--skip < 0) {
|
||||
if (bp > stack_top) {
|
||||
// Skip the signal handling.
|
||||
me->pcs[numpcs++] = (char*) pc;
|
||||
}
|
||||
bp = nextbp;
|
||||
|
@ -173,25 +170,14 @@ static void EndProfilingHook(int signum)
|
|||
//----------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
Log(u_long aTime, char *first)
|
||||
Log(u_long aTime, void* stack_top, void* top_instr_ptr)
|
||||
{
|
||||
// Static is simply to make debugging tollerable
|
||||
static malloc_log_entry me;
|
||||
|
||||
me.delTime = aTime;
|
||||
|
||||
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);
|
||||
CrawlStack(&me, stack_top, top_instr_ptr);
|
||||
|
||||
#ifndef NTO
|
||||
write(gLogFD, &me, offsetof(malloc_log_entry, pcs) + me.numpcs*sizeof(char*));
|
||||
|
@ -298,7 +284,7 @@ static int enableRTCSignals(bool enable)
|
|||
static void StackHook(
|
||||
int signum,
|
||||
siginfo_t *info,
|
||||
void *mystry)
|
||||
void *ucontext)
|
||||
{
|
||||
static struct timeval tFirst;
|
||||
static int first=1;
|
||||
|
@ -337,16 +323,13 @@ void *mystry)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef JPROF_PTHREAD_HACK
|
||||
Log(millisec, NULL);
|
||||
gregset_t &gregs = ((ucontext_t*)ucontext)->uc_mcontext.gregs;
|
||||
#ifdef __x86_64__
|
||||
Log(millisec, (void*)gregs[REG_RSP], (void*)gregs[REG_RIP]);
|
||||
#else
|
||||
// The mystry[19] thing is a hack to figure out where we were called from.
|
||||
// By playing around with the debugger it looks like [19] contains the
|
||||
// information I need.
|
||||
// it's really ((ucontext_t *)mystry)->uc_mcontext.gregs[14] which is
|
||||
// the EIP register when the handler was called
|
||||
Log(millisec, ((char**)mystry)[19]);
|
||||
Log(millisec, (void*)gregs[REG_ESP], (void*)gregs[REG_EIP]);
|
||||
#endif
|
||||
|
||||
if (!rtcHz)
|
||||
startSignalCounter(timerMiliSec);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче