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

📄 memory.c

📁 debug source code under unix platform.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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. *//* * Memory handling.  All memory access or handling routines that directly * access the system memory are interfaced from this module.  For UNIX SVR4 * systems, a useful reference book on operating system memory management is * The Magic Garden Explained, First Edition by Goodheart and Cox (Prentice * Hall, 1994, ISBN 0-130-98138-9). */#include "memory.h"#include "stack.h"#include "utils.h"#include <stdio.h>#include <errno.h>#include <limits.h>#if TARGET == TARGET_UNIX#if SYSTEM == SYSTEM_LYNXOS#ifndef POSIX4_D14_MEMCTL#define POSIX4_D14_MEMCTL 1#endif /* POSIX4_D14_MEMCTL */#elif SYSTEM == SYSTEM_SUNOS#ifndef _POSIX_ARG_MAX#define _POSIX_ARG_MAX 4096#endif /* _POSIX_ARG_MAX */#endif /* SYSTEM */#include <setjmp.h>#include <signal.h>#if MP_SIGINFO_SUPPORT#include <siginfo.h>#endif /* MP_SIGINFO_SUPPORT */#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#if SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_NETBSD || \    SYSTEM == SYSTEM_OPENBSD#ifndef MAP_ANONYMOUS#define MAP_ANONYMOUS MAP_ANON#endif /* MAP_ANONYMOUS */#endif /* SYSTEM */#if MP_WATCH_SUPPORT#if SYSTEM == SYSTEM_SOLARIS#include <procfs.h>#else /* SYSTEM */#include <sys/procfs.h>#endif /* SYSTEM */#endif /* MP_WATCH_SUPPORT */#elif TARGET == TARGET_AMIGA#include <proto/dos.h>#include <proto/exec.h>#include <exec/memory.h>#elif TARGET == TARGET_WINDOWS#include <windows.h>#include <winbase.h>#include <process.h>#elif TARGET == TARGET_NETWARE#include <nwthread.h>#include <nks/memory.h>#endif /* TARGET */#if MP_IDENT_SUPPORT#ident "$Id: memory.c,v 1.59 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *memory_id = "$Id: memory.c,v 1.59 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT */#if MP_WATCH_SUPPORT/* This structure is used to simplify the building of the watch command before * it is written to the control file of the /proc filesystem. */typedef struct watchcmd{    long cmd;       /* the command to set a watch point */    prwatch_t data; /* details of addresses to watch */}watchcmd;#endif /* MP_WATCH_SUPPORT */#ifdef __cplusplusextern "C"{#endif /* __cplusplus */#if MP_ARRAY_SUPPORT/* The static memory array used to implement a simulated heap.  This is * most likely to be zero-initialised at the beginning of program execution, * but this should not be relied upon as the memory it contains will be reused. */static char memoryarray[MP_ARRAY_SIZE];/* The current number of bytes that have been allocated from the static memory * array.  This will never be allowed to increase beyond MP_ARRAY_SIZE. */static size_t memorysize;#endif /* MP_ARRAY_SUPPORT */#if TARGET == TARGET_UNIXstatic jmp_buf memorystate;#if MP_SIGINFO_SUPPORTstatic struct sigaction membushandler;static struct sigaction memsegvhandler;#else /* MP_SIGINFO_SUPPORT */static void (*membushandler)(int);static void (*memsegvhandler)(int);#endif /* MP_SIGINFO_SUPPORT */#endif /* TARGET *//* Determine the minimum alignment for a general-purpose memory allocation * on this system. */staticsize_tminalign(void){    size_t a;    long n;    {        /* Hopefully the largest integral type.  If the compiler supports         * long long, it doesn't necessarily mean that it will have a more         * restrictive alignment than a long integer, but we allow that         * check anyway.         */#if MP_LONGLONG_SUPPORT        struct { char x; long long y; } z;#else /* MP_LONGLONG_SUPPORT */        struct { char x; long y; } z;#endif /* MP_LONGLONG_SUPPORT */        n = (char *) &z.y - &z.x;    }    a = n;    {        /* Hopefully the largest floating point type.  The long double         * type appeared with the ANSI standard and this code is written         * in ANSI C so we shouldn't need to worry about not supporting it.         */        struct { char x; long double y; } z;        n = (char *) &z.y - &z.x;    }    if (a < (unsigned long) n)        a = n;    {        /* A generic pointer type.  The assumption in this case is that         * a pointer to void is the most restrictive pointer type on this         * system.         */        struct { char x; void *y; } z;        n = (char *) &z.y - &z.x;    }    if (a < (unsigned long) n)        a = n;    return __mp_poweroftwo(a);}/* Return the system page size. */staticsize_tpagesize(void){#if TARGET == TARGET_WINDOWS    SYSTEM_INFO i;#endif /* TARGET */#if TARGET == TARGET_UNIX    /* This call could also be getpagesize() but it is more POSIX-conforming     * to call sysconf().  Unfortunately, SunOS and the BSD systems only have     * getpagesize().     */#if SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_NETBSD || \    SYSTEM == SYSTEM_OPENBSD || SYSTEM == SYSTEM_SUNOS    return getpagesize();#else /* SYSTEM */    return sysconf(_SC_PAGESIZE);#endif /* SYSTEM */#elif TARGET == TARGET_AMIGA    /* The Amiga has no virtual memory system (at least not supplied with     * AmigaOS), so we return a fixed value here because it doesn't really     * matter what the page size is.     */    return 4096;#elif TARGET == TARGET_WINDOWS    GetSystemInfo(&i);    return i.dwPageSize;#elif TARGET == TARGET_NETWARE    return NXGetPageSize();#else /* TARGET */    /* We just assume that any other operating systems have no virtual     * memory support and so anything we return here is irrelevant.     */    return 1024;#endif /* TARGET */}/* Determine the stack direction on this system. */staticintstackdirection(void *p){    unsigned long n;    n = (unsigned long) &p;    if (p == NULL)        return stackdirection(&n);    else if (&n < (unsigned long *) p)        return -1;    else        return 1;}/* Return the executable file name that the program was invoked with. * Note that this function will not be reentrant if the return value is * a pointer to a local static string buffer. */staticchar *progname(void){#if TARGET == TARGET_UNIX#if SYSTEM == SYSTEM_AIX    extern char **p_xargv;#elif SYSTEM == SYSTEM_HPUX    extern char **__argv_value;#elif SYSTEM == SYSTEM_IRIX || SYSTEM == SYSTEM_SINIX || SYSTEM == SYSTEM_TRU64    extern char **__Argv;#elif SYSTEM == SYSTEM_UNIXWARE    extern char **___Argv;#elif SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_LINUX || \      SYSTEM == SYSTEM_NETBSD || SYSTEM == SYSTEM_OPENBSD    static char c[256];    ssize_t l;    int f;#elif SYSTEM == SYSTEM_DGUX || SYSTEM == SYSTEM_DRSNX || \      SYSTEM == SYSTEM_DYNIX || SYSTEM == SYSTEM_LYNXOS || \      SYSTEM == SYSTEM_SOLARIS || SYSTEM == SYSTEM_SUNOS    extern char **environ;    char **e;    char *t;#endif /* SYSTEM */#if !MP_BUILTINSTACK_SUPPORT && !MP_LIBRARYSTACK_SUPPORT && \    (ARCH == ARCH_IX86 || ARCH == ARCH_M68K || ARCH == ARCH_MIPS || \     ARCH == ARCH_POWER || ARCH == ARCH_POWERPC || ARCH == ARCH_SPARC)    unsigned long *p;    stackinfo s;#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT && ARCH */#ifdef MP_PROCFS_EXENAME    static char b[64];#endif /* MP_PROCFS_EXENAME */#elif TARGET == TARGET_AMIGA || TARGET == TARGET_WINDOWS    static char p[256];#elif TARGET == TARGET_NETWARE    char *p, *t;#endif /* TARGET */#if TARGET == TARGET_UNIX    /* AIX, HP/UX, IRIX, SINIX, Tru64 and UnixWare have global variables     * containing argc and argv which we can use to determine the filename     * that the program was invoked with.     */#if SYSTEM == SYSTEM_AIX    if (p_xargv[0] != NULL)        return p_xargv[0];#elif SYSTEM == SYSTEM_HPUX    if (__argv_value[0] != NULL)        return __argv_value[0];#elif SYSTEM == SYSTEM_IRIX || SYSTEM == SYSTEM_SINIX || SYSTEM == SYSTEM_TRU64    if (__Argv[0] != NULL)        return __Argv[0];#elif SYSTEM == SYSTEM_UNIXWARE    if (___Argv[0] != NULL)        return ___Argv[0];#elif SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_LINUX || \      SYSTEM == SYSTEM_NETBSD || SYSTEM == SYSTEM_OPENBSD    /* The BSD variants and Linux have a file in the /proc filesystem which     * contains the argument vector that a process was invoked with.     */    l = 0;    sprintf(b, MP_PROCFS_CMDNAME, __mp_processid());    if ((f = open(b, O_RDONLY)) != -1)    {        if ((l = read(f, c, sizeof(c) - 1)) == -1)            l = 0;        close(f);    }    if (l > 0)    {        c[l] = '\0';        return c;    }#elif SYSTEM == SYSTEM_DGUX || SYSTEM == SYSTEM_DRSNX || \      SYSTEM == SYSTEM_DYNIX || SYSTEM == SYSTEM_LYNXOS || \      SYSTEM == SYSTEM_SOLARIS || SYSTEM == SYSTEM_SUNOS    /* We can access the argument vector from the pointer to the environment     * array on all other UNIX systems.  On DG/UX Intel, DRS/NX, DYNIX/ptx,     * Solaris and SunOS we stop scanning backwards along the array when we     * reach argc.  On DG/UX M88K and LynxOS we stop scanning forwards along     * the array when we reach a NULL pointer.  The contents of the argument     * vector then follow.     */#if (SYSTEM == SYSTEM_DGUX && ARCH == ARCH_M88K) || SYSTEM == SYSTEM_LYNXOS    for (e = environ; *e != NULL; e++);    t = (char *) (e + 1);#else /* SYSTEM && ARCH */    for (t = NULL, e = environ - 2; *e > (char *) _POSIX_ARG_MAX; t = *e--);#endif /* SYSTEM && ARCH */    if (t != NULL)        return t;#endif /* SYSTEM */#if !MP_BUILTINSTACK_SUPPORT && !MP_LIBRARYSTACK_SUPPORT && \    (ARCH == ARCH_IX86 || ARCH == ARCH_M68K || ARCH == ARCH_MIPS || \     ARCH == ARCH_POWER || ARCH == ARCH_POWERPC || ARCH == ARCH_SPARC)    /* Because there is no function to return the executable filename     * of a process on UNIX, we need to cheat and rely on the ABI by walking     * up the process stack till we reach the startup code and then find     * argv[0].  This is very OS-specific and is not my first choice for     * doing this, but unfortunately it seemed to be the only way.     */    __mp_newframe(&s, NULL);    for (p = NULL; __mp_getframe(&s); p = (unsigned long *) s.frame);    if (p != NULL)    {#if ARCH == ARCH_IX86#if SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_LINUX || \    SYSTEM == SYSTEM_NETBSD || SYSTEM == SYSTEM_OPENBSD        if (p = (unsigned long *) p[4])            return (char *) *p;#elif SYSTEM == SYSTEM_LYNXOS        if (p = (unsigned long *) p[3])            return (char *) *p;#else /* SYSTEM */        if (p = (unsigned long *) p[3])            return (char *) p;#endif /* SYSTEM */#elif ARCH == ARCH_M68K        if (p = (unsigned long *) p[3])            return (char *) *p;#elif ARCH == ARCH_MIPS        if (p = (unsigned long *) p[7])            return (char *) p;#elif ARCH == ARCH_POWER || ARCH == ARCH_POWERPC#if SYSTEM == SYSTEM_AIX        if (p = (unsigned long *) p[7])            return (char *) p;#else /* SYSTEM */        if (p = (unsigned long *) p[23])            return (char *) *p;#endif /* SYSTEM */#elif ARCH == ARCH_SPARC#if ENVIRON == ENVIRON_64        if (p = (unsigned long *) *(((unsigned long *) (*p + 0x7FF)) + 1))#else /* ENVIRON */        if (p = (unsigned long *) *(((unsigned long *) *p) + 1))#endif /* ENVIRON */            return (char *) *p;#endif /* ARCH */    }#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT && ARCH */#ifdef MP_PROCFS_EXENAME    /* If the /proc filesystem is supported then we can usually access the     * actual executable file that contains the current program through a     * special file in the current /proc entry.     */    sprintf(b, MP_PROCFS_EXENAME, __mp_processid());    return b;#endif /* MP_PROCFS_EXENAME */#elif TARGET == TARGET_AMIGA    if (GetProgramName(p, sizeof(p)))        return p;#elif TARGET == TARGET_WINDOWS    if (GetModuleFileName(NULL, p, sizeof(p)))        return p;#elif TARGET == TARGET_NETWARE    if (GetNLMNameFromNLMID(GetNLMID(), &p, &t) == 0)

⌨️ 快捷键说明

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