From 7c855bda1a9a9bd80ee53cb99f70dd50e6ee48c2 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Thu, 20 Jan 2005 23:41:17 +0000 Subject: [PATCH] Add built-in debug malloc wrapper. TODO: Remove the completed TODO item. configure.in: Add --with-malloc=srvx support. src/Makefile.am: Add alloc-srvx.c to extra sources. src/common.h: Reindent debug malloc directives; add directives for WITH_MALLOC_SRVX. src/dict-splay.c: Kludge around free() as macro vs function. git-archimport-id: srvx@srvx.net--2005-srvx/srvx--devo--1.3--patch-4 --- ChangeLog | 26 ++++++++++ TODO | 3 -- configure.in | 6 ++- src/Makefile.am | 2 +- src/alloc-srvx.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++ src/common.h | 49 +++++++++++------- src/dict-splay.c | 16 ++++-- 7 files changed, 204 insertions(+), 26 deletions(-) create mode 100644 src/alloc-srvx.c diff --git a/ChangeLog b/ChangeLog index 4f25483..518bff5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,32 @@ # arch-tag: automatic-ChangeLog--srvx@srvx.net--2005-srvx/srvx--devo--1.3 # +2005-01-20 23:41:17 GMT Michael Poole patch-4 + + Summary: + Add built-in debug malloc wrapper. + Revision: + srvx--devo--1.3--patch-4 + + TODO: Remove the completed TODO item. + + configure.in: Add --with-malloc=srvx support. + + src/Makefile.am: Add alloc-srvx.c to extra sources. + + src/common.h: Reindent debug malloc directives; add directives for + WITH_MALLOC_SRVX. + + src/dict-splay.c: Kludge around free() as macro vs function. + + new files: + src/.arch-ids/alloc-srvx.c.id src/alloc-srvx.c + + modified files: + ChangeLog TODO configure.in src/Makefile.am src/common.h + src/dict-splay.c + + 2005-01-20 22:51:54 GMT Michael Poole patch-3 Summary: diff --git a/TODO b/TODO index fdda819..cc40e98 100644 --- a/TODO +++ b/TODO @@ -18,6 +18,3 @@ [FEATREQ] Suspension durations and/or comments when suspending user access to a channel [FEATREQ] support "unregistered": ?ctrace print mode +s unregistered - -- rewrite memory allocation calls to use wrapper macros, and add - optional debugging for the stubs to tag size and/or type. diff --git a/configure.in b/configure.in index 26ef7dd..81dd91d 100644 --- a/configure.in +++ b/configure.in @@ -152,7 +152,7 @@ dnl Optional features. AC_MSG_CHECKING(which malloc to use) AC_ARG_WITH(malloc, [ --with-malloc=type Enables use of a special malloc library; one of: - system (the default), boehm-gc, dmalloc, mpatrol], + system (the default), boehm-gc, dmalloc, mpatrol, srvx], [], [withval="system"]) if test "x$withval" = "xsystem" ; then @@ -176,6 +176,10 @@ elif test "x$withval" = "xboehm-gc" ; then AC_CHECK_LIB(dl, dlopen, , AC_MSG_ERROR([libdl library is missing. boehm-gc build will fail.])) AC_CHECK_LIB(gc, GC_gcollect, , AC_MSG_ERROR([Boehm GC library is missing. boehm-gc build will fail.])) AC_DEFINE(WITH_MALLOC_BOEHM_GC, 1, [Define if using the Boehm GC to garbage collect and check memory leaks]) +elif test "x$withval" = "xsrvx" ; then + AC_MSG_RESULT(srvx) + AC_DEFINE(WITH_MALLOC_SRVX, 1, [Define if using the srvx internal debug allocator]) + MODULE_OBJS="$MODULE_OBJS alloc-srvx.\$(OBJEXT)" else AC_MSG_ERROR([Unknown malloc type $withval]) fi diff --git a/src/Makefile.am b/src/Makefile.am index f605f86..7fe7c1d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,7 @@ checkversion: mv $$TMPFILE arch-version.h ; \ fi -EXTRA_srvx_SOURCES = proto-bahamut.c proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c mod-helpserv.c mod-sockcheck.c +EXTRA_srvx_SOURCES = alloc-srvx.c proto-bahamut.c proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c mod-helpserv.c mod-sockcheck.c srvx_LDADD = @MODULE_OBJS@ srvx_DEPENDENCIES = @MODULE_OBJS@ srvx_SOURCES = \ diff --git a/src/alloc-srvx.c b/src/alloc-srvx.c new file mode 100644 index 0000000..91d9035 --- /dev/null +++ b/src/alloc-srvx.c @@ -0,0 +1,128 @@ +/* alloc-srvx.c - Debug allocation wrapper + * Copyright 2005 srvx Development Team + * + * This file is part of srvx. + * + * srvx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + */ + +#include "common.h" + +#undef malloc +#undef free + +/* cookies for anybody who recognizes these bytes without help :) */ +#define ALLOC_MAGIC 0x1acf +#define FREE_MAGIC 0xfc1d + +struct alloc_header { + unsigned int file_id : 8; + unsigned int size : 24; + unsigned int line : 16; + unsigned int magic : 16; +}; + +static char file_id_map[256][32]; +static unsigned int file_ids_used; + +static int +file_id_cmp(const void *a_, const void *b_) +{ + return strcmp(a_, b_); +} + +static unsigned int +get_file_id(const char *fname) +{ + void *entry; + + entry = bsearch(fname, file_id_map, file_ids_used, sizeof(file_id_map[0]), file_id_cmp); + if (entry) + return ((char*)entry - file_id_map[0]) / sizeof(file_id_map[0]); + strcpy(file_id_map[file_ids_used++], fname); + qsort(file_id_map, file_ids_used, sizeof(file_id_map[0]), file_id_cmp); + return file_ids_used - 1; +} + +void * +srvx_malloc(const char *file, unsigned int line, size_t size) +{ + struct alloc_header *block; + + block = malloc(sizeof(*block) + size); + assert(block != NULL); + memset(block, 0, sizeof(*block) + size); + block->file_id = get_file_id(file); + block->line = line; + block->size = size; + block->magic = ALLOC_MAGIC; + return block + 1; +} + +void * +srvx_realloc(const char *file, unsigned int line, void *ptr, size_t size) +{ + struct alloc_header *block = NULL, *newblock; + + if (ptr) { + block = (struct alloc_header *)ptr - 1; + assert(block->magic == ALLOC_MAGIC); + if (block->size >= size) + return block + 1; + } + + newblock = malloc(sizeof(*newblock) + size); + assert(newblock != NULL); + memset(newblock, 0, sizeof(*newblock) + size); + newblock->file_id = get_file_id(file); + newblock->line = line; + newblock->size = size; + newblock->magic = ALLOC_MAGIC; + + if (ptr) { + memcpy(newblock + 1, block + 1, block->size); + size = block->size + sizeof(*block); + memset(block, 0, size); + block->magic = FREE_MAGIC; + free(block); + } + + return newblock + 1; +} + +char * +srvx_strdup(const char *file, unsigned int line, const char *src) +{ + char *target; + size_t len; + + len = strlen(src) + 1; + target = srvx_malloc(file, line, len); + memcpy(target, src, len); + return target; +} + +void +srvx_free(const char *file, unsigned int line, void *ptr) +{ + struct alloc_header *block; + size_t size; + + if (!ptr) + return; + block = (struct alloc_header *)ptr - 1; + assert(block->magic == ALLOC_MAGIC); + size = block->size + sizeof(*block); + memset(block, 0, size); + block->magic = FREE_MAGIC; + free(block); + (void)file; (void)line; +} diff --git a/src/common.h b/src/common.h index 952b1de..a8458a3 100644 --- a/src/common.h +++ b/src/common.h @@ -64,25 +64,40 @@ extern struct tm *localtime_r(const time_t *clock, struct tm *res); #endif #if defined(WITH_MALLOC_DMALLOC) -#define DMALLOC_FUNC_CHECK 1 -#include -#include +# define DMALLOC_FUNC_CHECK 1 +# include +# include #elif defined(WITH_MALLOC_MPATROL) -#include -#include +# include +# include #elif defined(WITH_MALLOC_BOEHM_GC) -#if !defined(NDEBUG) -#define GC_DEBUG 1 -#endif -#include -#include -#include -#define malloc(n) GC_MALLOC(n) -#define calloc(m,n) GC_MALLOC((m)*(n)) -#define realloc(p,n) GC_REALLOC((p),(n)) -#define free(p) GC_FREE(p) -#undef HAVE_STRDUP -#undef strdup +# if !defined(NDEBUG) +# define GC_DEBUG 1 +# endif +# include +# include +# include +# define malloc(n) GC_MALLOC(n) +# define calloc(m,n) GC_MALLOC((m)*(n)) +# define realloc(p,n) GC_REALLOC((p),(n)) +# define free(p) GC_FREE(p) +# undef HAVE_STRDUP +# undef strdup +#elif defined(WITH_MALLOC_SRVX) +# undef malloc +# define malloc(n) srvx_malloc(__FILE__, __LINE__, (n)) +# undef calloc +# define calloc(m,n) srvx_malloc(__FILE__, __LINE__, (m)*(n)) +# undef realloc +# define realloc(p,n) srvx_realloc(__FILE__, __LINE__, (p), (n)) +# undef free +# define free(p) srvx_free(__FILE__, __LINE__, (p)) +# undef strdup +# define strdup(s) srvx_strdup(__FILE__, __LINE__, (s)) +extern void *srvx_malloc(const char *, unsigned int, size_t); +extern void *srvx_realloc(const char *, unsigned int, void *, size_t); +extern char *srvx_strdup(const char *, unsigned int, const char *); +extern void srvx_free(const char *, unsigned int, void *); #endif extern time_t now; diff --git a/src/dict-splay.c b/src/dict-splay.c index 42bb902..4619ce5 100644 --- a/src/dict-splay.c +++ b/src/dict-splay.c @@ -123,10 +123,18 @@ dict_splay(struct dict_node *node, const char *key) static void dict_dispose_node(struct dict_node *node, free_f free_keys, free_f free_data) { - if (free_keys && node->key) - free_keys((void*)node->key); - if (free_data && node->data) - free_data(node->data); + if (free_keys && node->key) { + if (free_keys == free) + free((void*)node->key); + else + free_keys((void*)node->key); + } + if (free_data && node->data) { + if (free_data == free) + free(node->data); + else + free_data(node->data); + } free(node); } -- 2.20.1