07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/*
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe This program is free software; you can redistribute it and/or modify it
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe under the terms of version 2.1 of the GNU Lesser General Public License
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe as published by the Free Software Foundation.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe This program is distributed in the hope that it would be useful, but
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe WITHOUT ANY WARRANTY; without even the implied warranty of
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe Further, this software is distributed without any warranty that it is
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe free of the rightful claim of any third person regarding infringement
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe or the like. Any license provided herein, whether implied or
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe otherwise, applies only to this software file. Patent licenses, if
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe any, provided herein do not apply to combinations of this program with
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe other software, or any other product whatsoever.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe You should have received a copy of the GNU Lesser General Public
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe License along with this program; if not, write the Free Software
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe USA.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe Mountain View, CA 94043, or:
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe http://www.sgi.com
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe For further information regarding this notice, see:
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe http://oss.sgi.com/projects/GenInfo/NoticeExplan
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe*/
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/* malloc_check.c For checking dealloc completeness.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe This code is as simple as possible and works ok for
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe reasonable size allocation counts.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe It treats allocation as global, and so will not
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe work very well if an application opens more than one
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe Dwarf_Debug.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe*/
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#include <stdio.h>
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#include <stdlib.h> /* for exit() and various malloc
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe prototypes */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#include "config.h"
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#include "dwarf_incl.h"
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#include "malloc_check.h"
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#ifdef WANT_LIBBDWARF_MALLOC_CHECK
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/* To turn off printing every entry, just change the define
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe to set PRINT_MALLOC_DETAILS 0.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe*/
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#define PRINT_MALLOC_DETAILS 0
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#define MC_TYPE_UNKNOWN 0
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#define MC_TYPE_ALLOC 1
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#define MC_TYPE_DEALLOC 2
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestruct mc_data_s {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s *mc_prev;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe unsigned long mc_address; /* Assumes this is large enough to hold
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe a pointer! */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long mc_alloc_number; /* Assigned in order by when record
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe created. */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe unsigned char mc_alloc_code; /* Allocation code, libdwarf. */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe unsigned char mc_type;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe unsigned char mc_dealloc_noted; /* Used on an ALLOC node. */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe unsigned char mc_dealloc_noted_count; /* Used on an ALLOC
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe node. */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe};
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/*
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe*/
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#define HASH_TABLE_SIZE 10501
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestatic struct mc_data_s *mc_data_hash[HASH_TABLE_SIZE];
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestatic long mc_data_list_size = 0;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestatic char *alloc_type_name[MAX_DW_DLA + 1] = {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_STRING",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_LOC",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_LOCDESC",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_ELLIST",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_BOUNDS",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_BLOCK",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_DEBUG",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_DIE",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_LINE",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_ATTR",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_TYPE",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_SUBSCR",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_GLOBAL",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_ERROR",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_LIST",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_LINEBUF",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_ARANGE",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_ABBREV",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_FRAME_OP",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_CIE",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_FDE",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_LOC_BLOCK",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_FRAME_BLOCK",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_FUNC",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_TYPENAME",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_VAR",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_WEAK",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_ADDR",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_ABBREV_LIST",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_CHAIN",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_CU_CONTEXT",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_FRAME",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_GLOBAL_CONTEXT",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_FILE_ENTRY",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_LINE_CONTEXT",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_LOC_CHAIN",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_HASH_TABLE",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_FUNC_CONTEXT",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_TYPENAME_CONTEXT",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_VAR_CONTEXT",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_WEAK_CONTEXT",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "DW_DLA_PUBTYPES_CONTEXT"
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe /* Don't forget to expand this list if the list of codes
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe expands. */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe};
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestatic unsigned
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowehash_address(unsigned long addr)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe{
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe unsigned long a = addr >> 2;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe return a % HASH_TABLE_SIZE;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe}
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#if PRINT_MALLOC_DETAILS
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestatic void
07dc1947c362e187fb955d283b692f8769dd5defRichard Loweprint_alloc_dealloc_detail(unsigned long addr,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe int code, char *whichisit)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe{
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "%s addr 0x%lx code %d (%s) entry %ld\n",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe whichisit, addr, code, alloc_type_name[code],
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe mc_data_list_size);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe}
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#else
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#define print_alloc_dealloc_detail(a,b,c) /* nothing */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#endif
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/* Create a zeroed struct or die. */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestatic void *
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowenewone(void)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe{
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s *newd = malloc(sizeof(struct mc_data_s));
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (newd == 0) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr, "out of memory , # %ld\n", mc_data_list_size);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe exit(1);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe memset(newd, 0, sizeof(struct mc_data_s));
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe return newd;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe}
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/* Notify checker that get_alloc has allocated user data. */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowevoid
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowedwarf_malloc_check_alloc_data(void *addr_in, unsigned char code)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe{
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s *newd = newone();
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe unsigned long addr = (unsigned long) addr_in;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s **base = &mc_data_hash[hash_address(addr)];
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe print_alloc_dealloc_detail(addr, code, "alloc ");
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_address = addr;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_alloc_code = code;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_type = MC_TYPE_ALLOC;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_alloc_number = mc_data_list_size;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_prev = *base;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe *base = newd;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_alloc_number = mc_data_list_size;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe mc_data_list_size += 1;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe}
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestatic void
07dc1947c362e187fb955d283b692f8769dd5defRichard Loweprint_entry(char *msg, struct mc_data_s *data)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe{
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "%s: 0x%08lx code %2d (%s) type %s dealloc noted %u ct %u\n",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe msg,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe (long) data->mc_address,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe data->mc_alloc_code,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe alloc_type_name[data->mc_alloc_code],
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe (data->mc_type == MC_TYPE_ALLOC) ? "alloc " :
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe (data->mc_type == MC_TYPE_DEALLOC) ? "dealloc" : "unknown",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe (unsigned) data->mc_dealloc_noted,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe (unsigned) data->mc_dealloc_noted_count);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe}
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/* newd is a 'dealloc'.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe*/
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowestatic long
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowebalanced_by_alloc_p(struct mc_data_s *newd,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long *addr_match_num,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s **addr_match,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s *base)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe{
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s *cur = base;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe for (; cur; cur = cur->mc_prev) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (cur->mc_address == newd->mc_address) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (cur->mc_type == MC_TYPE_ALLOC) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (cur->mc_alloc_code == newd->mc_alloc_code) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe *addr_match = cur;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe *addr_match_num = cur->mc_alloc_number;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe return cur->mc_alloc_number;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe } else {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe /* code mismatch */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe *addr_match = cur;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe *addr_match_num = cur->mc_alloc_number;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe return -1;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe } else {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe /* Unbalanced new/del */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe *addr_match = cur;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe *addr_match_num = cur->mc_alloc_number;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe return -1;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe return -1;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe}
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/* A dealloc is to take place. Ensure it balances an alloc.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe*/
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowevoid
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowedwarf_malloc_check_dealloc_data(void *addr_in, unsigned char code)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe{
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s *newd = newone();
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long prev;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long addr_match_num = -1;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s *addr_match = 0;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe unsigned long addr = (unsigned long) addr_in;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s **base = &mc_data_hash[hash_address(addr)];
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe print_alloc_dealloc_detail(addr, code, "dealloc ");
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_address = (unsigned long) addr;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_alloc_code = code;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_type = MC_TYPE_DEALLOC;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe newd->mc_prev = *base;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe prev =
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe balanced_by_alloc_p(newd, &addr_match_num, &addr_match, *base);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (prev < 0) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "Unbalanced dealloc at index %ld\n", mc_data_list_size);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe print_entry("new", newd);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr, "addr-match_num? %ld\n", addr_match_num);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (addr_match) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe print_entry("prev entry", addr_match);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (addr_match->mc_dealloc_noted > 1) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr, "Above is Duplicate dealloc!\n");
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe abort();
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe exit(3);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe addr_match->mc_dealloc_noted = 1;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe addr_match->mc_dealloc_noted_count += 1;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (addr_match->mc_dealloc_noted_count > 1) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr, "Double dealloc entry %ld\n", addr_match_num);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe print_entry("new dealloc entry", newd);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe print_entry("bad alloc entry", addr_match);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe *base = newd;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe mc_data_list_size += 1;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe}
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe/* Final check for leaks.
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe*/
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowevoid
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowedwarf_malloc_check_complete(char *msg)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe{
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long i = 0;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long total = mc_data_list_size;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long hash_slots_used = 0;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long max_chain_length = 0;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr, "Run complete, %s. %ld entries\n", msg, total);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe for (; i < HASH_TABLE_SIZE; ++i) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe struct mc_data_s *cur = mc_data_hash[i];
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe long cur_chain_length = 0;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (cur == 0)
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe continue;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe ++hash_slots_used;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe for (; cur; cur = cur->mc_prev) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe ++cur_chain_length;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (cur->mc_type == MC_TYPE_ALLOC) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (cur->mc_dealloc_noted) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (cur->mc_dealloc_noted > 1) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr,
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe " Duplicate dealloc! entry %ld\n",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe cur->mc_alloc_number);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe print_entry("duplicate dealloc", cur);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe continue;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe } else {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr, "malloc no dealloc, entry %ld\n",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe cur->mc_alloc_number);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe print_entry("dangle", cur);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe } else {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe /* mc_type is MC_TYPE_DEALLOC, already checked */
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe if (cur_chain_length > max_chain_length) {
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe max_chain_length = cur_chain_length;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe }
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe fprintf(stderr, "mc hash table slots=%ld, "
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe "used=%ld, maxchain=%ld\n",
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe (long) HASH_TABLE_SIZE, hash_slots_used, max_chain_length);
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe return;
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe}
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#else
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Loweextern void *libdwarf_an_unused_function_so_not_empty_c_file();
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe
07dc1947c362e187fb955d283b692f8769dd5defRichard Lowe#endif /* WANT_LIBBDWARF_MALLOC_CHECK */