add mpatrol package
This commit is contained in:
parent
28151cf8c7
commit
a7748b2f13
@ -96,6 +96,7 @@ source "package/microwin/Config.in"
|
||||
source "package/mkdosfs/Config.in"
|
||||
source "package/module-init-tools/Config.in"
|
||||
source "package/modutils/Config.in"
|
||||
source "package/mpatrol/Config.in"
|
||||
source "package/mpg123/Config.in"
|
||||
source "package/mrouted/Config.in"
|
||||
source "package/mtd/Config.in"
|
||||
|
10
package/mpatrol/Config.in
Normal file
10
package/mpatrol/Config.in
Normal file
@ -0,0 +1,10 @@
|
||||
config BR2_PACKAGE_MPATROL
|
||||
bool "mpatrol"
|
||||
default n
|
||||
help
|
||||
A debugging tool that attempts to diagnose run-time errors that are
|
||||
caused by the wrong use of dynamically allocated memory. It acts as
|
||||
a malloc() debugger for debugging dynamic memory allocations, although
|
||||
it can also trace and profile calls to malloc() and free() too.
|
||||
|
||||
http://www.cbmamiga.demon.co.uk/mpatrol/
|
552
package/mpatrol/mpatrol-uclibc.patch
Normal file
552
package/mpatrol/mpatrol-uclibc.patch
Normal file
@ -0,0 +1,552 @@
|
||||
Patches for mpatrol to support uClibc and MIPS full call stack tracing
|
||||
by Dan Howell <dahowell@directv.com>
|
||||
|
||||
diff -urN mpatrol/src/config.h mpatrol-uclibc/src/config.h
|
||||
--- mpatrol/src/config.h 2006-04-27 15:58:21.000000000 -0700
|
||||
+++ mpatrol-uclibc/src/config.h 2006-05-05 20:32:58.000000000 -0700
|
||||
@@ -795,6 +795,10 @@
|
||||
*/
|
||||
|
||||
#ifndef MP_INIT_SUPPORT
|
||||
+/* Note that machine.c currently only implements MP_INIT_SUPPORT for
|
||||
+ * x86, 68k, 88k, and Sparc architechtures. */
|
||||
+#if ARCH == ARCH_IX86 || ARCH == ARCH_M68K || \
|
||||
+ ARCH == ARCH_M88K || ARCH == ARCH_SPARC
|
||||
#if SYSTEM == SYSTEM_DGUX || SYSTEM == SYSTEM_DRSNX || \
|
||||
SYSTEM == SYSTEM_DYNIX || SYSTEM == SYSTEM_LINUX || \
|
||||
SYSTEM == SYSTEM_SOLARIS || SYSTEM == SYSTEM_UNIXWARE
|
||||
@@ -809,6 +813,9 @@
|
||||
#else /* SYSTEM */
|
||||
#define MP_INIT_SUPPORT 0
|
||||
#endif /* SYSTEM */
|
||||
+#else /* ARCH */
|
||||
+#define MP_INIT_SUPPORT 0
|
||||
+#endif
|
||||
#endif /* MP_INIT_SUPPORT */
|
||||
|
||||
|
||||
diff -urN mpatrol/src/inter.c mpatrol-uclibc/src/inter.c
|
||||
--- mpatrol/src/inter.c 2002-01-08 12:13:59.000000000 -0800
|
||||
+++ mpatrol-uclibc/src/inter.c 2006-05-17 18:02:04.000000000 -0700
|
||||
@@ -79,12 +79,24 @@
|
||||
|
||||
#if TARGET == TARGET_UNIX
|
||||
#if SYSTEM == SYSTEM_LINUX
|
||||
+#ifndef __UCLIBC__
|
||||
/* This contains a pointer to the environment variables for a process. If
|
||||
* it is not set up yet then we must use sbrk() to allocate all memory since
|
||||
* we can't initialise mpatrol until the environment variable can be read.
|
||||
*/
|
||||
|
||||
extern char **__environ;
|
||||
+#else /* __UCLIBC__ */
|
||||
+/* In uClibc, the dynamic loader calls malloc() and related functions,
|
||||
+ * and sets __environ before these calls, so we can't use it to determine
|
||||
+ * if we can initialize mpatrol. Instead, we use __progname, which is set
|
||||
+ * in __uClibc_main just before before uClibc transfers control to the
|
||||
+ * application's main() function (and static constructors, if any). Before
|
||||
+ * this, we must use sbrk() to allocate memory.
|
||||
+ */
|
||||
+
|
||||
+extern const char *__progname;
|
||||
+#endif /* __UCLIBC__ */
|
||||
#elif SYSTEM == SYSTEM_TRU64
|
||||
/* The exception support library on Tru64 always allocates some memory from
|
||||
* the heap in order to initialise the code address range tables. We need
|
||||
@@ -118,7 +130,11 @@
|
||||
|
||||
#if TARGET == TARGET_UNIX
|
||||
#if SYSTEM == SYSTEM_LINUX
|
||||
+#ifndef __UCLIBC__
|
||||
#define crt_initialised() (__environ)
|
||||
+#else /* __UCLIBC__ */
|
||||
+#define crt_initialised() (__progname)
|
||||
+#endif /* __UCLIBC__ */
|
||||
#elif SYSTEM == SYSTEM_TRU64
|
||||
#define crt_initialised() (__exc_crd_list_head && init_flag)
|
||||
#else /* SYSTEM */
|
||||
@@ -306,7 +322,7 @@
|
||||
alloctype t;
|
||||
int c;
|
||||
|
||||
- if (memhead.fini || (memhead.astack.size == 0))
|
||||
+ if (memhead.fini || (memhead.astack.size == 0) || memhead.recur != 1)
|
||||
return;
|
||||
#if MP_FULLSTACK
|
||||
/* Create the address nodes for the current call. This is not necessarily
|
||||
@@ -1307,7 +1323,7 @@
|
||||
loginfo v;
|
||||
int j;
|
||||
|
||||
- if (!memhead.init || memhead.fini)
|
||||
+ if (!memhead.init || memhead.fini || memhead.recur != 0)
|
||||
{
|
||||
__mp_memset(p, c, l);
|
||||
return p;
|
||||
@@ -1371,7 +1387,7 @@
|
||||
loginfo v;
|
||||
int j;
|
||||
|
||||
- if (!memhead.init || memhead.fini)
|
||||
+ if (!memhead.init || memhead.fini || memhead.recur != 0)
|
||||
if (f == AT_MEMCCPY)
|
||||
{
|
||||
if (r = __mp_memfind(p, l, &c, 1))
|
||||
diff -ur mpatrol/src/machine.c mpatrol-uclibc/src/machine.c
|
||||
--- mpatrol/src/machine.c 2002-01-08 12:13:59.000000000 -0800
|
||||
+++ mpatrol-uclibc/src/machine.c 2006-06-07 15:11:20.000000000 -0700
|
||||
@@ -217,6 +217,19 @@
|
||||
.end __mp_stackpointer
|
||||
|
||||
|
||||
+/* Obtain the frame pointer (s8) for the current function.
|
||||
+ */
|
||||
+
|
||||
+ .text
|
||||
+ .globl __mp_framepointer
|
||||
+ .ent __mp_framepointer
|
||||
+__mp_framepointer:
|
||||
+ .frame $29,0,$31
|
||||
+ move $2,$30
|
||||
+ j $31
|
||||
+ .end __mp_framepointer
|
||||
+
|
||||
+
|
||||
/* Obtain the return address for the current function.
|
||||
*/
|
||||
|
||||
diff -urN mpatrol/src/memory.c mpatrol-uclibc/src/memory.c
|
||||
--- mpatrol/src/memory.c 2002-01-08 12:13:59.000000000 -0800
|
||||
+++ mpatrol-uclibc/src/memory.c 2006-05-12 18:12:39.000000000 -0700
|
||||
@@ -47,7 +47,7 @@
|
||||
#endif /* SYSTEM */
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
-#if MP_SIGINFO_SUPPORT
|
||||
+#if MP_SIGINFO_SUPPORT && SYSTEM != SYSTEM_LINUX
|
||||
#include <siginfo.h>
|
||||
#endif /* MP_SIGINFO_SUPPORT */
|
||||
#include <fcntl.h>
|
||||
diff -urN mpatrol/src/signals.c mpatrol-uclibc/src/signals.c
|
||||
--- mpatrol/src/signals.c 2002-01-08 12:13:59.000000000 -0800
|
||||
+++ mpatrol-uclibc/src/signals.c 2006-05-12 18:12:19.000000000 -0700
|
||||
@@ -36,7 +36,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#if TARGET == TARGET_UNIX
|
||||
-#if MP_SIGINFO_SUPPORT
|
||||
+#if MP_SIGINFO_SUPPORT && SYSTEM != SYSTEM_LINUX
|
||||
#include <siginfo.h>
|
||||
#endif /* MP_SIGINFO_SUPPORT */
|
||||
#elif TARGET == TARGET_WINDOWS
|
||||
diff -urN mpatrol/src/stack.c mpatrol-uclibc/src/stack.c
|
||||
--- mpatrol/src/stack.c 2002-01-08 12:13:59.000000000 -0800
|
||||
+++ mpatrol-uclibc/src/stack.c 2006-06-22 15:39:04.000000000 -0700
|
||||
@@ -48,7 +48,7 @@
|
||||
#else /* MP_LIBRARYSTACK_SUPPORT */
|
||||
#if TARGET == TARGET_UNIX
|
||||
#include <setjmp.h>
|
||||
-#if MP_SIGINFO_SUPPORT
|
||||
+#if MP_SIGINFO_SUPPORT && SYSTEM != SYSTEM_LINUX
|
||||
#include <siginfo.h>
|
||||
#endif /* MP_SIGINFO_SUPPORT */
|
||||
#if SYSTEM == SYSTEM_DRSNX || SYSTEM == SYSTEM_SOLARIS
|
||||
@@ -58,6 +58,17 @@
|
||||
#define R_SP REG_SP
|
||||
#endif /* R_SP */
|
||||
#endif /* ARCH */
|
||||
+#elif SYSTEM == SYSTEM_LINUX
|
||||
+#if ARCH == ARCH_MIPS
|
||||
+#include <linux/unistd.h>
|
||||
+/* We need the ucontext defined in asm/ucontext.h, but sys/ucontext.h
|
||||
+ * has a conflicting definition of ucontext. So we'll trick the
|
||||
+ * preprocessor into letting the include file define a non-conflicting
|
||||
+ * name. */
|
||||
+#define ucontext asm_ucontext
|
||||
+#include <asm/ucontext.h>
|
||||
+#undef ucontext
|
||||
+#endif /* ARCH */
|
||||
#endif /* SYSTEM */
|
||||
#endif /* TARGET */
|
||||
#endif /* MP_LIBRARYSTACK_SUPPORT */
|
||||
@@ -122,6 +133,15 @@
|
||||
#define SP_OFFSET 2 /* stack pointer offset has been set */
|
||||
#define SP_LOWER 4 /* lower part of stack pointer offset has been set */
|
||||
#define SP_UPPER 8 /* upper part of stack pointer offset has been set */
|
||||
+#define BR_UNCOND 16 /* unconditional branch needs to be taken */
|
||||
+#define BR_COND 32 /* conditional branch encountered */
|
||||
+#define RA_NOFRAME 64 /* no frame - return address is in ra register */
|
||||
+#define SP_IN_FP 128 /* stack pointer stored in frame pointer (s8) register */
|
||||
+
|
||||
+#if SYSTEM == SYSTEM_LINUX
|
||||
+#define RA_SIGTRAMP 1 /* return address is a signal trampoline */
|
||||
+#define RA_SIGRETURN 2 /* return address is in the signalled function */
|
||||
+#endif /* SYSTEM */
|
||||
#endif /* TARGET && ARCH */
|
||||
#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */
|
||||
|
||||
@@ -152,6 +172,13 @@
|
||||
#endif /* SYSTEM */
|
||||
#endif /* SYSTEM */
|
||||
#else /* MP_LIBRARYSTACK_SUPPORT */
|
||||
+/* On some systems, such as those using uClibc, the signal() function may
|
||||
+ * call memcpy() or other memory related functions, so we need to guard
|
||||
+ * against recursion.
|
||||
+ */
|
||||
+
|
||||
+static unsigned char recursive;
|
||||
+
|
||||
static jmp_buf environment;
|
||||
#if MP_SIGINFO_SUPPORT
|
||||
static struct sigaction bushandler;
|
||||
@@ -261,23 +288,41 @@
|
||||
int
|
||||
unwind(frameinfo *f)
|
||||
{
|
||||
- long p, s;
|
||||
- unsigned long a, i, q;
|
||||
+ long p, m, s;
|
||||
+ unsigned long a, i, q, t, b, r;
|
||||
unsigned short l, u;
|
||||
|
||||
s = -1;
|
||||
- p = 0;
|
||||
+ p = m = 0;
|
||||
q = 0xFFFFFFFF;
|
||||
l = u = 0;
|
||||
a = 0;
|
||||
+ t = b = 0;
|
||||
/* Determine the current stack pointer and return address if we are
|
||||
* initiating call stack traversal.
|
||||
*/
|
||||
if (f->ra == 0)
|
||||
{
|
||||
f->sp = __mp_stackpointer();
|
||||
+ f->fp = __mp_framepointer();
|
||||
f->ra = __mp_returnaddress();
|
||||
}
|
||||
+#if SYSTEM == SYSTEM_LINUX
|
||||
+ /* Handle signal frames.
|
||||
+ */
|
||||
+ if (f->ra & RA_SIGRETURN)
|
||||
+ {
|
||||
+ /* in case of frameless function, get ra and sp from sigcontext */
|
||||
+ p = ((struct sigcontext *) f->sp)->sc_regs[31];
|
||||
+ f->fp = ((struct sigcontext *) f->sp)->sc_regs[30];
|
||||
+ f->sp = ((struct sigcontext *) f->sp)->sc_regs[29];
|
||||
+ a |= RA_NOFRAME;
|
||||
+ }
|
||||
+ f->ra &= ~3;
|
||||
+#endif
|
||||
+ /* Save initial code-reading starting point.
|
||||
+ */
|
||||
+ r = f->ra;
|
||||
/* Search for the return address offset in the stack frame.
|
||||
*/
|
||||
while (!((a & RA_OFFSET) && (a & SP_OFFSET)) && (f->ra < q))
|
||||
@@ -294,6 +339,67 @@
|
||||
s = 0;
|
||||
a |= SP_OFFSET;
|
||||
}
|
||||
+ else if (i == 0x03C0E821)
|
||||
+ {
|
||||
+ /* move sp,s8 */
|
||||
+ a |= SP_IN_FP;
|
||||
+ }
|
||||
+ else if ((i >> 28 == 0x1) || (i >> 26 == 0x01))
|
||||
+ {
|
||||
+ /* branch */
|
||||
+ t = f->ra + ((signed short)(i & 0xFFFF) * 4) + 4;
|
||||
+ if ((i >> 16 == 0x1000) && !(a & BR_COND))
|
||||
+ {
|
||||
+ /* unconditional branch, if no conditional branch could
|
||||
+ branch past this code */
|
||||
+ b = t;
|
||||
+ a |= BR_UNCOND;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* conditional branch, ignore if previous conditional branch
|
||||
+ is further forwards */
|
||||
+ if ((t > b) && (t > f->ra))
|
||||
+ {
|
||||
+ b = t;
|
||||
+ a |= BR_COND;
|
||||
+ /* can branch past an unconditional branch */
|
||||
+ if (b > q)
|
||||
+ q = 0xFFFFFFFF;
|
||||
+ }
|
||||
+ else if (t < r)
|
||||
+ {
|
||||
+ /* but if branching backwards, set reverse branch target to
|
||||
+ lowest address target encountered so far */
|
||||
+ r = t;
|
||||
+ /* ensure a loop back */
|
||||
+ q = 0xFFFFFFFF;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+#if SYSTEM == SYSTEM_LINUX
|
||||
+ else if (i == 0x0000000c)
|
||||
+ {
|
||||
+ /* syscall - check for signal handler trampolines */
|
||||
+ if (*((unsigned long *) (f->ra - 4)) == 0x24020000 + __NR_sigreturn)
|
||||
+ {
|
||||
+ /* li v0,__NR_sigreturn */
|
||||
+ /* get pointer to sigcontext */
|
||||
+ f->sp = f->ra + 4;
|
||||
+ f->ra = ((struct sigcontext *) f->sp)->sc_pc | RA_SIGRETURN;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ else if (*((unsigned long *) (f->ra - 4)) == 0x24020000 + __NR_rt_sigreturn)
|
||||
+ {
|
||||
+ /* li v0,__NR_rt_sigreturn */
|
||||
+ /* get pointer to sigcontext */
|
||||
+ f->sp = f->ra + 4 +
|
||||
+ sizeof(struct siginfo) + offsetof(struct asm_ucontext, uc_mcontext);
|
||||
+ f->ra = ((struct sigcontext *) f->sp)->sc_pc | RA_SIGRETURN;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
else
|
||||
switch (i >> 16)
|
||||
{
|
||||
@@ -319,6 +425,10 @@
|
||||
u = i & 0xFFFF;
|
||||
a |= SP_UPPER;
|
||||
break;
|
||||
+ case 0x8FBE:
|
||||
+ /* lw s8,##(sp) */
|
||||
+ m = i & 0xFFFF;
|
||||
+ break;
|
||||
case 0x8FBF:
|
||||
/* lw ra,##(sp) */
|
||||
p = i & 0xFFFF;
|
||||
@@ -326,9 +436,52 @@
|
||||
break;
|
||||
}
|
||||
f->ra += 4;
|
||||
+ /* Process branch instructions.
|
||||
+ */
|
||||
+ if (a & BR_COND)
|
||||
+ {
|
||||
+ if (f->ra >= b)
|
||||
+ {
|
||||
+ /* reached target of previous conditional branch */
|
||||
+ a &= ~BR_COND;
|
||||
+ b = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (a & BR_UNCOND)
|
||||
+ /* clear branch flag and process instruction in delay slot */
|
||||
+ a &= ~BR_UNCOND;
|
||||
+ else if (b != 0)
|
||||
+ {
|
||||
+ /* now follow the unconditional branch */
|
||||
+ if (b < f->ra)
|
||||
+ {
|
||||
+ /* avoid infinite loops */
|
||||
+ q = f->ra - 8;
|
||||
+ /* go back as far as possible */
|
||||
+ if (r < b)
|
||||
+ b = r;
|
||||
+ }
|
||||
+ f->ra = b;
|
||||
+ b = 0;
|
||||
+ }
|
||||
}
|
||||
if ((s == 0) && ((a & SP_LOWER) || (a & SP_UPPER)))
|
||||
s = (u << 16) | l;
|
||||
+#if SYSTEM == SYSTEM_LINUX
|
||||
+ if ((a & RA_NOFRAME) && !(a & RA_OFFSET) &&
|
||||
+ ((*((unsigned long *) (p - 8)) == 0x0320F809) ||
|
||||
+ (*((unsigned long *) (p - 8)) >> 16 == 0x0C10)))
|
||||
+ {
|
||||
+ /* jalr ra,t9 or jal ## */
|
||||
+ /* f->sp already set */
|
||||
+ f->ra = p;
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
+ if (a & SP_IN_FP)
|
||||
+ f->sp = f->fp;
|
||||
+ if (m > 0)
|
||||
+ f->fp = ((unsigned long *) f->sp)[m >> 2];
|
||||
if ((s > 0) && (i = ((unsigned long *) f->sp)[p >> 2]) &&
|
||||
((*((unsigned long *) (i - 8)) == 0x0320F809) ||
|
||||
(*((unsigned long *) (i - 8)) >> 16 == 0x0C10)))
|
||||
@@ -338,6 +491,19 @@
|
||||
f->ra = i;
|
||||
return 1;
|
||||
}
|
||||
+#if SYSTEM == SYSTEM_LINUX
|
||||
+ else if ((s > 0) && (i != 0) &&
|
||||
+ (*((unsigned long *) (i + 4)) == 0x0000000c) &&
|
||||
+ ((*((unsigned long *) i) == 0x24020000 + __NR_sigreturn) ||
|
||||
+ (*((unsigned long *) i) == 0x24020000 + __NR_rt_sigreturn)))
|
||||
+ {
|
||||
+ /* li v0,__NR_sigreturn or __NR_rt_sigreturn ; syscall */
|
||||
+ /* signal trampoline */
|
||||
+ f->sp += s;
|
||||
+ f->ra = i | RA_SIGTRAMP;
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
f->sp = f->ra = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -573,16 +739,14 @@
|
||||
}
|
||||
#endif /* TARGET */
|
||||
#else /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */
|
||||
-#if (TARGET == TARGET_UNIX && (ARCH == ARCH_IX86 || ARCH == ARCH_M68K || \
|
||||
- ARCH == ARCH_M88K || ARCH == ARCH_POWER || ARCH == ARCH_POWERPC || \
|
||||
- ARCH == ARCH_SPARC)) || ((TARGET == TARGET_WINDOWS || \
|
||||
- TARGET == TARGET_NETWARE) && ARCH == ARCH_IX86)
|
||||
- /* This section is not complete in any way for the OS / processor
|
||||
- * combinations it supports, as it is intended to be as portable as possible
|
||||
- * without writing in assembler. In particular, optimised code is likely
|
||||
- * to cause major problems for stack traversal on some platforms.
|
||||
- */
|
||||
#if TARGET == TARGET_UNIX
|
||||
+ /* On some systems, such as those using uClibc, the signal() function may
|
||||
+ * call memcpy() or other memory related functions, so we need to guard
|
||||
+ * against recursion here.
|
||||
+ */
|
||||
+ if (!recursive)
|
||||
+ {
|
||||
+ recursive = 1;
|
||||
#if MP_SIGINFO_SUPPORT
|
||||
i.sa_flags = 0;
|
||||
(void *) i.sa_handler = (void *) stackhandler;
|
||||
@@ -597,6 +761,15 @@
|
||||
__mp_newframe(p, p->first);
|
||||
else
|
||||
#endif /* TARGET */
|
||||
+#if (TARGET == TARGET_UNIX && (ARCH == ARCH_IX86 || ARCH == ARCH_M68K || \
|
||||
+ ARCH == ARCH_M88K || ARCH == ARCH_POWER || ARCH == ARCH_POWERPC || \
|
||||
+ ARCH == ARCH_SPARC)) || ((TARGET == TARGET_WINDOWS || \
|
||||
+ TARGET == TARGET_NETWARE) && ARCH == ARCH_IX86)
|
||||
+ /* This section is not complete in any way for the OS / processor
|
||||
+ * combinations it supports, as it is intended to be as portable as possible
|
||||
+ * without writing in assembler. In particular, optimised code is likely
|
||||
+ * to cause major problems for stack traversal on some platforms.
|
||||
+ */
|
||||
{
|
||||
if (p->frame == NULL)
|
||||
if (p->first == NULL)
|
||||
@@ -640,32 +813,10 @@
|
||||
r = 1;
|
||||
}
|
||||
}
|
||||
-#if TARGET == TARGET_UNIX
|
||||
-#if MP_SIGINFO_SUPPORT
|
||||
- sigaction(SIGBUS, &bushandler, NULL);
|
||||
- sigaction(SIGSEGV, &segvhandler, NULL);
|
||||
-#else /* MP_SIGINFO_SUPPORT */
|
||||
- signal(SIGBUS, bushandler);
|
||||
- signal(SIGSEGV, segvhandler);
|
||||
-#endif /* MP_SIGINFO_SUPPORT */
|
||||
-#endif /* TARGET */
|
||||
#elif TARGET == TARGET_UNIX && ARCH == ARCH_MIPS
|
||||
/* For the MIPS architecture we perform code reading to determine the
|
||||
* frame pointers and the return addresses.
|
||||
*/
|
||||
-#if MP_SIGINFO_SUPPORT
|
||||
- i.sa_flags = 0;
|
||||
- (void *) i.sa_handler = (void *) stackhandler;
|
||||
- sigfillset(&i.sa_mask);
|
||||
- sigaction(SIGBUS, &i, &bushandler);
|
||||
- sigaction(SIGSEGV, &i, &segvhandler);
|
||||
-#else /* MP_SIGINFO_SUPPORT */
|
||||
- bushandler = signal(SIGBUS, stackhandler);
|
||||
- segvhandler = signal(SIGSEGV, stackhandler);
|
||||
-#endif /* MP_SIGINFO_SUPPORT */
|
||||
- if (setjmp(environment))
|
||||
- __mp_newframe(p, p->first);
|
||||
- else
|
||||
{
|
||||
if (p->frame == NULL)
|
||||
unwind(&p->next);
|
||||
@@ -673,6 +824,10 @@
|
||||
{
|
||||
p->frame = (void *) p->next.sp;
|
||||
p->addr = (void *) (p->next.ra - 8);
|
||||
+#if SYSTEM == SYSTEM_LINUX
|
||||
+ if (p->next.ra & (RA_SIGTRAMP|RA_SIGRETURN))
|
||||
+ p->addr = (void *) (p->next.ra & ~3);
|
||||
+#endif /* SYSTEM */
|
||||
r = 1;
|
||||
}
|
||||
else
|
||||
@@ -681,6 +836,8 @@
|
||||
p->addr = NULL;
|
||||
}
|
||||
}
|
||||
+#endif /* TARGET && ARCH */
|
||||
+#if TARGET == TARGET_UNIX
|
||||
#if MP_SIGINFO_SUPPORT
|
||||
sigaction(SIGBUS, &bushandler, NULL);
|
||||
sigaction(SIGSEGV, &segvhandler, NULL);
|
||||
@@ -688,7 +845,9 @@
|
||||
signal(SIGBUS, bushandler);
|
||||
signal(SIGSEGV, segvhandler);
|
||||
#endif /* MP_SIGINFO_SUPPORT */
|
||||
-#endif /* TARGET && ARCH */
|
||||
+ recursive = 0;
|
||||
+ } /* if (!bushandler) */
|
||||
+#endif /* TARGET */
|
||||
#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */
|
||||
return r;
|
||||
}
|
||||
diff -ur mpatrol/src/stack.h mpatrol-uclibc/src/stack.h
|
||||
--- mpatrol/src/stack.h 2002-01-08 12:13:59.000000000 -0800
|
||||
+++ mpatrol-uclibc/src/stack.h 2006-06-07 15:12:58.000000000 -0700
|
||||
@@ -75,6 +75,7 @@
|
||||
typedef struct frameinfo
|
||||
{
|
||||
unsigned int sp; /* stack pointer */
|
||||
+ unsigned int fp; /* frame pointer (s8) */
|
||||
unsigned int ra; /* return address */
|
||||
}
|
||||
frameinfo;
|
||||
diff -urN mpatrol/src/symbol.c mpatrol-uclibc/src/symbol.c
|
||||
--- mpatrol/src/symbol.c 2002-01-08 12:13:59.000000000 -0800
|
||||
+++ mpatrol-uclibc/src/symbol.c 2006-05-24 15:43:04.000000000 -0700
|
||||
@@ -1157,7 +1157,7 @@
|
||||
__mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
|
||||
return 0;
|
||||
}
|
||||
- if (n == 0)
|
||||
+ if (n <= sizeof(asymbol *))
|
||||
{
|
||||
/* If we couldn't find the symbol table then it is likely that the file
|
||||
* has been stripped. However, if the file was dynamically linked then
|
||||
@@ -1172,7 +1172,7 @@
|
||||
__mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
|
||||
return 0;
|
||||
}
|
||||
- if (n == 0)
|
||||
+ if (n <= sizeof(asymbol *))
|
||||
{
|
||||
m = "missing symbol table";
|
||||
if (a != NULL)
|
||||
@@ -1893,6 +1893,17 @@
|
||||
l = (dynamiclink *) *((unsigned long *) d->d_un.d_ptr + 1);
|
||||
break;
|
||||
}
|
||||
+#if ARCH == ARCH_MIPS
|
||||
+ else if (d->d_tag == DT_MIPS_RLD_MAP)
|
||||
+ {
|
||||
+ /* MIPS elf has DT_MIPS_RLD_MAP instead of DT_DEBUG. */
|
||||
+ if (!d->d_un.d_ptr || !(*(unsigned long **) d->d_un.d_ptr))
|
||||
+ l = NULL;
|
||||
+ else
|
||||
+ l = (dynamiclink *) *((*(unsigned long **) d->d_un.d_ptr) + 1);
|
||||
+ break;
|
||||
+ }
|
||||
+#endif /* ARCH */
|
||||
/* We skip past the first item on the list since it represents the
|
||||
* executable file, but we may wish to record the name of the file
|
||||
* if we haven't already determined it.
|
208
package/mpatrol/mpatrol-unwindcache.patch
Normal file
208
package/mpatrol/mpatrol-unwindcache.patch
Normal file
@ -0,0 +1,208 @@
|
||||
Patch to improve MIPS call stack unwind performance by caching the results
|
||||
of code reading.
|
||||
by Dan Howell <dahowell@directv.com>
|
||||
|
||||
diff -urN mpatrol-uclibc/src/stack.c mpatrol-unwindcache/src/stack.c
|
||||
--- mpatrol-uclibc/src/stack.c 2006-06-22 15:39:04.000000000 -0700
|
||||
+++ mpatrol-unwindcache/src/stack.c 2006-06-22 15:42:20.000000000 -0700
|
||||
@@ -68,6 +68,7 @@
|
||||
#define ucontext asm_ucontext
|
||||
#include <asm/ucontext.h>
|
||||
#undef ucontext
|
||||
+#include "heap.h"
|
||||
#endif /* ARCH */
|
||||
#endif /* SYSTEM */
|
||||
#endif /* TARGET */
|
||||
@@ -280,6 +281,136 @@
|
||||
|
||||
#if !MP_BUILTINSTACK_SUPPORT && !MP_LIBRARYSTACK_SUPPORT
|
||||
#if TARGET == TARGET_UNIX && ARCH == ARCH_MIPS
|
||||
+/* Set up a tree to cache the results of code searching to determine the
|
||||
+ location of the return address for each code point encountered. */
|
||||
+
|
||||
+/* An unwind node belongs to a binary search tree of nodes, ordered by
|
||||
+ * code address, and contains call stack unwinding details for a given
|
||||
+ * code address. An internal index node stores details of a single memory
|
||||
+ * block allocated for unwind node slots.
|
||||
+ */
|
||||
+typedef union unwindnode
|
||||
+{
|
||||
+ struct
|
||||
+ {
|
||||
+ treenode node; /* internal tree node */
|
||||
+ void *block; /* pointer to block of memory */
|
||||
+ size_t size; /* size of block of memory */
|
||||
+ }
|
||||
+ index;
|
||||
+ struct
|
||||
+ {
|
||||
+ treenode node; /* tree node */
|
||||
+ long p; /* return address offset in the stack */
|
||||
+ long m; /* frame pointer offset in stack */
|
||||
+ long s; /* stack pointer offset from previous frame */
|
||||
+ unsigned long a; /* flags */
|
||||
+ }
|
||||
+ data;
|
||||
+}
|
||||
+unwindnode;
|
||||
+
|
||||
+/* An unwindhead holds the table of address node slots as well as the
|
||||
+ * internal list of memory blocks allocated for address node slots.
|
||||
+ */
|
||||
+typedef struct unwindhead
|
||||
+{
|
||||
+ heaphead heap; /* pointer to heap */
|
||||
+ slottable table; /* table of address nodes */
|
||||
+ treeroot itree; /* internal list of memory blocks */
|
||||
+ treeroot dtree; /* tree for sorting */
|
||||
+ size_t size; /* memory used by internal blocks */
|
||||
+ char init; /* initialization flag */
|
||||
+}
|
||||
+unwindhead;
|
||||
+
|
||||
+static unwindhead unwindcache;
|
||||
+
|
||||
+/* Initialise the fields of an unwindhead so that there are no allocated,
|
||||
+ * freed or free blocks.
|
||||
+ */
|
||||
+
|
||||
+static
|
||||
+void
|
||||
+newunwindcache(void)
|
||||
+{
|
||||
+ struct { char x; unwindnode y; } z;
|
||||
+ long n;
|
||||
+
|
||||
+ __mp_newheap(&unwindcache.heap);
|
||||
+ /* Determine the minimum alignment for an unwind node on this
|
||||
+ * system and force the alignment to be a power of two. This
|
||||
+ * information is used when initialising the slot table.
|
||||
+ */
|
||||
+ n = (char *) &z.y - &z.x;
|
||||
+ __mp_newslots(&unwindcache.table, sizeof(unwindnode), __mp_poweroftwo(n));
|
||||
+ __mp_newtree(&unwindcache.itree);
|
||||
+ __mp_newtree(&unwindcache.dtree);
|
||||
+ unwindcache.size = 0;
|
||||
+ unwindcache.init = 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Forget all unwind information.
|
||||
+ */
|
||||
+
|
||||
+static
|
||||
+void
|
||||
+deleteunwindcache(void)
|
||||
+{
|
||||
+ /* We don't need to explicitly free any memory as this is dealt with
|
||||
+ * at a lower level by the heap manager.
|
||||
+ */
|
||||
+ __mp_deleteheap(&unwindcache.heap);
|
||||
+ unwindcache.table.free = NULL;
|
||||
+ unwindcache.table.size = 0;
|
||||
+ __mp_newtree(&unwindcache.itree);
|
||||
+ __mp_newtree(&unwindcache.dtree);
|
||||
+ unwindcache.size = 0;
|
||||
+ unwindcache.init = 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Allocate a new unwind node.
|
||||
+ */
|
||||
+
|
||||
+static
|
||||
+unwindnode *
|
||||
+getunwindnode(void)
|
||||
+{
|
||||
+ unwindnode *n;
|
||||
+ heapnode *p;
|
||||
+
|
||||
+ /* If we have no more allocation node slots left then we must allocate
|
||||
+ * some more memory for them. An extra MP_ALLOCFACTOR pages of memory
|
||||
+ * should suffice.
|
||||
+ */
|
||||
+ if ((n = (unwindnode *) __mp_getslot(&unwindcache.table)) == NULL)
|
||||
+ {
|
||||
+ if ((p = __mp_heapalloc(&unwindcache.heap, unwindcache.heap.memory.page * MP_ALLOCFACTOR,
|
||||
+ unwindcache.table.entalign, 1)) == NULL)
|
||||
+ return NULL;
|
||||
+ __mp_initslots(&unwindcache.table, p->block, p->size);
|
||||
+ n = (unwindnode *) __mp_getslot(&unwindcache.table);
|
||||
+ __mp_treeinsert(&unwindcache.itree, &n->index.node, (unsigned long) p->block);
|
||||
+ n->index.block = p->block;
|
||||
+ n->index.size = p->size;
|
||||
+ unwindcache.size += p->size;
|
||||
+ n = (unwindnode *) __mp_getslot(&unwindcache.table);
|
||||
+ }
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+/* Search for the unwind node associated with a given address.
|
||||
+ */
|
||||
+static
|
||||
+unwindnode *
|
||||
+findunwindnode(unsigned long p)
|
||||
+{
|
||||
+ return (unwindnode *) __mp_search(unwindcache.dtree.root, p);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Determine the stack pointer and return address of the previous stack frame
|
||||
* by performing code reading.
|
||||
*/
|
||||
@@ -289,8 +420,9 @@
|
||||
unwind(frameinfo *f)
|
||||
{
|
||||
long p, m, s;
|
||||
- unsigned long a, i, q, t, b, r;
|
||||
+ unsigned long a, i, q, t, b, r, k;
|
||||
unsigned short l, u;
|
||||
+ unwindnode *n = NULL;
|
||||
|
||||
s = -1;
|
||||
p = m = 0;
|
||||
@@ -322,7 +454,23 @@
|
||||
#endif
|
||||
/* Save initial code-reading starting point.
|
||||
*/
|
||||
- r = f->ra;
|
||||
+ r = k = f->ra;
|
||||
+ /* Create the cache if not yet created.
|
||||
+ */
|
||||
+ if (!unwindcache.init)
|
||||
+ {
|
||||
+ newunwindcache();
|
||||
+ __mp_atexit(deleteunwindcache);
|
||||
+ }
|
||||
+ if ((n = findunwindnode(f->ra)) != NULL)
|
||||
+ {
|
||||
+ /* We've been here before, so get the cached information.
|
||||
+ */
|
||||
+ p = n->data.p;
|
||||
+ m = n->data.m;
|
||||
+ s = n->data.s;
|
||||
+ a = n->data.a;
|
||||
+ }
|
||||
/* Search for the return address offset in the stack frame.
|
||||
*/
|
||||
while (!((a & RA_OFFSET) && (a & SP_OFFSET)) && (f->ra < q))
|
||||
@@ -478,6 +626,19 @@
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
+ if (n == NULL)
|
||||
+ {
|
||||
+ if ((n = getunwindnode()) != NULL)
|
||||
+ {
|
||||
+ /* Cache the information we just got in the tree.
|
||||
+ */
|
||||
+ n->data.p = p;
|
||||
+ n->data.m = m;
|
||||
+ n->data.s = s;
|
||||
+ n->data.a = a;
|
||||
+ __mp_treeinsert(&unwindcache.dtree, &n->data.node, k);
|
||||
+ }
|
||||
+ }
|
||||
if (a & SP_IN_FP)
|
||||
f->sp = f->fp;
|
||||
if (m > 0)
|
91
package/mpatrol/mpatrol.mk
Normal file
91
package/mpatrol/mpatrol.mk
Normal file
@ -0,0 +1,91 @@
|
||||
#############################################################
|
||||
#
|
||||
# mpatrol
|
||||
#
|
||||
#############################################################
|
||||
MPATROL_VER:=1.4.8
|
||||
MPATROL_SOURCE:=mpatrol_$(MPATROL_VER).tar.gz
|
||||
MPATROL_SITE:=http://www.cbmamiga.demon.co.uk/mpatrol/files
|
||||
MPATROL_DIR:=$(BUILD_DIR)/mpatrol
|
||||
MPATROL_CAT:=zcat
|
||||
MPATROL_BINARY:=mleak
|
||||
MPATROL_BUILD_DIR:=$(MPATROL_DIR)/build/unix
|
||||
MPATROL_TARGET_BINARY:=usr/bin/mleak
|
||||
|
||||
# Pick a symbol library to use. We have a choice of GDB BFD, binutils BFD, or libelf.
|
||||
# If one of them is already being built, then use it, otherwise, default to GDB
|
||||
ifeq ($(BR2_PACKAGE_GDB),y)
|
||||
MPATROL_SYMBOL_LIBS:=-L$(GDB_TARGET_DIR)/bfd -lbfd -L$(GDB_TARGET_DIR)/libiberty -liberty
|
||||
MPATROL_SYMBOL_INCS:=-I$(GDB_TARGET_DIR)/bfd -I$(GDB_DIR)/include -DMP_SYMBOL_LIBS=
|
||||
MPATROL_SYMBOL_DEPS:=gdb_target
|
||||
else
|
||||
ifeq ($(BR2_PACKAGE_GCC_TARGET),y)
|
||||
MPATROL_SYMBOL_LIBS:=-L$(BINUTILS_DIR2)/bfd -lbfd -L$(BINUTILS_DIR2)/libiberty -liberty
|
||||
MPATROL_SYMBOL_INCS:=-I$(BINUTILS_DIR2)/bfd -I$(BINUTILS_DIR)/include -DMP_SYMBOL_LIBS=
|
||||
MPATROL_SYMBOL_DEPS:=binutils_target
|
||||
else
|
||||
ifeq ($(BR2_PACKAGE_LIBELF),y)
|
||||
MPATROL_SYMBOL_LIBS:=-L$(LIBELF_DIR)/lib -lelf
|
||||
MPATROL_SYMBOL_INCS:=-I$(STAGING_DIR)/usr/include -DFORMAT=FORMAT_ELF32 -DMP_SYMBOL_LIBS=
|
||||
MPATROL_SYMBOL_DEPS:=libelf
|
||||
else # use GDB by default
|
||||
MPATROL_SYMBOL_LIBS:=-L$(GDB_TARGET_DIR)/bfd -lbfd -L$(GDB_TARGET_DIR)/libiberty -liberty
|
||||
MPATROL_SYMBOL_INCS:=-I$(GDB_TARGET_DIR)/bfd -I$(GDB_DIR)/include -DMP_SYMBOL_LIBS=
|
||||
MPATROL_SYMBOL_DEPS:=gdb_target
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DL_DIR)/$(MPATROL_SOURCE):
|
||||
$(WGET) -P $(DL_DIR) $(MPATROL_SITE)/$(MPATROL_SOURCE)
|
||||
|
||||
mpatrol-source: $(DL_DIR)/$(MPATROL_SOURCE)
|
||||
|
||||
$(MPATROL_DIR)/.unpacked: $(DL_DIR)/$(MPATROL_SOURCE)
|
||||
$(MPATROL_CAT) $(DL_DIR)/$(MPATROL_SOURCE) | tar -C $(BUILD_DIR) $(TAR_OPTIONS) -
|
||||
toolchain/patch-kernel.sh $(MPATROL_DIR) package/mpatrol mpatrol\*.patch
|
||||
$(SED) '/LD.*MPTOBJS/s,$$, $$(LDLIBS),' $(MPATROL_BUILD_DIR)/Makefile
|
||||
$(SED) '/CFLAGS.*=/s,$$, $$(IFLAGS),' $(MPATROL_BUILD_DIR)/Makefile
|
||||
touch $(MPATROL_DIR)/.unpacked
|
||||
|
||||
$(MPATROL_BUILD_DIR)/$(MPATROL_BINARY): $(MPATROL_DIR)/.unpacked
|
||||
$(MAKE) CC=$(TARGET_CROSS)gcc AR=$(TARGET_CROSS)ar LD=$(TARGET_CROSS)gcc \
|
||||
IFLAGS="-g $(MPATROL_SYMBOL_INCS) -DMP_USE_ATEXIT=1 -DMP_SIGINFO_SUPPORT=1" \
|
||||
LDLIBS="$(MPATROL_SYMBOL_LIBS)" -C $(MPATROL_BUILD_DIR) all
|
||||
|
||||
$(TARGET_DIR)/$(MPATROL_TARGET_BINARY): $(MPATROL_BUILD_DIR)/$(MPATROL_BINARY)
|
||||
mkdir -p $(TARGET_DIR)/usr/lib
|
||||
(cd $(MPATROL_BUILD_DIR); \
|
||||
cp -dpf lib*.so* $(TARGET_DIR)/usr/lib; \
|
||||
cp -dpf mpatrol mprof mptrace mleak $(TARGET_DIR)/usr/bin)
|
||||
if [ ! -e $(TARGET_DIR)/lib/libpthread.so ] ; then \
|
||||
ln -sf libpthread.so.0 $(TARGET_DIR)/lib/libpthread.so; fi
|
||||
(cd $(MPATROL_DIR); \
|
||||
cp -dpf bin/mp* bin/hexwords $(TARGET_DIR)/usr/bin; \
|
||||
cp -dpf src/mp*.h $(STAGING_DIR)/include; \
|
||||
mkdir -p $(STAGING_DIR)/include/mpatrol; \
|
||||
cp -dpf tools/*.h $(STAGING_DIR)/include/mpatrol)
|
||||
touch $(TARGET_DIR)/$(MPATROL_TARGET_BINARY)
|
||||
|
||||
mpatrol: uclibc $(MPATROL_SYMBOL_DEPS) $(TARGET_DIR)/$(MPATROL_TARGET_BINARY)
|
||||
|
||||
mpatrol-clean:
|
||||
(cd $(TARGET_DIR)/usr/lib; rm -f libmpatrol* libmpalloc*)
|
||||
(cd $(TARGET_DIR)/usr/bin; \
|
||||
rm -f mpatrol mprof mptrace mleak mpsym mpedit hexwords)
|
||||
(cd $(STAGING_DIR)/include; \
|
||||
rm -rf mpatrol.h mpalloc.h mpdebug.h mpatrol)
|
||||
$(MAKE) -C $(MPATROL_DIR)/build/unix clobber
|
||||
|
||||
mpatrol-dirclean:
|
||||
rm -rf $(MPATROL_DIR)
|
||||
|
||||
|
||||
#############################################################
|
||||
#
|
||||
# Toplevel Makefile options
|
||||
#
|
||||
#############################################################
|
||||
ifeq ($(strip $(BR2_PACKAGE_MPATROL)),y)
|
||||
TARGETS+=mpatrol
|
||||
endif
|
Loading…
Reference in New Issue
Block a user