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