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

📄 signals.c

📁 debug source code under unix platform.
💻 C
字号:
/* * 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. *//* * Signal-handling.  The setting of signal-handlers and their actions * is controlled from this module. */#include "signals.h"#include "diag.h"#if MP_THREADS_SUPPORT#include "mutex.h"#endif /* MP_THREADS_SUPPORT */#include "inter.h"#include <stdio.h>#include <stdlib.h>#include <signal.h>#if TARGET == TARGET_UNIX#if MP_SIGINFO_SUPPORT#include <siginfo.h>#endif /* MP_SIGINFO_SUPPORT */#elif TARGET == TARGET_WINDOWS#include <windows.h>#endif /* TARGET */#if MP_IDENT_SUPPORT#ident "$Id: signals.c,v 1.26 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *signals_id = "$Id: signals.c,v 1.26 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT */#ifdef __cplusplusextern "C"{#endif /* __cplusplus *//* The type of the parameter that is passed to the signal() function. */typedef void (*handlerfunction)(int);#if TARGET == TARGET_UNIX || TARGET == TARGET_WINDOWS/* Handles any signals that result from illegal memory accesses. */#if TARGET == TARGET_UNIX#if MP_SIGINFO_SUPPORTstaticvoidsignalhandler(int s, siginfo_t *n, void *p)#else /* MP_SIGINFO_SUPPORT */#if SYSTEM == SYSTEM_AIX || SYSTEM == SYSTEM_FREEBSD || \    SYSTEM == SYSTEM_IRIX || SYSTEM == SYSTEM_LINUX || \    SYSTEM == SYSTEM_LYNXOS || SYSTEM == SYSTEM_NETBSD || \    SYSTEM == SYSTEM_OPENBSD || SYSTEM == SYSTEM_SUNOS#if SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_NETBSD || \    SYSTEM == SYSTEM_OPENBSD || SYSTEM == SYSTEM_SUNOSstaticvoidsignalhandler(int s, int c, struct sigcontext *n, void *f)#elif SYSTEM == SYSTEM_LINUX && ARCH == ARCH_IX86staticvoidsignalhandler(int s, struct sigcontext n)#else /* SYSTEM && ARCH */staticvoidsignalhandler(int s, int c, struct sigcontext *n)#endif /* SYSTEM && ARCH */#else /* SYSTEM */staticvoidsignalhandler(int s)#endif /* SYSTEM */#endif /* MP_SIGINFO_SUPPORT */#elif TARGET == TARGET_WINDOWSstaticlong __stdcallsignalhandler(EXCEPTION_POINTERS *e)#endif /* TARGET */{    infohead *h;    allocnode *t;    void *a;#if TARGET == TARGET_WINDOWS    EXCEPTION_RECORD *r;#endif /* TARGET */    stackinfo i;#if TARGET == TARGET_WINDOWS    /* This exception handler will catch all kinds of exceptions, but the     * only one we are interested in is an access violation, so we return     * control to the system to decide what to do in all other cases.     */    r = e->ExceptionRecord;    if (r->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)        return EXCEPTION_CONTINUE_SEARCH;#endif /* TARGET */#if MP_THREADS_SUPPORT    /* Attempt to lock the library data structures if we are thread-safe.     * Hopefully this will never result in a deadlock since we should block     * until all other threads have finished manipulating memory allocations.     */    __mp_lockmutex(MT_MAIN);#endif /* MP_THREADS_SUPPORT */    h = __mp_memhead();    h->recur++;    __mp_printsummary(h);#if TARGET == TARGET_UNIX#if MP_SIGINFO_SUPPORT && MP_WATCH_SUPPORT    /* If we received a TRAP signal then we should only say that it is an     * illegal memory access if it is a watch point error.  Otherwise we     * just do the default and abort the process.     */    if ((s == SIGTRAP) && (n != NULL) && (n->si_code != TRAP_RWATCH) &&        (n->si_code != TRAP_WWATCH) && (n->si_code != TRAP_XWATCH))    {        h->fini = 1;        __mp_abort();    }#endif /* MP_SIGINFO_SUPPORT && MP_WATCH_SUPPORT */#endif /* TARGET */    __mp_diag("\n");#if TARGET == TARGET_UNIX#if MP_SIGINFO_SUPPORT || SYSTEM == SYSTEM_AIX || SYSTEM == SYSTEM_FREEBSD || \    SYSTEM == SYSTEM_IRIX || SYSTEM == SYSTEM_LINUX || \    SYSTEM == SYSTEM_LYNXOS || SYSTEM == SYSTEM_NETBSD || \    SYSTEM == SYSTEM_OPENBSD || SYSTEM == SYSTEM_SUNOS#if MP_SIGINFO_SUPPORT    if ((n != NULL) && (n->si_code > 0))    {        /* With the siginfo_t structure we can determine which address         * caused the illegal memory access.  This is not always guaranteed         * to be the exact byte location, but it is at least guaranteed that         * it will be on the same page which will suffice for our purposes.         */        a = (void *) n->si_addr;#else /* MP_SIGINFO_SUPPORT */#if SYSTEM == SYSTEM_LINUX && ARCH == ARCH_IX86    if (&n != NULL)#else /* SYSTEM && ARCH */    if (n != NULL)#endif /* SYSTEM && ARCH */    {        /* With systems that do not contain support for passing the siginfo_t         * structure to a signal handler we need to use some other form of         * trickery.  Luckily, on most UNIX systems a sigcontext parameter         * is passed on the stack to all signal handlers which we can then         * use to decode the address that caused the illegal memory access.         */        a = NULL;#if SYSTEM == SYSTEM_AIX        a = (void *) n->sc_jmpbuf.jmp_context.o_vaddr;#elif SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_NETBSD || \      SYSTEM == SYSTEM_OPENBSD || SYSTEM == SYSTEM_SUNOS        a = f;#elif SYSTEM == SYSTEM_IRIX        a = (void *) ((long) n->sc_badvaddr);#elif SYSTEM == SYSTEM_LINUX#if ARCH == ARCH_ALPHA        a = (char *) n->sc_regs[(*((unsigned int *) n->sc_pc) >> 16) & 0x1F] +            ((*((unsigned int *) n->sc_pc) << 16) >> 16);#elif ARCH == ARCH_IX86        a = (void *) n.cr2;#elif ARCH == ARCH_M68K        switch ((n->sc_formatvec >> 12) & 0x0F)        {          case 4:            /* 68060 */            a = (void *) ((unsigned long *) (n + 1))[0];            break;          case 7:            /* 68040 */            a = (void *) ((unsigned long *) (n + 1))[3];            break;          case 10:          case 11:          default:            /* 68020/68030 */            a = (void *) ((unsigned long *) (n + 1))[2];            break;        }#endif /* ARCH */#elif SYSTEM == SYSTEM_LYNXOS#if ARCH == ARCH_IX86        a = (void *) n->eax;#elif ARCH == ARCH_POWER || ARCH == ARCH_POWERPC        if (n->fpscr < 0x4000)            a = (void *) n->fpscr;        else            a = (void *) (n->fpscr - ((n->fpscr & 7) << 1) + 7);#endif /* ARCH */#endif /* SYSTEM */#endif /* MP_SIGINFO_SUPPORT */        __mp_error(ET_ILLMEM, AT_MAX, NULL, 0, "illegal memory access at "                   "address " MP_POINTER, a);        if (t = __mp_findnode(&h->alloc, a, 1))            if (t->info != NULL)                __mp_printalloc(&h->syms, t);            else            {                __mp_diag("    within free block " MP_POINTER " (", t->block);                __mp_printsize(t->size);                __mp_diag(")\n");            }        else            __mp_diag("    " MP_POINTER " not in heap\n", a);    }    else#endif /* MP_SIGINFO_SUPPORT && SYSTEM */        __mp_error(ET_ILLMEM, AT_MAX, NULL, 0, "illegal memory access");    /* Obtain the call stack so that we can tell where the illegal memory     * access came from.  This relies on the assumption that the stack area     * for the signal handler is the same as the stack area for the main     * process.     */    __mp_newframe(&i, NULL);    if (__mp_getframe(&i) && __mp_getframe(&i) && __mp_getframe(&i))    {        __mp_diag("\n    call stack\n");        __mp_printstack(&h->syms, &i);    }#elif TARGET == TARGET_WINDOWS    /* The exception information provided for access violations allows us to     * determine the address of the violation and whether an attempt was made     * to read to or write from that address.     */    a = (void *) r->ExceptionInformation[1];    if (r->ExceptionInformation[0])        __mp_error(ET_ILLMEM, AT_MAX, NULL, 0, "illegal memory write at "                   "address " MP_POINTER, a);    else        __mp_error(ET_ILLMEM, AT_MAX, NULL, 0, "illegal memory read at "                   "address " MP_POINTER, a);    if (t = __mp_findnode(&h->alloc, a, 1))        if (t->info != NULL)            __mp_printalloc(&h->syms, t);        else        {            __mp_diag("    within free block " MP_POINTER " (", t->block);            __mp_printsize(t->size);            __mp_diag(")\n");        }    else        __mp_diag("    " MP_POINTER " not in heap\n", a);    /* Unfortunately, the call stack where the access violation came from     * is not linked to the stack frame of this function.  Therefore, we     * need to invoke the __mp_newframe() function with the proper frame     * pointer and explicitly display the first frame as well.     */#if !MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT    __mp_newframe(&i, (void *) e->ContextRecord);#else /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */    __mp_newframe(&i, (void *) e->ContextRecord->Ebp);#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */    if (__mp_getframe(&i))    {        a = (void *) e->ContextRecord->Eip;        __mp_diag("\n    call stack\n");        __mp_diag("\t" MP_POINTER " ", a);        __mp_printsymbol(&h->syms, a);        __mp_diag("\n");        __mp_printstack(&h->syms, &i);    }#endif /* TARGET */    h->fini = 1;    __mp_abort();#if TARGET == TARGET_WINDOWS    /* This line of code will not be executed due to the call to __mp_abort()     * on the previous line, but exists to suppress compiler warnings.     */    return EXCEPTION_CONTINUE_SEARCH;#endif /* TARGET */}#endif /* TARGET *//* Initialise a sighead structure. */MP_GLOBALvoid__mp_initsignals(sighead *s){#if TARGET == TARGET_UNIX#if MP_SIGINFO_SUPPORT    struct sigaction i;#endif /* MP_SIGINFO_SUPPORT */#endif /* TARGET */#if TARGET == TARGET_UNIX#if MP_SIGINFO_SUPPORT    i.sa_flags = SA_SIGINFO;    (void *) i.sa_handler = (void *) signalhandler;    sigfillset(&i.sa_mask);    sigaction(SIGBUS, &i, NULL);    sigaction(SIGSEGV, &i, NULL);#if MP_WATCH_SUPPORT    sigaction(SIGTRAP, &i, NULL);#endif /* MP_WATCH_SUPPORT */#else /* MP_SIGINFO_SUPPORT */    signal(SIGBUS, (handlerfunction) signalhandler);    signal(SIGSEGV, (handlerfunction) signalhandler);#if MP_WATCH_SUPPORT    signal(SIGTRAP, (handlerfunction) signalhandler);#endif /* MP_WATCH_SUPPORT */#endif /* MP_SIGINFO_SUPPORT */#elif TARGET == TARGET_WINDOWS    SetUnhandledExceptionFilter(signalhandler);#endif /* TARGET */    s->sigint = s->sigterm = NULL;    s->saved = 0;}/* Save the current signal handlers and set them to ignore. */MP_GLOBALvoid__mp_savesignals(sighead *s){    s->sigint = signal(SIGINT, SIG_IGN);    s->sigterm = signal(SIGTERM, SIG_IGN);    s->saved = 1;}/* Restore the previous signal handlers. */MP_GLOBALvoid__mp_restoresignals(sighead *s){    if (s->saved)    {        signal(SIGINT, s->sigint);        signal(SIGTERM, s->sigterm);        s->saved = 0;    }}/* Send the current process an ABORT signal. */MP_GLOBALvoid__mp_abort(void){#if TARGET == TARGET_UNIX || TARGET == TARGET_WINDOWS    /* Send the current process an ABORT signal for use in a debugger.     * Used on systems where this is supported.     */    fflush(NULL);    abort();#else /* TARGET */    /* Terminate the current process with a failure exit code.     * Used on systems where memory will not be automatically returned     * back to the system on process termination.     */    exit(EXIT_FAILURE);#endif /* TARGET */}#ifdef __cplusplus}#endif /* __cplusplus */

⌨️ 快捷键说明

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