|
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 |