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