|
1 /* |
|
2 |
|
3 Copyright (C) 2000,2001,2002,2003,2004,2005,2006 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 |
|
44 |
|
45 #include "config.h" |
|
46 #include "dwarf_incl.h" |
|
47 #ifdef HAVE_ELF_H |
|
48 #include <elf.h> |
|
49 #endif |
|
50 #include <stdio.h> |
|
51 #include "dwarf_die_deliv.h" |
|
52 |
|
53 |
|
54 /* |
|
55 For a given Dwarf_Debug dbg, this function checks |
|
56 if a CU that includes the given offset has been read |
|
57 or not. If yes, it returns the Dwarf_CU_Context |
|
58 for the CU. Otherwise it returns NULL. Being an |
|
59 internal routine, it is assumed that a valid dbg |
|
60 is passed. |
|
61 |
|
62 **This is a sequential search. May be too slow. |
|
63 |
|
64 If debug_info and debug_abbrev not loaded, this will |
|
65 wind up returning NULL. So no need to load before calling |
|
66 this. |
|
67 */ |
|
68 static Dwarf_CU_Context |
|
69 _dwarf_find_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset) |
|
70 { |
|
71 Dwarf_CU_Context cu_context; |
|
72 |
|
73 if (offset >= dbg->de_info_last_offset) |
|
74 return (NULL); |
|
75 |
|
76 if (dbg->de_cu_context != NULL && |
|
77 dbg->de_cu_context->cc_next != NULL && |
|
78 dbg->de_cu_context->cc_next->cc_debug_info_offset == offset) { |
|
79 |
|
80 return (dbg->de_cu_context->cc_next); |
|
81 } |
|
82 |
|
83 if (dbg->de_cu_context != NULL && |
|
84 dbg->de_cu_context->cc_debug_info_offset <= offset) { |
|
85 |
|
86 for (cu_context = dbg->de_cu_context; |
|
87 cu_context != NULL; cu_context = cu_context->cc_next) { |
|
88 |
|
89 if (offset >= cu_context->cc_debug_info_offset && |
|
90 offset < cu_context->cc_debug_info_offset + |
|
91 cu_context->cc_length + cu_context->cc_length_size |
|
92 + cu_context->cc_extension_size) { |
|
93 |
|
94 return (cu_context); |
|
95 } |
|
96 } |
|
97 } |
|
98 |
|
99 for (cu_context = dbg->de_cu_context_list; |
|
100 cu_context != NULL; cu_context = cu_context->cc_next) { |
|
101 |
|
102 if (offset >= cu_context->cc_debug_info_offset && |
|
103 offset < cu_context->cc_debug_info_offset + |
|
104 cu_context->cc_length + cu_context->cc_length_size |
|
105 + cu_context->cc_extension_size) { |
|
106 |
|
107 return (cu_context); |
|
108 } |
|
109 } |
|
110 |
|
111 return (NULL); |
|
112 } |
|
113 |
|
114 |
|
115 /* |
|
116 This routine checks the dwarf_offdie() list of |
|
117 CU contexts for the right CU context. |
|
118 */ |
|
119 static Dwarf_CU_Context |
|
120 _dwarf_find_offdie_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset) |
|
121 { |
|
122 Dwarf_CU_Context cu_context; |
|
123 |
|
124 for (cu_context = dbg->de_offdie_cu_context; |
|
125 cu_context != NULL; cu_context = cu_context->cc_next) |
|
126 |
|
127 if (offset >= cu_context->cc_debug_info_offset && |
|
128 offset < cu_context->cc_debug_info_offset + |
|
129 cu_context->cc_length + cu_context->cc_length_size |
|
130 + cu_context->cc_extension_size) |
|
131 |
|
132 return (cu_context); |
|
133 |
|
134 return (NULL); |
|
135 } |
|
136 |
|
137 |
|
138 /* |
|
139 This function is used to create a CU Context for |
|
140 a compilation-unit that begins at offset in |
|
141 .debug_info. The CU Context is attached to the |
|
142 list of CU Contexts for this dbg. It is assumed |
|
143 that the CU at offset has not been read before, |
|
144 and so do not call this routine before making |
|
145 sure of this with _dwarf_find_CU_Context(). |
|
146 Returns NULL on error. As always, being an |
|
147 internal routine, assumes a good dbg. |
|
148 |
|
149 This function must always set a dwarf error code |
|
150 before returning NULL. Always. |
|
151 */ |
|
152 static Dwarf_CU_Context |
|
153 _dwarf_make_CU_Context(Dwarf_Debug dbg, |
|
154 Dwarf_Off offset, Dwarf_Error * error) |
|
155 { |
|
156 Dwarf_CU_Context cu_context; |
|
157 Dwarf_Unsigned length; |
|
158 Dwarf_Signed abbrev_offset; |
|
159 Dwarf_Byte_Ptr cu_ptr; |
|
160 int local_extension_size = 0; |
|
161 int local_length_size; |
|
162 |
|
163 cu_context = |
|
164 (Dwarf_CU_Context) _dwarf_get_alloc(dbg, DW_DLA_CU_CONTEXT, 1); |
|
165 if (cu_context == NULL) { |
|
166 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); |
|
167 return (NULL); |
|
168 } |
|
169 cu_context->cc_dbg = dbg; |
|
170 |
|
171 cu_ptr = (Dwarf_Byte_Ptr) (dbg->de_debug_info + offset); |
|
172 |
|
173 /* READ_AREA_LENGTH updates cu_ptr for consumed bytes */ |
|
174 READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, |
|
175 cu_ptr, local_length_size, local_extension_size); |
|
176 cu_context->cc_length_size = local_length_size; |
|
177 cu_context->cc_extension_size = local_extension_size; |
|
178 |
|
179 |
|
180 cu_context->cc_length = (Dwarf_Word) length; |
|
181 |
|
182 READ_UNALIGNED(dbg, cu_context->cc_version_stamp, Dwarf_Half, |
|
183 cu_ptr, sizeof(Dwarf_Half)); |
|
184 cu_ptr += sizeof(Dwarf_Half); |
|
185 |
|
186 READ_UNALIGNED(dbg, abbrev_offset, Dwarf_Signed, |
|
187 cu_ptr, local_length_size); |
|
188 cu_ptr += local_length_size; |
|
189 cu_context->cc_abbrev_offset = (Dwarf_Sword) abbrev_offset; |
|
190 |
|
191 cu_context->cc_address_size = *(Dwarf_Small *) cu_ptr; |
|
192 |
|
193 if ((length < CU_VERSION_STAMP_SIZE + local_length_size + |
|
194 CU_ADDRESS_SIZE_SIZE) || |
|
195 (offset + length + local_length_size + |
|
196 local_extension_size > dbg->de_debug_info_size)) { |
|
197 |
|
198 dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); |
|
199 _dwarf_error(dbg, error, DW_DLE_CU_LENGTH_ERROR); |
|
200 return (NULL); |
|
201 } |
|
202 |
|
203 if (cu_context->cc_address_size != dbg->de_pointer_size) { |
|
204 dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); |
|
205 _dwarf_error(dbg, error, DW_DLE_CU_ADDRESS_SIZE_BAD); |
|
206 return (NULL); |
|
207 } |
|
208 |
|
209 if (cu_context->cc_version_stamp != CURRENT_VERSION_STAMP |
|
210 && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP3 |
|
211 && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP4) { |
|
212 dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); |
|
213 _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); |
|
214 return (NULL); |
|
215 } |
|
216 |
|
217 if (abbrev_offset >= dbg->de_debug_abbrev_size) { |
|
218 dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT); |
|
219 _dwarf_error(dbg, error, DW_DLE_ABBREV_OFFSET_ERROR); |
|
220 return (NULL); |
|
221 } |
|
222 |
|
223 cu_context->cc_abbrev_hash_table = |
|
224 (Dwarf_Hash_Table) _dwarf_get_alloc(dbg, DW_DLA_HASH_TABLE, 1); |
|
225 if (cu_context->cc_abbrev_hash_table == NULL) { |
|
226 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); |
|
227 return (NULL); |
|
228 } |
|
229 |
|
230 cu_context->cc_debug_info_offset = (Dwarf_Word) offset; |
|
231 dbg->de_info_last_offset = |
|
232 (Dwarf_Word) (offset + length + |
|
233 local_extension_size + local_length_size); |
|
234 |
|
235 if (dbg->de_cu_context_list == NULL) { |
|
236 dbg->de_cu_context_list = cu_context; |
|
237 dbg->de_cu_context_list_end = cu_context; |
|
238 } else { |
|
239 dbg->de_cu_context_list_end->cc_next = cu_context; |
|
240 dbg->de_cu_context_list_end = cu_context; |
|
241 } |
|
242 |
|
243 return (cu_context); |
|
244 } |
|
245 |
|
246 |
|
247 /* |
|
248 Returns offset of next compilation-unit thru next_cu_offset |
|
249 pointer. |
|
250 It basically sequentially moves from one |
|
251 cu to the next. The current cu is recorded |
|
252 internally by libdwarf. |
|
253 */ |
|
254 int |
|
255 dwarf_next_cu_header(Dwarf_Debug dbg, |
|
256 Dwarf_Unsigned * cu_header_length, |
|
257 Dwarf_Half * version_stamp, |
|
258 Dwarf_Unsigned * abbrev_offset, |
|
259 Dwarf_Half * address_size, |
|
260 Dwarf_Unsigned * next_cu_offset, |
|
261 Dwarf_Error * error) |
|
262 { |
|
263 /* Offset for current and new CU. */ |
|
264 Dwarf_Unsigned new_offset; |
|
265 |
|
266 /* CU Context for current CU. */ |
|
267 Dwarf_CU_Context cu_context; |
|
268 |
|
269 /* ***** BEGIN CODE ***** */ |
|
270 |
|
271 if (dbg == NULL) { |
|
272 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); |
|
273 return (DW_DLV_ERROR); |
|
274 } |
|
275 /* |
|
276 Get offset into .debug_info of next CU. If dbg has no context, |
|
277 this has to be the first one. */ |
|
278 if (dbg->de_cu_context == NULL) { |
|
279 new_offset = 0; |
|
280 if (!dbg->de_debug_info) { |
|
281 int res = _dwarf_load_debug_info(dbg, error); |
|
282 |
|
283 if (res != DW_DLV_OK) { |
|
284 return res; |
|
285 } |
|
286 } |
|
287 |
|
288 } else { |
|
289 new_offset = dbg->de_cu_context->cc_debug_info_offset + |
|
290 dbg->de_cu_context->cc_length + |
|
291 dbg->de_cu_context->cc_length_size + |
|
292 dbg->de_cu_context->cc_extension_size; |
|
293 } |
|
294 |
|
295 /* |
|
296 Check that there is room in .debug_info beyond the new offset |
|
297 for at least a new cu header. If not, return 0 to indicate end |
|
298 of debug_info section, and reset de_cu_debug_info_offset to |
|
299 enable looping back through the cu's. */ |
|
300 if ((new_offset + _dwarf_length_of_cu_header_simple(dbg)) >= |
|
301 dbg->de_debug_info_size) { |
|
302 dbg->de_cu_context = NULL; |
|
303 return (DW_DLV_NO_ENTRY); |
|
304 } |
|
305 |
|
306 /* Check if this CU has been read before. */ |
|
307 cu_context = _dwarf_find_CU_Context(dbg, new_offset); |
|
308 |
|
309 /* If not, make CU Context for it. */ |
|
310 if (cu_context == NULL) { |
|
311 cu_context = _dwarf_make_CU_Context(dbg, new_offset, error); |
|
312 if (cu_context == NULL) { |
|
313 /* Error if CU Context could not be made. Since |
|
314 _dwarf_make_CU_Context has already registered an error |
|
315 we do not do that here: we let the lower error pass |
|
316 thru. */ |
|
317 return (DW_DLV_ERROR); |
|
318 } |
|
319 } |
|
320 |
|
321 dbg->de_cu_context = cu_context; |
|
322 |
|
323 if (cu_header_length != NULL) |
|
324 *cu_header_length = cu_context->cc_length; |
|
325 |
|
326 if (version_stamp != NULL) |
|
327 *version_stamp = cu_context->cc_version_stamp; |
|
328 |
|
329 if (abbrev_offset != NULL) |
|
330 *abbrev_offset = cu_context->cc_abbrev_offset; |
|
331 |
|
332 if (address_size != NULL) |
|
333 *address_size = cu_context->cc_address_size; |
|
334 |
|
335 new_offset = new_offset + cu_context->cc_length + |
|
336 cu_context->cc_length_size + cu_context->cc_extension_size; |
|
337 *next_cu_offset = new_offset; |
|
338 return (DW_DLV_OK); |
|
339 } |
|
340 |
|
341 |
|
342 /* |
|
343 This function does two slightly different things |
|
344 depending on the input flag want_AT_sibling. If |
|
345 this flag is true, it checks if the input die has |
|
346 a DW_AT_sibling attribute. If it does it returns |
|
347 a pointer to the start of the sibling die in the |
|
348 .debug_info section. Otherwise it behaves the |
|
349 same as the want_AT_sibling false case. |
|
350 |
|
351 If the want_AT_sibling flag is false, it returns |
|
352 a pointer to the immediately adjacent die in the |
|
353 .debug_info section. |
|
354 |
|
355 Die_info_end points to the end of the .debug_info |
|
356 portion for the cu the die belongs to. It is used |
|
357 to check that the search for the next die does not |
|
358 cross the end of the current cu. Cu_info_start points |
|
359 to the start of the .debug_info portion for the |
|
360 current cu, and is used to add to the offset for |
|
361 DW_AT_sibling attributes. Finally, has_die_child |
|
362 is a pointer to a Dwarf_Bool that is set true if |
|
363 the present die has children, false otherwise. |
|
364 However, in case want_AT_child is true and the die |
|
365 has a DW_AT_sibling attribute *has_die_child is set |
|
366 false to indicate that the children are being skipped. |
|
367 |
|
368 die_info_end points to the last byte+1 of the cu. |
|
369 |
|
370 */ |
|
371 static Dwarf_Byte_Ptr |
|
372 _dwarf_next_die_info_ptr(Dwarf_Byte_Ptr die_info_ptr, |
|
373 Dwarf_CU_Context cu_context, |
|
374 Dwarf_Byte_Ptr die_info_end, |
|
375 Dwarf_Byte_Ptr cu_info_start, |
|
376 Dwarf_Bool want_AT_sibling, |
|
377 Dwarf_Bool * has_die_child) |
|
378 { |
|
379 Dwarf_Byte_Ptr info_ptr; |
|
380 Dwarf_Byte_Ptr abbrev_ptr; |
|
381 Dwarf_Word abbrev_code; |
|
382 Dwarf_Abbrev_List abbrev_list; |
|
383 Dwarf_Half attr; |
|
384 Dwarf_Half attr_form; |
|
385 Dwarf_Unsigned offset; |
|
386 Dwarf_Word leb128_length; |
|
387 Dwarf_Unsigned utmp; |
|
388 Dwarf_Debug dbg; |
|
389 |
|
390 info_ptr = die_info_ptr; |
|
391 DECODE_LEB128_UWORD(info_ptr, utmp); |
|
392 abbrev_code = (Dwarf_Word) utmp; |
|
393 if (abbrev_code == 0) { |
|
394 return NULL; |
|
395 } |
|
396 |
|
397 abbrev_list = _dwarf_get_abbrev_for_code(cu_context, abbrev_code); |
|
398 if (abbrev_list == NULL) { |
|
399 return (NULL); |
|
400 } |
|
401 dbg = cu_context->cc_dbg; |
|
402 |
|
403 *has_die_child = abbrev_list->ab_has_child; |
|
404 |
|
405 abbrev_ptr = abbrev_list->ab_abbrev_ptr; |
|
406 do { |
|
407 Dwarf_Unsigned utmp2; |
|
408 |
|
409 DECODE_LEB128_UWORD(abbrev_ptr, utmp2); |
|
410 attr = (Dwarf_Half) utmp2; |
|
411 DECODE_LEB128_UWORD(abbrev_ptr, utmp2); |
|
412 attr_form = (Dwarf_Half) utmp2; |
|
413 if (attr_form == DW_FORM_indirect) { |
|
414 Dwarf_Unsigned utmp6; |
|
415 |
|
416 /* READ_UNALIGNED does update info_ptr */ |
|
417 DECODE_LEB128_UWORD(info_ptr, utmp6); |
|
418 attr_form = (Dwarf_Half) utmp6; |
|
419 |
|
420 } |
|
421 |
|
422 if (want_AT_sibling && attr == DW_AT_sibling) { |
|
423 switch (attr_form) { |
|
424 case DW_FORM_ref1: |
|
425 offset = *(Dwarf_Small *) info_ptr; |
|
426 break; |
|
427 case DW_FORM_ref2: |
|
428 READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, |
|
429 info_ptr, sizeof(Dwarf_Half)); |
|
430 break; |
|
431 case DW_FORM_ref4: |
|
432 READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, |
|
433 info_ptr, sizeof(Dwarf_ufixed)); |
|
434 break; |
|
435 case DW_FORM_ref8: |
|
436 READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, |
|
437 info_ptr, sizeof(Dwarf_Unsigned)); |
|
438 break; |
|
439 case DW_FORM_ref_udata: |
|
440 offset = |
|
441 _dwarf_decode_u_leb128(info_ptr, &leb128_length); |
|
442 break; |
|
443 default: |
|
444 return (NULL); |
|
445 } |
|
446 |
|
447 /* Reset *has_die_child to indicate children skipped. */ |
|
448 *has_die_child = false; |
|
449 |
|
450 /* A value beyond die_info_end indicates an error. Exactly |
|
451 at die_info_end means 1-past-cu-end and simply means we |
|
452 are at the end, do not return NULL. Higher level code |
|
453 will detect that we are at the end. */ |
|
454 if (cu_info_start + offset > die_info_end) { |
|
455 /* Error case, bad DWARF. */ |
|
456 return (NULL); |
|
457 } |
|
458 /* At or before end-of-cu */ |
|
459 return (cu_info_start + offset); |
|
460 } |
|
461 |
|
462 if (attr_form != 0) { |
|
463 info_ptr += _dwarf_get_size_of_val(cu_context->cc_dbg, |
|
464 attr_form, info_ptr, |
|
465 cu_context-> |
|
466 cc_length_size); |
|
467 /* It is ok for info_ptr == die_info_end, as we will test |
|
468 later before using a too-large info_ptr */ |
|
469 if (info_ptr > die_info_end) { |
|
470 /* More than one-past-end indicates a bug somewhere, |
|
471 likely bad dwarf generation. */ |
|
472 return (NULL); |
|
473 } |
|
474 } |
|
475 } while (attr != 0 || attr_form != 0); |
|
476 |
|
477 return (info_ptr); |
|
478 } |
|
479 |
|
480 |
|
481 /* |
|
482 Given a Dwarf_Debug dbg, and a Dwarf_Die die, it returns |
|
483 a Dwarf_Die for the sibling of die. In case die is NULL, |
|
484 it returns (thru ptr) a Dwarf_Die for the first die in the current |
|
485 cu in dbg. Returns DW_DLV_ERROR on error. |
|
486 |
|
487 It is assumed that every sibling chain including those with |
|
488 only one element is terminated with a NULL die, except a |
|
489 chain with only a NULL die. |
|
490 |
|
491 The algorithm moves from one die to the adjacent one. It |
|
492 returns when the depth of children it sees equals the number |
|
493 of sibling chain terminations. A single count, child_depth |
|
494 is used to track the depth of children and sibling terminations |
|
495 encountered. Child_depth is incremented when a die has the |
|
496 Has-Child flag set unless the child happens to be a NULL die. |
|
497 Child_depth is decremented when a die has Has-Child false, |
|
498 and the adjacent die is NULL. Algorithm returns when |
|
499 child_depth is 0. |
|
500 |
|
501 **NOTE: Do not modify input die, since it is used at the end. |
|
502 */ |
|
503 int |
|
504 dwarf_siblingof(Dwarf_Debug dbg, |
|
505 Dwarf_Die die, |
|
506 Dwarf_Die * caller_ret_die, Dwarf_Error * error) |
|
507 { |
|
508 Dwarf_Die ret_die; |
|
509 Dwarf_Byte_Ptr die_info_ptr; |
|
510 Dwarf_Byte_Ptr cu_info_start = 0; |
|
511 |
|
512 /* die_info_end points 1-past end of die (once set) */ |
|
513 Dwarf_Byte_Ptr die_info_end = 0; |
|
514 Dwarf_Half abbrev_code; |
|
515 Dwarf_Unsigned utmp; |
|
516 |
|
517 |
|
518 if (dbg == NULL) { |
|
519 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); |
|
520 return (DW_DLV_ERROR); |
|
521 } |
|
522 |
|
523 if (die == NULL) { |
|
524 /* Find root die of cu */ |
|
525 /* die_info_end is untouched here, need not be set in this |
|
526 branch. */ |
|
527 Dwarf_Off off2; |
|
528 |
|
529 /* If we've not loaded debug_info, de_cu_context will be NULL, |
|
530 so no need to laod */ |
|
531 |
|
532 if (dbg->de_cu_context == NULL) { |
|
533 _dwarf_error(dbg, error, DW_DLE_DBG_NO_CU_CONTEXT); |
|
534 return (DW_DLV_ERROR); |
|
535 } |
|
536 |
|
537 off2 = dbg->de_cu_context->cc_debug_info_offset; |
|
538 die_info_ptr = dbg->de_debug_info + |
|
539 off2 + _dwarf_length_of_cu_header(dbg, off2); |
|
540 } else { |
|
541 /* Find sibling die. */ |
|
542 Dwarf_Bool has_child = false; |
|
543 Dwarf_Sword child_depth; |
|
544 |
|
545 /* We cannot have a legal die unless debug_info was loaded, so |
|
546 no need to load debug_info here. */ |
|
547 CHECK_DIE(die, DW_DLV_ERROR); |
|
548 |
|
549 die_info_ptr = die->di_debug_info_ptr; |
|
550 if (*die_info_ptr == 0) { |
|
551 return (DW_DLV_NO_ENTRY); |
|
552 } |
|
553 cu_info_start = dbg->de_debug_info + |
|
554 die->di_cu_context->cc_debug_info_offset; |
|
555 die_info_end = cu_info_start + die->di_cu_context->cc_length + |
|
556 die->di_cu_context->cc_length_size + |
|
557 die->di_cu_context->cc_extension_size; |
|
558 |
|
559 if ((*die_info_ptr) == 0) { |
|
560 return (DW_DLV_NO_ENTRY); |
|
561 } |
|
562 child_depth = 0; |
|
563 do { |
|
564 die_info_ptr = _dwarf_next_die_info_ptr(die_info_ptr, |
|
565 die->di_cu_context, |
|
566 die_info_end, |
|
567 cu_info_start, true, |
|
568 &has_child); |
|
569 if (die_info_ptr == NULL) { |
|
570 _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL); |
|
571 return (DW_DLV_ERROR); |
|
572 } |
|
573 |
|
574 /* die_info_end is one past end. Do not read it! |
|
575 A test for ``!= die_info_end'' would work as well, |
|
576 but perhaps < reads more like the meaning. */ |
|
577 if(die_info_ptr < die_info_end) { |
|
578 if ((*die_info_ptr) == 0 && has_child) { |
|
579 die_info_ptr++; |
|
580 has_child = false; |
|
581 } |
|
582 } |
|
583 |
|
584 /* die_info_ptr can be one-past-end. */ |
|
585 if ((die_info_ptr == die_info_end) || |
|
586 ((*die_info_ptr) == 0)) { |
|
587 for (; child_depth > 0 && *die_info_ptr == 0; |
|
588 child_depth--, die_info_ptr++); |
|
589 } else { |
|
590 child_depth = has_child ? child_depth + 1 : child_depth; |
|
591 } |
|
592 |
|
593 } while (child_depth != 0); |
|
594 } |
|
595 |
|
596 /* die_info_ptr > die_info_end is really a bug (possibly in dwarf |
|
597 generation)(but we are past end, no more DIEs here), whereas |
|
598 die_info_ptr == die_info_end means 'one past end, no more DIEs |
|
599 here'. */ |
|
600 if (die != NULL && die_info_ptr >= die_info_end) { |
|
601 return (DW_DLV_NO_ENTRY); |
|
602 } |
|
603 |
|
604 if ((*die_info_ptr) == 0) { |
|
605 return (DW_DLV_NO_ENTRY); |
|
606 } |
|
607 |
|
608 ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); |
|
609 if (ret_die == NULL) { |
|
610 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); |
|
611 return (DW_DLV_ERROR); |
|
612 } |
|
613 |
|
614 ret_die->di_debug_info_ptr = die_info_ptr; |
|
615 ret_die->di_cu_context = |
|
616 die == NULL ? dbg->de_cu_context : die->di_cu_context; |
|
617 |
|
618 DECODE_LEB128_UWORD(die_info_ptr, utmp); |
|
619 abbrev_code = (Dwarf_Half) utmp; |
|
620 if (abbrev_code == 0) { |
|
621 /* Zero means a null DIE */ |
|
622 dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); |
|
623 return (DW_DLV_NO_ENTRY); |
|
624 } |
|
625 ret_die->di_abbrev_list = |
|
626 _dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code); |
|
627 if (ret_die->di_abbrev_list == NULL || (die == NULL && |
|
628 ret_die->di_abbrev_list-> |
|
629 ab_tag != |
|
630 DW_TAG_compile_unit)) { |
|
631 dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); |
|
632 _dwarf_error(dbg, error, DW_DLE_FIRST_DIE_NOT_CU); |
|
633 return (DW_DLV_ERROR); |
|
634 } |
|
635 |
|
636 *caller_ret_die = ret_die; |
|
637 return (DW_DLV_OK); |
|
638 } |
|
639 |
|
640 |
|
641 int |
|
642 dwarf_child(Dwarf_Die die, |
|
643 Dwarf_Die * caller_ret_die, Dwarf_Error * error) |
|
644 { |
|
645 Dwarf_Byte_Ptr die_info_ptr = 0; |
|
646 |
|
647 /* die_info_end points one-past-end of die area. */ |
|
648 Dwarf_Byte_Ptr die_info_end = 0; |
|
649 Dwarf_Die ret_die = 0; |
|
650 Dwarf_Bool has_die_child = 0; |
|
651 Dwarf_Debug dbg; |
|
652 Dwarf_Half abbrev_code = 0; |
|
653 Dwarf_Unsigned utmp = 0; |
|
654 |
|
655 |
|
656 CHECK_DIE(die, DW_DLV_ERROR); |
|
657 dbg = die->di_cu_context->cc_dbg; |
|
658 die_info_ptr = die->di_debug_info_ptr; |
|
659 |
|
660 /* NULL die has no child. */ |
|
661 if ((*die_info_ptr) == 0) |
|
662 return (DW_DLV_NO_ENTRY); |
|
663 |
|
664 die_info_end = dbg->de_debug_info + |
|
665 die->di_cu_context->cc_debug_info_offset + |
|
666 die->di_cu_context->cc_length + |
|
667 die->di_cu_context->cc_length_size + |
|
668 die->di_cu_context->cc_extension_size; |
|
669 |
|
670 die_info_ptr = |
|
671 _dwarf_next_die_info_ptr(die_info_ptr, die->di_cu_context, |
|
672 die_info_end, NULL, false, |
|
673 &has_die_child); |
|
674 if (die_info_ptr == NULL) { |
|
675 _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL); |
|
676 return (DW_DLV_ERROR); |
|
677 } |
|
678 |
|
679 if (!has_die_child) |
|
680 return (DW_DLV_NO_ENTRY); |
|
681 |
|
682 ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); |
|
683 if (ret_die == NULL) { |
|
684 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); |
|
685 return (DW_DLV_ERROR); |
|
686 } |
|
687 ret_die->di_debug_info_ptr = die_info_ptr; |
|
688 ret_die->di_cu_context = die->di_cu_context; |
|
689 |
|
690 DECODE_LEB128_UWORD(die_info_ptr, utmp); |
|
691 abbrev_code = (Dwarf_Half) utmp; |
|
692 if (abbrev_code == 0) { |
|
693 /* We have arrived at a null DIE, at the end of a CU or the end |
|
694 of a list of siblings. */ |
|
695 *caller_ret_die = 0; |
|
696 dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); |
|
697 return DW_DLV_NO_ENTRY; |
|
698 } |
|
699 ret_die->di_abbrev_list = |
|
700 _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code); |
|
701 if (ret_die->di_abbrev_list == NULL) { |
|
702 dwarf_dealloc(dbg, ret_die, DW_DLA_DIE); |
|
703 _dwarf_error(dbg, error, DW_DLE_DIE_BAD); |
|
704 return (DW_DLV_ERROR); |
|
705 } |
|
706 |
|
707 *caller_ret_die = ret_die; |
|
708 return (DW_DLV_OK); |
|
709 } |
|
710 |
|
711 /* |
|
712 Given a die offset, this returns |
|
713 a pointer to a DIE thru *new_die. |
|
714 It is up to the caller to do a |
|
715 dwarf_dealloc(dbg,*new_die,DW_DLE_DIE); |
|
716 */ |
|
717 int |
|
718 dwarf_offdie(Dwarf_Debug dbg, |
|
719 Dwarf_Off offset, Dwarf_Die * new_die, Dwarf_Error * error) |
|
720 { |
|
721 Dwarf_CU_Context cu_context; |
|
722 Dwarf_Off new_cu_offset = 0; |
|
723 Dwarf_Die die = 0; |
|
724 Dwarf_Byte_Ptr info_ptr = 0; |
|
725 Dwarf_Half abbrev_code = 0; |
|
726 Dwarf_Unsigned utmp = 0; |
|
727 |
|
728 if (dbg == NULL) { |
|
729 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); |
|
730 return (DW_DLV_ERROR); |
|
731 } |
|
732 |
|
733 cu_context = _dwarf_find_CU_Context(dbg, offset); |
|
734 if (cu_context == NULL) |
|
735 cu_context = _dwarf_find_offdie_CU_Context(dbg, offset); |
|
736 |
|
737 if (cu_context == NULL) { |
|
738 int res = _dwarf_load_debug_info(dbg, error); |
|
739 |
|
740 if (res != DW_DLV_OK) { |
|
741 return res; |
|
742 } |
|
743 |
|
744 if (dbg->de_offdie_cu_context_end != NULL) { |
|
745 Dwarf_CU_Context lcu_context = |
|
746 dbg->de_offdie_cu_context_end; |
|
747 new_cu_offset = |
|
748 lcu_context->cc_debug_info_offset + |
|
749 lcu_context->cc_length + |
|
750 lcu_context->cc_length_size + |
|
751 lcu_context->cc_extension_size; |
|
752 } |
|
753 |
|
754 |
|
755 do { |
|
756 if ((new_cu_offset + |
|
757 _dwarf_length_of_cu_header_simple(dbg)) >= |
|
758 dbg->de_debug_info_size) { |
|
759 _dwarf_error(dbg, error, DW_DLE_OFFSET_BAD); |
|
760 return (DW_DLV_ERROR); |
|
761 } |
|
762 |
|
763 cu_context = |
|
764 _dwarf_make_CU_Context(dbg, new_cu_offset, error); |
|
765 if (cu_context == NULL) { |
|
766 /* Error if CU Context could not be made. Since |
|
767 _dwarf_make_CU_Context has already registered an |
|
768 error we do not do that here: we let the lower error |
|
769 pass thru. */ |
|
770 |
|
771 return (DW_DLV_ERROR); |
|
772 } |
|
773 |
|
774 if (dbg->de_offdie_cu_context == NULL) { |
|
775 dbg->de_offdie_cu_context = cu_context; |
|
776 dbg->de_offdie_cu_context_end = cu_context; |
|
777 } else { |
|
778 dbg->de_offdie_cu_context_end->cc_next = cu_context; |
|
779 dbg->de_offdie_cu_context_end = cu_context; |
|
780 } |
|
781 |
|
782 new_cu_offset = new_cu_offset + cu_context->cc_length + |
|
783 cu_context->cc_length_size; |
|
784 |
|
785 } while (offset >= new_cu_offset); |
|
786 } |
|
787 |
|
788 die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); |
|
789 if (die == NULL) { |
|
790 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); |
|
791 return (DW_DLV_ERROR); |
|
792 } |
|
793 die->di_cu_context = cu_context; |
|
794 |
|
795 info_ptr = dbg->de_debug_info + offset; |
|
796 die->di_debug_info_ptr = info_ptr; |
|
797 DECODE_LEB128_UWORD(info_ptr, utmp); |
|
798 abbrev_code = (Dwarf_Half) utmp; |
|
799 if (abbrev_code == 0) { |
|
800 /* we are at a null DIE (or there is a bug). */ |
|
801 *new_die = 0; |
|
802 dwarf_dealloc(dbg, die, DW_DLA_DIE); |
|
803 return DW_DLV_NO_ENTRY; |
|
804 } |
|
805 |
|
806 die->di_abbrev_list = |
|
807 _dwarf_get_abbrev_for_code(cu_context, abbrev_code); |
|
808 if (die->di_abbrev_list == NULL) { |
|
809 dwarf_dealloc(dbg, die, DW_DLA_DIE); |
|
810 _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL); |
|
811 return (DW_DLV_ERROR); |
|
812 } |
|
813 |
|
814 *new_die = die; |
|
815 return (DW_DLV_OK); |
|
816 } |