⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stack.c

📁 debug source code under unix platform.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * mpatrol * A library for controlling and tracing dynamic memory allocations. * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA. *//* * Call stacks.  The method for traversing a function call stack is * dependent on both the operating system and processor architecture. * The most correct way of doing this would be to perform code-reading * in order to ascertain the return address for a function.  However, * some operating systems provide support functions for doing this. */#include "stack.h"#include "memory.h"#include "machine.h"#include <string.h>#if !MP_BUILTINSTACK_SUPPORT#if MP_LIBRARYSTACK_SUPPORT#if TARGET == TARGET_UNIX#if SYSTEM == SYSTEM_IRIX#include <exception.h>#include <ucontext.h>#elif SYSTEM == SYSTEM_TRU64#include <excpt.h>#endif /* SYSTEM */#elif TARGET == TARGET_WINDOWS#include <setjmp.h>#endif /* TARGET */#else /* MP_LIBRARYSTACK_SUPPORT */#if TARGET == TARGET_UNIX#include <setjmp.h>#if MP_SIGINFO_SUPPORT#include <siginfo.h>#endif /* MP_SIGINFO_SUPPORT */#if SYSTEM == SYSTEM_DRSNX || SYSTEM == SYSTEM_SOLARIS#if ARCH == ARCH_SPARC#include <ucontext.h>#ifndef R_SP#define R_SP REG_SP#endif /* R_SP */#endif /* ARCH */#endif /* SYSTEM */#endif /* TARGET */#endif /* MP_LIBRARYSTACK_SUPPORT */#endif /* MP_BUILTINSTACK_SUPPORT */#if MP_IDENT_SUPPORT#ident "$Id: stack.c,v 1.30 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *stack_id = "$Id: stack.c,v 1.30 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT */#if MP_BUILTINSTACK_SUPPORT/* This method of call stack traversal uses two special builtin functions in * gcc called __builtin_frame_address() and __builtin_return_address().  Both * of these functions take the number of stack frames to traverse as a parameter * but this must currently be a constant, hence the reason for all of the * following complicated macros, and for the fact that there must currently * be a maximum number of stack frames to traverse that is determined at compile * time.  However, it may be the case that this method is slightly better than * manually traversing the call stack.  Perhaps in the future gcc might allow * these functions to accept non-constant parameters... */#define frameaddress(v, n) (v[n] = __builtin_frame_address(n))#define frameaddress1(v) frameaddress(v, 0)#define frameaddress2(v) frameaddress1(v) && frameaddress(v, 1)#define frameaddress3(v) frameaddress2(v) && frameaddress(v, 2)#define frameaddress4(v) frameaddress3(v) && frameaddress(v, 3)#define frameaddress5(v) frameaddress4(v) && frameaddress(v, 4)#define frameaddress6(v) frameaddress5(v) && frameaddress(v, 5)#define frameaddress7(v) frameaddress6(v) && frameaddress(v, 6)#define frameaddress8(v) frameaddress7(v) && frameaddress(v, 7)#define frameaddressn(v, w, n) if (frameaddress ## n(v)) \                                   w = __builtin_frame_address(n)#define frameaddresses(v, w, n) frameaddressn(v, w, n)#define returnaddress(v, n) (v[n] = __builtin_return_address(n))#define returnaddress1(v) returnaddress(v, 0)#define returnaddress2(v) returnaddress1(v) && returnaddress(v, 1)#define returnaddress3(v) returnaddress2(v) && returnaddress(v, 2)#define returnaddress4(v) returnaddress3(v) && returnaddress(v, 3)#define returnaddress5(v) returnaddress4(v) && returnaddress(v, 4)#define returnaddress6(v) returnaddress5(v) && returnaddress(v, 5)#define returnaddress7(v) returnaddress6(v) && returnaddress(v, 6)#define returnaddress8(v) returnaddress7(v) && returnaddress(v, 7)#define returnaddressn(v, w, n) if (returnaddress ## n(v)) \                                    w = __builtin_return_address(n)#define returnaddresses(v, w, n) returnaddressn(v, w, n)#if MP_MAXSTACK > 8#error not enough frameaddress() and returnaddress() macros#endif /* MP_MAXSTACK */#elif !MP_LIBRARYSTACK_SUPPORT#if TARGET == TARGET_UNIX && ARCH == ARCH_MIPS/* These macros are used by the unwind() function for setting flags when * certain instructions are seen. */#define RA_OFFSET 1 /* return address offset has been set */#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 */#endif /* TARGET && ARCH */#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */#ifdef __cplusplusextern "C"{#endif /* __cplusplus */#if !MP_BUILTINSTACK_SUPPORT && TARGET == TARGET_UNIX#if MP_LIBRARYSTACK_SUPPORT#if SYSTEM == SYSTEM_HPUX/* The following function is defined in the HP/UX traceback library (libcl). */int U_get_previous_frame(frameinfo *, frameinfo *);#elif SYSTEM == SYSTEM_IRIX || SYSTEM == SYSTEM_TRU64/* The unwind() function in the IRIX and Tru64 exception-handling libraries * (libexc) may call malloc() and several memory operation functions, so we * need to guard against this by preventing recursive calls. */static unsigned char recursive;#if SYSTEM == SYSTEM_TRU64MP_API char *__mp_symbol(void *);#endif /* SYSTEM */#endif /* SYSTEM */#else /* MP_LIBRARYSTACK_SUPPORT */static jmp_buf environment;#if MP_SIGINFO_SUPPORTstatic struct sigaction bushandler;static struct sigaction segvhandler;#else /* MP_SIGINFO_SUPPORT */static void (*bushandler)(int);static void (*segvhandler)(int);#endif /* MP_SIGINFO_SUPPORT */#endif /* MP_LIBRARYSTACK_SUPPORT */#endif /* MP_BUILTINSTACK_SUPPORT && TARGET *//* Initialise the fields of a stackinfo structure. */MP_GLOBALvoid__mp_newframe(stackinfo *s, void *f){    s->frame = s->addr = NULL;#if MP_BUILTINSTACK_SUPPORT    for (s->index = 0; s->index < MP_MAXSTACK; s->index++)        s->frames[s->index] = s->addrs[s->index] = NULL;    s->index = 0;#elif MP_LIBRARYSTACK_SUPPORT#if TARGET == TARGET_UNIX#if SYSTEM == SYSTEM_HPUX    __mp_memset(&s->next, 0, sizeof(frameinfo));#elif SYSTEM == SYSTEM_IRIX || SYSTEM == SYSTEM_TRU64    __mp_memset(&s->next, 0, sizeof(struct sigcontext));#endif /* SYSTEM */#elif TARGET == TARGET_WINDOWS    __mp_memset(&s->next, 0, sizeof(STACKFRAME));#endif /* TARGET */#else /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */#if TARGET == TARGET_UNIX && ARCH == ARCH_MIPS    s->next.sp = s->next.ra = 0;#else /* TARGET && ARCH */    s->next = NULL;#endif /* TARGET && ARCH */#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */    s->first = f;}#if !MP_BUILTINSTACK_SUPPORT && !MP_LIBRARYSTACK_SUPPORT && \    TARGET == TARGET_UNIX/* Handles any signals that result from illegal memory accesses whilst * traversing the call stack. */staticvoidstackhandler(int s){    longjmp(environment, 1);}#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT && TARGET */#if !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)/* Obtain the return address for the specified stack frame handle. */staticunsigned long *getaddr(unsigned long *p){    unsigned long *a;    /* This function relies heavily on the stack frame format of supported     * OS / processor combinations.  A better way to determine the return     * address would be to perform code reading, but on CISC processors this     * could be a nightmare.     */#if ARCH == ARCH_IX86 || ARCH == ARCH_M68K || ARCH == ARCH_M88K    a = (unsigned long *) *(p + 1);#elif ARCH == ARCH_POWER || ARCH == ARCH_POWERPC    a = (unsigned long *) *(p + 2);#elif ARCH == ARCH_SPARC    if (*p == 0)        a = NULL;#if ENVIRON == ENVIRON_64    else if (a = (unsigned long *) *((unsigned long *) (*p + 0x7FF) + 15))#else /* ENVIRON */    else if (a = (unsigned long *) *((unsigned long *) *p + 15))#endif /* ENVIRON */        a += 2;#endif /* ARCH */    return a;}#endif /* TARGET && ARCH */#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */#if !MP_BUILTINSTACK_SUPPORT && !MP_LIBRARYSTACK_SUPPORT#if TARGET == TARGET_UNIX && ARCH == ARCH_MIPS/* Determine the stack pointer and return address of the previous stack frame * by performing code reading. */staticintunwind(frameinfo *f){    long p, s;    unsigned long a, i, q;    unsigned short l, u;    s = -1;    p = 0;    q = 0xFFFFFFFF;    l = u = 0;    a = 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->ra = __mp_returnaddress();    }    /* Search for the return address offset in the stack frame.     */    while (!((a & RA_OFFSET) && (a & SP_OFFSET)) && (f->ra < q))    {        i = *((unsigned long *) f->ra);        if (i == 0x03E00008)        {            /* jr ra */            q = f->ra + 8;        }        else if (i == 0x03A1E821)        {            /* addu sp,sp,at */            s = 0;            a |= SP_OFFSET;        }        else            switch (i >> 16)            {              case 0x27BD:                /* addiu sp,sp,## */                s = i & 0xFFFF;                a |= SP_OFFSET;                break;              case 0x3401:                /* ori at,zero,## */                l = i & 0xFFFF;                u = 0;                a |= SP_LOWER;                break;              case 0x3421:                /* ori at,at,## */                l = i & 0xFFFF;                a |= SP_LOWER;                break;              case 0x3C01:                /* lui at,## */                l = 0;                u = i & 0xFFFF;                a |= SP_UPPER;                break;              case 0x8FBF:                /* lw ra,##(sp) */                p = i & 0xFFFF;                a |= RA_OFFSET;                break;            }        f->ra += 4;    }    if ((s == 0) && ((a & SP_LOWER) || (a & SP_UPPER)))        s = (u << 16) | l;    if ((s > 0) && (i = ((unsigned long *) f->sp)[p >> 2]) &&        ((*((unsigned long *) (i - 8)) == 0x0320F809) ||         (*((unsigned long *) (i - 8)) >> 16 == 0x0C10)))    {        /* jalr ra,t9 or jal ## */        f->sp += s;        f->ra = i;        return 1;    }    f->sp = f->ra = 0;    return 0;}#endif /* TARGET && ARCH */#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */#if !MP_BUILTINSTACK_SUPPORT && !MP_LIBRARYSTACK_SUPPORT && \    TARGET == TARGET_UNIX#if ARCH == ARCH_SPARC

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -