summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdwarf/common/dwarf_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdwarf/common/dwarf_alloc.c')
-rw-r--r--usr/src/lib/libdwarf/common/dwarf_alloc.c1866
1 files changed, 832 insertions, 1034 deletions
diff --git a/usr/src/lib/libdwarf/common/dwarf_alloc.c b/usr/src/lib/libdwarf/common/dwarf_alloc.c
index ddb423e841..2a4f06de25 100644
--- a/usr/src/lib/libdwarf/common/dwarf_alloc.c
+++ b/usr/src/lib/libdwarf/common/dwarf_alloc.c
@@ -1,61 +1,56 @@
/*
-
Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
- Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
-
- This program is free software; you can redistribute it and/or modify it
- 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:
-
- http://www.sgi.com
-
- For further information regarding this notice, see:
-
- http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ Portions Copyright (C) 2007-2020 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it
+ and/or modify it 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.
*/
-/* The address of the Free Software Foundation is
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- Boston, MA 02110-1301, USA.
- SGI has moved from the Crittenden Lane address.
+/* To see the full set of DW_DLA types and nothing
+ else try:
+ grep DW_DLA dwarf_alloc.c | grep 0x
*/
-
-#undef DEBUG
-
#include "config.h"
-#include "dwarf_incl.h"
#include <sys/types.h>
-
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#ifdef HAVE_MALLOC_H
+/* Useful include for some Windows compilers. */
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H */
#include <stdio.h>
-#include "malloc_check.h"
-
-/*
- These files are included to get the sizes
- of structs to set the ah_bytes_one_struct field
- of the Dwarf_Alloc_Hdr_s structs for each
- allocation type.
+#ifdef HAVE_STDINT_H
+#include <stdint.h> /* For uintptr_t */
+#endif /* HAVE_STDINT_H */
+#include "dwarf_incl.h"
+#include "dwarf_error.h"
+#include "dwarf_alloc.h"
+/* These files are included to get the sizes
+ of structs for malloc.
*/
+#include "dwarf_util.h"
#include "dwarf_line.h"
#include "dwarf_global.h"
#include "dwarf_arange.h"
@@ -67,538 +62,626 @@
#include "dwarf_types.h"
#include "dwarf_vars.h"
#include "dwarf_weaks.h"
+#include "dwarf_harmless.h"
+#include "dwarf_tsearch.h"
+#include "dwarf_gdbindex.h"
+#include "dwarf_xu_index.h"
+#include "dwarf_macro5.h"
+#include "dwarf_dnames.h"
+#include "dwarf_rnglists.h"
+#include "dwarf_dsc.h"
+#include "dwarfstring.h"
+#include "dwarf_str_offsets.h"
+
+#define TRUE 1
+#define FALSE 0
+/* Some allocations are simple some not. These reduce
+ the issue of determining which sort of thing to a simple
+ test. See ia_multiply_count
+ Usually when MULTIPLY_NO is set the count
+ is 1, so MULTIPY_CT would work as well. */
+#define MULTIPLY_NO 0
+#define MULTIPLY_CT 1
+#define MULTIPLY_SP 2
+/* This translates into de_alloc_hdr into a per-instance size
+ and allows room for a constructor/destructor pointer.
+ Rearranging the DW_DLA values would break binary compatibility
+ so that is not an option.
+*/
+struct ial_s {
+ /* In bytes, one struct instance. */
+ short ia_struct_size;
+ /* Not a count, but a MULTIPLY{_NO,_CT,_SP} value. */
+ short ia_multiply_count;
-static void _dwarf_free_special_error(Dwarf_Ptr space);
+ /* When we really need a constructor/destructor
+ these make applying such quite simple. */
+ int (*specialconstructor) (Dwarf_Debug, void *);
+ void (*specialdestructor) (void *);
+};
-#ifdef DWARF_SIMPLE_MALLOC
-static void _dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg,
- Dwarf_Ptr addr,
- unsigned long size,
- short alloc_type);
-static void _dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg,
- Dwarf_Ptr space,
- short alloc_type);
-void _dwarf_simple_malloc_botch(int err);
+/* Used as a way to return meaningful errors when
+ the malloc arena is exhausted (when malloc returns NULL).
+ Not normally used.
+ New in December 2014.*/
+struct Dwarf_Error_s _dwarf_failsafe_error = {
+ DW_DLE_FAILSAFE_ERRVAL,
+ 0,
+ 1
+};
-#endif /* DWARF_SIMPLE_MALLOC */
+/* If non-zero (the default) de_alloc_tree (see dwarf_alloc.c)
+ is used normally. If zero then dwarf allocations
+ are not tracked by libdwarf and dwarf_finish() cannot
+ clean up any per-Dwarf_Debug allocations the
+ caller forgot to dealloc. */
+static signed char global_de_alloc_tree_on = 1;
+#ifdef HAVE_GLOBAL_ALLOC_SUMS
+static Dwarf_Unsigned global_allocation_count;
+static Dwarf_Unsigned global_allocation_total;
+static Dwarf_Unsigned global_de_alloc_tree_count;
+static Dwarf_Unsigned global_de_alloc_tree_total;
+static Dwarf_Unsigned global_de_alloc_tree_early_dealloc_count;
+static Dwarf_Unsigned global_de_alloc_tree_early_dealloc_size;
+#endif /* HAVE_GLOBAL_ALLOC_SUMS */
+
+void _dwarf_alloc_tree_counts( UNUSEDARG Dwarf_Unsigned *allocount,
+ UNUSEDARG Dwarf_Unsigned *allosum,
+ UNUSEDARG Dwarf_Unsigned *treecount,
+ UNUSEDARG Dwarf_Unsigned *treesum,
+ UNUSEDARG Dwarf_Unsigned *earlydealloccount,
+ UNUSEDARG Dwarf_Unsigned *earlydeallocsize,
+ UNUSEDARG Dwarf_Unsigned *unused1,
+ UNUSEDARG Dwarf_Unsigned *unused2,
+ UNUSEDARG Dwarf_Unsigned *unused3)
+{
+#ifdef HAVE_GLOBAL_ALLOC_SUMS
+ *allocount = global_allocation_count;
+ *allosum = global_allocation_total;
+ *treecount = global_de_alloc_tree_count;
+ *treesum = global_de_alloc_tree_total;
+ *earlydealloccount =
+ global_de_alloc_tree_early_dealloc_count;
+ *earlydeallocsize =
+ global_de_alloc_tree_early_dealloc_size;
+ if (unused1) {
+ *unused1 = 0;
+ }
+ if (unused2) {
+ *unused2 = 0;
+ }
+ if (unused3) {
+ *unused3 = 0;
+ }
+#endif /* HAVE_GLOBAL_ALLOC_SUMS */
+}
+/* Defined March 7 2020. Allows a caller to
+ avoid most tracking by the de_alloc_tree hash
+ table if called with v of zero.
+ Returns the value the flag was before this call. */
+int dwarf_set_de_alloc_flag(int v)
+{
+ int ov = global_de_alloc_tree_on;
+ global_de_alloc_tree_on = v;
+ return ov;
+}
-/*
- This macro adds the size of a pointer to the size of a
- struct that is given to it. It rounds up the size to
- be a multiple of the size of a pointer. This is done
- so that every struct returned by _dwarf_get_alloc()
- can be preceded by a pointer to the chunk it came from.
- Before allocating, it checks if the size of struct is less than
- the size of a pointer. If yes, it returns the size
- of 2 pointers. The returned size should be at least
- the size of 2 pointers, since the first points to the
- chunk the struct was allocated from, and the second
- is used to link the free list.
-
- We want DW_RESERVE to be at least the size of
- a long long and at least the size of a pointer because
- our struct has a long long and we want that aligned right.
- Now Standard C defines long long as 8 bytes, so lets
- make that standard. It will become unworkable when
- long long or pointer grows beyound 8 bytes.
- Unclear what to do with wierd requirements, like
- 36 bit pointers.
+void
+_dwarf_error_destructor(void *m)
+{
+ Dwarf_Error er = (Dwarf_Error)m;
+ dwarfstring *erm = (dwarfstring *)er->er_msg;
+ if (! erm) {
+ return;
+ }
+#if DEBUG
+ printf("libdwarfdetector DEALLOC Now destruct error string %s\n",dwarfstring_string(erm));
+#endif
+ dwarfstring_destructor(erm);
+ free(erm);
+ er->er_msg = 0;
+ return;
+}
+/* To do destructors we need some extra data in every
+ _dwarf_get_alloc situation. */
+/* Here is the extra we malloc for a prefix. */
+struct reserve_size_s {
+ void *dummy_rsv1;
+ void *dummy_rsv2;
+};
+/* Here is how we use the extra prefix area. */
+struct reserve_data_s {
+ void *rd_dbg;
+ unsigned short rd_length;
+ unsigned short rd_type;
+};
+#define DW_RESERVE sizeof(struct reserve_size_s)
-*/
-#define DW_RESERVE 8
-/* Round size up to the next multiple of DW_RESERVE bytes
-*/
-#define ROUND_SIZE(inputsize) \
- (((inputsize) % (DW_RESERVE)) == 0 ? \
- (inputsize): \
- ((inputsize) + \
- (DW_RESERVE) - ((inputsize) % (DW_RESERVE)) ))
-
-#define ROUND_SIZE_WITH_POINTER(i_size) (ROUND_SIZE(i_size) + DW_RESERVE)
-
-/* SMALL_ALLOC is for trivia where allocation is a waste.
- Things that should be removed, really. */
-#define SMALL_ALLOC 2
-
-/* BASE_ALLOC is where a basic allocation makes sense, but 'not too large'.
- No thorough evaluation of this value has been done, though
- it was found wasteful of memory to have BASE_ALLOC be as large as
- BIG_ALLOC. */
-#define BASE_ALLOC 64
-
-/* BIG_ALLOC is where a larger-than-BASE_ALLOC
- allocation makes sense, but still 'not too large'.
- No thorough evaluation of this value has been done. */
-#define BIG_ALLOC 128
-
-/* This translates into de_alloc_hdr index
-** the 0,1,1 entries are special: they don't use the
-** table values at all.
-** Rearranging the DW_DLA values would break binary compatibility
-** so that is not an option.
-*/
-struct ial_s {
- int ia_al_num; /* Index into de_alloc_hdr table. */
+static const
+struct ial_s alloc_instance_basics[ALLOC_AREA_INDEX_TABLE_MAX] = {
+ /* 0 none */
+ { 1,MULTIPLY_NO, 0, 0},
- /* In bytes, one struct instance. This does not account for extra
- space needed per block, but that (DW_RESERVE) will be added in
- later where it is needed (DW_RESERVE space never added in here).
- */
- int ia_struct_size;
+ /* 0x1 x1 DW_DLA_STRING */
+ { 1,MULTIPLY_CT, 0, 0},
+ /* 0x2 DW_DLA_LOC */
+ { sizeof(Dwarf_Loc),MULTIPLY_NO, 0, 0} ,
- /* Number of instances per alloc block. MUST be > 0. */
- int ia_base_count;
+ /* x3 DW_DLA_LOCDESC */
+ { sizeof(Dwarf_Locdesc),MULTIPLY_NO, 0, 0},
- int (*specialconstructor) (Dwarf_Debug, void *);
- void (*specialdestructor) (void *);
-};
+ /* 0x4 DW_DLA_ELLIST */ /* not used */
+ { 1,MULTIPLY_NO, 0, 0},
-static const
-struct ial_s index_into_allocated[ALLOC_AREA_INDEX_TABLE_MAX] = {
- {0, 1, 1, 0, 0}, /* none */
- {0, 1, 1, 0, 0}, /* 1 DW_DLA_STRING */
- {1, sizeof(Dwarf_Loc), BASE_ALLOC, 0, 0}
- , /* 2 DW_DLA_LOC */
- {2, sizeof(Dwarf_Locdesc), BASE_ALLOC, 0, 0}
- , /* 3 DW_DLA_LOCDESC */
- {0, 1, 1, 0, 0}
- , /* not used *//* 4 DW_DLA_ELLIST */
- {0, 1, 1, 0, 0}
- , /* not used *//* 5 DW_DLA_BOUNDS */
- {3, sizeof(Dwarf_Block), BASE_ALLOC, 0, 0}
- , /* 6 DW_DLA_BLOCK */
- {0, 1, 1, 0, 0}
- , /* the actual dwarf_debug structure *//* 7 DW_DLA_DEBUG */
- {4, sizeof(struct Dwarf_Die_s), BIG_ALLOC, 0, 0}, /* 8 DW_DLA_DIE
- */
- {5, sizeof(struct Dwarf_Line_s), BIG_ALLOC, 0, 0}, /* 9
- DW_DLA_LINE */
- {6, sizeof(struct Dwarf_Attribute_s), BIG_ALLOC * 2, 0, 0},
- /* 10 DW_DLA_ATTR */
- {0, 1, 1, 0, 0}, /* not used *//* 11 DW_DLA_TYPE */
- {0, 1, 1, 0, 0}, /* not used *//* 12 DW_DLA_SUBSCR */
- {7, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 13
- DW_DLA_GLOBAL
- */
- {8, sizeof(struct Dwarf_Error_s), BASE_ALLOC, 0, 0}, /* 14
- DW_DLA_ERROR
- */
- {0, 1, 1, 0, 0}, /* 15 DW_DLA_LIST */
- {0, 1, 1, 0, 0}, /* not used *//* 16 DW_DLA_LINEBUF */
- {9, sizeof(struct Dwarf_Arange_s), BASE_ALLOC, 0, 0}, /* 17
- DW_DLA_ARANGE
- */
- {10, sizeof(struct Dwarf_Abbrev_s), BIG_ALLOC, 0, 0}, /* 18
- DW_DLA_ABBREV
- */
- {11, sizeof(Dwarf_Frame_Op), BIG_ALLOC, 0, 0}
- , /* 19 DW_DLA_FRAME_OP */
- {12, sizeof(struct Dwarf_Cie_s), BASE_ALLOC, 0, 0}, /* 20
- DW_DLA_CIE */
- {13, sizeof(struct Dwarf_Fde_s), BASE_ALLOC, 0, 0}, /* 21 DW_DLA_FDE */
- {0, 1, 1, 0, 0}, /* 22 DW_DLA_LOC_BLOCK */
- {0, 1, 1, 0, 0}, /* 23 DW_DLA_FRAME_BLOCK */
- {14, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 24 DW_DLA_FUNC
- UNUSED */
- {15, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 25
- DW_DLA_TYPENAME
- UNUSED */
- {16, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 26 DW_DLA_VAR
- UNUSED */
- {17, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0}, /* 27 DW_DLA_WEAK
- UNUSED */
- {0, 1, 1, 0, 0}, /* 28 DW_DLA_ADDR */
- {0, 1,1,0,0 }, /* 29 DW_DLA_RANGES */
-
- /* The following DW_DLA data types
- are known only inside libdwarf. */
-
- {18, sizeof(struct Dwarf_Abbrev_List_s), BIG_ALLOC, 0, 0},
- /* 30 DW_DLA_ABBREV_LIST */
-
- {19, sizeof(struct Dwarf_Chain_s), BIG_ALLOC, 0, 0}, /* 31 DW_DLA_CHAIN */
- {20, sizeof(struct Dwarf_CU_Context_s), BASE_ALLOC, 0, 0},
- /* 32 DW_DLA_CU_CONTEXT */
- {21, sizeof(struct Dwarf_Frame_s), BASE_ALLOC,
- _dwarf_frame_constructor,
- _dwarf_frame_destructor}, /* 33 DW_DLA_FRAME */
- {22, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
- /* 34 DW_DLA_GLOBAL_CONTEXT */
- {23, sizeof(struct Dwarf_File_Entry_s), BASE_ALLOC, 0, 0}, /* 34 */
- /* 35 DW_DLA_FILE_ENTRY */
- {24, sizeof(struct Dwarf_Line_Context_s), BASE_ALLOC, 0, 0},
- /* 36 DW_DLA_LINE_CONTEXT */
- {25, sizeof(struct Dwarf_Loc_Chain_s), BASE_ALLOC, 0, 0}, /* 36 */
- /* 37 DW_DLA_LOC_CHAIN */
-
- {26, sizeof(struct Dwarf_Hash_Table_s),BASE_ALLOC, 0, 0}, /* 37 */
- /* 38 DW_DLA_HASH_TABLE */
-
-/* The following really use Global struct: used to be unique struct
- per type, but now merged (11/99). The opaque types
- are visible in the interface. The types for
- DW_DLA_FUNC,
- DW_DLA_TYPENAME, DW_DLA_VAR, DW_DLA_WEAK also use
- the global types.
-
-*/
- {27, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
- /* 39 DW_DLA_FUNC_CONTEXT */
- {28, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
- /* 40 DW_DLA_TYPENAME_CONTEXT */
- {29, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
- /* 41 DW_DLA_VAR_CONTEXT */
- {30, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
- /* 42 DW_DLA_WEAK_CONTEXT */
- {31, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
- /* 43 DW_DLA_PUBTYPES_CONTEXT DWARF3 */
+ /* 0x5 DW_DLA_BOUNDS */ /* not used */
+ { 1,MULTIPLY_NO, 0, 0},
- {0,1,1,0,0 },
- /* 44 DW_DLA_HASH_TABLE_ENTRY */
+ /* 0x6 DW_DLA_BLOCK */
+ { sizeof(Dwarf_Block),MULTIPLY_NO, 0, 0},
+ /* x7 DW_DLA_DEBUG */
+ /* the actual dwarf_debug structure */
+ { 1,MULTIPLY_NO, 0, 0} ,
-};
+ /* x8 DW_DLA_DIE */
+ {sizeof(struct Dwarf_Die_s),MULTIPLY_NO, 0, 0},
-#ifndef DWARF_SIMPLE_MALLOC
+ /* x9 DW_DLA_LINE */
+ {sizeof(struct Dwarf_Line_s),MULTIPLY_NO, 0, 0},
-/*
- This function is given a pointer to the header
- structure that is used to allocate 1 struct of
- the type given by alloc_type. It first checks
- if a struct is available in its free list. If
- not, it checks if 1 is available in its blob,
- which is a chunk of memory that is reserved for
- its use. If not, it malloc's a chunk. The
- initial part of it is used to store the end
- address of the chunk, and also to keep track
- of the number of free structs in that chunk.
- This information is used for freeing the chunk
- when all the structs in it are free.
-
- Assume all input arguments have been validated.
-
- This function can be used only to allocate 1
- struct of the given type.
-
- It returns a pointer to the struct that the
- user can use. It returns NULL only when it
- is out of free structs, and cannot malloc
- any more. The struct returned is zero-ed.
-
- A pointer to the chunk that the struct belongs
- to is stored in the bytes preceding the
- returned address. Since this pointer it
- never overwritten, when a struct is allocated
- from the free_list this pointer does not
- have to be written. In the 2 other cases,
- where the struct is allocated from a new
- chunk, or the blob, a pointer to the chunk
- is written.
-*/
-static Dwarf_Ptr
-_dwarf_find_memory(Dwarf_Alloc_Hdr alloc_hdr)
-{
- /* Pointer to the struct allocated. */
- Dwarf_Small *ret_mem = 0;
+ /* 0xa 10 DW_DLA_ATTR */
+ {sizeof(struct Dwarf_Attribute_s),MULTIPLY_NO, 0, 0},
- /* Pointer to info about chunks allocated. */
- Dwarf_Alloc_Area alloc_area;
+ /* 0xb DW_DLA_TYPE *//* not used */
+ {1,MULTIPLY_NO, 0, 0},
- /* Size of chunk malloc'ed when no free structs left. */
- Dwarf_Signed mem_block_size;
+ /* 0xc DW_DLA_SUBSCR *//* not used */
+ {1,MULTIPLY_NO, 0, 0},
- /* Pointer to block malloc'ed. */
- Dwarf_Small *mem_block;
+ /* 0xd 13 DW_DLA_GLOBAL */
+ {sizeof(struct Dwarf_Global_s),MULTIPLY_NO, 0, 0},
- /*
- Check the alloc_area from which the last allocation was made
- (most recent new block). If that is not successful, then search
- the list of alloc_area's from alloc_header. */
- alloc_area = alloc_hdr->ah_last_alloc_area;
- if (alloc_area == NULL || alloc_area->aa_free_structs_in_chunk == 0)
- for (alloc_area = alloc_hdr->ah_alloc_area_head;
- alloc_area != NULL; alloc_area = alloc_area->aa_next) {
+ /* 0xe 14 DW_DLA_ERROR */
+ {sizeof(struct Dwarf_Error_s),MULTIPLY_NO, 0,
+ _dwarf_error_destructor},
- if (alloc_area->aa_free_structs_in_chunk > 0) {
- break; /* found a free entry! */
- }
+ /* 0xf DW_DLA_LIST */
+ {sizeof(Dwarf_Ptr),MULTIPLY_CT, 0, 0},
- }
+ /* 0x10 DW_DLA_LINEBUF */ /* not used */
+ {1,MULTIPLY_NO, 0, 0},
- if (alloc_area != NULL) {
- alloc_area->aa_free_structs_in_chunk--;
-
- if (alloc_area->aa_free_list != NULL) {
- ret_mem = alloc_area->aa_free_list;
-
- /*
- Update the free list. The initial part of the struct is
- used to hold a pointer to the next struct on the free
- list. In this way, the free list chain is maintained at
- 0 memory cost. */
- alloc_area->aa_free_list =
- ((Dwarf_Free_List) ret_mem)->fl_next;
- } else if (alloc_area->aa_blob_start < alloc_area->aa_blob_end) {
- ret_mem = alloc_area->aa_blob_start;
-
- /*
- Store pointer to chunk this struct belongs to in the
- first few bytes. Return pointer to bytes after this
- pointer storage. */
- *(Dwarf_Alloc_Area *) ret_mem = alloc_area;
- ret_mem += DW_RESERVE;
-
- alloc_area->aa_blob_start += alloc_hdr->ah_bytes_one_struct;
- } else {
- /* else fall thru , though it should be impossible to fall
- thru. And represents a disastrous programming error if
- we get here. */
-#ifdef DEBUG
- fprintf(stderr, "libdwarf Internal error start %x end %x\n",
- (int) alloc_area->aa_blob_start,
- (int) alloc_area->aa_blob_end);
-#endif
- }
- }
+ /* 0x11 17 DW_DLA_ARANGE */
+ {sizeof(struct Dwarf_Arange_s),MULTIPLY_NO, 0, 0},
- /* New memory has to malloc'ed since there are no free structs. */
- if (ret_mem == 0) {
- Dwarf_Word rounded_area_hdr_size;
+ /* 0x12 18 DW_DLA_ABBREV */
+ {sizeof(struct Dwarf_Abbrev_s),MULTIPLY_NO, 0, 0},
- alloc_hdr->ah_chunks_allocated++;
+ /* 0x13 19 DW_DLA_FRAME_OP */
+ {sizeof(Dwarf_Frame_Op),MULTIPLY_NO, 0, 0} ,
- { /* this nonsense avoids a warning */
- /* CONSTCOND would be better */
- unsigned long v = sizeof(struct Dwarf_Alloc_Area_s);
+ /* 0x14 20 DW_DLA_CIE */
+ {sizeof(struct Dwarf_Cie_s),MULTIPLY_NO, 0, 0},
- rounded_area_hdr_size = ROUND_SIZE(v);
- }
+ /* 0x15 DW_DLA_FDE */
+ {sizeof(struct Dwarf_Fde_s),MULTIPLY_NO, 0,
+ _dwarf_fde_destructor},
- /*
- Allocate memory to contain the required number of structs
- and the Dwarf_Alloc_Area_s to control it. */
- mem_block_size = alloc_hdr->ah_bytes_malloc_per_chunk +
- rounded_area_hdr_size;
+ /* 0x16 DW_DLA_LOC_BLOCK */
+ {sizeof(Dwarf_Loc),MULTIPLY_CT, 0, 0},
- mem_block = malloc(mem_block_size);
- if (mem_block == NULL) {
- return (NULL);
- }
+ /* 0x17 DW_DLA_FRAME_BLOCK */
+ {sizeof(Dwarf_Frame_Op),MULTIPLY_CT, 0, 0},
+ /* 0x18 DW_DLA_FUNC UNUSED */
+ {sizeof(struct Dwarf_Global_s),MULTIPLY_NO, 0, 0},
- /*
- Attach the Dwarf_Alloc_Area_s struct to the list of chunks
- malloc'ed for this struct type. Also initialize the fields
- of the Dwarf_Alloc_Area_s. */
- alloc_area = (Dwarf_Alloc_Area) mem_block;
- alloc_area->aa_prev = 0;
- if (alloc_hdr->ah_alloc_area_head != NULL) {
- alloc_hdr->ah_alloc_area_head->aa_prev = alloc_area;
- }
- alloc_area->aa_free_list = 0;
- alloc_area->aa_next = alloc_hdr->ah_alloc_area_head;
- alloc_hdr->ah_alloc_area_head = alloc_area;
-
- alloc_area->aa_alloc_hdr = alloc_hdr;
- alloc_area->aa_free_structs_in_chunk =
- (Dwarf_Sword) alloc_hdr->ah_structs_per_chunk - 1;
- if (alloc_area->aa_free_structs_in_chunk < 1) {
- /* If we get here, there is a disastrous programming error
- somewhere. */
-#ifdef DEBUG
- fprintf(stderr,
- "libdwarf Internal error: free structs in chunk %d\n",
- (int) alloc_area->aa_free_structs_in_chunk);
-#endif
- return NULL;
- }
+ /* 0x19 DW_DLA_TYPENAME UNUSED */
+ {sizeof(struct Dwarf_Global_s),MULTIPLY_NO, 0, 0},
- /*
- The struct returned begins immediately after the
- Dwarf_Alloc_Area_s struct. */
- ret_mem = mem_block + rounded_area_hdr_size;
- alloc_area->aa_blob_start =
- ret_mem + alloc_hdr->ah_bytes_one_struct;
- alloc_area->aa_blob_end = mem_block + mem_block_size;
-
- /*
- Store pointer to chunk this struct belongs to in the first
- few bytes. Return pointer to bytes after this pointer
- storage. */
- *(Dwarf_Alloc_Area *) ret_mem = alloc_area;
- ret_mem += DW_RESERVE;
- }
+ /* 0x1a DW_DLA_VAR UNUSED */
+ {sizeof(struct Dwarf_Global_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x1b DW_DLA_WEAK UNUSED */
+ {sizeof(struct Dwarf_Global_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x1c DW_DLA_ADDR */
+ {1,MULTIPLY_SP, 0, 0},
+
+ /* 0x1d DW_DLA_RANGES */
+ {sizeof(Dwarf_Ranges),MULTIPLY_CT, 0,0 },
+
+ /* The following DW_DLA data types
+ are known only inside libdwarf. */
+
+ /* 0x1e DW_DLA_ABBREV_LIST */
+ { sizeof(struct Dwarf_Abbrev_List_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x1f DW_DLA_CHAIN */
+ {sizeof(struct Dwarf_Chain_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x20 DW_DLA_CU_CONTEXT */
+ {sizeof(struct Dwarf_CU_Context_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x21 DW_DLA_FRAME */
+ {sizeof(struct Dwarf_Frame_s),MULTIPLY_NO,
+ _dwarf_frame_constructor,
+ _dwarf_frame_destructor},
+
+ /* 0x22 DW_DLA_GLOBAL_CONTEXT */
+ {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x23 DW_DLA_FILE_ENTRY */
+ {sizeof(struct Dwarf_File_Entry_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x24 DW_DLA_LINE_CONTEXT */
+ {sizeof(struct Dwarf_Line_Context_s),MULTIPLY_NO,
+ _dwarf_line_context_constructor,
+ _dwarf_line_context_destructor},
+
+ /* 0x25 DW_DLA_LOC_CHAIN */
+ {sizeof(struct Dwarf_Loc_Chain_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x26 0x26 DW_DLA_HASH_TABLE */
+ {sizeof(struct Dwarf_Hash_Table_s),MULTIPLY_NO, 0, 0},
- alloc_hdr->ah_last_alloc_area = alloc_area;
- alloc_hdr->ah_struct_user_holds++;
- memset(ret_mem, 0, alloc_hdr->ah_bytes_one_struct - DW_RESERVE);
- return (ret_mem);
+ /* The following really use Global struct: used to be unique struct
+ per type, but now merged (11/99). The opaque types
+ are visible in the interface. The types for
+ DW_DLA_FUNC, DW_DLA_TYPENAME, DW_DLA_VAR, DW_DLA_WEAK also use
+ the global types. */
+
+ /* 0x27 DW_DLA_FUNC_CONTEXT */
+ {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x28 40 DW_DLA_TYPENAME_CONTEXT */
+ {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x29 41 DW_DLA_VAR_CONTEXT */
+ {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x2a 42 DW_DLA_WEAK_CONTEXT */
+ {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x2b 43 DW_DLA_PUBTYPES_CONTEXT DWARF3 */
+ {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x2c 44 DW_DLA_HASH_TABLE_ENTRY */
+ {sizeof(struct Dwarf_Hash_Table_Entry_s),MULTIPLY_CT,0,0 },
+
+ /* 0x2d -0x34 reserved */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x2e 46 reserved for future use */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x2f 47 reserved for future use */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x30 reserved for future internal use */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x31 reserved for future internal use */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x32 50 reserved for future internal use */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x33 51 reserved for future internal use */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x34 52 reserved for future internal use */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x35 53 reserved for future use. */
+ {sizeof(int),MULTIPLY_NO, 0, 0},
+
+ /* 0x36 54 Used starting May 2020 DW_DLA_RNGLISTS_HEAD */
+ {sizeof(struct Dwarf_Rnglists_Head_s),MULTIPLY_NO, 0,
+ _dwarf_rnglists_head_destructor},
+
+ /* now, we have types that are public. */
+ /* 0x37 55. New in June 2014. Gdb. */
+ {sizeof(struct Dwarf_Gdbindex_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x38 56. New in July 2014. */
+ /* DWARF5 DebugFission dwp file sections
+ .debug_cu_index and .debug_tu_index . */
+ {sizeof(struct Dwarf_Xu_Index_Header_s),MULTIPLY_NO, 0, 0},
+
+ /* These required by new features in DWARF5. Also usable
+ for DWARF2,3,4. */
+ /* 0x39 57 DW_DLA_LOC_BLOCK_C DWARF5 */
+ {sizeof(struct Dwarf_Loc_Expr_Op_s),MULTIPLY_CT, 0, 0},
+
+ /* 0x3a 58 DW_DLA_LOCDESC_C */
+ {sizeof(struct Dwarf_Locdesc_c_s),MULTIPLY_CT, 0, 0},
+
+ /* 0x3b 59 DW_DLA_LOC_HEAD_C */
+ {sizeof(struct Dwarf_Loc_Head_c_s),MULTIPLY_NO, 0, 0},
+
+ /* 0x3c 60 DW_DLA_MACRO_CONTEXT */
+ {sizeof(struct Dwarf_Macro_Context_s),MULTIPLY_NO,
+ _dwarf_macro_constructor,
+ _dwarf_macro_destructor},
+
+ /* 0x3d 61 DW_DLA_CHAIN_2 */
+ {sizeof(struct Dwarf_Chain_o),MULTIPLY_NO, 0, 0},
+
+ /* 0x3e 62 DW_DLA_DSC_HEAD */
+ {sizeof(struct Dwarf_Dsc_Head_s),MULTIPLY_NO, 0,
+ _dwarf_dsc_destructor},
+
+ /* 0x3f 63 DW_DLA_DNAMES_HEAD */
+ {sizeof(struct Dwarf_Dnames_Head_s),MULTIPLY_NO, 0,
+ _dwarf_debugnames_destructor},
+
+ /* 0x40 64 DW_DLA_STR_OFFSETS */
+ {sizeof(struct Dwarf_Str_Offsets_Table_s),MULTIPLY_NO, 0,0},
+};
+
+/* We are simply using the incoming pointer as the key-pointer.
+*/
+
+static DW_TSHASHTYPE
+simple_value_hashfunc(const void *keyp)
+{
+ DW_TSHASHTYPE up = (DW_TSHASHTYPE)(uintptr_t)keyp;
+ return up;
+}
+/* We did alloc something but not a fixed-length thing.
+ Instead, it starts with some special data we noted.
+ The incoming pointer is to the caller data, we
+ destruct based on caller, but find the special
+ extra data in a prefix area. */
+static void
+tdestroy_free_node(void *nodep)
+{
+ char * m = (char *)nodep;
+ char * malloc_addr = m - DW_RESERVE;
+ struct reserve_data_s * reserve =(struct reserve_data_s *)malloc_addr;
+ unsigned type = reserve->rd_type;
+ if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
+ /* Internal error, corrupted data. */
+ return;
+ }
+ if(!reserve->rd_dbg) {
+ /* Unused (corrupted?) node in the tree.
+ Should never happen. */
+ return;
+ }
+ if(!reserve->rd_type) {
+ /* Unused (corrupted?) node in the tree.
+ Should never happen. */
+ return;
+ }
+ if (alloc_instance_basics[type].specialdestructor) {
+ alloc_instance_basics[type].specialdestructor(m);
+ }
+ free(malloc_addr);
}
-#endif /* ndef DWARF_SIMPLE_MALLOC */
+/* The sort of hash table entries result in very simple helper functions. */
+static int
+simple_compare_function(const void *l, const void *r)
+{
+ DW_TSHASHTYPE lp = (DW_TSHASHTYPE)(uintptr_t)l;
+ DW_TSHASHTYPE rp = (DW_TSHASHTYPE)(uintptr_t)r;
+ if(lp < rp) {
+ return -1;
+ }
+ if(lp > rp) {
+ return 1;
+ }
+ return 0;
+}
-/*
- This function returns a pointer to a region
+/* This function returns a pointer to a region
of memory. For alloc_types that are not
strings or lists of pointers, only 1 struct
can be requested at a time. This is indicated
- by an input count of 1. For strings, count
+ by an input count of 1. For strings, count
equals the length of the string it will
contain, i.e it the length of the string
plus 1 for the terminating null. For lists
of pointers, count is equal to the number of
- pointers. For DW_DLA_FRAME_BLOCK, DW_DLA_RANGES, and
+ pointers. For DW_DLA_FRAME_BLOCK, DW_DLA_RANGES, and
DW_DLA_LOC_BLOCK allocation types also, count
is the count of the number of structs needed.
- This function cannot be used to allocate a
- Dwarf_Debug_s struct.
+ This function cannot be used to allocate a
+ Dwarf_Debug_s struct. */
-*/
-Dwarf_Ptr
+char *
_dwarf_get_alloc(Dwarf_Debug dbg,
- Dwarf_Small alloc_type, Dwarf_Unsigned count)
+ Dwarf_Small alloc_type, Dwarf_Unsigned count)
{
- Dwarf_Alloc_Hdr alloc_hdr;
-
- Dwarf_Ptr ret_mem;
-
+ char * alloc_mem = 0;
+ Dwarf_Signed basesize = 0;
Dwarf_Signed size = 0;
- unsigned int index;
unsigned int type = alloc_type;
+ short action = 0;
if (dbg == NULL) {
- return (NULL);
+ return NULL;
}
-
if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
/* internal error */
return NULL;
}
- index = index_into_allocated[type].ia_al_num;
- /* zero also illegal but not tested for */
-
- /* If the Dwarf_Debug is not fully set up, we will get index 0 for
- any type and must do something. 'Not fully set up' can only
- happen for DW_DLA_ERROR, I (davea) believe, and for that we call
- special code here.. */
-
- if (index == 0) {
- if (alloc_type == DW_DLA_STRING) {
- size = count;
- } else if (alloc_type == DW_DLA_LIST) {
- size = count * sizeof(Dwarf_Ptr);
- } else if (alloc_type == DW_DLA_FRAME_BLOCK) {
- size = count * sizeof(Dwarf_Frame_Op);
- } else if (alloc_type == DW_DLA_LOC_BLOCK) {
- size = count * sizeof(Dwarf_Loc);
- } else if (alloc_type == DW_DLA_HASH_TABLE_ENTRY) {
- size = count * sizeof(struct Dwarf_Hash_Table_Entry_s);
- } else if (alloc_type == DW_DLA_ADDR) {
- size = count *
- (sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ?
- sizeof(Dwarf_Addr) : sizeof(Dwarf_Off));
- } else if (alloc_type == DW_DLA_RANGES) {
- size = count * sizeof(Dwarf_Ranges);
- } else if (alloc_type == DW_DLA_ERROR) {
- void *m = _dwarf_special_no_dbg_error_malloc();
-
- dwarf_malloc_check_alloc_data(m, DW_DLA_ERROR);
- return m;
-
- } else {
- /* If we get here, there is a disastrous programming error
- somewhere. */
-#ifdef DEBUG
- fprintf(stderr,
- "libdwarf Internal error: type %d unexpected\n",
- (int) type);
-#endif
+ basesize = alloc_instance_basics[alloc_type].ia_struct_size;
+ action = alloc_instance_basics[alloc_type].ia_multiply_count;
+ if(action == MULTIPLY_NO) {
+ /* Usually count is 1, but do not assume it. */
+ size = basesize;
+ } else if (action == MULTIPLY_CT) {
+ size = basesize * count;
+ } else {
+ /* MULTIPLY_SP */
+ /* DW_DLA_ADDR.. count * largest size */
+ size = count *
+ (sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ?
+ sizeof(Dwarf_Addr) : sizeof(Dwarf_Off));
+ }
+ size += DW_RESERVE;
+ alloc_mem = malloc(size);
+ if (!alloc_mem) {
+ return NULL;
+ }
+ {
+ char * ret_mem = alloc_mem + DW_RESERVE;
+ void *key = ret_mem;
+ struct reserve_data_s *r = (struct reserve_data_s*)alloc_mem;
+ void *result = 0;
+
+ memset(alloc_mem, 0, size);
+ /* We are not actually using rd_dbg, we are using rd_type. */
+ r->rd_dbg = dbg;
+ r->rd_type = alloc_type;
+ r->rd_length = size;
+ if (alloc_instance_basics[type].specialconstructor) {
+ int res = alloc_instance_basics[type].
+ specialconstructor(dbg, ret_mem);
+ if (res != DW_DLV_OK) {
+ /* We leak what we allocated in
+ _dwarf_find_memory when
+ constructor fails. */
+ return NULL;
+ }
}
- } else {
- alloc_hdr = &dbg->de_alloc_hdr[index];
- if (alloc_hdr->ah_bytes_one_struct > 0) {
-#ifdef DWARF_SIMPLE_MALLOC
- size = alloc_hdr->ah_bytes_one_struct;
-#else
- {
- void *m = _dwarf_find_memory(alloc_hdr);
-
- dwarf_malloc_check_alloc_data(m, type);
- if (index_into_allocated[type].specialconstructor) {
- int res =
- index_into_allocated[type].
- specialconstructor(dbg, m);
- if (res != DW_DLV_OK) {
- /* We leak what we allocated in
- _dwarf_find_memory when constructor fails. */
- return NULL;
- }
- }
- return m;
+ /* See global flag.
+ If zero then caller choses not
+ to track allocations, so dwarf_finish()
+ is unable to free anything the caller
+ omitted to dealloc. Normally
+ the global flag is non-zero */
+#ifdef HAVE_GLOBAL_ALLOC_SUMS
+ global_allocation_count++;
+ global_allocation_total += size;
+#endif /* HAVE_GLOBAL_ALLOC_SUMS */
+
+ /* As of March 14, 2020 it's
+ not necessary to test for alloc type, but instead
+ only call tsearch if de_alloc_tree_on. */
+ if (global_de_alloc_tree_on) {
+#ifdef HAVE_GLOBAL_ALLOC_SUMS
+ global_de_alloc_tree_total += size;
+ global_de_alloc_tree_count++;
+#endif /* HAVE_GLOBAL_ALLOC_SUMS */
+ result = dwarf_tsearch((void *)key,
+ &dbg->de_alloc_tree,simple_compare_function);
+ if(!result) {
+ /* Something badly wrong. Out of memory.
+ pretend all is well. */
}
+ }
+#if DEBUG
+ printf("libdwarfdetector ALLOC ret 0x%lx type 0x%x size %lu line %d %s\n",(unsigned long)ret_mem,(unsigned)alloc_type,(unsigned long)size,__LINE__,__FILE__);
#endif
+ return (ret_mem);
+ }
+}
- } else {
- /* Special case: should not really happen at all. */
- if (type == DW_DLA_ERROR) {
- /* dwarf_init failure. Because dbg is incomplete we
- won't use it to record the malloc. */
- void *m = _dwarf_special_no_dbg_error_malloc();
-
- dwarf_malloc_check_alloc_data(m, DW_DLA_ERROR);
- return m;
- } else {
- /* If we get here, there is a disastrous programming
- error somewhere. */
-#ifdef DWARF_SIMPLE_MALLOC
- _dwarf_simple_malloc_botch(3);
-#endif
+/* This was once a long list of tests using dss_data
+ and dss_size to see if 'space' was inside a debug section.
+ This tfind approach removes that maintenance headache. */
+static int
+string_is_in_debug_section(Dwarf_Debug dbg,void * space)
+{
+ /* See dwarf_line.c dwarf_srcfiles()
+ for one way we can wind up with
+ a DW_DLA_STRING string that may or may not be malloc-ed
+ by _dwarf_get_alloc().
+
+ dwarf_formstring(), for example, returns strings
+ which point into .debug_info or .debug_types but
+ dwarf_dealloc is never supposed to be applied
+ to strings dwarf_formstring() returns!
+
+ Lots of calls returning strings
+ have always been documented as requiring
+ dwarf_dealloc(...DW_DLA_STRING) when the code
+ just returns a pointer to a portion of a loaded section!
+ It is too late to change the documentation. */
+
+ void *result = 0;
+ result = dwarf_tfind((void *)space,
+ &dbg->de_alloc_tree,simple_compare_function);
+ if(!result) {
+ /* Not in the tree, so not malloc-ed
+ Nothing to delete. */
+ return TRUE;
+ }
+ /* We found the address in the tree, so it is NOT
+ part of .debug_info or any other dwarf section,
+ but is space malloc-d in _dwarf_get_alloc(). */
+ return FALSE;
+}
+
+
+/* These wrappers for dwarf_dealloc enable type-checking
+ at call points. */
+void
+dwarf_dealloc_error(Dwarf_Debug dbg, Dwarf_Error err)
+{
+ dwarf_dealloc(dbg,err,DW_DLA_ERROR);
+}
+void
+dwarf_dealloc_die( Dwarf_Die die)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_CU_Context context = 0;
+
+ if (!die) {
#ifdef DEBUG
- fprintf(stderr,
- "libdwarf Internal error: Type %d unexpected\n",
- (int) type);
+ printf("DEALLOC does nothing, die NULL line %d %s\n",
+ __LINE__,__FILE__);
+ fflush(stdout);
#endif
- }
- }
+ return;
}
-
- ret_mem = malloc(size);
-#ifdef DWARF_SIMPLE_MALLOC
- _dwarf_simple_malloc_add_to_list(dbg, ret_mem, (unsigned long) size,
- type);
+ context = die->di_cu_context;
+ if (!context) {
+#ifdef DEBUG
+ printf("DEALLOC does nothing, context NULL line %d %s\n",
+ __LINE__,__FILE__);
+ fflush(stdout);
#endif
- if (ret_mem != NULL)
- memset(ret_mem, 0, size);
-
- dwarf_malloc_check_alloc_data(ret_mem, type);
- if (index_into_allocated[type].specialconstructor) {
- int res =
- index_into_allocated[type].specialconstructor(dbg, ret_mem);
- if (res != DW_DLV_OK) {
- /* We leak what we allocated in _dwarf_find_memory when
- constructor fails. */
- return NULL;
- }
+ return;
}
-
- return (ret_mem);
+ dbg = context->cc_dbg;
+ dwarf_dealloc(dbg,die,DW_DLA_DIE);
}
+void
+dwarf_dealloc_attribute(Dwarf_Attribute attr)
+{
+ Dwarf_Debug dbg = 0;
+ if (!attr) {
+#ifdef DEBUG
+ printf("DEALLOC does nothing, attr is NULL line %d %s\n",
+ __LINE__,__FILE__);
+ fflush(stdout);
+#endif
+ return;
+ }
+ dbg = attr->ar_dbg;
+ dwarf_dealloc(dbg,attr,DW_DLA_ATTR);
+}
/*
This function is used to deallocate a region of memory
that was obtained by a call to _dwarf_get_alloc. Note
- that though dwarf_dealloc() is a public function,
- _dwarf_get_alloc() isn't.
+ that though dwarf_dealloc() is a public function,
+ _dwarf_get_alloc() isn't.
For lists, typically arrays of pointers, it is assumed
that the space was allocated by a direct call to malloc,
@@ -606,296 +689,203 @@ _dwarf_get_alloc(Dwarf_Debug dbg,
for variable length blocks such as DW_DLA_FRAME_BLOCK
and DW_DLA_LOC_BLOCK and DW_DLA_RANGES.
- For strings, the pointer might point to a string in
+ For strings, the pointer might point to a string in
.debug_info or .debug_string. After this is checked,
and if found not to be the case, a free() is done,
again on the assumption that a malloc was used to
obtain the space.
- For other types of structs, a pointer to the chunk that
- the struct was allocated out of, is present in the bytes
- preceding the pointer passed in. For this chunk it is
- checked whether all the structs in that chunk are now free.
- If so, the entire chunk is free_ed. Otherwise, the space
- is added to the free list for that chunk, and the free count
- incremented.
-
This function does not return anything.
+ The _dwarf_error_destructor() will be called
+ to free the er_msg string
+ (if this is a Dwarf_Error) just before the
+ Dwarf_Error is freed here. See...specialdestructor()
+ below.
+
*/
void
dwarf_dealloc(Dwarf_Debug dbg,
- Dwarf_Ptr space, Dwarf_Unsigned alloc_type)
+ Dwarf_Ptr space, Dwarf_Unsigned alloc_type)
{
- Dwarf_Alloc_Hdr alloc_hdr;
- Dwarf_Alloc_Area alloc_area;
- unsigned int type = alloc_type;
- unsigned int index;
+ unsigned int type = 0;
+ char * malloc_addr = 0;
+ struct reserve_data_s * r = 0;
- if (space == NULL) {
+ if (!space) {
+#ifdef DEBUG
+ printf("DEALLOC does nothing, space NULL line %d %s\n",
+ __LINE__,__FILE__);
+ fflush(stdout);
+abort();
+#endif /* DEBUG*/
return;
}
- if (type == DW_DLA_ERROR) {
- /* Get pointer to Dwarf_Alloc_Area this struct came from. See
- dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */
- alloc_area =
- *(Dwarf_Alloc_Area *) ((char *) space - DW_RESERVE);
- if (alloc_area == 0) {
- /* This is the special case of a failed dwarf_init(). Also
- (and more signficantly) there are a variety of other
- situations where libdwarf does not *know* what dbg is
- involved (because of a libdwarf-caller-error) so
- libdwarf uses NULL as the dbg. Those too wind up here. */
- _dwarf_free_special_error(space);
- dwarf_malloc_check_dealloc_data(space, type);
+ if (!dbg) {
+ /* App error, or an app that failed to succeed in a
+ dwarf_init() call. */
+#ifdef DEBUG
+ printf( "DEALLOC does nothing, dbg NULL line %d %s\n",
+ __LINE__,__FILE__);
+ fflush(stdout);
+#endif /* DEBUG*/
+ return;
+ }
+ if (dbg->de_alloc_tree) {
+ /* If it's a string in debug_info etc doing
+ (char *)space - DW_RESERVE is totally bogus. */
+ if (alloc_type == DW_DLA_STRING &&
+ string_is_in_debug_section(dbg,space)) {
+ /* A string pointer may point into .debug_info or
+ .debug_string etc.
+ So must not be freed. And strings have
+ no need of a specialdestructor().
+ Mostly a historical mistake here.
+ Corrected in libdwarf March 14,2020. */
return;
}
-
}
- if (dbg == NULL) {
- /* App error, or an app that failed to succeed in a
- dwarf_init() call. */
+ /* Otherwise it might be allocated string so it is ok
+ do the (char *)space - DW_RESERVE */
+
+ /* If it's a DW_DLA_STRING case and erroneous
+ the following pointer operations might
+ result in a coredump if the pointer
+ is to the beginning of a string section.
+ If not DW_DLA_STRING
+ no correctly written caller could coredump
+ here. */
+ malloc_addr = (char *)space - DW_RESERVE;
+ r =(struct reserve_data_s *)malloc_addr;
+ if(dbg != r->rd_dbg) {
+ /* Something is mixed up. */
+#ifdef DEBUG
+ printf("DEALLOC does nothing, dbg 0x%lx rd_dbg 0x%lx space 0x%lx line %d %s\n",
+ (unsigned long)dbg,
+ (unsigned long)r->rd_dbg,
+ (unsigned long)space,
+ __LINE__,__FILE__);
+ fflush(stdout);
+#endif /* DEBUG*/
return;
}
- if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
- /* internal or user app error */
+ if(alloc_type != r->rd_type) {
+ /* Something is mixed up. */
+#ifdef DEBUG
+ printf("DEALLOC does nothing, type 0x%lx rd_type 0x%lx space 0x%lx line %d %s\n",
+ (unsigned long)alloc_type,
+ (unsigned long)r->rd_type,
+ (unsigned long)space,
+ __LINE__,__FILE__);
+ fflush(stdout);
+#endif /* DEBUG*/
return;
}
-
- index = index_into_allocated[type].ia_al_num;
- /*
- A string pointer may point into .debug_info or .debug_string.
- Otherwise, they are directly malloc'ed. */
- dwarf_malloc_check_dealloc_data(space, type);
- if (index == 0) {
- if (type == DW_DLA_STRING) {
- if ((Dwarf_Small *) space >= dbg->de_debug_info.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_info.dss_data + dbg->de_debug_info.dss_size)
- return;
-
- if (dbg->de_debug_line.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_line.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_line.dss_data + dbg->de_debug_line.dss_size)
- return;
-
- if (dbg->de_debug_pubnames.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_pubnames.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_pubnames.dss_data +
- dbg->de_debug_pubnames.dss_size)
- return;
-
- if (dbg->de_debug_frame.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_frame.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_frame.dss_data + dbg->de_debug_frame.dss_size)
- return;
-
- if (dbg->de_debug_str.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_str.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_str.dss_data + dbg->de_debug_str.dss_size)
- return;
-
- if (dbg->de_debug_funcnames.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_funcnames.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_funcnames.dss_data +
- dbg->de_debug_funcnames.dss_size)
- return;
-
- if (dbg->de_debug_typenames.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_typenames.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_typenames.dss_data +
- dbg->de_debug_typenames.dss_size)
- return;
- if (dbg->de_debug_pubtypes.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_pubtypes.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_pubtypes.dss_data +
- dbg->de_debug_pubtypes.dss_size)
- return;
-
- if (dbg->de_debug_varnames.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_varnames.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_varnames.dss_data +
- dbg->de_debug_varnames.dss_size)
- return;
-
- if (dbg->de_debug_weaknames.dss_data != NULL &&
- (Dwarf_Small *) space >= dbg->de_debug_weaknames.dss_data &&
- (Dwarf_Small *) space <
- dbg->de_debug_weaknames.dss_data +
- dbg->de_debug_weaknames.dss_size)
- return;
-
-#ifdef DWARF_SIMPLE_MALLOC
- _dwarf_simple_malloc_delete_from_list(dbg, space, type);
-#endif
- free(space);
+ if (alloc_type == DW_DLA_ERROR) {
+ Dwarf_Error ep = (Dwarf_Error)space;
+
+ if (ep->er_static_alloc == DE_STATIC) {
+ /* This is special, malloc arena
+ was exhausted or a NULL dbg
+ was used for the error because the real
+ dbg was unavailable.
+ There is nothing to delete, really.
+ Set er_errval to signal that the
+ space was dealloc'd.
+ Not dealing with destructor here. */
+ _dwarf_failsafe_error.er_errval =
+ DW_DLE_FAILSAFE_ERRVAL;
+#ifdef DEBUG
+ printf("DEALLOC does nothing, DE_STATIC line %d %s\n",
+ __LINE__,__FILE__);
+ fflush(stdout);
+#endif /* DEBUG*/
return;
}
-
- if (type == DW_DLA_LIST ||
- type == DW_DLA_FRAME_BLOCK ||
- type == DW_DLA_LOC_BLOCK || type == DW_DLA_ADDR ||
- type == DW_DLA_RANGES ||
- type == DW_DLA_HASH_TABLE_ENTRY) {
-
-#ifdef DWARF_SIMPLE_MALLOC
- _dwarf_simple_malloc_delete_from_list(dbg, space, type);
-#endif
+ if (ep->er_static_alloc == DE_MALLOC) {
+ /* This is special, we had no arena
+ so just malloc'd a Dwarf_Error_s.
+ Not dealing with destructor here. */
free(space);
return;
}
- /* else is an alloc type that is not used */
- /* app or internal error */
-#ifdef DWARF_SIMPLE_MALLOC
- _dwarf_simple_malloc_botch(4);
-#endif
- return;
-
+ /* Was normal alloc, use normal dealloc. */
+ /* DW_DLA_ERROR has a specialdestructor */
}
- if (index_into_allocated[type].specialdestructor) {
- index_into_allocated[type].specialdestructor(space);
+ type = alloc_type;
+#if DEBUG
+ if(dbg != r->rd_dbg) {
+ /* Something is badly wrong. Better to leak than
+ to crash. */
+ return;
}
-#ifdef DWARF_SIMPLE_MALLOC
- _dwarf_simple_malloc_delete_from_list(dbg, space, type);
- free(space);
-#else /* !DWARF_SIMPLE_MALLOC */
- alloc_hdr = &dbg->de_alloc_hdr[index];
-
- /* Get pointer to Dwarf_Alloc_Area this struct came from. See
- dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */
- alloc_area = *(Dwarf_Alloc_Area *) ((char *) space - DW_RESERVE);
-
- /* ASSERT: alloc_area != NULL If NULL we could abort, let it
- coredump below, or return, pretending all is well. We go on,
- letting program crash. Is caller error. */
-
- /*
- Check that the alloc_hdr field of the alloc_area we have is
- pointing to the right alloc_hdr. This is used to catch use of
- incorrect deallocation code by the user. */
- if (alloc_area->aa_alloc_hdr != alloc_hdr) {
- /* If we get here, the user has called dwarf_dealloc wrongly or
- there is some other disastrous error. By leaking mem here we
- try to be safe... */
-#ifdef DEBUG
- fprintf(stderr,
- "libdwarf Internal error: type %d hdr mismatch %lx %lx "
- "area ptr %lx\n",
- (int) type,
- (long) alloc_area->aa_alloc_hdr,
- (long) alloc_hdr, (long) alloc_area);
#endif
+#if DEBUG
+ printf("libdwarfdetector DEALLOC ret 0x%lx type 0x%x size %lu line %d %s\n",(unsigned long)space,(unsigned)type,(unsigned long)r->rd_length,__LINE__,__FILE__);
+#endif
+ if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
+ /* internal or user app error */
+#ifdef DEBUG
+ printf("DEALLOC does nothing, type too big %lu line %d %s\n",
+ (unsigned long)type,
+ __LINE__,__FILE__);
+#endif /* DEBUG*/
return;
}
-
- alloc_hdr->ah_struct_user_holds--;
- alloc_area->aa_free_structs_in_chunk++;
-
- /*
- Give chunk back to malloc only when every struct is freed */
- if (alloc_area->aa_free_structs_in_chunk ==
- alloc_hdr->ah_structs_per_chunk) {
- if (alloc_area->aa_prev != NULL) {
- alloc_area->aa_prev->aa_next = alloc_area->aa_next;
- } else {
- alloc_hdr->ah_alloc_area_head = alloc_area->aa_next;
- }
-
- if (alloc_area->aa_next != NULL) {
- alloc_area->aa_next->aa_prev = alloc_area->aa_prev;
- }
-
- alloc_hdr->ah_chunks_allocated--;
-
- if (alloc_area == alloc_hdr->ah_last_alloc_area) {
- alloc_hdr->ah_last_alloc_area = NULL;
- }
- memset(alloc_area, 0, sizeof(*alloc_area));
- free(alloc_area);
+#ifdef HAVE_GLOBAL_ALLOC_SUMS
+ global_de_alloc_tree_early_dealloc_count++;
+ global_de_alloc_tree_early_dealloc_size += r->rd_length;
+#endif /* HAVE_GLOBAL_ALLOC_SUMS */
+ if (alloc_instance_basics[type].specialdestructor) {
+ alloc_instance_basics[type].specialdestructor(space);
}
-
- else {
- ((Dwarf_Free_List) space)->fl_next = alloc_area->aa_free_list;
- alloc_area->aa_free_list = space;
+ if (dbg->de_alloc_tree) {
+ /* The 'space' pointer we get points after the
+ reserve space. The key is 'space'
+ and address to free
+ is just a few bytes before 'space'. */
+ void *key = space;
+
+ dwarf_tdelete(key,&dbg->de_alloc_tree,
+ simple_compare_function);
+ /* If dwarf_tdelete returns NULL it might mean
+ a) tree is empty.
+ b) If hashsearch, then a single chain might
+ now be empty,
+ so we do not know of a 'parent node'.
+ c) We did not find that key, we did nothing.
+
+ In any case, we simply don't worry about it.
+ Not Supposed To Happen. */
}
-#endif /* !DWARF_SIMPLE_MALLOC */
+ r->rd_dbg = (void *)0xfeadbeef;
+ r->rd_length = 0;
+ r->rd_type = 0;
+ free(malloc_addr);
+ return;
}
-
/*
Allocates space for a Dwarf_Debug_s struct,
since one does not exist.
*/
Dwarf_Debug
-_dwarf_get_debug(void
- )
+_dwarf_get_debug(void)
{
Dwarf_Debug dbg;
dbg = (Dwarf_Debug) malloc(sizeof(struct Dwarf_Debug_s));
- if (dbg == NULL)
+ if (dbg == NULL) {
return (NULL);
- else
- memset(dbg, 0, sizeof(struct Dwarf_Debug_s));
- return (dbg);
-}
-
-
-/*
- Sets up the Dwarf_Debug_s struct for all the
- allocation types currently defined.
- Allocation types DW_DLA_STRING, DW_DLA_LIST,
- DW_DLA_FRAME_BLOCK, DW_DLA_LOC_BLOCK, DW_DLA_RANGES are
- malloc'ed directly.
-
- This routine should be called after _dwarf_setup(),
- so that information about the sizes of the Dwarf
- sections can be used to decide the number of
- structs of each type malloc'ed.
-
- Also DW_DLA_ELLIST, DW_DLA_BOUNDS, DW_DLA_TYPE,
- DW_DLA_SUBSCR, DW_DLA_LINEBUF allocation types
- are currently not used.
- The ah_bytes_one_struct and ah_structs_per_chunk fields for
- these types have been set to 1 for efficiency
- in dwarf_get_alloc().
-
- Ah_alloc_num should be greater than 1 for all
- types that are currently being used.
-
- Therefore, for these allocation types the
- ah_bytes_one_struct, and ah_structs_per_chunk fields do not
- need to be initialized.
-
- Being an internal routine, assume proper dbg.
-*/
-
-Dwarf_Debug
-_dwarf_setup_debug(Dwarf_Debug dbg)
-{
- int i;
-
- for (i = 1; i <= MAX_DW_DLA; i++) {
- const struct ial_s *ialp = &index_into_allocated[i];
- unsigned int hdr_index = ialp->ia_al_num;
- Dwarf_Word str_size = ialp->ia_struct_size;
- Dwarf_Word str_count = ialp->ia_base_count;
- Dwarf_Word rnded_size = ROUND_SIZE_WITH_POINTER(str_size);
-
- Dwarf_Alloc_Hdr alloc_hdr = &dbg->de_alloc_hdr[hdr_index];
-
- alloc_hdr->ah_bytes_one_struct = (Dwarf_Half) rnded_size;
-
- /* ah_structs_per_chunk must be >0 else we are in trouble */
- alloc_hdr->ah_structs_per_chunk = str_count;
- alloc_hdr->ah_bytes_malloc_per_chunk = rnded_size * str_count;
+ }
+ memset(dbg, 0, sizeof(struct Dwarf_Debug_s));
+ /* Set up for a dwarf_tsearch hash table */
+
+ /* Leaving initialization on so we can track
+ DW_DLA_STRING even when global_de_alloc_tree_on
+ is zero. */
+ if (global_de_alloc_tree_on) {
+ dwarf_initialize_search_hash(&dbg->de_alloc_tree,
+ simple_value_hashfunc,0);
}
return (dbg);
}
@@ -903,116 +893,18 @@ _dwarf_setup_debug(Dwarf_Debug dbg)
/*
This function prints out the statistics
collected on allocation of memory chunks.
+ No longer used.
*/
void
-dwarf_print_memory_stats(Dwarf_Debug dbg)
+dwarf_print_memory_stats(UNUSEDARG Dwarf_Debug dbg)
{
- Dwarf_Alloc_Hdr alloc_hdr;
- Dwarf_Shalf i;
-
- /*
- Alloc types start at 1, not 0. Hence, the first NULL string, and
- also a size of MAX_DW_DLA + 1. */
- char *alloc_type_name[MAX_DW_DLA + 1] = {
- "",
- "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_RANGES",
- "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",
- "DW_DLA_HASH_TABLE_ENTRY",
- };
-
- if (dbg == NULL)
- return;
-
- printf("Size of Dwarf_Debug %4ld bytes\n",
- (long) sizeof(*dbg));
- printf("Size of Dwarf_Alloc_Hdr_s %4ld bytes\n",
- (long) sizeof(struct Dwarf_Alloc_Hdr_s));
- printf("size of Dwarf_Alloc_Area_s %4ld bytes\n",
- (long) sizeof(struct Dwarf_Alloc_Area_s));
-
- printf(" Alloc Type Curr Structs byt str\n");
- printf(" ---------- ---- ------- per per\n");
- for (i = 1; i <= MAX_DW_DLA; i++) {
- int indx = index_into_allocated[i].ia_al_num;
-
- alloc_hdr = &dbg->de_alloc_hdr[indx];
- if (alloc_hdr->ah_bytes_one_struct != 1) {
- printf("%2d %-25s %6d %8d %6d %6d\n",
- (int) i,
- alloc_type_name[i],
- (int) alloc_hdr->ah_chunks_allocated,
- (int) alloc_hdr->ah_struct_user_holds,
- (int) alloc_hdr->ah_bytes_malloc_per_chunk,
- (int) alloc_hdr->ah_structs_per_chunk);
- }
- }
}
-#ifndef DWARF_SIMPLE_MALLOC
-/*
- This recursively frees
- the chunks still allocated, and
- forward chained through the aa_next
- pointer.
-*/
-static void
-_dwarf_recursive_free(Dwarf_Alloc_Area alloc_area)
-{
- if (alloc_area->aa_next != NULL) {
- _dwarf_recursive_free(alloc_area->aa_next);
- }
-
- alloc_area->aa_next = 0;
- alloc_area->aa_prev = 0;
- free(alloc_area);
-}
-#endif
/* In the 'rela' relocation case we might have malloc'd
space to ensure it is read-write. In that case, free the space. */
-static void
+static void
rela_free(struct Dwarf_Section_s * sec)
{
if (sec->dss_data_was_malloc) {
@@ -1022,9 +914,30 @@ rela_free(struct Dwarf_Section_s * sec)
sec->dss_data_was_malloc = 0;
}
+static void
+freecontextlist(Dwarf_Debug dbg, Dwarf_Debug_InfoTypes dis)
+{
+ Dwarf_CU_Context context = 0;
+ Dwarf_CU_Context nextcontext = 0;
+ for (context = dis->de_cu_context_list;
+ context; context = nextcontext) {
+ Dwarf_Hash_Table hash_table = context->cc_abbrev_hash_table;
+ _dwarf_free_abbrev_hash_table_contents(dbg,hash_table);
+ hash_table->tb_entries = 0;
+ nextcontext = context->cc_next;
+ context->cc_next = 0;
+ /* See also local_dealloc_cu_context() in
+ dwarf_die_deliv.c */
+ dwarf_dealloc(dbg, hash_table, DW_DLA_HASH_TABLE);
+ context->cc_abbrev_hash_table = 0;
+ dwarf_dealloc(dbg, context, DW_DLA_CU_CONTEXT);
+ }
+ dis->de_cu_context_list = 0;
+}
+
/*
Used to free all space allocated for this Dwarf_Debug.
- The caller should assume that the Dwarf_Debug pointer
+ The caller should assume that the Dwarf_Debug pointer
itself is no longer valid upon return from this function.
In case of difficulty, this function simply returns quietly.
@@ -1032,71 +945,45 @@ rela_free(struct Dwarf_Section_s * sec)
int
_dwarf_free_all_of_one_debug(Dwarf_Debug dbg)
{
- Dwarf_Alloc_Hdr alloc_hdr;
- Dwarf_Shalf i;
- Dwarf_CU_Context context = 0;
- Dwarf_CU_Context nextcontext = 0;
+ unsigned g = 0;
- if (dbg == NULL)
+ if (dbg == NULL) {
return (DW_DLV_ERROR);
-
- /* To do complete validation that we have no surprising missing or
- erroneous deallocs it is advisable to do the dwarf_deallocs here
- that are not things the user can otherwise request.
- Housecleaning. */
-
- for (context = dbg->de_cu_context_list;
- context; context = nextcontext) {
- Dwarf_Hash_Table hash_table = context->cc_abbrev_hash_table;
- _dwarf_free_abbrev_hash_table_contents(dbg,hash_table);
- nextcontext = context->cc_next;
- dwarf_dealloc(dbg, hash_table, DW_DLA_HASH_TABLE);
- dwarf_dealloc(dbg, context, DW_DLA_CU_CONTEXT);
}
-
- /* Housecleaning done. Now really free all the space. */
-#ifdef DWARF_SIMPLE_MALLOC
- if (dbg->de_simple_malloc_base) {
- struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base;
-
- while (smp) {
- int i;
- struct simple_malloc_record_s *prev_smp = 0;
-
- for (i = 0; i < smp->sr_used; ++i) {
- struct simple_malloc_entry_s *cur;
-
- cur = &smp->sr_entry[i];
- if (cur->se_addr != 0) {
- free(cur->se_addr);
- cur->se_addr = 0;
- }
- }
- prev_smp = smp;
- smp = smp->sr_next;
- free(prev_smp);
- }
- dbg->de_simple_malloc_base = 0;
+ /* To do complete validation that we have no surprising
+ missing or erroneous deallocs it is advisable to do
+ the dwarf_deallocs here
+ that are not things the user can otherwise request.
+ Housecleaning. */
+ if (dbg->de_cu_hashindex_data) {
+ dwarf_xu_header_free(dbg->de_cu_hashindex_data);
+ dbg->de_cu_hashindex_data = 0;
}
-#else
- for (i = 1; i < ALLOC_AREA_REAL_TABLE_MAX; i++) {
- int indx = i;
-
- alloc_hdr = &dbg->de_alloc_hdr[indx];
- if (alloc_hdr->ah_alloc_area_head != NULL) {
- _dwarf_recursive_free(alloc_hdr->ah_alloc_area_head);
- }
+ if (dbg->de_tu_hashindex_data) {
+ dwarf_xu_header_free(dbg->de_tu_hashindex_data);
+ dbg->de_tu_hashindex_data = 0;
+ }
+ if( dbg->de_printf_callback_null_device_handle) {
+ fclose(dbg->de_printf_callback_null_device_handle);
+ dbg->de_printf_callback_null_device_handle = 0;
}
+ freecontextlist(dbg,&dbg->de_info_reading);
+ freecontextlist(dbg,&dbg->de_types_reading);
-#endif
+ /* Housecleaning done. Now really free all the space. */
rela_free(&dbg->de_debug_info);
+ rela_free(&dbg->de_debug_types);
rela_free(&dbg->de_debug_abbrev);
rela_free(&dbg->de_debug_line);
+ rela_free(&dbg->de_debug_line_str);
rela_free(&dbg->de_debug_loc);
rela_free(&dbg->de_debug_aranges);
rela_free(&dbg->de_debug_macinfo);
+ rela_free(&dbg->de_debug_macro);
+ rela_free(&dbg->de_debug_names);
rela_free(&dbg->de_debug_pubnames);
rela_free(&dbg->de_debug_str);
+ rela_free(&dbg->de_debug_sup);
rela_free(&dbg->de_debug_frame);
rela_free(&dbg->de_debug_frame_eh_gnu);
rela_free(&dbg->de_debug_pubtypes);
@@ -1105,154 +992,65 @@ _dwarf_free_all_of_one_debug(Dwarf_Debug dbg)
rela_free(&dbg->de_debug_varnames);
rela_free(&dbg->de_debug_weaknames);
rela_free(&dbg->de_debug_ranges);
+ rela_free(&dbg->de_debug_str_offsets);
+ rela_free(&dbg->de_debug_addr);
+ rela_free(&dbg->de_debug_gdbindex);
+ rela_free(&dbg->de_debug_cu_index);
+ rela_free(&dbg->de_debug_tu_index);
dwarf_harmless_cleanout(&dbg->de_harmless_errors);
+ _dwarf_dealloc_rnglists_context(dbg);
+ _dwarf_dealloc_loclists_context(dbg);
+ if (dbg->de_printf_callback.dp_buffer &&
+ !dbg->de_printf_callback.dp_buffer_user_provided ) {
+ free(dbg->de_printf_callback.dp_buffer);
+ }
+
+ _dwarf_destroy_group_map(dbg);
+ /* de_alloc_tree might be NULL if
+ global_de_alloc_tree_on is zero. */
+ if (dbg->de_alloc_tree) {
+ dwarf_tdestroy(dbg->de_alloc_tree,tdestroy_free_node);
+ dbg->de_alloc_tree = 0;
+ }
+ if (dbg->de_tied_data.td_tied_search) {
+ dwarf_tdestroy(dbg->de_tied_data.td_tied_search,
+ _dwarf_tied_destroy_free_node);
+ dbg->de_tied_data.td_tied_search = 0;
+ }
+ free((void *)dbg->de_path);
+ dbg->de_path = 0;
+ for (g = 0; g < dbg->de_gnu_global_path_count; ++g) {
+ free((char *)dbg->de_gnu_global_paths[g]);
+ dbg->de_gnu_global_paths[g] = 0;
+ }
+ free((void*)dbg->de_gnu_global_paths);
+ dbg->de_gnu_global_paths = 0;
+ dbg->de_gnu_global_path_count = 0;
memset(dbg, 0, sizeof(*dbg)); /* Prevent accidental use later. */
free(dbg);
return (DW_DLV_OK);
}
+/* A special case: we have no dbg, no alloc header etc.
+ So create something out of thin air that we can recognize
+ in dwarf_dealloc.
+ Something with the prefix (prefix space hidden from caller).
-/* A special case: we have no dbg, no alloc header etc.
- So create something out of thin air that we can recognize
- in dwarf_dealloc.
- Something with the prefix (prefix space hidden from caller).
-
- Only applies to DW_DLA_ERROR, making up an error record.
+ Only applies to DW_DLA_ERROR, and making up an error record.
+ The allocated space simply leaks.
*/
-
struct Dwarf_Error_s *
_dwarf_special_no_dbg_error_malloc(void)
{
- /* the union unused things are to guarantee proper alignment */
- union u {
- Dwarf_Alloc_Area ptr_not_used;
- struct Dwarf_Error_s base_not_used;
- char data_space[sizeof(struct Dwarf_Error_s) +
- (DW_RESERVE * 2)];
- };
- char *mem;
-
- mem = malloc(sizeof(union u));
+ Dwarf_Error e = 0;
+ Dwarf_Unsigned len = sizeof(struct Dwarf_Error_s);
+ char *mem = (char *)malloc(len);
if (mem == 0) {
return 0;
-
}
- memset(mem, 0, sizeof(union u));
- mem += DW_RESERVE;
- return (struct Dwarf_Error_s *) mem;
-}
-
-/* The free side of _dwarf_special_no_dbg_error_malloc()
-*/
-static void
-_dwarf_free_special_error(Dwarf_Ptr space)
-{
- char *mem = (char *) space;
-
- mem -= DW_RESERVE;
- free(mem);
-}
-
-
-#ifdef DWARF_SIMPLE_MALLOC
-/* here solely for planting a breakpoint. */
-/* ARGSUSED */
-void
-_dwarf_simple_malloc_botch(int err)
-{
- fprintf(stderr,"simple malloc botch %d\n",err);
+ memset(mem, 0, len);
+ e = (Dwarf_Error)mem;
+ e->er_static_alloc = DE_MALLOC;
+ return e;
}
-static void
-_dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg,
- Dwarf_Ptr addr,
- unsigned long size, short alloc_type)
-{
- struct simple_malloc_record_s *cur;
- struct simple_malloc_entry_s *newentry;
-
- if (!dbg->de_simple_malloc_base) {
- /* First entry to this routine. */
- dbg->de_simple_malloc_base =
- malloc(sizeof(struct simple_malloc_record_s));
- if (!dbg->de_simple_malloc_base) {
- _dwarf_simple_malloc_botch(7);
- return; /* no memory, give up */
- }
- memset(dbg->de_simple_malloc_base,
- 0, sizeof(struct simple_malloc_record_s));
- }
- cur = dbg->de_simple_malloc_base;
-
- if (cur->sr_used >= DSM_BLOCK_COUNT) {
- /* Better not be > than as that means chaos */
-
- /* Create a new block to link at the head. */
-
- struct simple_malloc_record_s *newblock =
- malloc(sizeof(struct simple_malloc_record_s));
- if (!newblock) {
- _dwarf_simple_malloc_botch(8);
- return; /* Can do nothing, out of memory */
- }
- memset(newblock, 0, sizeof(struct simple_malloc_record_s));
- /* Link the new block at the head of the chain, and make it
- 'current' */
- dbg->de_simple_malloc_base = newblock;
- newblock->sr_next = cur;
- cur = newblock;
- }
- newentry = &cur->sr_entry[cur->sr_used];
- newentry->se_addr = addr;
- newentry->se_size = size;
- newentry->se_type = alloc_type;
- ++cur->sr_used;
-}
-
-/*
- DWARF_SIMPLE_MALLOC: testing the hypothesis that the existing
- malloc scheme here (see _dwarf_get_alloc()) is pointless complexity.
-
- DWARF_SIMPLE_MALLOC also makes it easy for a malloc-tracing
- tool to verify libdwarf malloc has no botches (though of course
- such does not test the complicated standard-libdwarf-alloc code).
-
- To properly answer the question, the simple-malloc allocate
- and delete should be something other than a simple list.
- Perhaps a heap, or perhaps a red-black tree.
-
-*/
-static void
-_dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg,
- Dwarf_Ptr space, short alloc_type)
-{
- if (space == 0) {
- _dwarf_simple_malloc_botch(6);
- }
- if (dbg->de_simple_malloc_base) {
- struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base;
-
- while (smp) {
- int i;
-
- for (i = 0; i < smp->sr_used; ++i) {
- struct simple_malloc_entry_s *cur;
-
- cur = &smp->sr_entry[i];
- if (cur->se_addr == space) {
- if (cur->se_type != alloc_type) {
- _dwarf_simple_malloc_botch(0);
- }
- cur->se_addr = 0;
- return;
- }
- }
- smp = smp->sr_next;
- }
- }
- /* Never found the space. */
- _dwarf_simple_malloc_botch(1);
- return;
-
-}
-#endif