From: Ted Lemon Date: Tue, 25 Jan 2000 01:02:26 +0000 (+0000) Subject: Support new debug malloc. X-Git-Tag: V3-BETA-2-PATCH-1~431 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=49bc3bc5d1a3a550802a0b9e4a76ca7eafaa4544;p=thirdparty%2Fdhcp.git Support new debug malloc. --- diff --git a/common/alloc.c b/common/alloc.c index b924373f1..b09daab8e 100644 --- a/common/alloc.c +++ b/common/alloc.c @@ -22,7 +22,7 @@ #ifndef lint static char copyright[] = -"$Id: alloc.c,v 1.36 2000/01/05 17:57:03 mellon Exp $ Copyright (c) 1995, 1996, 1998 The Internet Software Consortium. All rights reserved.\n"; +"$Id: alloc.c,v 1.37 2000/01/25 01:02:26 mellon Exp $ Copyright (c) 1995, 1996, 1998 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -30,117 +30,372 @@ static char copyright[] = struct dhcp_packet *dhcp_free_list; struct packet *packet_free_list; -VOIDPTR dmalloc (size, name) +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) +struct dmalloc_preamble *dmalloc_list; +unsigned long dmalloc_outstanding; +unsigned long dmalloc_longterm; +unsigned long dmalloc_generation; +unsigned long dmalloc_cutoff_generation; +#endif + +#if defined (DEBUG_RC_HISTORY) +struct rc_history_entry rc_history [RC_HISTORY_MAX]; +int rc_history_index; +#endif + +VOIDPTR dmalloc (size, file, line) unsigned size; - const char *name; + const char *file; + int line; { - VOIDPTR foo = (VOIDPTR)malloc (size); - if (!foo) + unsigned char *foo = malloc (size + DMDSIZE); + int i; + VOIDPTR *bar; +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) + struct dmalloc_preamble *dp; +#endif + if (!foo) { log_error ("No memory for %s.", name); - else - memset (foo, 0, size); - return foo; + return (VOIDPTR)0; + } + bar = (VOIDPTR)(foo + DMDOFFSET); + memset (bar, 0, size); + +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) + dp = (struct dmalloc_preamble *)foo; + dp -> prev = dmalloc_list; + if (dmalloc_list) + dmalloc_list -> next = dp; + dmalloc_list = dp; + dp -> next = (struct dmalloc_preamble *)0; + dp -> size = size; + dp -> file = file; + dp -> line = line; + dp -> generation = dmalloc_generation++; + dmalloc_outstanding += size; + for (i = 0; i < DMLFSIZE; i++) + dp -> low_fence [i] = + (((unsigned long) + (&dp -> low_fence [i])) % 143) + 113; + for (i = DMDOFFSET; i < DMDSIZE; i++) + foo [i + size] = + (((unsigned long) + (&foo [i + size])) % 143) + 113; +#if defined (DEBUG_MALLOC_POOL_EXHAUSTIVELY) + /* Check _every_ entry in the pool! Very expensive. */ + for (dp = dmalloc_list; dp; dp = dp -> prev) { + for (i = 0; i < DMLFSIZE; i++) { + if (dp -> low_fence [i] != + (((unsigned long) + (&dp -> low_fence [i])) % 143) + 113) + { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + foo = (unsigned char *)dp; + for (i = DMDOFFSET; i < DMDSIZE; i++) { + if (foo [i + dp -> size] != + (((unsigned long) + (&foo [i + dp -> size])) % 143) + 113) { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + } +#endif +#endif + return bar; } -void dfree (ptr, name) +void dfree (ptr, file, line) VOIDPTR ptr; - const char *name; + const char *file; + int line; { if (!ptr) { - log_error ("dfree %s: free on null pointer.", name); + log_error ("dfree %s(%d): free on null pointer.", file, line); return; } +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) + { + unsigned char *bar = ptr; + struct dmalloc_preamble *dp, *cur; + int i; + bar -= DMDOFFSET; + cur = (struct dmalloc_preamble *)bar; + for (dp = dmalloc_list; dp; dp = dp -> prev) + if (dp == cur) + break; + if (!dp) { + log_error ("%s(%d): freeing unknown memory: %lx", + dp -> file, dp -> line, (unsigned long)cur); + abort (); + } + if (dp -> prev) + dp -> prev -> next = dp -> next; + if (dp -> next) + dp -> next -> prev = dp -> prev; + if (dp == dmalloc_list) + dmalloc_list = dp -> prev; + if (dp -> generation >= dmalloc_cutoff_generation) + dmalloc_outstanding -= dp -> size; + else + dmalloc_longterm -= dp -> size; + + for (i = 0; i < DMLFSIZE; i++) { + if (dp -> low_fence [i] != + (((unsigned long) + (&dp -> low_fence [i])) % 143) + 113) + { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + for (i = DMDOFFSET; i < DMDSIZE; i++) { + if (bar [i + dp -> size] != + (((unsigned long) + (&bar [i + dp -> size])) % 143) + 113) { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + ptr = bar; + } +#endif free (ptr); } -struct dhcp_packet *new_dhcp_packet (name) - const char *name; +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) +/* For allocation functions that keep their own free lists, we want to + account for the reuse of the memory. */ + +void dmalloc_reuse (foo, file, line, justref) + VOIDPTR foo; + const char *file; + int line; + int justref; +{ + struct dmalloc_preamble *dp; + + /* Get the pointer to the dmalloc header. */ + dp = foo; + dp--; + + /* If we just allocated this and are now referencing it, this + function would almost be a no-op, except that it would + increment the generation count needlessly. So just return + in this case. */ + if (dp -> generation == dmalloc_generation) + return; + + /* If this is longterm data, and we just made reference to it, + don't put it on the short-term list or change its name - + we don't need to know about this. */ + if (dp -> generation < dmalloc_cutoff_generation && justref) + return; + + /* Take it out of the place in the allocated list where it was. */ + if (dp -> prev) + dp -> prev -> next = dp -> next; + if (dp -> next) + dp -> next -> prev = dp -> prev; + if (dp == dmalloc_list) + dmalloc_list = dp -> prev; + + /* Account for its removal. */ + if (dp -> generation >= dmalloc_cutoff_generation) + dmalloc_outstanding -= dp -> size; + else + dmalloc_longterm -= dp -> size; + + /* Now put it at the head of the list. */ + dp -> prev = dmalloc_list; + if (dmalloc_list) + dmalloc_list -> next = dp; + dmalloc_list = dp; + dp -> next = (struct dmalloc_preamble *)0; + + /* Change the reference location information. */ + dp -> file = file; + dp -> line = line; + + /* Increment the generation. */ + dp -> generation = dmalloc_generation++; + + /* Account for it. */ + dmalloc_outstanding += dp -> size; +} + +void dmalloc_dump_outstanding () +{ + static unsigned long dmalloc_cutoff_point; + struct dmalloc_preamble *dp; + unsigned char *foo; + int i; + + if (!dmalloc_cutoff_point) + dmalloc_cutoff_point = dmalloc_cutoff_generation; + for (dp = dmalloc_list; dp; dp = dp -> prev) { + if (dp -> generation <= dmalloc_cutoff_point) + break; +#if defined (DEBUG_MALLOC_POOL) + for (i = 0; i < DMLFSIZE; i++) { + if (dp -> low_fence [i] != + (((unsigned long) + (&dp -> low_fence [i])) % 143) + 113) + { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + foo = (unsigned char *)dp; + for (i = DMDOFFSET; i < DMDSIZE; i++) { + if (foo [i + dp -> size] != + (((unsigned long) + (&foo [i + dp -> size])) % 143) + 113) { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } +#endif +#if defined (DEBUG_MEMORY_LEAKAGE) + /* Don't count data that's actually on a free list + somewhere. */ + if (dp -> file) + log_info (" %s(%d): %d", + dp -> file, dp -> line, dp -> size); +#endif + } + if (dmalloc_list) + dmalloc_cutoff_point = dmalloc_list -> generation; +} +#endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */ + +#if defined (DEBUG_RC_HISTORY) +void dump_rc_history () +{ + int i; + + i = rc_history_index; + do { + log_info (" referenced by %s(%d): addr = %lx refcnt = %x\n", + rc_history [i].file, rc_history [i].line, + (unsigned long)rc_history [i].addr, + rc_history [i].refcnt); + ++i; + if (i == RC_HISTORY_MAX) + i = 0; + } while (i != rc_history_index && rc_history [i].file); +} +#endif + +struct dhcp_packet *new_dhcp_packet (file, line) + const char *file; + int line; { struct dhcp_packet *rval; rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet), - name); + file, line); return rval; } -struct hash_table *new_hash_table (count, name) +struct hash_table *new_hash_table (count, file, line) int count; - const char *name; + const char *file; + int line; { struct hash_table *rval = dmalloc (sizeof (struct hash_table) - (DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *)) + (count * sizeof (struct hash_bucket *)), - name); + file, line); rval -> hash_count = count; return rval; } -struct hash_bucket *new_hash_bucket (name) - const char *name; +struct hash_bucket *new_hash_bucket (file, line) + const char *file; + int line; { - struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), name); + struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), + file, line); return rval; } -struct lease *new_leases (n, name) +struct lease *new_leases (n, file, line) unsigned n; - const char *name; + const char *file; + int line; { - struct lease *rval = dmalloc (n * sizeof (struct lease), name); + struct lease *rval = dmalloc (n * sizeof (struct lease), file, line); return rval; } -struct lease *new_lease (name) - const char *name; +struct lease *new_lease (file, line) + const char *file; + int line; { - struct lease *rval = dmalloc (sizeof (struct lease), name); + struct lease *rval = dmalloc (sizeof (struct lease), file, line); return rval; } -struct subnet *new_subnet (name) - const char *name; +struct subnet *new_subnet (file, line) + const char *file; + int line; { - struct subnet *rval = dmalloc (sizeof (struct subnet), name); + struct subnet *rval = dmalloc (sizeof (struct subnet), file, line); return rval; } -struct class *new_class (name) - const char *name; +struct class *new_class (file, line) + const char *file; + int line; { - struct class *rval = dmalloc (sizeof (struct class), name); + struct class *rval = dmalloc (sizeof (struct class), file, line); return rval; } -struct shared_network *new_shared_network (name) - const char *name; +struct shared_network *new_shared_network (file, line) + const char *file; + int line; { struct shared_network *rval = - dmalloc (sizeof (struct shared_network), name); + dmalloc (sizeof (struct shared_network), file, line); return rval; } -struct group *new_group (name) - const char *name; +struct group *new_group (file, line) + const char *file; + int line; { struct group *rval = - dmalloc (sizeof (struct group), name); + dmalloc (sizeof (struct group), file, line); if (rval) memset (rval, 0, sizeof *rval); return rval; } -struct protocol *new_protocol (name) - const char *name; +struct protocol *new_protocol (file, line) + const char *file; + int line; { - struct protocol *rval = dmalloc (sizeof (struct protocol), name); + struct protocol *rval = dmalloc (sizeof (struct protocol), file, line); return rval; } struct lease_state *free_lease_states; -struct lease_state *new_lease_state (name) - const char *name; +struct lease_state *new_lease_state (file, line) + const char *file; + int line; { struct lease_state *rval; @@ -148,236 +403,268 @@ struct lease_state *new_lease_state (name) rval = free_lease_states; free_lease_states = (struct lease_state *)(free_lease_states -> next); + dmalloc_reuse (rval, file, line, 0); } else { - rval = dmalloc (sizeof (struct lease_state), name); + rval = dmalloc (sizeof (struct lease_state), file, line); if (!rval) return rval; } memset (rval, 0, sizeof *rval); - if (!option_state_allocate (&rval -> options, name)) { - free_lease_state (rval, name); + if (!option_state_allocate (&rval -> options, file, line)) { + free_lease_state (rval, file, line); return (struct lease_state *)0; } return rval; } -struct domain_search_list *new_domain_search_list (name) - const char *name; +struct domain_search_list *new_domain_search_list (file, line) + const char *file; + int line; { struct domain_search_list *rval = - dmalloc (sizeof (struct domain_search_list), name); + dmalloc (sizeof (struct domain_search_list), file, line); return rval; } -struct name_server *new_name_server (name) - const char *name; +struct name_server *new_name_server (file, line) + const char *file; + int line; { struct name_server *rval = - dmalloc (sizeof (struct name_server), name); + dmalloc (sizeof (struct name_server), file, line); return rval; } -void free_name_server (ptr, name) +void free_name_server (ptr, file, line) struct name_server *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -struct option *new_option (name) - const char *name; +struct option *new_option (file, line) + const char *file; + int line; { struct option *rval = - dmalloc (sizeof (struct option), name); + dmalloc (sizeof (struct option), file, line); if (rval) memset (rval, 0, sizeof *rval); return rval; } -void free_option (ptr, name) +void free_option (ptr, file, line) struct option *ptr; - const char *name; + const char *file; + int line; { /* XXX have to put all options on heap before this is possible. */ #if 0 if (ptr -> name) - dfree ((VOIDPTR)option -> name, name); - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)option -> name, file, line); + dfree ((VOIDPTR)ptr, file, line); #endif } -struct universe *new_universe (name) - const char *name; +struct universe *new_universe (file, line) + const char *file; + int line; { struct universe *rval = - dmalloc (sizeof (struct universe), name); + dmalloc (sizeof (struct universe), file, line); return rval; } -void free_universe (ptr, name) +void free_universe (ptr, file, line) struct universe *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_domain_search_list (ptr, name) +void free_domain_search_list (ptr, file, line) struct domain_search_list *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_lease_state (ptr, name) +void free_lease_state (ptr, file, line) struct lease_state *ptr; - const char *name; + const char *file; + int line; { if (ptr -> options) - option_state_dereference (&ptr -> options, name); + option_state_dereference (&ptr -> options, file, line); if (ptr -> packet) - packet_dereference (&ptr -> packet, name); + packet_dereference (&ptr -> packet, file, line); + data_string_forget (&state -> parameter_request_list, file, line); + data_string_forget (&state -> filename, file, line); + data_string_forget (&state -> server_name, file, line); ptr -> next = free_lease_states; free_lease_states = ptr; + dmalloc_reuse (free_lease_states, (char *)0, 0, 0); } -void free_protocol (ptr, name) +void free_protocol (ptr, file, line) struct protocol *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_group (ptr, name) +void free_group (ptr, file, line) struct group *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_shared_network (ptr, name) +void free_shared_network (ptr, file, line) struct shared_network *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_class (ptr, name) +void free_class (ptr, file, line) struct class *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_subnet (ptr, name) +void free_subnet (ptr, file, line) struct subnet *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_lease (ptr, name) +void free_lease (ptr, file, line) struct lease *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_hash_bucket (ptr, name) +void free_hash_bucket (ptr, file, line) struct hash_bucket *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_hash_table (ptr, name) +void free_hash_table (ptr, file, line) struct hash_table *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -void free_dhcp_packet (ptr, name) +void free_dhcp_packet (ptr, file, line) struct dhcp_packet *ptr; - const char *name; + const char *file; + int line; { - dfree ((VOIDPTR)ptr, name); + dfree ((VOIDPTR)ptr, file, line); } -struct client_lease *new_client_lease (name) - const char *name; +struct client_lease *new_client_lease (file, line) + const char *file; + int line; { return (struct client_lease *)dmalloc (sizeof (struct client_lease), - name); + file, line); } -void free_client_lease (lease, name) +void free_client_lease (lease, file, line) struct client_lease *lease; - const char *name; + const char *file; + int line; { - dfree (lease, name); + dfree (lease, file, line); } -struct pool *new_pool (name) - const char *name; +struct pool *new_pool (file, line) + const char *file; + int line; { struct pool *pool = ((struct pool *) - dmalloc (sizeof (struct pool), name)); + dmalloc (sizeof (struct pool), file, line)); if (!pool) return pool; memset (pool, 0, sizeof *pool); return pool; } -void free_pool (pool, name) +void free_pool (pool, file, line) struct pool *pool; - const char *name; + const char *file; + int line; { - dfree (pool, name); + dfree (pool, file, line); } -struct auth_key *new_auth_key (len, name) +struct auth_key *new_auth_key (len, file, line) unsigned len; - const char *name; + const char *file; + int line; { struct auth_key *peer; unsigned size = len - 1 + sizeof (struct auth_key); - peer = (struct auth_key *)dmalloc (size, name); + peer = (struct auth_key *)dmalloc (size, file, line); if (!peer) return peer; memset (peer, 0, size); return peer; } -void free_auth_key (peer, name) +void free_auth_key (peer, file, line) struct auth_key *peer; - const char *name; + const char *file; + int line; { - dfree (peer, name); + dfree (peer, file, line); } -struct permit *new_permit (name) - const char *name; +struct permit *new_permit (file, line) + const char *file; + int line; { struct permit *permit = ((struct permit *) - dmalloc (sizeof (struct permit), name)); + dmalloc (sizeof (struct permit), file, line)); if (!permit) return permit; memset (permit, 0, sizeof *permit); return permit; } -void free_permit (permit, name) +void free_permit (permit, file, line) struct permit *permit; - const char *name; + const char *file; + int line; { - dfree (permit, name); + dfree (permit, file, line); } pair free_pairs; -pair new_pair (name) - const char *name; +pair new_pair (file, line) + const char *file; + int line; { pair foo; @@ -385,29 +672,33 @@ pair new_pair (name) foo = free_pairs; free_pairs = foo -> cdr; memset (foo, 0, sizeof *foo); + dmalloc_reuse (foo, file, line, 0); return foo; } - foo = dmalloc (sizeof *foo, name); + foo = dmalloc (sizeof *foo, file, line); if (!foo) return foo; memset (foo, 0, sizeof *foo); return foo; } -void free_pair (foo, name) +void free_pair (foo, file, line) pair foo; - const char *name; + const char *file; + int line; { foo -> cdr = free_pairs; free_pairs = foo; + dmalloc_reuse (free_expressions, (char *)0, 0, 0); } struct expression *free_expressions; -int expression_allocate (cptr, name) +int expression_allocate (cptr, file, line) struct expression **cptr; - const char *name; + const char *file; + int line; { struct expression *rval; @@ -415,29 +706,23 @@ int expression_allocate (cptr, name) rval = free_expressions; free_expressions = rval -> data.not; } else { - rval = dmalloc (sizeof (struct expression), name); + rval = dmalloc (sizeof (struct expression), file, line); if (!rval) return 0; } memset (rval, 0, sizeof *rval); - return expression_reference (cptr, rval, name); -} - -void free_expression (expr, name) - struct expression *expr; - const char *name; -{ - expr -> data.not = free_expressions; - free_expressions = expr; + return expression_reference (cptr, rval, file, line); } -int expression_reference (ptr, src, name) +int expression_reference (ptr, src, file, line) struct expression **ptr; struct expression *src; - const char *name; + const char *file; + int line; { if (!ptr) { - log_error ("Null pointer in expression_reference: %s", name); + log_error ("Null pointer in expression_reference: %s", + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -446,7 +731,7 @@ int expression_reference (ptr, src, name) } if (*ptr) { log_error ("Non-null pointer in expression_reference (%s)", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -455,14 +740,28 @@ int expression_reference (ptr, src, name) } *ptr = src; src -> refcnt++; + rc_register (file, line, src, src -> refcnt); + dmalloc_reuse (src, file, line, 1); return 1; } +void free_expression (expr, file, line) + struct expression *expr; + const char *file; + int line; +{ + expr -> data.not = free_expressions; + free_expressions = expr; + dmalloc_reuse (free_expressions, (char *)0, 0, 0); +} + + struct option_cache *free_option_caches; -int option_cache_allocate (cptr, name) +int option_cache_allocate (cptr, file, line) struct option_cache **cptr; - const char *name; + const char *file; + int line; { struct option_cache *rval; @@ -470,22 +769,25 @@ int option_cache_allocate (cptr, name) rval = free_option_caches; free_option_caches = (struct option_cache *)(rval -> expression); + dmalloc_reuse (rval, file, line, 0); } else { - rval = dmalloc (sizeof (struct option_cache), name); + rval = dmalloc (sizeof (struct option_cache), file, line); if (!rval) return 0; } memset (rval, 0, sizeof *rval); - return option_cache_reference (cptr, rval, name); + return option_cache_reference (cptr, rval, file, line); } -int option_cache_reference (ptr, src, name) +int option_cache_reference (ptr, src, file, line) struct option_cache **ptr; struct option_cache *src; - const char *name; + const char *file; + int line; { if (!ptr) { - log_error ("Null pointer in option_cache_reference: %s", name); + log_error ("Null pointer in option_cache_reference: %s", + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -494,7 +796,7 @@ int option_cache_reference (ptr, src, name) } if (*ptr) { log_error ("Non-null pointer in option_cache_reference (%s)", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -503,32 +805,36 @@ int option_cache_reference (ptr, src, name) } *ptr = src; src -> refcnt++; + rc_register (file, line, src, src -> refcnt); + dmalloc_reuse (src, file, line, 1); return 1; } -int buffer_allocate (ptr, len, name) +int buffer_allocate (ptr, len, file, line) struct buffer **ptr; unsigned len; - const char *name; + const char *file; + int line; { struct buffer *bp; - bp = dmalloc (len + sizeof *bp, name); + bp = dmalloc (len + sizeof *bp, file, line); if (!bp) return 0; memset (bp, 0, sizeof *bp); bp -> refcnt = 0; - return buffer_reference (ptr, bp, name); + return buffer_reference (ptr, bp, file, line); } -int buffer_reference (ptr, bp, name) +int buffer_reference (ptr, bp, file, line) struct buffer **ptr; struct buffer *bp; - const char *name; + const char *file; + int line; { if (!ptr) { log_error ("Null pointer passed to buffer_reference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -536,7 +842,8 @@ int buffer_reference (ptr, bp, name) #endif } if (*ptr) { - log_error ("Non-null pointer in buffer_reference (%s)", name); + log_error ("Non-null pointer in buffer_reference (%s)", + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -545,18 +852,21 @@ int buffer_reference (ptr, bp, name) } *ptr = bp; bp -> refcnt++; + rc_register (file, line, bp, bp -> refcnt); + dmalloc_reuse (bp, file, line, 1); return 1; } -int buffer_dereference (ptr, name) +int buffer_dereference (ptr, file, line) struct buffer **ptr; - const char *name; + const char *file; + int line; { struct buffer *bp; if (!ptr) { log_error ("Null pointer passed to buffer_dereference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -565,7 +875,8 @@ int buffer_dereference (ptr, name) } if (!*ptr) { - log_error ("Null pointer in buffer_dereference: %s", name); + log_error ("Null pointer in buffer_dereference: %s", + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -574,36 +885,50 @@ int buffer_dereference (ptr, name) } (*ptr) -> refcnt--; + rc_register (name, line, *ptr, (*ptr) -> refcnt); if (!(*ptr) -> refcnt) - dfree ((*ptr), name); + dfree ((*ptr), file, line); + if ((*ptr) -> refcnt < 0) { + log_error ("buffer_dereference: negative refcnt!"); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (); +#endif +#if defined (POINTER_DEBUG) + abort (); +#else + return 0; +#endif + } *ptr = (struct buffer *)0; return 1; } -int dns_host_entry_allocate (ptr, hostname, name) +int dns_host_entry_allocate (ptr, hostname, file, line) struct dns_host_entry **ptr; const char *hostname; - const char *name; + const char *file; + int line; { struct dns_host_entry *bp; - bp = dmalloc (strlen (hostname) + sizeof *bp, name); + bp = dmalloc (strlen (hostname) + sizeof *bp, file, line); if (!bp) return 0; memset (bp, 0, sizeof *bp); bp -> refcnt = 0; strcpy (bp -> hostname, hostname); - return dns_host_entry_reference (ptr, bp, name); + return dns_host_entry_reference (ptr, bp, file, line); } -int dns_host_entry_reference (ptr, bp, name) +int dns_host_entry_reference (ptr, bp, file, line) struct dns_host_entry **ptr; struct dns_host_entry *bp; - const char *name; + const char *file; + int line; { if (!ptr) { log_error ("Null pointer in dns_host_entry_reference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -612,7 +937,7 @@ int dns_host_entry_reference (ptr, bp, name) } if (*ptr) { log_error ("Non-null pointer in dns_host_entry_reference (%s)", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -621,18 +946,21 @@ int dns_host_entry_reference (ptr, bp, name) } *ptr = bp; bp -> refcnt++; + rc_register (file, line, bp, bp -> refcnt); + dmalloc_reuse (bp, file, line, 1); return 1; } -int dns_host_entry_dereference (ptr, name) +int dns_host_entry_dereference (ptr, file, line) struct dns_host_entry **ptr; - const char *name; + const char *file; + int line; { struct dns_host_entry *bp; if (!ptr || !*ptr) { log_error ("Null pointer in dns_host_entry_dereference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -641,21 +969,34 @@ int dns_host_entry_dereference (ptr, name) } (*ptr) -> refcnt--; + rc_register (file, line, bp, bp -> refcnt); if (!(*ptr) -> refcnt) - dfree ((*ptr), name); + dfree ((*ptr), file, line); + if ((*ptr) -> refcnt < 0) { + log_error ("dns_host_entry_dereference: negative refcnt!"); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (); +#endif +#if defined (POINTER_DEBUG) + abort (); +#else + return 0; +#endif + } *ptr = (struct dns_host_entry *)0; return 1; } -int option_state_allocate (ptr, name) +int option_state_allocate (ptr, file, line) struct option_state **ptr; - const char *name; + const char *file; + int line; { unsigned size; if (!ptr) { log_error ("Null pointer passed to option_state_allocate: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -664,7 +1005,7 @@ int option_state_allocate (ptr, name) } if (*ptr) { log_error ("Non-null pointer in option_state_allocate (%s)", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -673,24 +1014,26 @@ int option_state_allocate (ptr, name) } size = sizeof **ptr + (universe_count - 1) * sizeof (VOIDPTR); - *ptr = dmalloc (size, name); + *ptr = dmalloc (size, file, line); if (*ptr) { memset (*ptr, 0, size); (*ptr) -> universe_count = universe_count; (*ptr) -> refcnt = 1; + rc_register (file, line, *ptr, (*ptr) -> refcnt); return 1; } return 0; } -int option_state_reference (ptr, bp, name) +int option_state_reference (ptr, bp, file, line) struct option_state **ptr; struct option_state *bp; - const char *name; + const char *file; + int line; { if (!ptr) { log_error ("Null pointer in option_state_reference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -699,7 +1042,7 @@ int option_state_reference (ptr, bp, name) } if (*ptr) { log_error ("Non-null pointer in option_state_reference (%s)", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -708,19 +1051,22 @@ int option_state_reference (ptr, bp, name) } *ptr = bp; bp -> refcnt++; + rc_register (file, line, bp, bp -> refcnt); + dmalloc_reuse (bp, file, line, 1); return 1; } -int option_state_dereference (ptr, name) +int option_state_dereference (ptr, file, line) struct option_state **ptr; - const char *name; + const char *file; + int line; { int i; struct option_state *options; if (!ptr || !*ptr) { log_error ("Null pointer in option_state_dereference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -731,9 +1077,22 @@ int option_state_dereference (ptr, name) options = *ptr; *ptr = (struct option_state *)0; --options -> refcnt; - if (options -> refcnt) + rc_register (file, line, options, options -> refcnt); + if (options -> refcnt > 0) return 1; + if (options -> refcnt < 0) { + log_error ("option_state_dereference: negative refcnt!"); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (); +#endif +#if defined (POINTER_DEBUG) + abort (); +#else + return 0; +#endif + } + /* Loop through the per-universe state. */ for (i = 0; i < options -> universe_count; i++) if (options -> universes [i] && @@ -741,32 +1100,33 @@ int option_state_dereference (ptr, name) ((*(universes [i] -> option_state_dereference)) (universes [i], options)); - dfree (options, name); + dfree (options, file, line); return 1; } -int executable_statement_allocate (ptr, name) +int executable_statement_allocate (ptr, file, line) struct executable_statement **ptr; - const char *name; + const char *file; + int line; { struct executable_statement *bp; - bp = dmalloc (sizeof *bp, name); + bp = dmalloc (sizeof *bp, file, line); if (!bp) return 0; memset (bp, 0, sizeof *bp); - bp -> refcnt = 0; - return executable_statement_reference (ptr, bp, name); + return executable_statement_reference (ptr, bp, file, line); } -int executable_statement_reference (ptr, bp, name) +int executable_statement_reference (ptr, bp, file, line) struct executable_statement **ptr; struct executable_statement *bp; - const char *name; + const char *file; + int line; { if (!ptr) { log_error ("Null ptr in executable_statement_reference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -775,7 +1135,7 @@ int executable_statement_reference (ptr, bp, name) } if (*ptr) { log_error ("Nonnull ptr in executable_statement_reference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -784,20 +1144,23 @@ int executable_statement_reference (ptr, bp, name) } *ptr = bp; bp -> refcnt++; + rc_register (file, line, bp, bp -> refcnt); + dmalloc_reuse (bp, file, line, 1); return 1; } static struct packet *free_packets; -int packet_allocate (ptr, name) +int packet_allocate (ptr, file, line) struct packet **ptr; - const char *name; + const char *file; + int line; { int size; if (!ptr) { log_error ("Null pointer passed to packet_allocate: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -806,7 +1169,7 @@ int packet_allocate (ptr, name) } if (*ptr) { log_error ("Non-null pointer in packet_allocate (%s)", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -814,7 +1177,7 @@ int packet_allocate (ptr, name) #endif } - *ptr = dmalloc (sizeof **ptr, name); + *ptr = dmalloc (sizeof **ptr, file, line); if (*ptr) { memset (*ptr, 0, sizeof **ptr); (*ptr) -> refcnt = 1; @@ -823,14 +1186,15 @@ int packet_allocate (ptr, name) return 0; } -int packet_reference (ptr, bp, name) +int packet_reference (ptr, bp, file, line) struct packet **ptr; struct packet *bp; - const char *name; + const char *file; + int line; { if (!ptr) { log_error ("Null pointer in packet_reference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -839,7 +1203,7 @@ int packet_reference (ptr, bp, name) } if (*ptr) { log_error ("Non-null pointer in packet_reference (%s)", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -848,19 +1212,22 @@ int packet_reference (ptr, bp, name) } *ptr = bp; bp -> refcnt++; + rc_register (file, line, bp, bp -> refcnt); + dmalloc_reuse (bp, file, line, 1); return 1; } -int packet_dereference (ptr, name) +int packet_dereference (ptr, file, line) struct packet **ptr; - const char *name; + const char *file; + int line; { int i; struct packet *packet; if (!ptr || !*ptr) { log_error ("Null pointer in packet_dereference: %s", - name); + file, line); #if defined (POINTER_DEBUG) abort (); #else @@ -871,12 +1238,103 @@ int packet_dereference (ptr, name) packet = *ptr; *ptr = (struct packet *)0; --packet -> refcnt; - if (packet -> refcnt) + rc_register (file, line, packet, packet -> refcnt); + if (packet -> refcnt > 0) return 1; + if (packet -> refcnt < 0) { + log_error ("option_state_dereference: negative refcnt!"); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (); +#endif +#if defined (POINTER_DEBUG) + abort (); +#else + return 0; +#endif + } + if (packet -> options) - option_state_dereference (&packet -> options, name); + option_state_dereference (&packet -> options, file, line); packet -> raw = (struct dhcp_packet *)free_packets; free_packets = packet; + dmalloc_reuse (free_packets, (char *)0, 0); + return 1; +} + +int binding_scope_allocate (ptr, file, line) + struct binding_scope **ptr; + const char *file; + int line; +{ + struct binding_scope *bp; + + if (!ptr) { + log_error ("Null pointer in binding_scope_allocate: %s", + file, line); +#if defined (POINTER_DEBUG) + abort (); +#else + return 0; +#endif + } + + if (*ptr) { + log_error ("Non-null pointer in binding_scope_allocate: %s", + file, line); +#if defined (POINTER_DEBUG) + abort (); +#else + return 0; +#endif + } + + bp = dmalloc (sizeof *bp, file, line); + if (!bp) + return 0; + memset (bp, 0, sizeof *bp); + *ptr = bp; return 1; } + +/* Make a copy of the data in data_string, upping the buffer reference + count if there's a buffer. */ + +void data_string_copy (dest, src, file, line) + struct data_string *dest; + struct data_string *src; + const char *name; + int line; +{ + if (src -> buffer) + buffer_reference (&dest -> buffer, src -> buffer, file, line); + dest -> data = src -> data; + dest -> terminated = src -> terminated; + dest -> len = src -> len; +} + +/* Release the reference count to a data string's buffer (if any) and + zero out the other information, yielding the null data string. */ + +void data_string_forget (data, name) + struct data_string *data; + const char *file; + int line; +{ + if (data -> buffer) + buffer_dereference (&data -> buffer, file, line); + memset (data, 0, sizeof *data); +} + +/* Make a copy of the data in data_string, upping the buffer reference + count if there's a buffer. */ + +void data_string_truncate (dp, len) + struct data_string *dp; + int len; +{ + if (len < dp -> len) { + dp -> terminated = 0; + dp -> len = len; + } +}