xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_die_deliv.c (revision 33c72b7598992897b94815b1f47b7b8077e53808)
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
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
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
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
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
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
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
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
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
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