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
_dwarf_find_CU_Context(Dwarf_Debug dbg,Dwarf_Off offset)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
_dwarf_find_offdie_CU_Context(Dwarf_Debug dbg,Dwarf_Off offset)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
_dwarf_make_CU_Context(Dwarf_Debug dbg,Dwarf_Off offset,Dwarf_Error * error)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
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*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
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*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
_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*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
dwarf_siblingof(Dwarf_Debug dbg,Dwarf_Die die,Dwarf_Die * caller_ret_die,Dwarf_Error * error)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
dwarf_child(Dwarf_Die die,Dwarf_Die * caller_ret_die,Dwarf_Error * error)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
dwarf_offdie(Dwarf_Debug dbg,Dwarf_Off offset,Dwarf_Die * new_die,Dwarf_Error * error)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