xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_alloc.c (revision d48be21240dfd051b689384ce2b23479d757f2d8)
1 /*
2   Copyright (C) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
3   Portions Copyright (C) 2007-2020  David Anderson. All Rights Reserved.
4 
5   This program is free software; you can redistribute it
6   and/or modify it under the terms of version 2.1 of the
7   GNU Lesser General Public License as published by the Free
8   Software Foundation.
9 
10   This program is distributed in the hope that it would be
11   useful, but WITHOUT ANY WARRANTY; without even the implied
12   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13   PURPOSE.
14 
15   Further, this software is distributed without any warranty
16   that it is free of the rightful claim of any third person
17   regarding infringement or the like.  Any license provided
18   herein, whether implied or otherwise, applies only to this
19   software file.  Patent licenses, if any, provided herein
20   do not apply to combinations of this program with other
21   software, or any other product whatsoever.
22 
23   You should have received a copy of the GNU Lesser General
24   Public License along with this program; if not, write the
25   Free Software Foundation, Inc., 51 Franklin Street - Fifth
26   Floor, Boston MA 02110-1301, USA.
27 
28 */
29 /*  To see the full set of DW_DLA types and nothing
30     else  try:
31     grep DW_DLA dwarf_alloc.c | grep 0x
32 */
33 
34 #include "config.h"
35 #include <sys/types.h>
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif /* HAVE_STDLIB_H */
39 #ifdef HAVE_MALLOC_H
40 /* Useful include for some Windows compilers. */
41 #include <malloc.h>
42 #endif /* HAVE_MALLOC_H */
43 #include <stdio.h>
44 #ifdef HAVE_STDINT_H
45 #include <stdint.h> /* For uintptr_t */
46 #endif /* HAVE_STDINT_H */
47 #include "dwarf_incl.h"
48 #include "dwarf_error.h"
49 #include "dwarf_alloc.h"
50 /*  These files are included to get the sizes
51     of structs for malloc.
52 */
53 #include "dwarf_util.h"
54 #include "dwarf_line.h"
55 #include "dwarf_global.h"
56 #include "dwarf_arange.h"
57 #include "dwarf_abbrev.h"
58 #include "dwarf_die_deliv.h"
59 #include "dwarf_frame.h"
60 #include "dwarf_loc.h"
61 #include "dwarf_funcs.h"
62 #include "dwarf_types.h"
63 #include "dwarf_vars.h"
64 #include "dwarf_weaks.h"
65 #include "dwarf_harmless.h"
66 #include "dwarf_tsearch.h"
67 #include "dwarf_gdbindex.h"
68 #include "dwarf_xu_index.h"
69 #include "dwarf_macro5.h"
70 #include "dwarf_dnames.h"
71 #include "dwarf_rnglists.h"
72 #include "dwarf_dsc.h"
73 #include "dwarfstring.h"
74 #include "dwarf_str_offsets.h"
75 
76 #define TRUE 1
77 #define FALSE 0
78 /*  Some allocations are simple some not. These reduce
79     the issue of determining which sort of thing to a simple
80     test. See ia_multiply_count
81     Usually when MULTIPLY_NO is set the count
82     is 1, so MULTIPY_CT would work as well.  */
83 #define MULTIPLY_NO 0
84 #define MULTIPLY_CT 1
85 #define MULTIPLY_SP 2
86 /*  This translates into de_alloc_hdr into a per-instance size
87     and allows room for a constructor/destructor pointer.
88     Rearranging the DW_DLA values would break binary compatibility
89     so that is not an option.
90 */
91 struct ial_s {
92     /*  In bytes, one struct instance.  */
93     short ia_struct_size;
94 
95     /*  Not a count, but a MULTIPLY{_NO,_CT,_SP} value. */
96     short ia_multiply_count;
97 
98     /*  When we really need a constructor/destructor
99         these make applying such quite simple. */
100     int (*specialconstructor) (Dwarf_Debug, void *);
101     void (*specialdestructor) (void *);
102 };
103 
104 /*  Used as a way to return meaningful errors when
105     the malloc arena is exhausted (when malloc returns NULL).
106     Not normally used.
107     New in December 2014.*/
108 struct Dwarf_Error_s _dwarf_failsafe_error = {
109     DW_DLE_FAILSAFE_ERRVAL,
110     0,
111     1
112 };
113 
114 /*  If non-zero (the default) de_alloc_tree (see dwarf_alloc.c)
115     is used normally.  If zero then dwarf allocations
116     are not tracked by libdwarf and dwarf_finish() cannot
117     clean up any per-Dwarf_Debug allocations the
118     caller forgot to dealloc. */
119 static signed char global_de_alloc_tree_on = 1;
120 #ifdef HAVE_GLOBAL_ALLOC_SUMS
121 static Dwarf_Unsigned global_allocation_count;
122 static Dwarf_Unsigned global_allocation_total;
123 static Dwarf_Unsigned global_de_alloc_tree_count;
124 static Dwarf_Unsigned global_de_alloc_tree_total;
125 static Dwarf_Unsigned global_de_alloc_tree_early_dealloc_count;
126 static Dwarf_Unsigned global_de_alloc_tree_early_dealloc_size;
127 #endif /* HAVE_GLOBAL_ALLOC_SUMS */
128 
129 void _dwarf_alloc_tree_counts( UNUSEDARG Dwarf_Unsigned *allocount,
130     UNUSEDARG Dwarf_Unsigned *allosum,
131     UNUSEDARG Dwarf_Unsigned *treecount,
132     UNUSEDARG Dwarf_Unsigned *treesum,
133     UNUSEDARG Dwarf_Unsigned *earlydealloccount,
134     UNUSEDARG Dwarf_Unsigned *earlydeallocsize,
135     UNUSEDARG Dwarf_Unsigned *unused1,
136     UNUSEDARG Dwarf_Unsigned *unused2,
137     UNUSEDARG Dwarf_Unsigned *unused3)
138 {
139 #ifdef HAVE_GLOBAL_ALLOC_SUMS
140     *allocount = global_allocation_count;
141     *allosum =   global_allocation_total;
142     *treecount = global_de_alloc_tree_count;
143     *treesum =   global_de_alloc_tree_total;
144     *earlydealloccount =
145         global_de_alloc_tree_early_dealloc_count;
146     *earlydeallocsize =
147         global_de_alloc_tree_early_dealloc_size;
148     if (unused1) {
149         *unused1 = 0;
150     }
151     if (unused2) {
152         *unused2 = 0;
153     }
154     if (unused3) {
155         *unused3 = 0;
156     }
157 #endif /* HAVE_GLOBAL_ALLOC_SUMS */
158 }
159 
160 /*  Defined March 7 2020. Allows a caller to
161     avoid most tracking by the de_alloc_tree hash
162     table if called with v of zero.
163     Returns the value the flag was before this call. */
164 int dwarf_set_de_alloc_flag(int v)
165 {
166     int ov = global_de_alloc_tree_on;
167     global_de_alloc_tree_on = v;
168     return ov;
169 }
170 
171 
172 
173 void
174 _dwarf_error_destructor(void *m)
175 {
176     Dwarf_Error er = (Dwarf_Error)m;
177     dwarfstring *erm = (dwarfstring *)er->er_msg;
178     if (! erm) {
179         return;
180     }
181 #if DEBUG
182     printf("libdwarfdetector DEALLOC Now destruct error string %s\n",dwarfstring_string(erm));
183 #endif
184     dwarfstring_destructor(erm);
185     free(erm);
186     er->er_msg = 0;
187     return;
188 }
189 
190 /*  To do destructors we need some extra data in every
191     _dwarf_get_alloc situation. */
192 /* Here is the extra we malloc for a prefix. */
193 struct reserve_size_s {
194    void *dummy_rsv1;
195    void *dummy_rsv2;
196 };
197 /* Here is how we use the extra prefix area. */
198 struct reserve_data_s {
199    void *rd_dbg;
200    unsigned short rd_length;
201    unsigned short rd_type;
202 };
203 #define DW_RESERVE sizeof(struct reserve_size_s)
204 
205 
206 static const
207 struct ial_s alloc_instance_basics[ALLOC_AREA_INDEX_TABLE_MAX] = {
208     /* 0  none */
209     { 1,MULTIPLY_NO, 0, 0},
210 
211     /* 0x1 x1 DW_DLA_STRING */
212     { 1,MULTIPLY_CT, 0, 0},
213 
214     /* 0x2 DW_DLA_LOC */
215     { sizeof(Dwarf_Loc),MULTIPLY_NO, 0, 0} ,
216 
217     /* x3 DW_DLA_LOCDESC */
218     { sizeof(Dwarf_Locdesc),MULTIPLY_NO, 0, 0},
219 
220     /* 0x4 DW_DLA_ELLIST */ /* not used */
221     { 1,MULTIPLY_NO, 0, 0},
222 
223     /* 0x5 DW_DLA_BOUNDS */ /* not used */
224     { 1,MULTIPLY_NO, 0, 0},
225 
226     /* 0x6 DW_DLA_BLOCK */
227     { sizeof(Dwarf_Block),MULTIPLY_NO,  0, 0},
228 
229     /* x7 DW_DLA_DEBUG */
230     /* the actual dwarf_debug structure */
231     { 1,MULTIPLY_NO, 0, 0} ,
232 
233     /* x8 DW_DLA_DIE */
234     {sizeof(struct Dwarf_Die_s),MULTIPLY_NO, 0, 0},
235 
236     /* x9 DW_DLA_LINE */
237     {sizeof(struct Dwarf_Line_s),MULTIPLY_NO, 0, 0},
238 
239     /* 0xa  10 DW_DLA_ATTR */
240     {sizeof(struct Dwarf_Attribute_s),MULTIPLY_NO,  0, 0},
241 
242     /* 0xb DW_DLA_TYPE *//* not used */
243     {1,MULTIPLY_NO,  0, 0},
244 
245     /* 0xc DW_DLA_SUBSCR *//* not used */
246     {1,MULTIPLY_NO,  0, 0},
247 
248     /* 0xd 13 DW_DLA_GLOBAL */
249     {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
250 
251     /* 0xe 14 DW_DLA_ERROR */
252     {sizeof(struct Dwarf_Error_s),MULTIPLY_NO,  0,
253         _dwarf_error_destructor},
254 
255     /* 0xf DW_DLA_LIST */
256     {sizeof(Dwarf_Ptr),MULTIPLY_CT, 0, 0},
257 
258     /* 0x10 DW_DLA_LINEBUF */ /* not used */
259     {1,MULTIPLY_NO, 0, 0},
260 
261     /* 0x11 17 DW_DLA_ARANGE */
262     {sizeof(struct Dwarf_Arange_s),MULTIPLY_NO,  0, 0},
263 
264     /* 0x12 18 DW_DLA_ABBREV */
265     {sizeof(struct Dwarf_Abbrev_s),MULTIPLY_NO,  0, 0},
266 
267     /* 0x13 19 DW_DLA_FRAME_OP */
268     {sizeof(Dwarf_Frame_Op),MULTIPLY_NO,  0, 0} ,
269 
270     /* 0x14  20 DW_DLA_CIE */
271     {sizeof(struct Dwarf_Cie_s),MULTIPLY_NO,  0, 0},
272 
273     /* 0x15 DW_DLA_FDE */
274     {sizeof(struct Dwarf_Fde_s),MULTIPLY_NO,  0,
275         _dwarf_fde_destructor},
276 
277     /* 0x16 DW_DLA_LOC_BLOCK */
278     {sizeof(Dwarf_Loc),MULTIPLY_CT, 0, 0},
279 
280     /* 0x17 DW_DLA_FRAME_BLOCK */
281     {sizeof(Dwarf_Frame_Op),MULTIPLY_CT, 0, 0},
282 
283     /* 0x18 DW_DLA_FUNC UNUSED */
284     {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
285 
286     /* 0x19 DW_DLA_TYPENAME UNUSED */
287     {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
288 
289     /* 0x1a DW_DLA_VAR UNUSED  */
290     {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
291 
292     /* 0x1b DW_DLA_WEAK UNUSED */
293     {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
294 
295     /* 0x1c DW_DLA_ADDR */
296     {1,MULTIPLY_SP, 0, 0},
297 
298     /* 0x1d DW_DLA_RANGES */
299     {sizeof(Dwarf_Ranges),MULTIPLY_CT, 0,0 },
300 
301     /*  The following DW_DLA data types
302         are known only inside libdwarf.  */
303 
304     /* 0x1e DW_DLA_ABBREV_LIST */
305     { sizeof(struct Dwarf_Abbrev_List_s),MULTIPLY_NO, 0, 0},
306 
307     /* 0x1f DW_DLA_CHAIN */
308     {sizeof(struct Dwarf_Chain_s),MULTIPLY_NO, 0, 0},
309 
310     /* 0x20 DW_DLA_CU_CONTEXT */
311     {sizeof(struct Dwarf_CU_Context_s),MULTIPLY_NO,  0, 0},
312 
313     /* 0x21 DW_DLA_FRAME */
314     {sizeof(struct Dwarf_Frame_s),MULTIPLY_NO,
315         _dwarf_frame_constructor,
316         _dwarf_frame_destructor},
317 
318     /* 0x22 DW_DLA_GLOBAL_CONTEXT */
319     {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
320 
321     /* 0x23 DW_DLA_FILE_ENTRY */
322     {sizeof(struct Dwarf_File_Entry_s),MULTIPLY_NO,  0, 0},
323 
324     /* 0x24 DW_DLA_LINE_CONTEXT */
325     {sizeof(struct Dwarf_Line_Context_s),MULTIPLY_NO,
326         _dwarf_line_context_constructor,
327         _dwarf_line_context_destructor},
328 
329     /* 0x25 DW_DLA_LOC_CHAIN */
330     {sizeof(struct Dwarf_Loc_Chain_s),MULTIPLY_NO,  0, 0},
331 
332     /* 0x26 0x26 DW_DLA_HASH_TABLE */
333     {sizeof(struct Dwarf_Hash_Table_s),MULTIPLY_NO, 0, 0},
334 
335     /*  The following really use Global struct: used to be unique struct
336     per type, but now merged (11/99).  The opaque types
337     are visible in the interface. The types  for
338     DW_DLA_FUNC, DW_DLA_TYPENAME, DW_DLA_VAR, DW_DLA_WEAK also use
339     the global types.  */
340 
341     /* 0x27 DW_DLA_FUNC_CONTEXT */
342     {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
343 
344     /* 0x28 40 DW_DLA_TYPENAME_CONTEXT */
345     {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
346 
347     /* 0x29 41 DW_DLA_VAR_CONTEXT */
348     {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
349 
350     /* 0x2a 42 DW_DLA_WEAK_CONTEXT */
351     {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
352 
353     /* 0x2b 43 DW_DLA_PUBTYPES_CONTEXT DWARF3 */
354     {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
355 
356     /* 0x2c 44 DW_DLA_HASH_TABLE_ENTRY */
357     {sizeof(struct Dwarf_Hash_Table_Entry_s),MULTIPLY_CT,0,0 },
358 
359     /* 0x2d -0x34 reserved */
360     {sizeof(int),MULTIPLY_NO,  0, 0},
361 
362     /* 0x2e 46 reserved for future use  */
363     {sizeof(int),MULTIPLY_NO,  0, 0},
364 
365     /* 0x2f 47  reserved for future use  */
366     {sizeof(int),MULTIPLY_NO,  0, 0},
367 
368     /* 0x30 reserved for future internal use */
369     {sizeof(int),MULTIPLY_NO,  0, 0},
370 
371     /* 0x31 reserved for future internal use */
372     {sizeof(int),MULTIPLY_NO,  0, 0},
373 
374     /* 0x32 50 reserved for future internal use */
375     {sizeof(int),MULTIPLY_NO,  0, 0},
376 
377     /* 0x33 51 reserved for future internal use */
378     {sizeof(int),MULTIPLY_NO,  0, 0},
379 
380     /* 0x34 52 reserved for future internal use */
381     {sizeof(int),MULTIPLY_NO,  0, 0},
382 
383     /* 0x35 53 reserved for future use. */
384     {sizeof(int),MULTIPLY_NO,  0, 0},
385 
386     /* 0x36 54 Used starting May 2020  DW_DLA_RNGLISTS_HEAD */
387     {sizeof(struct Dwarf_Rnglists_Head_s),MULTIPLY_NO,  0,
388         _dwarf_rnglists_head_destructor},
389 
390     /*  now,  we have types that are public. */
391     /* 0x37 55.  New in June 2014. Gdb. */
392     {sizeof(struct Dwarf_Gdbindex_s),MULTIPLY_NO,  0, 0},
393 
394     /* 0x38 56.  New in July 2014. */
395     /* DWARF5 DebugFission dwp file sections
396         .debug_cu_index and .debug_tu_index . */
397     {sizeof(struct Dwarf_Xu_Index_Header_s),MULTIPLY_NO,  0, 0},
398 
399     /*  These required by new features in DWARF5. Also usable
400         for DWARF2,3,4. */
401     /* 0x39 57 DW_DLA_LOC_BLOCK_C DWARF5 */
402     {sizeof(struct Dwarf_Loc_Expr_Op_s),MULTIPLY_CT, 0, 0},
403 
404     /* 0x3a 58  DW_DLA_LOCDESC_C */
405     {sizeof(struct Dwarf_Locdesc_c_s),MULTIPLY_CT, 0, 0},
406 
407     /* 0x3b 59 DW_DLA_LOC_HEAD_C */
408     {sizeof(struct Dwarf_Loc_Head_c_s),MULTIPLY_NO, 0, 0},
409 
410     /* 0x3c 60 DW_DLA_MACRO_CONTEXT */
411     {sizeof(struct Dwarf_Macro_Context_s),MULTIPLY_NO,
412         _dwarf_macro_constructor,
413         _dwarf_macro_destructor},
414 
415     /* 0x3d 61 DW_DLA_CHAIN_2 */
416     {sizeof(struct Dwarf_Chain_o),MULTIPLY_NO, 0, 0},
417 
418     /* 0x3e 62 DW_DLA_DSC_HEAD */
419     {sizeof(struct Dwarf_Dsc_Head_s),MULTIPLY_NO, 0,
420         _dwarf_dsc_destructor},
421 
422     /* 0x3f 63 DW_DLA_DNAMES_HEAD */
423     {sizeof(struct Dwarf_Dnames_Head_s),MULTIPLY_NO, 0,
424         _dwarf_debugnames_destructor},
425 
426     /* 0x40 64 DW_DLA_STR_OFFSETS */
427     {sizeof(struct Dwarf_Str_Offsets_Table_s),MULTIPLY_NO, 0,0},
428 };
429 
430 /*  We are simply using the incoming pointer as the key-pointer.
431 */
432 
433 static DW_TSHASHTYPE
434 simple_value_hashfunc(const void *keyp)
435 {
436     DW_TSHASHTYPE up = (DW_TSHASHTYPE)(uintptr_t)keyp;
437     return up;
438 }
439 /*  We did alloc something but not a fixed-length thing.
440     Instead, it starts with some special data we noted.
441     The incoming pointer is to the caller data, we
442     destruct based on caller, but find the special
443     extra data in a prefix area. */
444 static void
445 tdestroy_free_node(void *nodep)
446 {
447     char * m = (char *)nodep;
448     char * malloc_addr = m - DW_RESERVE;
449     struct reserve_data_s * reserve =(struct reserve_data_s *)malloc_addr;
450     unsigned type = reserve->rd_type;
451     if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
452         /* Internal error, corrupted data. */
453         return;
454     }
455     if(!reserve->rd_dbg) {
456         /*  Unused (corrupted?) node in the tree.
457             Should never happen. */
458         return;
459     }
460     if(!reserve->rd_type) {
461         /*  Unused (corrupted?) node in the tree.
462             Should never happen. */
463         return;
464     }
465     if (alloc_instance_basics[type].specialdestructor) {
466         alloc_instance_basics[type].specialdestructor(m);
467     }
468     free(malloc_addr);
469 }
470 
471 /* The sort of hash table entries result in very simple helper functions. */
472 static int
473 simple_compare_function(const void *l, const void *r)
474 {
475     DW_TSHASHTYPE lp = (DW_TSHASHTYPE)(uintptr_t)l;
476     DW_TSHASHTYPE rp = (DW_TSHASHTYPE)(uintptr_t)r;
477     if(lp < rp) {
478         return -1;
479     }
480     if(lp > rp) {
481         return 1;
482     }
483     return 0;
484 }
485 
486 /*  This function returns a pointer to a region
487     of memory.  For alloc_types that are not
488     strings or lists of pointers, only 1 struct
489     can be requested at a time.  This is indicated
490     by an input count of 1.  For strings, count
491     equals the length of the string it will
492     contain, i.e it the length of the string
493     plus 1 for the terminating null.  For lists
494     of pointers, count is equal to the number of
495     pointers.  For DW_DLA_FRAME_BLOCK, DW_DLA_RANGES, and
496     DW_DLA_LOC_BLOCK allocation types also, count
497     is the count of the number of structs needed.
498 
499     This function cannot be used to allocate a
500     Dwarf_Debug_s struct.  */
501 
502 char *
503 _dwarf_get_alloc(Dwarf_Debug dbg,
504     Dwarf_Small alloc_type, Dwarf_Unsigned count)
505 {
506     char * alloc_mem = 0;
507     Dwarf_Signed basesize = 0;
508     Dwarf_Signed size = 0;
509     unsigned int type = alloc_type;
510     short action = 0;
511 
512     if (dbg == NULL) {
513         return NULL;
514     }
515     if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
516         /* internal error */
517         return NULL;
518     }
519     basesize = alloc_instance_basics[alloc_type].ia_struct_size;
520     action = alloc_instance_basics[alloc_type].ia_multiply_count;
521     if(action == MULTIPLY_NO) {
522         /* Usually count is 1, but do not assume it. */
523         size = basesize;
524     } else if (action == MULTIPLY_CT) {
525         size = basesize * count;
526     }  else {
527         /* MULTIPLY_SP */
528         /* DW_DLA_ADDR.. count * largest size */
529         size = count *
530             (sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ?
531             sizeof(Dwarf_Addr) : sizeof(Dwarf_Off));
532     }
533     size += DW_RESERVE;
534     alloc_mem = malloc(size);
535     if (!alloc_mem) {
536         return NULL;
537     }
538     {
539         char * ret_mem = alloc_mem + DW_RESERVE;
540         void *key = ret_mem;
541         struct reserve_data_s *r = (struct reserve_data_s*)alloc_mem;
542         void *result = 0;
543 
544         memset(alloc_mem, 0, size);
545         /* We are not actually using rd_dbg, we are using rd_type. */
546         r->rd_dbg = dbg;
547         r->rd_type = alloc_type;
548         r->rd_length = size;
549         if (alloc_instance_basics[type].specialconstructor) {
550             int res = alloc_instance_basics[type].
551                 specialconstructor(dbg, ret_mem);
552             if (res != DW_DLV_OK) {
553                 /*  We leak what we allocated in
554                     _dwarf_find_memory when
555                     constructor fails. */
556                 return NULL;
557             }
558         }
559         /*  See global flag.
560             If zero then caller choses not
561             to track allocations, so dwarf_finish()
562             is unable to free anything the caller
563             omitted to dealloc. Normally
564             the global flag is non-zero */
565 #ifdef HAVE_GLOBAL_ALLOC_SUMS
566         global_allocation_count++;
567         global_allocation_total += size;
568 #endif /* HAVE_GLOBAL_ALLOC_SUMS */
569 
570         /*  As of March 14, 2020 it's
571             not necessary to test for alloc type, but instead
572             only call tsearch if de_alloc_tree_on. */
573         if (global_de_alloc_tree_on) {
574 #ifdef HAVE_GLOBAL_ALLOC_SUMS
575             global_de_alloc_tree_total += size;
576             global_de_alloc_tree_count++;
577 #endif /* HAVE_GLOBAL_ALLOC_SUMS */
578             result = dwarf_tsearch((void *)key,
579                 &dbg->de_alloc_tree,simple_compare_function);
580             if(!result) {
581                 /*  Something badly wrong. Out of memory.
582                     pretend all is well. */
583             }
584         }
585 #if DEBUG
586     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__);
587 #endif
588         return (ret_mem);
589     }
590 }
591 
592 /*  This was once a long list of tests using dss_data
593     and dss_size to see if 'space' was inside a debug section.
594     This tfind approach removes that maintenance headache. */
595 static int
596 string_is_in_debug_section(Dwarf_Debug dbg,void * space)
597 {
598     /*  See dwarf_line.c dwarf_srcfiles()
599         for one way we can wind up with
600         a DW_DLA_STRING string that may or may not be malloc-ed
601         by _dwarf_get_alloc().
602 
603         dwarf_formstring(), for example, returns strings
604         which point into .debug_info or .debug_types but
605         dwarf_dealloc is never supposed to be applied
606         to strings dwarf_formstring() returns!
607 
608         Lots of calls returning strings
609         have always been documented as requiring
610         dwarf_dealloc(...DW_DLA_STRING) when the code
611         just returns a pointer to a portion of a loaded section!
612         It is too late to change the documentation. */
613 
614     void *result = 0;
615     result = dwarf_tfind((void *)space,
616         &dbg->de_alloc_tree,simple_compare_function);
617     if(!result) {
618         /*  Not in the tree, so not malloc-ed
619             Nothing to delete. */
620         return TRUE;
621     }
622     /*  We found the address in the tree, so it is NOT
623         part of .debug_info or any other dwarf section,
624         but is space malloc-d in _dwarf_get_alloc(). */
625     return FALSE;
626 }
627 
628 
629 /*  These wrappers for dwarf_dealloc enable type-checking
630     at call points. */
631 void
632 dwarf_dealloc_error(Dwarf_Debug dbg, Dwarf_Error err)
633 {
634     dwarf_dealloc(dbg,err,DW_DLA_ERROR);
635 }
636 void
637 dwarf_dealloc_die( Dwarf_Die die)
638 {
639     Dwarf_Debug dbg = 0;
640     Dwarf_CU_Context context = 0;
641 
642     if (!die) {
643 #ifdef DEBUG
644         printf("DEALLOC does nothing, die NULL line %d %s\n",
645             __LINE__,__FILE__);
646         fflush(stdout);
647 #endif
648         return;
649     }
650     context = die->di_cu_context;
651     if (!context) {
652 #ifdef DEBUG
653         printf("DEALLOC does nothing, context NULL line %d %s\n",
654             __LINE__,__FILE__);
655         fflush(stdout);
656 #endif
657         return;
658     }
659     dbg = context->cc_dbg;
660     dwarf_dealloc(dbg,die,DW_DLA_DIE);
661 }
662 
663 
664 void
665 dwarf_dealloc_attribute(Dwarf_Attribute attr)
666 {
667     Dwarf_Debug dbg = 0;
668 
669     if (!attr) {
670 #ifdef DEBUG
671         printf("DEALLOC does nothing, attr is NULL line %d %s\n",
672             __LINE__,__FILE__);
673         fflush(stdout);
674 #endif
675         return;
676     }
677     dbg = attr->ar_dbg;
678     dwarf_dealloc(dbg,attr,DW_DLA_ATTR);
679 }
680 /*
681     This function is used to deallocate a region of memory
682     that was obtained by a call to _dwarf_get_alloc.  Note
683     that though dwarf_dealloc() is a public function,
684     _dwarf_get_alloc() isn't.
685 
686     For lists, typically arrays of pointers, it is assumed
687     that the space was allocated by a direct call to malloc,
688     and so a straight free() is done.  This is also the case
689     for variable length blocks such as DW_DLA_FRAME_BLOCK
690     and DW_DLA_LOC_BLOCK and DW_DLA_RANGES.
691 
692     For strings, the pointer might point to a string in
693     .debug_info or .debug_string.  After this is checked,
694     and if found not to be the case, a free() is done,
695     again on the assumption that a malloc was used to
696     obtain the space.
697 
698     This function does not return anything.
699     The _dwarf_error_destructor() will be called
700     to free the er_msg string
701     (if this is a Dwarf_Error) just before the
702     Dwarf_Error is freed here. See...specialdestructor()
703     below.
704 
705 */
706 void
707 dwarf_dealloc(Dwarf_Debug dbg,
708     Dwarf_Ptr space, Dwarf_Unsigned alloc_type)
709 {
710     unsigned int type = 0;
711     char * malloc_addr = 0;
712     struct reserve_data_s * r = 0;
713 
714     if (!space) {
715 #ifdef DEBUG
716         printf("DEALLOC does nothing, space NULL line %d %s\n",
717             __LINE__,__FILE__);
718         fflush(stdout);
719 abort();
720 #endif /* DEBUG*/
721         return;
722     }
723     if (!dbg) {
724         /*  App error, or an app that failed to succeed in a
725             dwarf_init() call. */
726 #ifdef DEBUG
727         printf( "DEALLOC does nothing, dbg NULL line %d %s\n",
728             __LINE__,__FILE__);
729         fflush(stdout);
730 #endif /* DEBUG*/
731         return;
732     }
733     if (dbg->de_alloc_tree) {
734         /*  If it's a string in debug_info etc doing
735             (char *)space - DW_RESERVE is totally bogus. */
736         if (alloc_type == DW_DLA_STRING &&
737             string_is_in_debug_section(dbg,space)) {
738             /*  A string pointer may point into .debug_info or
739                 .debug_string etc.
740                 So must not be freed.  And strings have
741                 no need of a specialdestructor().
742                 Mostly a historical mistake here.
743                 Corrected in libdwarf March 14,2020. */
744             return;
745         }
746     }
747     /*  Otherwise it might be allocated string so it is ok
748         do the (char *)space - DW_RESERVE  */
749 
750     /*  If it's a DW_DLA_STRING case and erroneous
751         the following pointer operations might
752         result in a coredump if the pointer
753         is to the beginning of a string section.
754         If not DW_DLA_STRING
755         no correctly written caller could coredump
756         here.  */
757     malloc_addr = (char *)space - DW_RESERVE;
758     r =(struct reserve_data_s *)malloc_addr;
759     if(dbg != r->rd_dbg) {
760         /*  Something is mixed up. */
761 #ifdef DEBUG
762         printf("DEALLOC does nothing, dbg 0x%lx rd_dbg 0x%lx space 0x%lx line %d %s\n",
763             (unsigned long)dbg,
764             (unsigned long)r->rd_dbg,
765             (unsigned long)space,
766             __LINE__,__FILE__);
767         fflush(stdout);
768 #endif /* DEBUG*/
769         return;
770     }
771     if(alloc_type != r->rd_type) {
772         /*  Something is mixed up. */
773 #ifdef DEBUG
774         printf("DEALLOC does nothing, type 0x%lx rd_type 0x%lx space 0x%lx line %d %s\n",
775             (unsigned long)alloc_type,
776             (unsigned long)r->rd_type,
777             (unsigned long)space,
778             __LINE__,__FILE__);
779         fflush(stdout);
780 #endif /* DEBUG*/
781         return;
782     }
783     if (alloc_type == DW_DLA_ERROR) {
784         Dwarf_Error ep = (Dwarf_Error)space;
785 
786         if (ep->er_static_alloc == DE_STATIC) {
787             /*  This is special, malloc arena
788                 was exhausted or a NULL dbg
789                 was used for the error because the real
790                 dbg was unavailable.
791                 There is nothing to delete, really.
792                 Set er_errval to signal that the
793                 space was dealloc'd.
794                 Not dealing with destructor here. */
795             _dwarf_failsafe_error.er_errval =
796                 DW_DLE_FAILSAFE_ERRVAL;
797 #ifdef DEBUG
798             printf("DEALLOC does nothing, DE_STATIC line %d %s\n",
799                 __LINE__,__FILE__);
800             fflush(stdout);
801 #endif /* DEBUG*/
802             return;
803         }
804         if (ep->er_static_alloc == DE_MALLOC) {
805             /*  This is special, we had no arena
806                 so just malloc'd a Dwarf_Error_s.
807                 Not dealing with destructor here. */
808             free(space);
809             return;
810         }
811         /* Was normal alloc, use normal dealloc. */
812         /* DW_DLA_ERROR has a specialdestructor */
813     }
814     type = alloc_type;
815 #if DEBUG
816     if(dbg != r->rd_dbg) {
817         /*  Something is badly wrong. Better to leak than
818             to crash. */
819         return;
820     }
821 #endif
822 #if DEBUG
823     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__);
824 #endif
825     if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
826         /* internal or user app error */
827 #ifdef DEBUG
828         printf("DEALLOC does nothing, type too big %lu line %d %s\n",
829             (unsigned long)type,
830             __LINE__,__FILE__);
831 #endif /* DEBUG*/
832         return;
833     }
834 #ifdef HAVE_GLOBAL_ALLOC_SUMS
835     global_de_alloc_tree_early_dealloc_count++;
836     global_de_alloc_tree_early_dealloc_size += r->rd_length;
837 #endif /* HAVE_GLOBAL_ALLOC_SUMS */
838     if (alloc_instance_basics[type].specialdestructor) {
839         alloc_instance_basics[type].specialdestructor(space);
840     }
841     if (dbg->de_alloc_tree) {
842         /*  The 'space' pointer we get points after the
843             reserve space.  The key is 'space'
844             and address to free
845             is just a few bytes before 'space'. */
846         void *key = space;
847 
848         dwarf_tdelete(key,&dbg->de_alloc_tree,
849             simple_compare_function);
850         /*  If dwarf_tdelete returns NULL it might mean
851             a) tree is empty.
852             b) If hashsearch, then a single chain might
853                 now be empty,
854                 so we do not know of a 'parent node'.
855             c) We did not find that key, we did nothing.
856 
857             In any case, we simply don't worry about it.
858             Not Supposed To Happen. */
859     }
860     r->rd_dbg  = (void *)0xfeadbeef;
861     r->rd_length = 0;
862     r->rd_type = 0;
863     free(malloc_addr);
864     return;
865 }
866 
867 /*
868     Allocates space for a Dwarf_Debug_s struct,
869     since one does not exist.
870 */
871 Dwarf_Debug
872 _dwarf_get_debug(void)
873 {
874     Dwarf_Debug dbg;
875 
876     dbg = (Dwarf_Debug) malloc(sizeof(struct Dwarf_Debug_s));
877     if (dbg == NULL) {
878         return (NULL);
879     }
880     memset(dbg, 0, sizeof(struct Dwarf_Debug_s));
881     /* Set up for a dwarf_tsearch hash table */
882 
883     /* Leaving initialization on so we can track
884         DW_DLA_STRING even when global_de_alloc_tree_on
885         is zero. */
886     if (global_de_alloc_tree_on) {
887         dwarf_initialize_search_hash(&dbg->de_alloc_tree,
888             simple_value_hashfunc,0);
889     }
890     return (dbg);
891 }
892 
893 /*
894     This function prints out the statistics
895     collected on allocation of memory chunks.
896     No longer used.
897 */
898 void
899 dwarf_print_memory_stats(UNUSEDARG Dwarf_Debug dbg)
900 {
901 }
902 
903 
904 
905 /* In the 'rela' relocation case we might have malloc'd
906    space to ensure it is read-write. In that case, free the space.  */
907 static void
908 rela_free(struct Dwarf_Section_s * sec)
909 {
910     if (sec->dss_data_was_malloc) {
911         free(sec->dss_data);
912     }
913     sec->dss_data = 0;
914     sec->dss_data_was_malloc = 0;
915 }
916 
917 static void
918 freecontextlist(Dwarf_Debug dbg, Dwarf_Debug_InfoTypes dis)
919 {
920     Dwarf_CU_Context context = 0;
921     Dwarf_CU_Context nextcontext = 0;
922     for (context = dis->de_cu_context_list;
923         context; context = nextcontext) {
924         Dwarf_Hash_Table hash_table = context->cc_abbrev_hash_table;
925         _dwarf_free_abbrev_hash_table_contents(dbg,hash_table);
926         hash_table->tb_entries = 0;
927         nextcontext = context->cc_next;
928         context->cc_next = 0;
929         /*  See also  local_dealloc_cu_context() in
930             dwarf_die_deliv.c */
931         dwarf_dealloc(dbg, hash_table, DW_DLA_HASH_TABLE);
932         context->cc_abbrev_hash_table = 0;
933         dwarf_dealloc(dbg, context, DW_DLA_CU_CONTEXT);
934     }
935     dis->de_cu_context_list = 0;
936 }
937 
938 /*
939     Used to free all space allocated for this Dwarf_Debug.
940     The caller should assume that the Dwarf_Debug pointer
941     itself is no longer valid upon return from this function.
942 
943     In case of difficulty, this function simply returns quietly.
944 */
945 int
946 _dwarf_free_all_of_one_debug(Dwarf_Debug dbg)
947 {
948     unsigned g = 0;
949 
950     if (dbg == NULL) {
951         return (DW_DLV_ERROR);
952     }
953     /*  To do complete validation that we have no surprising
954         missing or erroneous deallocs it is advisable to do
955         the dwarf_deallocs here
956         that are not things the user can otherwise request.
957         Housecleaning.  */
958     if (dbg->de_cu_hashindex_data) {
959         dwarf_xu_header_free(dbg->de_cu_hashindex_data);
960         dbg->de_cu_hashindex_data = 0;
961     }
962     if (dbg->de_tu_hashindex_data) {
963         dwarf_xu_header_free(dbg->de_tu_hashindex_data);
964         dbg->de_tu_hashindex_data = 0;
965     }
966     if( dbg->de_printf_callback_null_device_handle) {
967         fclose(dbg->de_printf_callback_null_device_handle);
968         dbg->de_printf_callback_null_device_handle = 0;
969     }
970     freecontextlist(dbg,&dbg->de_info_reading);
971     freecontextlist(dbg,&dbg->de_types_reading);
972 
973     /* Housecleaning done. Now really free all the space. */
974     rela_free(&dbg->de_debug_info);
975     rela_free(&dbg->de_debug_types);
976     rela_free(&dbg->de_debug_abbrev);
977     rela_free(&dbg->de_debug_line);
978     rela_free(&dbg->de_debug_line_str);
979     rela_free(&dbg->de_debug_loc);
980     rela_free(&dbg->de_debug_aranges);
981     rela_free(&dbg->de_debug_macinfo);
982     rela_free(&dbg->de_debug_macro);
983     rela_free(&dbg->de_debug_names);
984     rela_free(&dbg->de_debug_pubnames);
985     rela_free(&dbg->de_debug_str);
986     rela_free(&dbg->de_debug_sup);
987     rela_free(&dbg->de_debug_frame);
988     rela_free(&dbg->de_debug_frame_eh_gnu);
989     rela_free(&dbg->de_debug_pubtypes);
990     rela_free(&dbg->de_debug_funcnames);
991     rela_free(&dbg->de_debug_typenames);
992     rela_free(&dbg->de_debug_varnames);
993     rela_free(&dbg->de_debug_weaknames);
994     rela_free(&dbg->de_debug_ranges);
995     rela_free(&dbg->de_debug_str_offsets);
996     rela_free(&dbg->de_debug_addr);
997     rela_free(&dbg->de_debug_gdbindex);
998     rela_free(&dbg->de_debug_cu_index);
999     rela_free(&dbg->de_debug_tu_index);
1000     dwarf_harmless_cleanout(&dbg->de_harmless_errors);
1001 
1002     _dwarf_dealloc_rnglists_context(dbg);
1003     _dwarf_dealloc_loclists_context(dbg);
1004     if (dbg->de_printf_callback.dp_buffer &&
1005         !dbg->de_printf_callback.dp_buffer_user_provided ) {
1006         free(dbg->de_printf_callback.dp_buffer);
1007     }
1008 
1009     _dwarf_destroy_group_map(dbg);
1010     /*  de_alloc_tree might be NULL if
1011         global_de_alloc_tree_on is zero. */
1012     if (dbg->de_alloc_tree) {
1013         dwarf_tdestroy(dbg->de_alloc_tree,tdestroy_free_node);
1014         dbg->de_alloc_tree = 0;
1015     }
1016     if (dbg->de_tied_data.td_tied_search) {
1017         dwarf_tdestroy(dbg->de_tied_data.td_tied_search,
1018             _dwarf_tied_destroy_free_node);
1019         dbg->de_tied_data.td_tied_search = 0;
1020     }
1021     free((void *)dbg->de_path);
1022     dbg->de_path = 0;
1023     for (g = 0; g < dbg->de_gnu_global_path_count; ++g) {
1024         free((char *)dbg->de_gnu_global_paths[g]);
1025         dbg->de_gnu_global_paths[g] = 0;
1026     }
1027     free((void*)dbg->de_gnu_global_paths);
1028     dbg->de_gnu_global_paths = 0;
1029     dbg->de_gnu_global_path_count = 0;
1030     memset(dbg, 0, sizeof(*dbg)); /* Prevent accidental use later. */
1031     free(dbg);
1032     return (DW_DLV_OK);
1033 }
1034 /*  A special case: we have no dbg, no alloc header etc.
1035     So create something out of thin air that we can recognize
1036     in dwarf_dealloc.
1037     Something with the prefix (prefix space hidden from caller).
1038 
1039     Only applies to DW_DLA_ERROR, and  making up an error record.
1040     The allocated space simply leaks.
1041 */
1042 struct Dwarf_Error_s *
1043 _dwarf_special_no_dbg_error_malloc(void)
1044 {
1045     Dwarf_Error e = 0;
1046     Dwarf_Unsigned len = sizeof(struct Dwarf_Error_s);
1047     char *mem = (char *)malloc(len);
1048 
1049     if (mem == 0) {
1050         return 0;
1051     }
1052     memset(mem, 0, len);
1053     e = (Dwarf_Error)mem;
1054     e->er_static_alloc = DE_MALLOC;
1055     return e;
1056 }
1057