1 /*
2
3 Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
4 Portions Copyright (C) 2007-2010 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
_dwarf_find_CU_Context(Dwarf_Debug dbg,Dwarf_Off offset)69 _dwarf_find_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset)
70 {
71 Dwarf_CU_Context cu_context = 0;
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
_dwarf_find_offdie_CU_Context(Dwarf_Debug dbg,Dwarf_Off offset)120 _dwarf_find_offdie_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset)
121 {
122 Dwarf_CU_Context cu_context = 0;
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
_dwarf_make_CU_Context(Dwarf_Debug dbg,Dwarf_Off offset,Dwarf_Error * error)153 _dwarf_make_CU_Context(Dwarf_Debug dbg,
154 Dwarf_Off offset, Dwarf_Error * error)
155 {
156 Dwarf_CU_Context cu_context = 0;
157 Dwarf_Unsigned length = 0;
158 Dwarf_Signed abbrev_offset = 0;
159 Dwarf_Byte_Ptr cu_ptr = 0;
160 int local_extension_size = 0;
161 int local_length_size = 0;
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.dss_data + 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.dss_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_version_stamp != CURRENT_VERSION_STAMP
204 && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP3
205 && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP4) {
206 dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT);
207 _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
208 return (NULL);
209 }
210
211 if (abbrev_offset >= dbg->de_debug_abbrev.dss_size) {
212 dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT);
213 _dwarf_error(dbg, error, DW_DLE_ABBREV_OFFSET_ERROR);
214 return (NULL);
215 }
216
217 cu_context->cc_abbrev_hash_table =
218 (Dwarf_Hash_Table) _dwarf_get_alloc(dbg, DW_DLA_HASH_TABLE, 1);
219 if (cu_context->cc_abbrev_hash_table == NULL) {
220 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
221 return (NULL);
222 }
223
224 cu_context->cc_debug_info_offset = (Dwarf_Word) offset;
225 dbg->de_info_last_offset =
226 (Dwarf_Word) (offset + length +
227 local_extension_size + local_length_size);
228
229 if (dbg->de_cu_context_list == NULL) {
230 dbg->de_cu_context_list = cu_context;
231 dbg->de_cu_context_list_end = cu_context;
232 } else {
233 dbg->de_cu_context_list_end->cc_next = cu_context;
234 dbg->de_cu_context_list_end = cu_context;
235 }
236
237 return (cu_context);
238 }
239
240
241 /*
242 Returns offset of next compilation-unit thru next_cu_offset
243 pointer.
244 It basically sequentially moves from one
245 cu to the next. The current cu is recorded
246 internally by libdwarf.
247
248 The _b form is new for DWARF4 adding new returned fields.
249 */
250 int
dwarf_next_cu_header(Dwarf_Debug dbg,Dwarf_Unsigned * cu_header_length,Dwarf_Half * version_stamp,Dwarf_Unsigned * abbrev_offset,Dwarf_Half * address_size,Dwarf_Unsigned * next_cu_offset,Dwarf_Error * error)251 dwarf_next_cu_header(Dwarf_Debug dbg,
252 Dwarf_Unsigned * cu_header_length,
253 Dwarf_Half * version_stamp,
254 Dwarf_Unsigned * abbrev_offset,
255 Dwarf_Half * address_size,
256 Dwarf_Unsigned * next_cu_offset,
257 Dwarf_Error * error)
258 {
259 return dwarf_next_cu_header_b(dbg,
260 cu_header_length,
261 version_stamp,
262 abbrev_offset,
263 address_size,
264 0,0,
265 next_cu_offset,
266 error);
267 }
268 int
dwarf_next_cu_header_b(Dwarf_Debug dbg,Dwarf_Unsigned * cu_header_length,Dwarf_Half * version_stamp,Dwarf_Unsigned * abbrev_offset,Dwarf_Half * address_size,Dwarf_Half * offset_size,Dwarf_Half * extension_size,Dwarf_Unsigned * next_cu_offset,Dwarf_Error * error)269 dwarf_next_cu_header_b(Dwarf_Debug dbg,
270 Dwarf_Unsigned * cu_header_length,
271 Dwarf_Half * version_stamp,
272 Dwarf_Unsigned * abbrev_offset,
273 Dwarf_Half * address_size,
274 Dwarf_Half * offset_size,
275 Dwarf_Half * extension_size,
276 Dwarf_Unsigned * next_cu_offset,
277 Dwarf_Error * error)
278 {
279 /* Offset for current and new CU. */
280 Dwarf_Unsigned new_offset = 0;
281
282 /* CU Context for current CU. */
283 Dwarf_CU_Context cu_context = 0;
284
285 /* ***** BEGIN CODE ***** */
286
287 if (dbg == NULL) {
288 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
289 return (DW_DLV_ERROR);
290 }
291 /*
292 Get offset into .debug_info of next CU. If dbg has no context,
293 this has to be the first one. */
294 if (dbg->de_cu_context == NULL) {
295 new_offset = 0;
296 if (!dbg->de_debug_info.dss_data) {
297 int res = _dwarf_load_debug_info(dbg, error);
298
299 if (res != DW_DLV_OK) {
300 return res;
301 }
302 }
303
304 } else {
305 new_offset = dbg->de_cu_context->cc_debug_info_offset +
306 dbg->de_cu_context->cc_length +
307 dbg->de_cu_context->cc_length_size +
308 dbg->de_cu_context->cc_extension_size;
309 }
310
311 /*
312 Check that there is room in .debug_info beyond the new offset
313 for at least a new cu header. If not, return 0 to indicate end
314 of debug_info section, and reset de_cu_debug_info_offset to
315 enable looping back through the cu's. */
316 if ((new_offset + _dwarf_length_of_cu_header_simple(dbg)) >=
317 dbg->de_debug_info.dss_size) {
318 dbg->de_cu_context = NULL;
319 return (DW_DLV_NO_ENTRY);
320 }
321
322 /* Check if this CU has been read before. */
323 cu_context = _dwarf_find_CU_Context(dbg, new_offset);
324
325 /* If not, make CU Context for it. */
326 if (cu_context == NULL) {
327 cu_context = _dwarf_make_CU_Context(dbg, new_offset, error);
328 if (cu_context == NULL) {
329 /* Error if CU Context could not be made. Since
330 _dwarf_make_CU_Context has already registered an error
331 we do not do that here: we let the lower error pass
332 thru. */
333 return (DW_DLV_ERROR);
334 }
335 }
336
337 dbg->de_cu_context = cu_context;
338
339 if (cu_header_length != NULL)
340 *cu_header_length = cu_context->cc_length;
341
342 if (version_stamp != NULL)
343 *version_stamp = cu_context->cc_version_stamp;
344
345 if (abbrev_offset != NULL)
346 *abbrev_offset = cu_context->cc_abbrev_offset;
347
348 if (address_size != NULL)
349 *address_size = cu_context->cc_address_size;
350 if (offset_size != NULL)
351 *offset_size = cu_context->cc_length_size;
352 if (extension_size != NULL)
353 *extension_size = cu_context->cc_extension_size;
354
355 new_offset = new_offset + cu_context->cc_length +
356 cu_context->cc_length_size + cu_context->cc_extension_size;
357 *next_cu_offset = new_offset;
358 return (DW_DLV_OK);
359 }
360
361
362 /*
363 This function does two slightly different things
364 depending on the input flag want_AT_sibling. If
365 this flag is true, it checks if the input die has
366 a DW_AT_sibling attribute. If it does it returns
367 a pointer to the start of the sibling die in the
368 .debug_info section. Otherwise it behaves the
369 same as the want_AT_sibling false case.
370
371 If the want_AT_sibling flag is false, it returns
372 a pointer to the immediately adjacent die in the
373 .debug_info section.
374
375 Die_info_end points to the end of the .debug_info
376 portion for the cu the die belongs to. It is used
377 to check that the search for the next die does not
378 cross the end of the current cu. Cu_info_start points
379 to the start of the .debug_info portion for the
380 current cu, and is used to add to the offset for
381 DW_AT_sibling attributes. Finally, has_die_child
382 is a pointer to a Dwarf_Bool that is set true if
383 the present die has children, false otherwise.
384 However, in case want_AT_child is true and the die
385 has a DW_AT_sibling attribute *has_die_child is set
386 false to indicate that the children are being skipped.
387
388 die_info_end points to the last byte+1 of the cu.
389
390 */
391 static Dwarf_Byte_Ptr
_dwarf_next_die_info_ptr(Dwarf_Byte_Ptr die_info_ptr,Dwarf_CU_Context cu_context,Dwarf_Byte_Ptr die_info_end,Dwarf_Byte_Ptr cu_info_start,Dwarf_Bool want_AT_sibling,Dwarf_Bool * has_die_child)392 _dwarf_next_die_info_ptr(Dwarf_Byte_Ptr die_info_ptr,
393 Dwarf_CU_Context cu_context,
394 Dwarf_Byte_Ptr die_info_end,
395 Dwarf_Byte_Ptr cu_info_start,
396 Dwarf_Bool want_AT_sibling,
397 Dwarf_Bool * has_die_child)
398 {
399 Dwarf_Byte_Ptr info_ptr = 0;
400 Dwarf_Byte_Ptr abbrev_ptr = 0;
401 Dwarf_Word abbrev_code = 0;
402 Dwarf_Abbrev_List abbrev_list;
403 Dwarf_Half attr = 0;
404 Dwarf_Half attr_form = 0;
405 Dwarf_Unsigned offset = 0;
406 Dwarf_Word leb128_length = 0;
407 Dwarf_Unsigned utmp = 0;
408 Dwarf_Debug dbg = 0;
409
410 info_ptr = die_info_ptr;
411 DECODE_LEB128_UWORD(info_ptr, utmp);
412 abbrev_code = (Dwarf_Word) utmp;
413 if (abbrev_code == 0) {
414 return NULL;
415 }
416
417
418 abbrev_list = _dwarf_get_abbrev_for_code(cu_context, abbrev_code);
419 if (abbrev_list == NULL) {
420 return (NULL);
421 }
422 dbg = cu_context->cc_dbg;
423
424 *has_die_child = abbrev_list->ab_has_child;
425
426 abbrev_ptr = abbrev_list->ab_abbrev_ptr;
427 do {
428 Dwarf_Unsigned utmp2;
429
430 DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
431 attr = (Dwarf_Half) utmp2;
432 DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
433 attr_form = (Dwarf_Half) utmp2;
434 if (attr_form == DW_FORM_indirect) {
435 Dwarf_Unsigned utmp6;
436
437 /* DECODE_LEB128_UWORD updates info_ptr */
438 DECODE_LEB128_UWORD(info_ptr, utmp6);
439 attr_form = (Dwarf_Half) utmp6;
440
441 }
442
443 if (want_AT_sibling && attr == DW_AT_sibling) {
444 switch (attr_form) {
445 case DW_FORM_ref1:
446 offset = *(Dwarf_Small *) info_ptr;
447 break;
448 case DW_FORM_ref2:
449 /* READ_UNALIGNED does not update info_ptr */
450 READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
451 info_ptr, sizeof(Dwarf_Half));
452 break;
453 case DW_FORM_ref4:
454 READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
455 info_ptr, sizeof(Dwarf_ufixed));
456 break;
457 case DW_FORM_ref8:
458 READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
459 info_ptr, sizeof(Dwarf_Unsigned));
460 break;
461 case DW_FORM_ref_udata:
462 offset =
463 _dwarf_decode_u_leb128(info_ptr, &leb128_length);
464 break;
465 case DW_FORM_ref_addr:
466 /* Very unusual. The FORM is intended to refer to
467 a different CU, but a different CU cannot
468 be a sibling, can it?
469 We could ignore this and treat as if no DW_AT_sibling
470 present. Or derive the offset from it and if
471 it is in the same CU use it directly.
472 The offset here is *supposed* to be a global offset,
473 so adding cu_info_start is wrong to any offset
474 we find here unless cu_info_start
475 is zero! Lets pretend there is no DW_AT_sibling
476 attribute. */
477 goto no_sibling_attr;
478 default:
479 return (NULL);
480 }
481
482 /* Reset *has_die_child to indicate children skipped. */
483 *has_die_child = false;
484
485 /* A value beyond die_info_end indicates an error. Exactly
486 at die_info_end means 1-past-cu-end and simply means we
487 are at the end, do not return NULL. Higher level code
488 will detect that we are at the end. */
489 if (cu_info_start + offset > die_info_end) {
490 /* Error case, bad DWARF. */
491 return (NULL);
492 }
493 /* At or before end-of-cu */
494 return (cu_info_start + offset);
495 }
496
497 no_sibling_attr:
498 if (attr_form != 0) {
499 info_ptr += _dwarf_get_size_of_val(cu_context->cc_dbg,
500 attr_form,
501 cu_context->cc_address_size,
502 info_ptr,
503 cu_context->cc_length_size);
504 /* It is ok for info_ptr == die_info_end, as we will test
505 later before using a too-large info_ptr */
506 if (info_ptr > die_info_end) {
507 /* More than one-past-end indicates a bug somewhere,
508 likely bad dwarf generation. */
509 return (NULL);
510 }
511 }
512 } while (attr != 0 || attr_form != 0);
513
514 return (info_ptr);
515 }
516
517
518 /*
519 Given a Dwarf_Debug dbg, and a Dwarf_Die die, it returns
520 a Dwarf_Die for the sibling of die. In case die is NULL,
521 it returns (thru ptr) a Dwarf_Die for the first die in the current
522 cu in dbg. Returns DW_DLV_ERROR on error.
523
524 It is assumed that every sibling chain including those with
525 only one element is terminated with a NULL die, except a
526 chain with only a NULL die.
527
528 The algorithm moves from one die to the adjacent one. It
529 returns when the depth of children it sees equals the number
530 of sibling chain terminations. A single count, child_depth
531 is used to track the depth of children and sibling terminations
532 encountered. Child_depth is incremented when a die has the
533 Has-Child flag set unless the child happens to be a NULL die.
534 Child_depth is decremented when a die has Has-Child false,
535 and the adjacent die is NULL. Algorithm returns when
536 child_depth is 0.
537
538 **NOTE: Do not modify input die, since it is used at the end.
539 */
540 int
dwarf_siblingof(Dwarf_Debug dbg,Dwarf_Die die,Dwarf_Die * caller_ret_die,Dwarf_Error * error)541 dwarf_siblingof(Dwarf_Debug dbg,
542 Dwarf_Die die,
543 Dwarf_Die * caller_ret_die, Dwarf_Error * error)
544 {
545 Dwarf_Die ret_die = 0;
546 Dwarf_Byte_Ptr die_info_ptr = 0;
547 Dwarf_Byte_Ptr cu_info_start = 0;
548
549 /* die_info_end points 1-past end of die (once set) */
550 Dwarf_Byte_Ptr die_info_end = 0;
551 Dwarf_Word abbrev_code = 0;
552 Dwarf_Unsigned utmp = 0;
553
554
555 if (dbg == NULL) {
556 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
557 return (DW_DLV_ERROR);
558 }
559
560 if (die == NULL) {
561 /* Find root die of cu */
562 /* die_info_end is untouched here, need not be set in this
563 branch. */
564 Dwarf_Off off2;
565
566 /* If we've not loaded debug_info, de_cu_context will be NULL,
567 so no need to laod */
568
569 if (dbg->de_cu_context == NULL) {
570 _dwarf_error(dbg, error, DW_DLE_DBG_NO_CU_CONTEXT);
571 return (DW_DLV_ERROR);
572 }
573
574 off2 = dbg->de_cu_context->cc_debug_info_offset;
575 die_info_ptr = dbg->de_debug_info.dss_data +
576 off2 + _dwarf_length_of_cu_header(dbg, off2);
577 } else {
578 /* Find sibling die. */
579 Dwarf_Bool has_child = false;
580 Dwarf_Sword child_depth = 0;
581
582 /* We cannot have a legal die unless debug_info was loaded, so
583 no need to load debug_info here. */
584 CHECK_DIE(die, DW_DLV_ERROR);
585
586 die_info_ptr = die->di_debug_info_ptr;
587 if (*die_info_ptr == 0) {
588 return (DW_DLV_NO_ENTRY);
589 }
590 cu_info_start = dbg->de_debug_info.dss_data +
591 die->di_cu_context->cc_debug_info_offset;
592 die_info_end = cu_info_start + die->di_cu_context->cc_length +
593 die->di_cu_context->cc_length_size +
594 die->di_cu_context->cc_extension_size;
595
596 if ((*die_info_ptr) == 0) {
597 return (DW_DLV_NO_ENTRY);
598 }
599 child_depth = 0;
600 do {
601 die_info_ptr = _dwarf_next_die_info_ptr(die_info_ptr,
602 die->di_cu_context,
603 die_info_end,
604 cu_info_start, true,
605 &has_child);
606 if (die_info_ptr == NULL) {
607 _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
608 return (DW_DLV_ERROR);
609 }
610
611 /* die_info_end is one past end. Do not read it!
612 A test for ``!= die_info_end'' would work as well,
613 but perhaps < reads more like the meaning. */
614 if(die_info_ptr < die_info_end) {
615 if ((*die_info_ptr) == 0 && has_child) {
616 die_info_ptr++;
617 has_child = false;
618 }
619 }
620
621 /* die_info_ptr can be one-past-end. */
622 if ((die_info_ptr == die_info_end) ||
623 ((*die_info_ptr) == 0)) {
624 for (; child_depth > 0 && *die_info_ptr == 0;
625 child_depth--, die_info_ptr++);
626 } else {
627 child_depth = has_child ? child_depth + 1 : child_depth;
628 }
629
630 } while (child_depth != 0);
631 }
632
633 /* die_info_ptr > die_info_end is really a bug (possibly in dwarf
634 generation)(but we are past end, no more DIEs here), whereas
635 die_info_ptr == die_info_end means 'one past end, no more DIEs
636 here'. */
637 if (die != NULL && die_info_ptr >= die_info_end) {
638 return (DW_DLV_NO_ENTRY);
639 }
640
641 if ((*die_info_ptr) == 0) {
642 return (DW_DLV_NO_ENTRY);
643 }
644
645 ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
646 if (ret_die == NULL) {
647 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
648 return (DW_DLV_ERROR);
649 }
650
651 ret_die->di_debug_info_ptr = die_info_ptr;
652 ret_die->di_cu_context =
653 die == NULL ? dbg->de_cu_context : die->di_cu_context;
654
655 DECODE_LEB128_UWORD(die_info_ptr, utmp);
656 abbrev_code = (Dwarf_Word) utmp;
657 if (abbrev_code == 0) {
658 /* Zero means a null DIE */
659 dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
660 return (DW_DLV_NO_ENTRY);
661 }
662 ret_die->di_abbrev_code = abbrev_code;
663 ret_die->di_abbrev_list =
664 _dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code);
665 if (ret_die->di_abbrev_list == NULL || (die == NULL &&
666 ret_die->di_abbrev_list->
667 ab_tag !=
668 DW_TAG_compile_unit)) {
669 dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
670 _dwarf_error(dbg, error, DW_DLE_FIRST_DIE_NOT_CU);
671 return (DW_DLV_ERROR);
672 }
673
674 *caller_ret_die = ret_die;
675 return (DW_DLV_OK);
676 }
677
678
679 int
dwarf_child(Dwarf_Die die,Dwarf_Die * caller_ret_die,Dwarf_Error * error)680 dwarf_child(Dwarf_Die die,
681 Dwarf_Die * caller_ret_die, Dwarf_Error * error)
682 {
683 Dwarf_Byte_Ptr die_info_ptr = 0;
684
685 /* die_info_end points one-past-end of die area. */
686 Dwarf_Byte_Ptr die_info_end = 0;
687 Dwarf_Die ret_die = 0;
688 Dwarf_Bool has_die_child = 0;
689 Dwarf_Debug dbg;
690 Dwarf_Word abbrev_code = 0;
691 Dwarf_Unsigned utmp = 0;
692
693
694 CHECK_DIE(die, DW_DLV_ERROR);
695 dbg = die->di_cu_context->cc_dbg;
696 die_info_ptr = die->di_debug_info_ptr;
697
698 /* NULL die has no child. */
699 if ((*die_info_ptr) == 0)
700 return (DW_DLV_NO_ENTRY);
701
702 die_info_end = dbg->de_debug_info.dss_data +
703 die->di_cu_context->cc_debug_info_offset +
704 die->di_cu_context->cc_length +
705 die->di_cu_context->cc_length_size +
706 die->di_cu_context->cc_extension_size;
707
708 die_info_ptr =
709 _dwarf_next_die_info_ptr(die_info_ptr, die->di_cu_context,
710 die_info_end, NULL, false,
711 &has_die_child);
712 if (die_info_ptr == NULL) {
713 _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
714 return (DW_DLV_ERROR);
715 }
716
717 if (!has_die_child)
718 return (DW_DLV_NO_ENTRY);
719
720 ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
721 if (ret_die == NULL) {
722 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
723 return (DW_DLV_ERROR);
724 }
725 ret_die->di_debug_info_ptr = die_info_ptr;
726 ret_die->di_cu_context = die->di_cu_context;
727
728 DECODE_LEB128_UWORD(die_info_ptr, utmp);
729 abbrev_code = (Dwarf_Word) utmp;
730 if (abbrev_code == 0) {
731 /* We have arrived at a null DIE, at the end of a CU or the end
732 of a list of siblings. */
733 *caller_ret_die = 0;
734 dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
735 return DW_DLV_NO_ENTRY;
736 }
737 ret_die->di_abbrev_code = abbrev_code;
738 ret_die->di_abbrev_list =
739 _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code);
740 if (ret_die->di_abbrev_list == NULL) {
741 dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
742 _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
743 return (DW_DLV_ERROR);
744 }
745
746 *caller_ret_die = ret_die;
747 return (DW_DLV_OK);
748 }
749
750 /*
751 Given a (global, not cu_relative) die offset, this returns
752 a pointer to a DIE thru *new_die.
753 It is up to the caller to do a
754 dwarf_dealloc(dbg,*new_die,DW_DLE_DIE);
755 */
756 int
dwarf_offdie(Dwarf_Debug dbg,Dwarf_Off offset,Dwarf_Die * new_die,Dwarf_Error * error)757 dwarf_offdie(Dwarf_Debug dbg,
758 Dwarf_Off offset, Dwarf_Die * new_die, Dwarf_Error * error)
759 {
760 Dwarf_CU_Context cu_context = 0;
761 Dwarf_Off new_cu_offset = 0;
762 Dwarf_Die die = 0;
763 Dwarf_Byte_Ptr info_ptr = 0;
764 Dwarf_Unsigned abbrev_code = 0;
765 Dwarf_Unsigned utmp = 0;
766
767 if (dbg == NULL) {
768 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
769 return (DW_DLV_ERROR);
770 }
771
772 cu_context = _dwarf_find_CU_Context(dbg, offset);
773 if (cu_context == NULL)
774 cu_context = _dwarf_find_offdie_CU_Context(dbg, offset);
775
776 if (cu_context == NULL) {
777 int res = _dwarf_load_debug_info(dbg, error);
778
779 if (res != DW_DLV_OK) {
780 return res;
781 }
782
783 if (dbg->de_offdie_cu_context_end != NULL) {
784 Dwarf_CU_Context lcu_context =
785 dbg->de_offdie_cu_context_end;
786 new_cu_offset =
787 lcu_context->cc_debug_info_offset +
788 lcu_context->cc_length +
789 lcu_context->cc_length_size +
790 lcu_context->cc_extension_size;
791 }
792
793
794 do {
795 if ((new_cu_offset +
796 _dwarf_length_of_cu_header_simple(dbg)) >=
797 dbg->de_debug_info.dss_size) {
798 _dwarf_error(dbg, error, DW_DLE_OFFSET_BAD);
799 return (DW_DLV_ERROR);
800 }
801
802 cu_context =
803 _dwarf_make_CU_Context(dbg, new_cu_offset, error);
804 if (cu_context == NULL) {
805 /* Error if CU Context could not be made. Since
806 _dwarf_make_CU_Context has already registered an
807 error we do not do that here: we let the lower error
808 pass thru. */
809
810 return (DW_DLV_ERROR);
811 }
812
813 if (dbg->de_offdie_cu_context == NULL) {
814 dbg->de_offdie_cu_context = cu_context;
815 dbg->de_offdie_cu_context_end = cu_context;
816 } else {
817 dbg->de_offdie_cu_context_end->cc_next = cu_context;
818 dbg->de_offdie_cu_context_end = cu_context;
819 }
820
821 new_cu_offset = new_cu_offset + cu_context->cc_length +
822 cu_context->cc_length_size;
823
824 } while (offset >= new_cu_offset);
825 }
826
827 die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
828 if (die == NULL) {
829 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
830 return (DW_DLV_ERROR);
831 }
832 die->di_cu_context = cu_context;
833
834 info_ptr = dbg->de_debug_info.dss_data + offset;
835 die->di_debug_info_ptr = info_ptr;
836 DECODE_LEB128_UWORD(info_ptr, utmp);
837 abbrev_code = utmp;
838 if (abbrev_code == 0) {
839 /* we are at a null DIE (or there is a bug). */
840 *new_die = 0;
841 dwarf_dealloc(dbg, die, DW_DLA_DIE);
842 return DW_DLV_NO_ENTRY;
843 }
844 die->di_abbrev_code = abbrev_code;
845 die->di_abbrev_list =
846 _dwarf_get_abbrev_for_code(cu_context, abbrev_code);
847 if (die->di_abbrev_list == NULL) {
848 dwarf_dealloc(dbg, die, DW_DLA_DIE);
849 _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL);
850 return (DW_DLV_ERROR);
851 }
852
853 *new_die = die;
854 return (DW_DLV_OK);
855 }
856