xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_alloc.c (revision 49d3bc91e27cd871b950d56c01398fa2f2e12ab4)
1 /*
2 
3   Copyright (C) 2000,2002,2004 Silicon Graphics, Inc.  All Rights Reserved.
4 
5   This program is free software; you can redistribute it and/or modify it
6   under the terms of version 2.1 of the GNU Lesser General Public License
7   as published by the Free Software Foundation.
8 
9   This program is distributed in the hope that it would be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13   Further, this software is distributed without any warranty that it is
14   free of the rightful claim of any third person regarding infringement
15   or the like.  Any license provided herein, whether implied or
16   otherwise, applies only to this software file.  Patent licenses, if
17   any, provided herein do not apply to combinations of this program with
18   other software, or any other product whatsoever.
19 
20   You should have received a copy of the GNU Lesser General Public
21   License along with this program; if not, write the Free Software
22   Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
23   USA.
24 
25   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
26   Mountain View, CA 94043, or:
27 
28   http://www.sgi.com
29 
30   For further information regarding this notice, see:
31 
32   http://oss.sgi.com/projects/GenInfo/NoticeExplan
33 
34 */
35 
36 
37 
38 #include "config.h"
39 #include "dwarf_incl.h"
40 #include <sys/types.h>
41 
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <malloc.h>
45 
46 /*
47     These files are included to get the sizes
48     of structs to set the ah_bytes_one_struct field
49     of the Dwarf_Alloc_Hdr_s structs for each
50     allocation type.
51 */
52 #include "dwarf_line.h"
53 #include "dwarf_global.h"
54 #include "dwarf_arange.h"
55 #include "dwarf_abbrev.h"
56 #include "dwarf_die_deliv.h"
57 #include "dwarf_frame.h"
58 #include "dwarf_loc.h"
59 #include "dwarf_funcs.h"
60 #include "dwarf_types.h"
61 #include "dwarf_vars.h"
62 #include "dwarf_weaks.h"
63 
64 static void _dwarf_free_special_error(Dwarf_Ptr space);
65 #ifdef DWARF_SIMPLE_MALLOC
66 static void _dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg,
67 		Dwarf_Ptr addr,
68 		unsigned long size,
69         	short alloc_type);
70 static void _dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg,
71 		Dwarf_Ptr space,
72 		short alloc_type);
73 void _dwarf_simple_malloc_botch(int err);
74 
75 #endif /* DWARF_SIMPLE_MALLOC */
76 
77 
78 
79 
80 /*
81     This macro adds the size of a pointer to the size of a
82     struct that is given to it.  It rounds up the size to
83     be a multiple of the size of a pointer.  This is done
84     so that every struct returned by _dwarf_get_alloc()
85     can be preceded by a pointer to the chunk it came from.
86     Before, it checks if the size of struct is less than
87     the size of a pointer.  If yes, it returns the size
88     of 2 pointers.  The returned size should be at least
89     the size of 2 pointers, since the first points to the
90     chunk the struct was allocated from, and the second
91     is used to link the free list.
92 
93     If this is n32, we want the sizes to be 64-bit aligned
94     so that longlong in the structure we return to user
95     is aligned properly. Thus the _dw_fac of 2
96 
97     Only long longs need to be properly aligned: we don't
98     have long double and don't align for that.
99 
100 */
101 #if _MIPS_SIM == _MIPS_SIM_NABI32
102 #define _DW_FAC 2
103 #define _DW_PS sizeof(void *)
104 #else
105 #define _DW_FAC 1
106 #define _DW_PS sizeof(void *)
107 #endif
108 #define _DW_RESERVE (_DW_FAC * _DW_PS)
109 
110 /* Round size up to the next multiple of _DW_RESERVE bytes
111 */
112 #define ROUND_SIZE(inputsize)                 \
113         (((inputsize) % (_DW_RESERVE)) == 0 ? \
114             (inputsize):                      \
115             ((inputsize)  +                   \
116                (_DW_RESERVE) - ((inputsize) % (_DW_RESERVE)) ))
117 
118 #define ROUND_SIZE_WITH_POINTER(i_size) (ROUND_SIZE(i_size) + _DW_RESERVE)
119 #define BASE_ALLOC 64
120 #define BIG_ALLOC  128
121 
122 /* This translates into de_alloc_hdr index
123 ** the 0,1,1 entries are special: they don't use the
124 ** table values at all.
125 ** Rearranging the DW_DLA values would break binary compatibility
126 ** so that is not an option.
127 */
128 struct ial_s {
129     int ia_al_num;		/* Index into de_alloc_hdr table. */
130 
131     /* In bytes, one struct instance. This does not account for extra
132        space needed per block, but that (_DW_RESERVE) will be added in
133        later where it is needed (_DW_RESERVE space never added in
134        here). */
135     int ia_struct_size;
136 
137 
138     /* Number of instances per alloc block. MUST be > 0. */
139     int ia_base_count;
140 };
141 
142 static const
143 struct ial_s index_into_allocated[ALLOC_AREA_INDEX_TABLE_MAX] = {
144     {0, 1, 1},			/* none */
145     {0, 1, 1,},			/* 1 DW_DLA_STRING */
146     {1, sizeof(Dwarf_Loc), BASE_ALLOC}
147     ,				/* 2 DW_DLA_LOC */
148     {2, sizeof(Dwarf_Locdesc), BASE_ALLOC}
149     ,				/* 3 DW_DLA_LOCDESC */
150     {0, 1, 1}
151     ,				/* not used *//* 4 DW_DLA_ELLIST */
152     {0, 1, 1}
153     ,				/* not used *//* 5 DW_DLA_BOUNDS */
154     {3, sizeof(Dwarf_Block), BASE_ALLOC}
155     ,				/* 6 DW_DLA_BLOCK */
156     {0, 1, 1}
157     ,				/* the actual dwarf_debug structure *//* 7 DW_DLA_DEBUG */
158     {4, sizeof(struct Dwarf_Die_s), BIG_ALLOC},	/* 8 DW_DLA_DIE */
159     {5, sizeof(struct Dwarf_Line_s), BIG_ALLOC},	/* 9
160 							   DW_DLA_LINE */
161     {6, sizeof(struct Dwarf_Attribute_s), BIG_ALLOC * 2},
162     /* 10 DW_DLA_ATTR */
163     {0, 1, 1},			/* not used *//* 11 DW_DLA_TYPE */
164     {0, 1, 1},			/* not used *//* 12 DW_DLA_SUBSCR */
165     {7, sizeof(struct Dwarf_Global_s), BIG_ALLOC},	/* 13
166 							   DW_DLA_GLOBAL
167 							 */
168     {8, sizeof(struct Dwarf_Error_s), BASE_ALLOC},	/* 14
169 							   DW_DLA_ERROR
170 							 */
171     {0, 1, 1},			/* 15 DW_DLA_LIST */
172     {0, 1, 1},			/* not used *//* 16 DW_DLA_LINEBUF */
173     {9, sizeof(struct Dwarf_Arange_s), BASE_ALLOC},	/* 17
174 							   DW_DLA_ARANGE
175 							 */
176     {10, sizeof(struct Dwarf_Abbrev_s), BIG_ALLOC},	/* 18
177 							   DW_DLA_ABBREV
178 							 */
179     {11, sizeof(Dwarf_Frame_Op), BIG_ALLOC}
180     ,				/* 19 DW_DLA_FRAME_OP */
181     {12, sizeof(struct Dwarf_Cie_s), BASE_ALLOC},	/* 20
182 							   DW_DLA_CIE */
183     {13, sizeof(struct Dwarf_Fde_s), BASE_ALLOC},	/* 21
184 							   DW_DLA_FDE */
185     {0, 1, 1},			/* 22 DW_DLA_LOC_BLOCK */
186     {0, 1, 1},			/* 23 DW_DLA_FRAME_BLOCK */
187     {14, sizeof(struct Dwarf_Global_s), BIG_ALLOC},	/* 24
188 							   DW_DLA_FUNC */
189     {15, sizeof(struct Dwarf_Global_s), BIG_ALLOC},	/* 25
190 							   DW_DLA_TYPENAME
191 							 */
192     {16, sizeof(struct Dwarf_Global_s), BIG_ALLOC},	/* 26
193 							   DW_DLA_VAR */
194     {17, sizeof(struct Dwarf_Global_s), BASE_ALLOC},	/* 27
195 							   DW_DLA_WEAK */
196     {0, 1, 1},			/* 28 DW_DLA_ADDR */
197     {18, sizeof(struct Dwarf_Abbrev_List_s), BIG_ALLOC},
198     /* 29 DW_DLA_ABBREV_LIST */
199     {19, sizeof(struct Dwarf_Chain_s), BIG_ALLOC},	/* 30
200 							   DW_DLA_CHAIN
201 							 */
202     {20, sizeof(struct Dwarf_CU_Context_s), BASE_ALLOC},
203     /* 31 DW_DLA_CU_CONTEXT */
204     {21, sizeof(struct Dwarf_Frame_s), BASE_ALLOC},	/* 32
205 							   DW_DLA_FRAME
206 							 */
207     {22, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
208     /* 33 DW_DLA_GLOBAL_CONTEXT */
209     {23, sizeof(struct Dwarf_File_Entry_s), BASE_ALLOC},
210     /* 34 DW_DLA_FILE_ENTRY */
211     {24, sizeof(struct Dwarf_Line_Context_s), BASE_ALLOC},
212     /* 35 DW_DLA_LINE_CONTEXT */
213     {25, sizeof(struct Dwarf_Loc_Chain_s), BASE_ALLOC},
214     /* 36 DW_DLA_LOC_CHAIN */
215     {26, ABBREV_HASH_TABLE_SIZE * 2 * sizeof(Dwarf_Abbrev_List),
216      BASE_ALLOC}
217     ,
218     /* 37 DW_DLA_HASH_TABLE */
219 
220 /* The following really use Global struct: used to be unique struct
221    per type, but now merged (11/99).  The opaque types
222    are visible in the interface. The types are left in existence,
223    with unchanged numbers.
224 */
225     {27, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
226     /* 38 DW_DLA_FUNC_CONTEXT */
227     {28, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
228     /* 39 DW_DLA_TYPENAME_CONTEXT */
229     {29, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
230     /* 40 DW_DLA_VAR_CONTEXT */
231     {30, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
232     /* 41 DW_DLA_WEAK_CONTEXT */
233 };
234 
235 #ifndef DWARF_SIMPLE_MALLOC
236 
237 /*
238     This function is given a pointer to the header
239     structure that is used to allocate 1 struct of
240     the type given by alloc_type.  It first checks
241     if a struct is available in its free list.  If
242     not, it checks if 1 is available in its blob,
243     which is a chunk of memory that is reserved for
244     its use.  If not, it malloc's a chunk.  The
245     initial part of it is used to store the end
246     address of the chunk, and also to keep track
247     of the number of free structs in that chunk.
248     This information is used for freeing the chunk
249     when all the structs in it are free.
250 
251     Assume all input arguments have been validated.
252 
253     This function can be used only to allocate 1
254     struct of the given type.
255 
256     It returns a pointer to the struct that the
257     user can use.  It returns NULL only when it
258     is out of free structs, and cannot malloc
259     any more.  The struct returned is zero-ed.
260 
261     A pointer to the chunk that the struct belongs
262     to is stored in the bytes preceding the
263     returned address.  Since this pointer it
264     never overwritten, when a struct is allocated
265     from the free_list this pointer does not
266     have to be written.  In the 2 other cases,
267     where the struct is allocated from a new
268     chunk, or the blob, a pointer to the chunk
269     is written.
270 */
271 static Dwarf_Ptr
272 _dwarf_find_memory(Dwarf_Alloc_Hdr alloc_hdr)
273 {
274     /* Pointer to the struct allocated. */
275     Dwarf_Small *ret_mem = 0;
276 
277     /* Pointer to info about chunks allocated. */
278     Dwarf_Alloc_Area alloc_area;
279 
280     /* Size of chunk malloc'ed when no free structs left. */
281     Dwarf_Signed mem_block_size;
282 
283     /* Pointer to block malloc'ed. */
284     Dwarf_Small *mem_block;
285 
286     /*
287        Check the alloc_area from which the last allocation was made
288        (most recent new block). If that is not successful, then
289        search the list of alloc_area's from alloc_header. */
290     alloc_area = alloc_hdr->ah_last_alloc_area;
291     if (alloc_area == NULL || alloc_area->aa_free_structs_in_chunk == 0)
292 	for (alloc_area = alloc_hdr->ah_alloc_area_head;
293 	     alloc_area != NULL; alloc_area = alloc_area->aa_next) {
294 
295 	    if (alloc_area->aa_free_structs_in_chunk > 0) {
296 		break;		/* found a free entry! */
297 	    }
298 
299 	}
300 
301     if (alloc_area != NULL) {
302 	alloc_area->aa_free_structs_in_chunk--;
303 
304 	if (alloc_area->aa_free_list != NULL) {
305 	    ret_mem = alloc_area->aa_free_list;
306 
307 	    /*
308 	       Update the free list.  The initial part of the struct is
309 	       used to hold a pointer to the next struct on the free
310 	       list.  In this way, the free list chain is maintained at
311 	       0 memory cost. */
312 	    alloc_area->aa_free_list =
313 		((Dwarf_Free_List) ret_mem)->fl_next;
314 	} else if (alloc_area->aa_blob_start < alloc_area->aa_blob_end) {
315 	    ret_mem = alloc_area->aa_blob_start;
316 
317 	    /*
318 	       Store pointer to chunk this struct belongs to in the
319 	       first few bytes.  Return pointer to bytes after this
320 	       pointer storage. */
321 	    *(Dwarf_Alloc_Area *) ret_mem = alloc_area;
322 	    ret_mem += _DW_RESERVE;
323 
324 	    alloc_area->aa_blob_start += alloc_hdr->ah_bytes_one_struct;
325 	} else {
326 	    /* else fall thru , though it should be impossible to fall
327 	       thru. And represents a disastrous programming error if
328 	       we get here. */
329 #ifdef DEBUG
330 	    fprintf(stderr, "libdwarf Internal error start %x end %x\n",
331 		    (int) alloc_area->aa_blob_start,
332 		    (int) alloc_area->aa_blob_end);
333 #endif
334 	}
335     }
336 
337     /* New memory has to malloc'ed since there are no free structs. */
338     if (ret_mem == 0) {
339 	Dwarf_Word rounded_area_hdr_size;
340 
341 	alloc_hdr->ah_chunks_allocated++;
342 
343 	{			/* this nonsense avoids a warning */
344 	    /* CONSTCOND would be better */
345 	    unsigned long v = sizeof(struct Dwarf_Alloc_Area_s);
346 
347 	    rounded_area_hdr_size = ROUND_SIZE(v);
348 	}
349 
350 	/*
351 	   Allocate memory to contain the required number of structs
352 	   and the Dwarf_Alloc_Area_s to control it. */
353 	mem_block_size = alloc_hdr->ah_bytes_malloc_per_chunk +
354 	    rounded_area_hdr_size;
355 
356 	mem_block = malloc(mem_block_size);
357 	if (mem_block == NULL) {
358 	    return (NULL);
359 	}
360 
361 
362 	/*
363 	   Attach the Dwarf_Alloc_Area_s struct to the list of chunks
364 	   malloc'ed for this struct type. Also initialize the fields
365 	   of the Dwarf_Alloc_Area_s. */
366 	alloc_area = (Dwarf_Alloc_Area) mem_block;
367 	alloc_area->aa_prev = 0;
368 	if (alloc_hdr->ah_alloc_area_head != NULL) {
369 	    alloc_hdr->ah_alloc_area_head->aa_prev = alloc_area;
370 	}
371 	alloc_area->aa_free_list = 0;
372 	alloc_area->aa_next = alloc_hdr->ah_alloc_area_head;
373 	alloc_hdr->ah_alloc_area_head = alloc_area;
374 
375 	alloc_area->aa_alloc_hdr = alloc_hdr;
376 	alloc_area->aa_free_structs_in_chunk =
377 	    (Dwarf_Sword) alloc_hdr->ah_structs_per_chunk - 1;
378 	if (alloc_area->aa_free_structs_in_chunk < 1) {
379 	    /* If we get here, there is a disastrous programming error
380 	       somewhere. */
381 #ifdef DEBUG
382 	    fprintf(stderr,
383 		    "libdwarf Internal error: free structs in chunk %d\n",
384 		    (int) alloc_area->aa_free_structs_in_chunk);
385 #endif
386 	    return NULL;
387 	}
388 
389 	/*
390 	   The struct returned begins immediately after the
391 	   Dwarf_Alloc_Area_s struct. */
392 	ret_mem = mem_block + rounded_area_hdr_size;
393 	alloc_area->aa_blob_start =
394 	    ret_mem + alloc_hdr->ah_bytes_one_struct;
395 	alloc_area->aa_blob_end = mem_block + mem_block_size;
396 
397 	/*
398 	   Store pointer to chunk this struct belongs to in the first
399 	   few bytes.  Return pointer to bytes after this pointer
400 	   storage. */
401 	*(Dwarf_Alloc_Area *) ret_mem = alloc_area;
402 	ret_mem += _DW_RESERVE;
403     }
404 
405     alloc_hdr->ah_last_alloc_area = alloc_area;
406     alloc_hdr->ah_struct_user_holds++;
407     memset(ret_mem,0, alloc_hdr->ah_bytes_one_struct - _DW_RESERVE);
408     return (ret_mem);
409 }
410 
411 #endif /* ndef DWARF_SIMPLE_MALLOC */
412 
413 /*
414     This function returns a pointer to a region
415     of memory.  For alloc_types that are not
416     strings or lists of pointers, only 1 struct
417     can be requested at a time.  This is indicated
418     by an input count of 1.  For strings, count
419     equals the length of the string it will
420     contain, i.e it the length of the string
421     plus 1 for the terminating null.  For lists
422     of pointers, count is equal to the number of
423     pointers.  For DW_DLA_FRAME_BLOCK, and
424     DW_DLA_LOC_BLOCK allocation types also, count
425     is the count of the number of structs needed.
426 
427     This function cannot be used to allocate a
428     Dwarf_Debug_s struct.
429 */
430 Dwarf_Ptr
431 _dwarf_get_alloc(Dwarf_Debug dbg,
432 		 Dwarf_Small alloc_type, Dwarf_Unsigned count)
433 {
434     Dwarf_Alloc_Hdr alloc_hdr;
435 
436     Dwarf_Ptr ret_mem;
437 
438     Dwarf_Signed size = 0;
439     unsigned int index;
440     unsigned int type = alloc_type;
441 
442     if (dbg == NULL) {
443 	return (NULL);
444     }
445 
446     if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
447 	/* internal error */
448 	return NULL;
449     }
450     index = index_into_allocated[type].ia_al_num;
451     /* zero also illegal but not tested for */
452 
453     /* If the Dwarf_Debug is not fully set up, we will get index 0 for
454        any type and must do something.  'Not fully set up' can only
455        happen for DW_DLA_ERROR, I (davea) believe, and for that we call
456        special code here.. */
457 
458     if (index == 0) {
459 	if (alloc_type == DW_DLA_STRING) {
460 	    size = count;
461 	} else if (alloc_type == DW_DLA_LIST) {
462 	    size = count * sizeof(Dwarf_Ptr);
463 	} else if (alloc_type == DW_DLA_FRAME_BLOCK) {
464 	    size = count * sizeof(Dwarf_Frame_Op);
465 	} else if (alloc_type == DW_DLA_LOC_BLOCK) {
466 	    size = count * sizeof(Dwarf_Loc);
467 	} else if (alloc_type == DW_DLA_ADDR) {
468 	    size = count *
469 		(sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ?
470 		 sizeof(Dwarf_Addr) : sizeof(Dwarf_Off));
471 	} else if (alloc_type == DW_DLA_ERROR) {
472 	    return _dwarf_special_no_dbg_error_malloc();
473 	} else {
474 	    /* If we get here, there is a disastrous programming error
475 	       somewhere. */
476 #ifdef DEBUG
477 	    fprintf(stderr,
478 		    "libdwarf Internal error: type %d  unexpected\n",
479 		    (int) type);
480 #endif
481 	}
482     } else {
483 	alloc_hdr = &dbg->de_alloc_hdr[index];
484 	if (alloc_hdr->ah_bytes_one_struct > 0) {
485 #ifdef DWARF_SIMPLE_MALLOC
486 	    size = alloc_hdr->ah_bytes_one_struct;
487 #else
488 	    return (_dwarf_find_memory(alloc_hdr));
489 #endif
490 
491 	} else {
492 	    /* Special case: should not really happen at all. */
493 	    if (type == DW_DLA_ERROR) {
494 		/* dwarf_init failure. Because dbg is incomplete we
495 		   won't use it to record the malloc. */
496 		return _dwarf_special_no_dbg_error_malloc();
497 	    } else {
498 		/* If we get here, there is a disastrous programming
499 		   error somewhere. */
500 #ifdef DWARF_SIMPLE_MALLOC
501 		_dwarf_simple_malloc_botch(3);
502 #endif
503 #ifdef DEBUG
504 		fprintf(stderr,
505 			"libdwarf Internal error: Type %d  unexpected\n",
506 			(int) type);
507 #endif
508 	    }
509 	}
510     }
511 
512     ret_mem = malloc(size);
513 #ifdef DWARF_SIMPLE_MALLOC
514     _dwarf_simple_malloc_add_to_list(dbg,ret_mem,(unsigned long)size,
515 		alloc_type);
516 #endif
517     if (ret_mem != NULL)
518 	memset(ret_mem,0, size);
519 
520     return (ret_mem);
521 }
522 
523 
524 /*
525     This function is used to deallocate a region of memory
526     that was obtained by a call to _dwarf_get_alloc.  Note
527     that though dwarf_dealloc() is a public function,
528     _dwarf_get_alloc() isn't.
529 
530     For lists, typically arrays of pointers, it is assumed
531     that the space was allocated by a direct call to malloc,
532     and so a straight free() is done.  This is also the case
533     for variable length blocks such as DW_DLA_FRAME_BLOCK
534     and DW_DLA_LOC_BLOCK.
535 
536     For strings, the pointer might point to a string in
537     .debug_info or .debug_string.  After this is checked,
538     and if found not to be the case, a free() is done,
539     again on the assumption that a malloc was used to
540     obtain the space.
541 
542     For other types of structs, a pointer to the chunk that
543     the struct was allocated out of, is present in the bytes
544     preceding the pointer passed in.  For this chunk it is
545     checked whether all the structs in that chunk are now free.
546     If so, the entire chunk is free_ed.  Otherwise, the space
547     is added to the free list for that chunk, and the free count
548     incremented.
549 
550     This function does not return anything.
551 */
552 void
553 dwarf_dealloc(Dwarf_Debug dbg,
554 	      Dwarf_Ptr space, Dwarf_Unsigned alloc_type)
555 {
556     Dwarf_Alloc_Hdr alloc_hdr;
557     Dwarf_Alloc_Area alloc_area;
558     unsigned int type = alloc_type;
559     unsigned int index;
560 
561     if (space == NULL) {
562 	return;
563     }
564     if (alloc_type == DW_DLA_ERROR) {
565 	/* Get pointer to Dwarf_Alloc_Area this struct came from. See
566 	   dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */
567 	alloc_area =
568 	    *(Dwarf_Alloc_Area *) ((char *) space - _DW_RESERVE);
569 	if (alloc_area == 0) {
570 	    /* This is the special case of a failed dwarf_init(). Also
571 	       (and more signficantly) there are a variety of other
572 	       situations where libdwarf does not *know* what dbg is
573 	       involved (because of a libdwarf-caller-error) so
574 	       libdwarf uses NULL as the dbg. Those too wind up here. */
575 	    _dwarf_free_special_error(space);
576 	    return;
577 	}
578 
579     }
580     if (dbg == NULL) {
581 	/* App error, or an app that failed to succeed in a
582 	   dwarf_init() call. */
583 	return;
584     }
585     if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
586 	/* internal or user app error */
587 	return;
588     }
589 
590     index = index_into_allocated[alloc_type].ia_al_num;
591     /*
592        A string pointer may point into .debug_info or .debug_string.
593        Otherwise, they are directly malloc'ed. */
594     if (index == 0) {
595 	if (alloc_type == DW_DLA_STRING) {
596 	    if ((Dwarf_Small *) space >= dbg->de_debug_info &&
597 		(Dwarf_Small *) space <
598 		dbg->de_debug_info + dbg->de_debug_info_size)
599 		return;
600 
601 	    if (dbg->de_debug_line != NULL &&
602 		(Dwarf_Small *) space >= dbg->de_debug_line &&
603 		(Dwarf_Small *) space <
604 		dbg->de_debug_line + dbg->de_debug_line_size)
605 		return;
606 
607 	    if (dbg->de_debug_pubnames != NULL &&
608 		(Dwarf_Small *) space >= dbg->de_debug_pubnames &&
609 		(Dwarf_Small *) space <
610 		dbg->de_debug_pubnames + dbg->de_debug_pubnames_size)
611 		return;
612 
613 	    if (dbg->de_debug_frame != NULL &&
614 		(Dwarf_Small *) space >= dbg->de_debug_frame &&
615 		(Dwarf_Small *) space <
616 		dbg->de_debug_frame + dbg->de_debug_frame_size)
617 		return;
618 
619 	    if (dbg->de_debug_str != NULL &&
620 		(Dwarf_Small *) space >= dbg->de_debug_str &&
621 		(Dwarf_Small *) space <
622 		dbg->de_debug_str + dbg->de_debug_str_size)
623 		return;
624 
625 	    if (dbg->de_debug_funcnames != NULL &&
626 		(Dwarf_Small *) space >= dbg->de_debug_funcnames &&
627 		(Dwarf_Small *) space <
628 		dbg->de_debug_funcnames + dbg->de_debug_funcnames_size)
629 		return;
630 
631 	    if (dbg->de_debug_typenames != NULL &&
632 		(Dwarf_Small *) space >= dbg->de_debug_typenames &&
633 		(Dwarf_Small *) space <
634 		dbg->de_debug_typenames + dbg->de_debug_typenames_size)
635 		return;
636 
637 	    if (dbg->de_debug_varnames != NULL &&
638 		(Dwarf_Small *) space >= dbg->de_debug_varnames &&
639 		(Dwarf_Small *) space <
640 		dbg->de_debug_varnames + dbg->de_debug_varnames_size)
641 		return;
642 
643 	    if (dbg->de_debug_weaknames != NULL &&
644 		(Dwarf_Small *) space >= dbg->de_debug_weaknames &&
645 		(Dwarf_Small *) space <
646 		dbg->de_debug_weaknames + dbg->de_debug_weaknames_size)
647 		return;
648 
649 	    free(space);
650 	    return;
651 	}
652 
653 	if (alloc_type == DW_DLA_LIST ||
654 	    alloc_type == DW_DLA_FRAME_BLOCK ||
655 	    alloc_type == DW_DLA_LOC_BLOCK ||
656 	    alloc_type == DW_DLA_ADDR) {
657 
658 	    free(space);
659 	    return;
660 	}
661 	/* else is an alloc type that is not used */
662 	/* app or internal error */
663 #ifdef DWARF_SIMPLE_MALLOC
664         _dwarf_simple_malloc_botch(4);
665 #endif
666 	return;
667 
668     }
669 
670 #ifdef DWARF_SIMPLE_MALLOC
671     _dwarf_simple_malloc_delete_from_list(dbg, space, alloc_type);
672     free(space);
673 #else  /* !DWARF_SIMPLE_MALLOC */
674     alloc_hdr = &dbg->de_alloc_hdr[index];
675 
676     /* Get pointer to Dwarf_Alloc_Area this struct came from. See
677        dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */
678     alloc_area = *(Dwarf_Alloc_Area *) ((char *) space - _DW_RESERVE);
679 
680     /* ASSERT: alloc_area != NULL
681        If NULL we could abort, let it coredump below,
682        or return, pretending all is well. We go
683        on, letting program crash. Is caller error. */
684 
685     /*
686        Check that the alloc_hdr field of the alloc_area we have is
687        pointing to the right alloc_hdr.  This is used to catch use of
688        incorrect deallocation code by the user. */
689     if (alloc_area->aa_alloc_hdr != alloc_hdr) {
690 	/* If we get here, the user has called dwarf_dealloc wrongly or
691 	   there is some other disastrous error. By leaking mem here we
692 	   try to be safe... */
693 #ifdef DEBUG
694 	fprintf(stderr,
695 		"libdwarf Internal error: type %d hdr mismatch %x %x area ptr %x\n",
696 		(int) alloc_type,
697 		(int) alloc_area->aa_alloc_hdr,
698 		(int) alloc_hdr, (int) alloc_area);
699 #endif
700 	return;
701     }
702 
703     alloc_hdr->ah_struct_user_holds--;
704     alloc_area->aa_free_structs_in_chunk++;
705 
706     /*
707        Give chunk back to malloc only when every struct is freed */
708     if (alloc_area->aa_free_structs_in_chunk ==
709 	alloc_hdr->ah_structs_per_chunk) {
710 	if (alloc_area->aa_prev != NULL) {
711 	    alloc_area->aa_prev->aa_next = alloc_area->aa_next;
712 	} else {
713 	    alloc_hdr->ah_alloc_area_head = alloc_area->aa_next;
714 	}
715 
716 	if (alloc_area->aa_next != NULL) {
717 	    alloc_area->aa_next->aa_prev = alloc_area->aa_prev;
718 	}
719 
720 	alloc_hdr->ah_chunks_allocated--;
721 
722 	if (alloc_area == alloc_hdr->ah_last_alloc_area) {
723 	    alloc_hdr->ah_last_alloc_area = NULL;
724 	}
725 	memset(alloc_area,0, sizeof(*alloc_area));
726 	free(alloc_area);
727     }
728 
729     else {
730 	((Dwarf_Free_List) space)->fl_next = alloc_area->aa_free_list;
731 	alloc_area->aa_free_list = space;
732     }
733 #endif /* !DWARF_SIMPLE_MALLOC */
734 }
735 
736 
737 /*
738     Allocates space for a Dwarf_Debug_s struct,
739     since one does not exist.
740 */
741 Dwarf_Debug
742 _dwarf_get_debug(void
743     )
744 {
745     Dwarf_Debug dbg;
746 
747     dbg = (Dwarf_Debug) malloc(sizeof(struct Dwarf_Debug_s));
748     if (dbg == NULL)
749 	return (NULL);
750     else
751 	memset(dbg,0, sizeof(struct Dwarf_Debug_s));
752 
753     return (dbg);
754 }
755 
756 
757 /*
758     Sets up the Dwarf_Debug_s struct for all the
759     allocation types currently defined.
760     Allocation types DW_DLA_STRING, DW_DLA_LIST,
761     DW_DLA_FRAME_BLOCK, DW_DLA_LOC_BLOCK are
762     malloc'ed directly.
763 
764     This routine should be called after _dwarf_setup(),
765     so that information about the sizes of the Dwarf
766     sections can be used to decide the number of
767     structs of each type malloc'ed.
768 
769     Also DW_DLA_ELLIST, DW_DLA_BOUNDS, DW_DLA_TYPE,
770     DW_DLA_SUBSCR, DW_DLA_LINEBUF allocation types
771     are currently not used.
772     The ah_bytes_one_struct and ah_structs_per_chunk fields for
773     these types have been set to 1 for efficiency
774     in dwarf_get_alloc().
775 
776     Ah_alloc_num should be greater than 1 for all
777     types that are currently being used.
778 
779     Therefore, for these allocation types the
780     ah_bytes_one_struct, and ah_structs_per_chunk fields do not
781     need to be initialized.
782 
783     Being an internal routine, assume proper dbg.
784 
785 
786 
787 
788 */
789 /*
790 **  Set up all the Dwarf_Alloc_Hdr records.
791 */
792 
793 Dwarf_Debug
794 _dwarf_setup_debug(Dwarf_Debug dbg)
795 {
796     int i;
797 
798     for (i = 1; i <= MAX_DW_DLA; i++) {
799 	const struct ial_s *ialp = &index_into_allocated[i];
800 	unsigned int hdr_index = ialp->ia_al_num;
801 	Dwarf_Word str_size = ialp->ia_struct_size;
802 	Dwarf_Word str_count = ialp->ia_base_count;
803 	Dwarf_Word rnded_size = ROUND_SIZE_WITH_POINTER(str_size);
804 
805 	Dwarf_Alloc_Hdr alloc_hdr = &dbg->de_alloc_hdr[hdr_index];
806 
807 	alloc_hdr->ah_bytes_one_struct = (Dwarf_Half) rnded_size;
808 
809 	/* ah_structs_per_chunk must be >0 else we are in trouble */
810 	alloc_hdr->ah_structs_per_chunk = str_count;
811 	alloc_hdr->ah_bytes_malloc_per_chunk = rnded_size * str_count;
812     }
813     return (dbg);
814 }
815 
816 /*
817     This function prints out the statistics
818     collected on allocation of memory chunks.
819 */
820 void
821 dwarf_print_memory_stats(Dwarf_Debug dbg)
822 {
823     Dwarf_Alloc_Hdr alloc_hdr;
824     Dwarf_Shalf i;
825 
826     /*
827        Alloc types start at 1, not 0. Hence, the first NULL string,
828        and also a size of MAX_DW_DLA + 1. */
829     char *alloc_type_name[MAX_DW_DLA + 1] = {
830 	"",
831 	"DW_DLA_STRING",
832 	"DW_DLA_LOC",
833 	"DW_DLA_LOCDESC",
834 	"DW_DLA_ELLIST",
835 	"DW_DLA_BOUNDS",
836 	"DW_DLA_BLOCK",
837 	"DW_DLA_DEBUG",
838 	"DW_DLA_DIE",
839 	"DW_DLA_LINE",
840 	"DW_DLA_ATTR",
841 	"DW_DLA_TYPE",
842 	"DW_DLA_SUBSCR",
843 	"DW_DLA_GLOBAL",
844 	"DW_DLA_ERROR",
845 	"DW_DLA_LIST",
846 	"DW_DLA_LINEBUF",
847 	"DW_DLA_ARANGE",
848 	"DW_DLA_ABBREV",
849 	"DW_DLA_FRAME_OP",
850 	"DW_DLA_CIE",
851 	"DW_DLA_FDE",
852 	"DW_DLA_LOC_BLOCK",
853 	"DW_DLA_FRAME_BLOCK",
854 	"DW_DLA_FUNC",
855 	"DW_DLA_TYPENAME",
856 	"DW_DLA_VAR",
857 	"DW_DLA_WEAK",
858 	"DW_DLA_ADDR",
859 	"DW_DLA_ABBREV_LIST",
860 	"DW_DLA_CHAIN",
861 	"DW_DLA_CU_CONTEXT",
862 	"DW_DLA_FRAME",
863 	"DW_DLA_GLOBAL_CONTEXT",
864 	"DW_DLA_FILE_ENTRY",
865 	"DW_DLA_LINE_CONTEXT",
866 	"DW_DLA_LOC_CHAIN",
867 	"DW_DLA_HASH_TABLE",
868 	"DW_DLA_FUNC_CONTEXT",
869 	"DW_DLA_TYPENAME_CONTEXT",
870 	"DW_DLA_VAR_CONTEXT",
871 	"DW_DLA_WEAK_CONTEXT"
872     };
873 
874     if (dbg == NULL)
875 	return;
876 
877     printf("Size of Dwarf_Debug        %4ld bytes\n",
878 	   (long) sizeof(*dbg));
879     printf("Size of Dwarf_Alloc_Hdr_s  %4ld bytes\n",
880 	   (long) sizeof(struct Dwarf_Alloc_Hdr_s));
881     printf("size of Dwarf_Alloc_Area_s %4ld bytes\n",
882 	   (long) sizeof(struct Dwarf_Alloc_Area_s));
883 
884     printf("   Alloc Type                   Curr  Structs byt   str\n");
885     printf("   ----------                   ----  ------- per   per\n");
886     for (i = 1; i <= MAX_DW_DLA; i++) {
887 	int indx = index_into_allocated[i].ia_al_num;
888 
889 	alloc_hdr = &dbg->de_alloc_hdr[indx];
890 	if (alloc_hdr->ah_bytes_one_struct != 1) {
891 	    printf("%2d %-25s   %6d %8d %6d %6d\n",
892 		   (int) i,
893 		   alloc_type_name[i],
894 		   (int) alloc_hdr->ah_chunks_allocated,
895 		   (int) alloc_hdr->ah_struct_user_holds,
896 		   (int) alloc_hdr->ah_bytes_malloc_per_chunk,
897 		   (int) alloc_hdr->ah_structs_per_chunk);
898 	}
899     }
900 }
901 
902 
903 #ifndef DWARF_SIMPLE_MALLOC
904 /*
905     This function is used to recursively
906     free the chunks still allocated, and
907     forward chained through the aa_next
908     pointer.
909 */
910 static void
911 _dwarf_recursive_free(Dwarf_Alloc_Area alloc_area)
912 {
913     if (alloc_area->aa_next != NULL) {
914 	_dwarf_recursive_free(alloc_area->aa_next);
915     }
916 
917     alloc_area->aa_next = 0;
918     alloc_area->aa_prev = 0;
919     free(alloc_area);
920 }
921 #endif
922 
923 /*
924     Used to free all space allocated for this Dwarf_Debug.
925     The caller should assume that the Dwarf_Debug pointer
926     itself is no longer valid upon return from this function.
927 
928     In case of difficulty, this function simply returns quietly.
929 */
930 int
931 _dwarf_free_all_of_one_debug(Dwarf_Debug dbg)
932 {
933     Dwarf_Alloc_Hdr alloc_hdr;
934     Dwarf_Shalf i;
935 
936     if (dbg == NULL)
937 	return (DW_DLV_ERROR);
938 
939 #ifdef DWARF_SIMPLE_MALLOC
940     if(dbg->de_simple_malloc_base) {
941 	struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base;
942 	while( smp)
943 	{
944 	    int i;
945 	    struct simple_malloc_record_s *prev_smp = 0;
946 
947 	    for(i = 0; i < smp->sr_used; ++i) {
948 	        struct simple_malloc_entry_s *cur;
949 		cur = &smp->sr_entry[i];
950 		if(cur->se_addr != 0) {
951 		     free(cur->se_addr);
952 		     cur->se_addr = 0;
953 	        }
954 	    }
955 	    prev_smp = smp;
956 	    smp = smp->sr_next;
957 	    free(prev_smp);
958 	}
959 	dbg->de_simple_malloc_base = 0;
960 	dbg->de_simple_malloc_current = 0;
961     }
962 #else
963     for (i = 1; i < ALLOC_AREA_REAL_TABLE_MAX; i++) {
964 	int indx = i;
965 
966 	alloc_hdr = &dbg->de_alloc_hdr[indx];
967 	if (alloc_hdr->ah_alloc_area_head != NULL) {
968 	    _dwarf_recursive_free(alloc_hdr->ah_alloc_area_head);
969 	}
970     }
971 
972 #endif
973 
974     memset(dbg,0, sizeof(*dbg));	/* prevent accidental use later */
975     free(dbg);
976     return (DW_DLV_OK);
977 }
978 
979 /* A special case: we have no dbg, no alloc header etc.
980    So create something out of thin air that we can recognize
981    in dwarf_dealloc.
982    Something with the prefix (prefix space hidden from caller).
983 
984    Only applies to DW_DLA_ERROR, making up an error record.
985 */
986 
987 struct Dwarf_Error_s *
988 _dwarf_special_no_dbg_error_malloc(void)
989 {
990     /* the union unused things are to guarantee proper alignment */
991     union u {
992 	Dwarf_Alloc_Area ptr_not_used;
993 	struct Dwarf_Error_s base_not_used;
994 	char data_space[sizeof(struct Dwarf_Error_s) +
995 			(_DW_RESERVE * 2)];
996     };
997     char *mem;
998 
999     mem = malloc(sizeof(union u));
1000 
1001     if (mem == 0) {
1002 	return 0;
1003 
1004     }
1005     memset(mem,0, sizeof(union u));
1006     mem += _DW_RESERVE;
1007     return (struct Dwarf_Error_s *) mem;
1008 }
1009 
1010 /* The free side of  _dwarf_special_no_dbg_error_malloc()
1011 */
1012 static void
1013 _dwarf_free_special_error(Dwarf_Ptr space)
1014 {
1015     char *mem = (char *) space;
1016 
1017     mem -= _DW_RESERVE;
1018     free(mem);
1019 }
1020 
1021 
1022 #ifdef DWARF_SIMPLE_MALLOC
1023 /* here solely for planting a breakpoint. */
1024 /* ARGSUSED */
1025 void
1026 _dwarf_simple_malloc_botch(int err)
1027 {
1028 }
1029 static void
1030 _dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg,
1031 	Dwarf_Ptr addr,
1032 	unsigned long size,
1033 	short alloc_type)
1034 {
1035 	struct simple_malloc_record_s *cur;
1036 	struct simple_malloc_entry_s *newentry;
1037 	if (!dbg->de_simple_malloc_current) {
1038 	  /* First entry to this routine. */
1039 	  dbg->de_simple_malloc_current =
1040 		malloc(sizeof(struct simple_malloc_record_s));
1041 	  if(!dbg->de_simple_malloc_current) {
1042 		return; /* no memory, give up */
1043 	  }
1044 	  memset(dbg->de_simple_malloc_current,
1045 		0,
1046 		sizeof(struct simple_malloc_record_s));
1047 	  dbg->de_simple_malloc_base = dbg->de_simple_malloc_current;
1048 	}
1049 	cur = dbg->de_simple_malloc_current;
1050 
1051 	if(cur->sr_used >= DSM_BLOCK_COUNT) {
1052 	    /* better not be > than as that means chaos */
1053 
1054 	    /* Create a new block to link at the head. */
1055 
1056 	    struct simple_malloc_record_s *newblock =
1057 	        malloc(sizeof(struct simple_malloc_record_s));
1058 	    if(!newblock) {
1059 		return; /* Can do nothing, out of memory */
1060 	    }
1061 	    memset(newblock,0, sizeof(struct simple_malloc_record_s));
1062 	    /* Link the new block at the head of the chain,
1063 	       and make it 'current'
1064 	    */
1065 	    dbg->de_simple_malloc_current = newblock;
1066 	    newblock->sr_next = cur;
1067 	    cur = newblock;
1068 	}
1069 	newentry = &cur->sr_entry[cur->sr_used];
1070 	newentry->se_addr = addr;
1071 	newentry->se_size = size;
1072 	newentry->se_type = alloc_type;
1073 	++cur->sr_used;
1074 }
1075 /*
1076    DWARF_SIMPLE_MALLOC is for testing the hypothesis that the existing
1077    complex malloc scheme in libdwarf is pointless complexity.
1078 
1079    DWARF_SIMPLE_MALLOC also makes it easy for a malloc-tracing
1080    tool to verify libdwarf malloc has no botches (though of course
1081    such does not test the complicated standard-libdwarf-alloc code).
1082 
1083    To properly answer the question, the simple-malloc allocate
1084    and delete should be something other than a simple list.
1085    Perhaps a heap, or perhaps a red-black tree.
1086 
1087 */
1088 static void
1089 _dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg,
1090 	Dwarf_Ptr space,
1091 	short alloc_type)
1092 {
1093     if(space == 0) {
1094 	_dwarf_simple_malloc_botch(6);
1095     }
1096     if(dbg->de_simple_malloc_base) {
1097         struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base;
1098         while( smp)
1099         {
1100             int i;
1101 
1102             for(i = 0; i < smp->sr_used; ++i) {
1103                 struct simple_malloc_entry_s *cur;
1104                 cur = &smp->sr_entry[i];
1105                 if(cur->se_addr == space) {
1106 		     if(cur->se_type != alloc_type ) {
1107 			 _dwarf_simple_malloc_botch(0);
1108 		     }
1109                      cur->se_addr = 0;
1110 		     return;
1111                 }
1112             }
1113             smp = smp->sr_next;
1114         }
1115     }
1116     /* Never found the space */
1117     _dwarf_simple_malloc_botch(1);
1118     return;
1119 
1120 }
1121 #endif
1122 
1123