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