From a7748b2f132b1e7c1a87a5f3d80cb64e46ce5219 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Tue, 12 Dec 2006 22:18:15 +0000 Subject: add mpatrol package --- package/mpatrol/mpatrol-uclibc.patch | 552 +++++++++++++++++++++++++++++++++++ 1 file changed, 552 insertions(+) create mode 100644 package/mpatrol/mpatrol-uclibc.patch (limited to 'package/mpatrol/mpatrol-uclibc.patch') diff --git a/package/mpatrol/mpatrol-uclibc.patch b/package/mpatrol/mpatrol-uclibc.patch new file mode 100644 index 000000000..aab70a876 --- /dev/null +++ b/package/mpatrol/mpatrol-uclibc.patch @@ -0,0 +1,552 @@ +Patches for mpatrol to support uClibc and MIPS full call stack tracing +by Dan Howell + +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 + #include +-#if MP_SIGINFO_SUPPORT ++#if MP_SIGINFO_SUPPORT && SYSTEM != SYSTEM_LINUX + #include + #endif /* MP_SIGINFO_SUPPORT */ + #include +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 + #include + #if TARGET == TARGET_UNIX +-#if MP_SIGINFO_SUPPORT ++#if MP_SIGINFO_SUPPORT && SYSTEM != SYSTEM_LINUX + #include + #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 +-#if MP_SIGINFO_SUPPORT ++#if MP_SIGINFO_SUPPORT && SYSTEM != SYSTEM_LINUX + #include + #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 ++/* 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 ++#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. -- cgit v1.2.3