/*
Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
under the terms of version 2.1 of the GNU Lesser General Public License
as published by the Free Software Foundation.
This program is distributed in the hope that it would be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Further, this software is distributed without any warranty that it is
free of the rightful claim of any third person regarding infringement
or the like. Any license provided herein, whether implied or
otherwise, applies only to this software file. Patent licenses, if
any, provided herein do not apply to combinations of this program with
other software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
USA.
Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
Mountain View, CA 94043, or:
For further information regarding this notice, see:
*/
/* malloc_check.c For checking dealloc completeness.
This code is as simple as possible and works ok for
reasonable size allocation counts.
It treats allocation as global, and so will not
work very well if an application opens more than one
Dwarf_Debug.
*/
#include <stdio.h>
#include <stdlib.h> /* for exit() and various malloc
prototypes */
#include "config.h"
#include "dwarf_incl.h"
#include "malloc_check.h"
#ifdef WANT_LIBBDWARF_MALLOC_CHECK
/* To turn off printing every entry, just change the define
to set PRINT_MALLOC_DETAILS 0.
*/
#define PRINT_MALLOC_DETAILS 0
#define MC_TYPE_UNKNOWN 0
struct mc_data_s {
a pointer! */
created. */
unsigned char mc_type;
node. */
};
/*
*/
static long mc_data_list_size = 0;
"",
"DW_DLA_STRING",
"DW_DLA_LOC",
"DW_DLA_LOCDESC",
"DW_DLA_ELLIST",
"DW_DLA_BOUNDS",
"DW_DLA_BLOCK",
"DW_DLA_DEBUG",
"DW_DLA_DIE",
"DW_DLA_LINE",
"DW_DLA_ATTR",
"DW_DLA_TYPE",
"DW_DLA_SUBSCR",
"DW_DLA_GLOBAL",
"DW_DLA_ERROR",
"DW_DLA_LIST",
"DW_DLA_LINEBUF",
"DW_DLA_ARANGE",
"DW_DLA_ABBREV",
"DW_DLA_FRAME_OP",
"DW_DLA_CIE",
"DW_DLA_FDE",
"DW_DLA_LOC_BLOCK",
"DW_DLA_FRAME_BLOCK",
"DW_DLA_FUNC",
"DW_DLA_TYPENAME",
"DW_DLA_VAR",
"DW_DLA_WEAK",
"DW_DLA_ADDR",
"DW_DLA_ABBREV_LIST",
"DW_DLA_CHAIN",
"DW_DLA_CU_CONTEXT",
"DW_DLA_FRAME",
"DW_DLA_GLOBAL_CONTEXT",
"DW_DLA_FILE_ENTRY",
"DW_DLA_LINE_CONTEXT",
"DW_DLA_LOC_CHAIN",
"DW_DLA_HASH_TABLE",
"DW_DLA_FUNC_CONTEXT",
"DW_DLA_TYPENAME_CONTEXT",
"DW_DLA_VAR_CONTEXT",
"DW_DLA_WEAK_CONTEXT",
"DW_DLA_PUBTYPES_CONTEXT"
/* Don't forget to expand this list if the list of codes
expands. */
};
static unsigned
{
unsigned long a = addr >> 2;
return a % HASH_TABLE_SIZE;
}
static void
{
"%s addr 0x%lx code %d (%s) entry %ld\n",
}
#else
#endif
/* Create a zeroed struct or die. */
static void *
newone(void)
{
if (newd == 0) {
exit(1);
}
return newd;
}
/* Notify checker that get_alloc has allocated user data. */
void
{
mc_data_list_size += 1;
}
static void
{
"%s: 0x%08lx code %2d (%s) type %s dealloc noted %u ct %u\n",
msg,
(long) data->mc_address,
(unsigned) data->mc_dealloc_noted,
(unsigned) data->mc_dealloc_noted_count);
}
/* newd is a 'dealloc'.
*/
static long
long *addr_match_num,
struct mc_data_s **addr_match,
{
*addr_match = cur;
return cur->mc_alloc_number;
} else {
/* code mismatch */
*addr_match = cur;
return -1;
}
} else {
*addr_match = cur;
return -1;
}
}
}
return -1;
}
/* A dealloc is to take place. Ensure it balances an alloc.
*/
void
{
long prev;
prev =
if (prev < 0) {
"Unbalanced dealloc at index %ld\n", mc_data_list_size);
if (addr_match) {
}
}
abort();
exit(3);
}
}
mc_data_list_size += 1;
}
/* Final check for leaks.
*/
void
{
long i = 0;
long hash_slots_used = 0;
long max_chain_length = 0;
for (; i < HASH_TABLE_SIZE; ++i) {
long cur_chain_length = 0;
if (cur == 0)
continue;
if (cur->mc_dealloc_noted) {
" Duplicate dealloc! entry %ld\n",
}
continue;
} else {
}
} else {
/* mc_type is MC_TYPE_DEALLOC, already checked */
}
}
if (cur_chain_length > max_chain_length) {
}
}
"used=%ld, maxchain=%ld\n",
return;
}
#else
extern void *libdwarf_an_unused_function_so_not_empty_c_file();
#endif /* WANT_LIBBDWARF_MALLOC_CHECK */