1*7fd79137SRobert Mustacchi /*
2*7fd79137SRobert Mustacchi
3*7fd79137SRobert Mustacchi Copyright (C) 2000-2005 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 #include <stdio.h>
48*7fd79137SRobert Mustacchi #include "dwarf_global.h"
49*7fd79137SRobert Mustacchi
50*7fd79137SRobert Mustacchi
51*7fd79137SRobert Mustacchi #ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */
52*7fd79137SRobert Mustacchi /* The 'fixup' here intended for IRIX targets only.
53*7fd79137SRobert Mustacchi With a 2+GB Elf64 IRIX executable (under 4GB in size),
54*7fd79137SRobert Mustacchi some DIE offsets wrongly
55*7fd79137SRobert Mustacchi got the 32bit upper bit sign extended. For the cu-header
56*7fd79137SRobert Mustacchi offset in the .debug_pubnames section and in the
57*7fd79137SRobert Mustacchi .debug_aranges section.
58*7fd79137SRobert Mustacchi the 'varp' here is a pointer to an offset into .debug_info.
59*7fd79137SRobert Mustacchi We fix up the offset here if it seems advisable..
60*7fd79137SRobert Mustacchi
61*7fd79137SRobert Mustacchi As of June 2005 we have identified a series of mistakes
62*7fd79137SRobert Mustacchi in ldx64 that can cause this (64 bit values getting passed
63*7fd79137SRobert Mustacchi thru 32-bit signed knothole).
64*7fd79137SRobert Mustacchi */
65*7fd79137SRobert Mustacchi void
_dwarf_fix_up_offset_irix(Dwarf_Debug dbg,Dwarf_Unsigned * varp,char * caller_site_name)66*7fd79137SRobert Mustacchi _dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
67*7fd79137SRobert Mustacchi Dwarf_Unsigned * varp, char *caller_site_name)
68*7fd79137SRobert Mustacchi {
69*7fd79137SRobert Mustacchi
70*7fd79137SRobert Mustacchi Dwarf_Unsigned var = *varp;
71*7fd79137SRobert Mustacchi
72*7fd79137SRobert Mustacchi #define UPPER33 0xffffffff80000000LL
73*7fd79137SRobert Mustacchi #define LOWER32 0xffffffffLL
74*7fd79137SRobert Mustacchi /* Restrict the hack to the known case. Upper 32 bits erroneously
75*7fd79137SRobert Mustacchi sign extended from lower 32 upper bit. */
76*7fd79137SRobert Mustacchi if ((var & UPPER33) == UPPER33) {
77*7fd79137SRobert Mustacchi var &= LOWER32;
78*7fd79137SRobert Mustacchi /* Apply the fix. Dreadful hack. */
79*7fd79137SRobert Mustacchi *varp = var;
80*7fd79137SRobert Mustacchi }
81*7fd79137SRobert Mustacchi #undef UPPER33
82*7fd79137SRobert Mustacchi #undef LOWER32
83*7fd79137SRobert Mustacchi return;
84*7fd79137SRobert Mustacchi }
85*7fd79137SRobert Mustacchi #endif
86*7fd79137SRobert Mustacchi
87*7fd79137SRobert Mustacchi
88*7fd79137SRobert Mustacchi int
dwarf_get_globals(Dwarf_Debug dbg,Dwarf_Global ** globals,Dwarf_Signed * return_count,Dwarf_Error * error)89*7fd79137SRobert Mustacchi dwarf_get_globals(Dwarf_Debug dbg,
90*7fd79137SRobert Mustacchi Dwarf_Global ** globals,
91*7fd79137SRobert Mustacchi Dwarf_Signed * return_count, Dwarf_Error * error)
92*7fd79137SRobert Mustacchi {
93*7fd79137SRobert Mustacchi int res = _dwarf_load_section(dbg, &dbg->de_debug_pubnames,error);
94*7fd79137SRobert Mustacchi if (res != DW_DLV_OK) {
95*7fd79137SRobert Mustacchi return res;
96*7fd79137SRobert Mustacchi }
97*7fd79137SRobert Mustacchi
98*7fd79137SRobert Mustacchi return _dwarf_internal_get_pubnames_like_data(dbg,
99*7fd79137SRobert Mustacchi dbg->de_debug_pubnames.dss_data,
100*7fd79137SRobert Mustacchi dbg->de_debug_pubnames.dss_size,
101*7fd79137SRobert Mustacchi globals,
102*7fd79137SRobert Mustacchi return_count,
103*7fd79137SRobert Mustacchi error,
104*7fd79137SRobert Mustacchi DW_DLA_GLOBAL_CONTEXT,
105*7fd79137SRobert Mustacchi DW_DLA_GLOBAL,
106*7fd79137SRobert Mustacchi DW_DLE_PUBNAMES_LENGTH_BAD,
107*7fd79137SRobert Mustacchi DW_DLE_PUBNAMES_VERSION_ERROR);
108*7fd79137SRobert Mustacchi
109*7fd79137SRobert Mustacchi }
110*7fd79137SRobert Mustacchi
111*7fd79137SRobert Mustacchi /* Deallocating fully requires deallocating the list
112*7fd79137SRobert Mustacchi and all entries. But some internal data is
113*7fd79137SRobert Mustacchi not exposed, so we need a function with internal knowledge.
114*7fd79137SRobert Mustacchi */
115*7fd79137SRobert Mustacchi
116*7fd79137SRobert Mustacchi void
dwarf_globals_dealloc(Dwarf_Debug dbg,Dwarf_Global * dwgl,Dwarf_Signed count)117*7fd79137SRobert Mustacchi dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
118*7fd79137SRobert Mustacchi Dwarf_Signed count)
119*7fd79137SRobert Mustacchi {
120*7fd79137SRobert Mustacchi _dwarf_internal_globals_dealloc(dbg, dwgl,
121*7fd79137SRobert Mustacchi count,
122*7fd79137SRobert Mustacchi DW_DLA_GLOBAL_CONTEXT,
123*7fd79137SRobert Mustacchi DW_DLA_GLOBAL, DW_DLA_LIST);
124*7fd79137SRobert Mustacchi return;
125*7fd79137SRobert Mustacchi }
126*7fd79137SRobert Mustacchi
127*7fd79137SRobert Mustacchi void
_dwarf_internal_globals_dealloc(Dwarf_Debug dbg,Dwarf_Global * dwgl,Dwarf_Signed count,int context_code,int global_code,int list_code)128*7fd79137SRobert Mustacchi _dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
129*7fd79137SRobert Mustacchi Dwarf_Signed count,
130*7fd79137SRobert Mustacchi int context_code,
131*7fd79137SRobert Mustacchi int global_code, int list_code)
132*7fd79137SRobert Mustacchi {
133*7fd79137SRobert Mustacchi Dwarf_Signed i;
134*7fd79137SRobert Mustacchi struct Dwarf_Global_Context_s *gcp = 0;
135*7fd79137SRobert Mustacchi struct Dwarf_Global_Context_s *lastgcp = 0;
136*7fd79137SRobert Mustacchi
137*7fd79137SRobert Mustacchi for (i = 0; i < count; i++) {
138*7fd79137SRobert Mustacchi Dwarf_Global dgb = dwgl[i];
139*7fd79137SRobert Mustacchi
140*7fd79137SRobert Mustacchi gcp = dgb->gl_context;
141*7fd79137SRobert Mustacchi
142*7fd79137SRobert Mustacchi if (lastgcp != gcp) {
143*7fd79137SRobert Mustacchi lastgcp = gcp;
144*7fd79137SRobert Mustacchi dwarf_dealloc(dbg, gcp, context_code);
145*7fd79137SRobert Mustacchi }
146*7fd79137SRobert Mustacchi dwarf_dealloc(dbg, dgb, global_code);
147*7fd79137SRobert Mustacchi }
148*7fd79137SRobert Mustacchi dwarf_dealloc(dbg, dwgl, list_code);
149*7fd79137SRobert Mustacchi return;
150*7fd79137SRobert Mustacchi }
151*7fd79137SRobert Mustacchi
152*7fd79137SRobert Mustacchi
153*7fd79137SRobert Mustacchi /* Sweeps the complete section.
154*7fd79137SRobert Mustacchi */
155*7fd79137SRobert Mustacchi int
_dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,Dwarf_Small * section_data_ptr,Dwarf_Unsigned section_length,Dwarf_Global ** globals,Dwarf_Signed * return_count,Dwarf_Error * error,int context_code,int global_code,int length_err_num,int version_err_num)156*7fd79137SRobert Mustacchi _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
157*7fd79137SRobert Mustacchi Dwarf_Small * section_data_ptr,
158*7fd79137SRobert Mustacchi Dwarf_Unsigned section_length,
159*7fd79137SRobert Mustacchi Dwarf_Global ** globals,
160*7fd79137SRobert Mustacchi Dwarf_Signed * return_count,
161*7fd79137SRobert Mustacchi Dwarf_Error * error,
162*7fd79137SRobert Mustacchi int context_code,
163*7fd79137SRobert Mustacchi int global_code,
164*7fd79137SRobert Mustacchi int length_err_num,
165*7fd79137SRobert Mustacchi int version_err_num)
166*7fd79137SRobert Mustacchi {
167*7fd79137SRobert Mustacchi
168*7fd79137SRobert Mustacchi
169*7fd79137SRobert Mustacchi Dwarf_Small *pubnames_like_ptr = 0;
170*7fd79137SRobert Mustacchi
171*7fd79137SRobert Mustacchi
172*7fd79137SRobert Mustacchi
173*7fd79137SRobert Mustacchi /* Points to the context for the current set of global names, and
174*7fd79137SRobert Mustacchi contains information to identify the compilation-unit that the
175*7fd79137SRobert Mustacchi set refers to. */
176*7fd79137SRobert Mustacchi Dwarf_Global_Context pubnames_context = 0;
177*7fd79137SRobert Mustacchi
178*7fd79137SRobert Mustacchi Dwarf_Half version = 0;
179*7fd79137SRobert Mustacchi
180*7fd79137SRobert Mustacchi /*
181*7fd79137SRobert Mustacchi Offset from the start of compilation-unit for the current
182*7fd79137SRobert Mustacchi global. */
183*7fd79137SRobert Mustacchi Dwarf_Off die_offset_in_cu = 0;
184*7fd79137SRobert Mustacchi
185*7fd79137SRobert Mustacchi Dwarf_Unsigned global_count = 0;
186*7fd79137SRobert Mustacchi
187*7fd79137SRobert Mustacchi /* Points to the current global read. */
188*7fd79137SRobert Mustacchi Dwarf_Global global = 0;
189*7fd79137SRobert Mustacchi
190*7fd79137SRobert Mustacchi /* Used to chain the Dwarf_Global_s structs for creating contiguous
191*7fd79137SRobert Mustacchi list of pointers to the structs. */
192*7fd79137SRobert Mustacchi Dwarf_Chain curr_chain = 0;
193*7fd79137SRobert Mustacchi Dwarf_Chain prev_chain = 0;
194*7fd79137SRobert Mustacchi Dwarf_Chain head_chain = 0;
195*7fd79137SRobert Mustacchi
196*7fd79137SRobert Mustacchi /* Points to contiguous block of Dwarf_Global's to be returned. */
197*7fd79137SRobert Mustacchi Dwarf_Global *ret_globals = 0;
198*7fd79137SRobert Mustacchi
199*7fd79137SRobert Mustacchi /* Temporary counter. */
200*7fd79137SRobert Mustacchi Dwarf_Unsigned i = 0;
201*7fd79137SRobert Mustacchi
202*7fd79137SRobert Mustacchi
203*7fd79137SRobert Mustacchi
204*7fd79137SRobert Mustacchi
205*7fd79137SRobert Mustacchi if (dbg == NULL) {
206*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
207*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
208*7fd79137SRobert Mustacchi }
209*7fd79137SRobert Mustacchi /* We will eventually need the .debug_info data. Load it now. */
210*7fd79137SRobert Mustacchi if (!dbg->de_debug_info.dss_data) {
211*7fd79137SRobert Mustacchi int res = _dwarf_load_debug_info(dbg, error);
212*7fd79137SRobert Mustacchi
213*7fd79137SRobert Mustacchi if (res != DW_DLV_OK) {
214*7fd79137SRobert Mustacchi return res;
215*7fd79137SRobert Mustacchi }
216*7fd79137SRobert Mustacchi }
217*7fd79137SRobert Mustacchi
218*7fd79137SRobert Mustacchi if (section_data_ptr == NULL) {
219*7fd79137SRobert Mustacchi return (DW_DLV_NO_ENTRY);
220*7fd79137SRobert Mustacchi }
221*7fd79137SRobert Mustacchi
222*7fd79137SRobert Mustacchi pubnames_like_ptr = section_data_ptr;
223*7fd79137SRobert Mustacchi do {
224*7fd79137SRobert Mustacchi Dwarf_Unsigned length = 0;
225*7fd79137SRobert Mustacchi int local_extension_size = 0;
226*7fd79137SRobert Mustacchi int local_length_size = 0;
227*7fd79137SRobert Mustacchi
228*7fd79137SRobert Mustacchi /* Some compilers emit padding at the end of each cu's area.
229*7fd79137SRobert Mustacchi pubnames_ptr_past_end_cu records the true area end for this
230*7fd79137SRobert Mustacchi cu's data. Essentially the length in the header and the 0
231*7fd79137SRobert Mustacchi terminator of the data are redundant information. The
232*7fd79137SRobert Mustacchi dwarf2/3 spec does not mention what to do if the length is
233*7fd79137SRobert Mustacchi past the 0 terminator. So we take any bytes left after the 0
234*7fd79137SRobert Mustacchi as padding and ignore them. */
235*7fd79137SRobert Mustacchi Dwarf_Small *pubnames_ptr_past_end_cu = 0;
236*7fd79137SRobert Mustacchi
237*7fd79137SRobert Mustacchi
238*7fd79137SRobert Mustacchi pubnames_context = (Dwarf_Global_Context)
239*7fd79137SRobert Mustacchi _dwarf_get_alloc(dbg, context_code, 1);
240*7fd79137SRobert Mustacchi if (pubnames_context == NULL) {
241*7fd79137SRobert Mustacchi _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
242*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
243*7fd79137SRobert Mustacchi }
244*7fd79137SRobert Mustacchi /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed
245*7fd79137SRobert Mustacchi bytes. */
246*7fd79137SRobert Mustacchi READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
247*7fd79137SRobert Mustacchi pubnames_like_ptr, local_length_size,
248*7fd79137SRobert Mustacchi local_extension_size);
249*7fd79137SRobert Mustacchi pubnames_context->pu_length_size = local_length_size;
250*7fd79137SRobert Mustacchi pubnames_context->pu_extension_size = local_extension_size;
251*7fd79137SRobert Mustacchi pubnames_context->pu_dbg = dbg;
252*7fd79137SRobert Mustacchi
253*7fd79137SRobert Mustacchi pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
254*7fd79137SRobert Mustacchi
255*7fd79137SRobert Mustacchi READ_UNALIGNED(dbg, version, Dwarf_Half,
256*7fd79137SRobert Mustacchi pubnames_like_ptr, sizeof(Dwarf_Half));
257*7fd79137SRobert Mustacchi pubnames_like_ptr += sizeof(Dwarf_Half);
258*7fd79137SRobert Mustacchi if (version != CURRENT_VERSION_STAMP) {
259*7fd79137SRobert Mustacchi _dwarf_error(dbg, error, version_err_num);
260*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
261*7fd79137SRobert Mustacchi }
262*7fd79137SRobert Mustacchi
263*7fd79137SRobert Mustacchi /* Offset of CU header in debug section. */
264*7fd79137SRobert Mustacchi READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header,
265*7fd79137SRobert Mustacchi Dwarf_Off, pubnames_like_ptr,
266*7fd79137SRobert Mustacchi pubnames_context->pu_length_size);
267*7fd79137SRobert Mustacchi pubnames_like_ptr += pubnames_context->pu_length_size;
268*7fd79137SRobert Mustacchi
269*7fd79137SRobert Mustacchi FIX_UP_OFFSET_IRIX_BUG(dbg,
270*7fd79137SRobert Mustacchi pubnames_context->pu_offset_of_cu_header,
271*7fd79137SRobert Mustacchi "pubnames cu header offset");
272*7fd79137SRobert Mustacchi
273*7fd79137SRobert Mustacchi
274*7fd79137SRobert Mustacchi READ_UNALIGNED(dbg, pubnames_context->pu_info_length,
275*7fd79137SRobert Mustacchi Dwarf_Unsigned, pubnames_like_ptr,
276*7fd79137SRobert Mustacchi pubnames_context->pu_length_size);
277*7fd79137SRobert Mustacchi pubnames_like_ptr += pubnames_context->pu_length_size;
278*7fd79137SRobert Mustacchi
279*7fd79137SRobert Mustacchi if (pubnames_like_ptr > (section_data_ptr + section_length)) {
280*7fd79137SRobert Mustacchi _dwarf_error(dbg, error, length_err_num);
281*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
282*7fd79137SRobert Mustacchi }
283*7fd79137SRobert Mustacchi
284*7fd79137SRobert Mustacchi /* Read initial offset (of DIE within CU) of a pubname, final
285*7fd79137SRobert Mustacchi entry is not a pair, just a zero offset. */
286*7fd79137SRobert Mustacchi READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
287*7fd79137SRobert Mustacchi pubnames_like_ptr,
288*7fd79137SRobert Mustacchi pubnames_context->pu_length_size);
289*7fd79137SRobert Mustacchi pubnames_like_ptr += pubnames_context->pu_length_size;
290*7fd79137SRobert Mustacchi FIX_UP_OFFSET_IRIX_BUG(dbg,
291*7fd79137SRobert Mustacchi die_offset_in_cu, "offset of die in cu");
292*7fd79137SRobert Mustacchi
293*7fd79137SRobert Mustacchi /* Loop thru pairs. DIE off with CU followed by string. */
294*7fd79137SRobert Mustacchi while (die_offset_in_cu != 0) {
295*7fd79137SRobert Mustacchi
296*7fd79137SRobert Mustacchi /* Already read offset, pubnames_like_ptr now points to the
297*7fd79137SRobert Mustacchi string. */
298*7fd79137SRobert Mustacchi global =
299*7fd79137SRobert Mustacchi (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1);
300*7fd79137SRobert Mustacchi if (global == NULL) {
301*7fd79137SRobert Mustacchi _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
302*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
303*7fd79137SRobert Mustacchi }
304*7fd79137SRobert Mustacchi global_count++;
305*7fd79137SRobert Mustacchi
306*7fd79137SRobert Mustacchi global->gl_context = pubnames_context;
307*7fd79137SRobert Mustacchi
308*7fd79137SRobert Mustacchi global->gl_named_die_offset_within_cu = die_offset_in_cu;
309*7fd79137SRobert Mustacchi
310*7fd79137SRobert Mustacchi global->gl_name = pubnames_like_ptr;
311*7fd79137SRobert Mustacchi
312*7fd79137SRobert Mustacchi pubnames_like_ptr = pubnames_like_ptr +
313*7fd79137SRobert Mustacchi strlen((char *) pubnames_like_ptr) + 1;
314*7fd79137SRobert Mustacchi
315*7fd79137SRobert Mustacchi
316*7fd79137SRobert Mustacchi /* finish off current entry chain */
317*7fd79137SRobert Mustacchi curr_chain =
318*7fd79137SRobert Mustacchi (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
319*7fd79137SRobert Mustacchi if (curr_chain == NULL) {
320*7fd79137SRobert Mustacchi _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
321*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
322*7fd79137SRobert Mustacchi }
323*7fd79137SRobert Mustacchi
324*7fd79137SRobert Mustacchi /* Put current global on singly_linked list. */
325*7fd79137SRobert Mustacchi curr_chain->ch_item = (Dwarf_Global) global;
326*7fd79137SRobert Mustacchi
327*7fd79137SRobert Mustacchi if (head_chain == NULL)
328*7fd79137SRobert Mustacchi head_chain = prev_chain = curr_chain;
329*7fd79137SRobert Mustacchi else {
330*7fd79137SRobert Mustacchi prev_chain->ch_next = curr_chain;
331*7fd79137SRobert Mustacchi prev_chain = curr_chain;
332*7fd79137SRobert Mustacchi }
333*7fd79137SRobert Mustacchi
334*7fd79137SRobert Mustacchi /* read offset for the *next* entry */
335*7fd79137SRobert Mustacchi READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
336*7fd79137SRobert Mustacchi pubnames_like_ptr,
337*7fd79137SRobert Mustacchi pubnames_context->pu_length_size);
338*7fd79137SRobert Mustacchi
339*7fd79137SRobert Mustacchi pubnames_like_ptr += pubnames_context->pu_length_size;
340*7fd79137SRobert Mustacchi FIX_UP_OFFSET_IRIX_BUG(dbg,
341*7fd79137SRobert Mustacchi die_offset_in_cu,
342*7fd79137SRobert Mustacchi "offset of next die in cu");
343*7fd79137SRobert Mustacchi
344*7fd79137SRobert Mustacchi if (pubnames_like_ptr > (section_data_ptr + section_length)) {
345*7fd79137SRobert Mustacchi _dwarf_error(dbg, error, length_err_num);
346*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
347*7fd79137SRobert Mustacchi }
348*7fd79137SRobert Mustacchi }
349*7fd79137SRobert Mustacchi /* ASSERT: die_offset_in_cu == 0 */
350*7fd79137SRobert Mustacchi if (pubnames_like_ptr > pubnames_ptr_past_end_cu) {
351*7fd79137SRobert Mustacchi /* This is some kind of error. This simply cannot happen.
352*7fd79137SRobert Mustacchi The encoding is wrong or the length in the header for
353*7fd79137SRobert Mustacchi this cu's contribution is wrong. */
354*7fd79137SRobert Mustacchi _dwarf_error(dbg, error, length_err_num);
355*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
356*7fd79137SRobert Mustacchi }
357*7fd79137SRobert Mustacchi /* If there is some kind of padding at the end of the section,
358*7fd79137SRobert Mustacchi as emitted by some compilers, skip over that padding and
359*7fd79137SRobert Mustacchi simply ignore the bytes thus passed-over. With most
360*7fd79137SRobert Mustacchi compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at
361*7fd79137SRobert Mustacchi this point */
362*7fd79137SRobert Mustacchi pubnames_like_ptr = pubnames_ptr_past_end_cu;
363*7fd79137SRobert Mustacchi
364*7fd79137SRobert Mustacchi } while (pubnames_like_ptr < (section_data_ptr + section_length));
365*7fd79137SRobert Mustacchi
366*7fd79137SRobert Mustacchi /* Points to contiguous block of Dwarf_Global's. */
367*7fd79137SRobert Mustacchi ret_globals = (Dwarf_Global *)
368*7fd79137SRobert Mustacchi _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
369*7fd79137SRobert Mustacchi if (ret_globals == NULL) {
370*7fd79137SRobert Mustacchi _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
371*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
372*7fd79137SRobert Mustacchi }
373*7fd79137SRobert Mustacchi
374*7fd79137SRobert Mustacchi /*
375*7fd79137SRobert Mustacchi Store pointers to Dwarf_Global_s structs in contiguous block,
376*7fd79137SRobert Mustacchi and deallocate the chain. */
377*7fd79137SRobert Mustacchi curr_chain = head_chain;
378*7fd79137SRobert Mustacchi for (i = 0; i < global_count; i++) {
379*7fd79137SRobert Mustacchi *(ret_globals + i) = curr_chain->ch_item;
380*7fd79137SRobert Mustacchi prev_chain = curr_chain;
381*7fd79137SRobert Mustacchi curr_chain = curr_chain->ch_next;
382*7fd79137SRobert Mustacchi dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
383*7fd79137SRobert Mustacchi }
384*7fd79137SRobert Mustacchi
385*7fd79137SRobert Mustacchi *globals = ret_globals;
386*7fd79137SRobert Mustacchi *return_count = (Dwarf_Signed) global_count;
387*7fd79137SRobert Mustacchi return DW_DLV_OK;
388*7fd79137SRobert Mustacchi }
389*7fd79137SRobert Mustacchi
390*7fd79137SRobert Mustacchi
391*7fd79137SRobert Mustacchi /*
392*7fd79137SRobert Mustacchi Given a pubnames entry (or other like section entry)
393*7fd79137SRobert Mustacchi return thru the ret_name pointer
394*7fd79137SRobert Mustacchi a pointer to the string which is the entry name.
395*7fd79137SRobert Mustacchi
396*7fd79137SRobert Mustacchi */
397*7fd79137SRobert Mustacchi int
dwarf_globname(Dwarf_Global glob,char ** ret_name,Dwarf_Error * error)398*7fd79137SRobert Mustacchi dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
399*7fd79137SRobert Mustacchi {
400*7fd79137SRobert Mustacchi if (glob == NULL) {
401*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
402*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
403*7fd79137SRobert Mustacchi }
404*7fd79137SRobert Mustacchi
405*7fd79137SRobert Mustacchi *ret_name = (char *) (glob->gl_name);
406*7fd79137SRobert Mustacchi return DW_DLV_OK;
407*7fd79137SRobert Mustacchi }
408*7fd79137SRobert Mustacchi
409*7fd79137SRobert Mustacchi
410*7fd79137SRobert Mustacchi /*
411*7fd79137SRobert Mustacchi Given a pubnames entry (or other like section entry)
412*7fd79137SRobert Mustacchi return thru the ret_off pointer the
413*7fd79137SRobert Mustacchi global offset of the DIE for this entry.
414*7fd79137SRobert Mustacchi The global offset is the offset within the .debug_info
415*7fd79137SRobert Mustacchi section as a whole.
416*7fd79137SRobert Mustacchi */
417*7fd79137SRobert Mustacchi int
dwarf_global_die_offset(Dwarf_Global global,Dwarf_Off * ret_off,Dwarf_Error * error)418*7fd79137SRobert Mustacchi dwarf_global_die_offset(Dwarf_Global global,
419*7fd79137SRobert Mustacchi Dwarf_Off * ret_off, Dwarf_Error * error)
420*7fd79137SRobert Mustacchi {
421*7fd79137SRobert Mustacchi if (global == NULL) {
422*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
423*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
424*7fd79137SRobert Mustacchi }
425*7fd79137SRobert Mustacchi
426*7fd79137SRobert Mustacchi if (global->gl_context == NULL) {
427*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
428*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
429*7fd79137SRobert Mustacchi }
430*7fd79137SRobert Mustacchi
431*7fd79137SRobert Mustacchi *ret_off = (global->gl_named_die_offset_within_cu +
432*7fd79137SRobert Mustacchi global->gl_context->pu_offset_of_cu_header);
433*7fd79137SRobert Mustacchi return DW_DLV_OK;
434*7fd79137SRobert Mustacchi }
435*7fd79137SRobert Mustacchi
436*7fd79137SRobert Mustacchi /*
437*7fd79137SRobert Mustacchi Given a pubnames entry (or other like section entry)
438*7fd79137SRobert Mustacchi return thru the ret_off pointer the
439*7fd79137SRobert Mustacchi offset of the compilation unit header of the
440*7fd79137SRobert Mustacchi compilation unit the global is part of.
441*7fd79137SRobert Mustacchi
442*7fd79137SRobert Mustacchi In early versions of this, the value returned was
443*7fd79137SRobert Mustacchi the offset of the compilation unit die, and
444*7fd79137SRobert Mustacchi other cu-local die offsets were faked so adding this to
445*7fd79137SRobert Mustacchi such a cu-local offset got a true section offset.
446*7fd79137SRobert Mustacchi Now things do as they say (adding *cu_header_offset to
447*7fd79137SRobert Mustacchi a cu-local offset gets the section offset).
448*7fd79137SRobert Mustacchi
449*7fd79137SRobert Mustacchi */
450*7fd79137SRobert Mustacchi int
dwarf_global_cu_offset(Dwarf_Global global,Dwarf_Off * cu_header_offset,Dwarf_Error * error)451*7fd79137SRobert Mustacchi dwarf_global_cu_offset(Dwarf_Global global,
452*7fd79137SRobert Mustacchi Dwarf_Off * cu_header_offset,
453*7fd79137SRobert Mustacchi Dwarf_Error * error)
454*7fd79137SRobert Mustacchi {
455*7fd79137SRobert Mustacchi Dwarf_Global_Context con = 0;
456*7fd79137SRobert Mustacchi
457*7fd79137SRobert Mustacchi if (global == NULL) {
458*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
459*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
460*7fd79137SRobert Mustacchi }
461*7fd79137SRobert Mustacchi
462*7fd79137SRobert Mustacchi con = global->gl_context;
463*7fd79137SRobert Mustacchi
464*7fd79137SRobert Mustacchi if (con == NULL) {
465*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
466*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
467*7fd79137SRobert Mustacchi }
468*7fd79137SRobert Mustacchi
469*7fd79137SRobert Mustacchi /* In early libdwarf, this incorrectly returned the offset of the
470*7fd79137SRobert Mustacchi CU DIE. Now correctly returns the header offset. */
471*7fd79137SRobert Mustacchi *cu_header_offset = con->pu_offset_of_cu_header;
472*7fd79137SRobert Mustacchi
473*7fd79137SRobert Mustacchi return DW_DLV_OK;
474*7fd79137SRobert Mustacchi }
475*7fd79137SRobert Mustacchi
476*7fd79137SRobert Mustacchi /*
477*7fd79137SRobert Mustacchi Give back the pubnames entry (or any other like section)
478*7fd79137SRobert Mustacchi name, symbol DIE offset, and the cu-DIE offset.
479*7fd79137SRobert Mustacchi
480*7fd79137SRobert Mustacchi Various errors are possible.
481*7fd79137SRobert Mustacchi
482*7fd79137SRobert Mustacchi The string pointer returned thru ret_name is not
483*7fd79137SRobert Mustacchi dwarf_get_alloc()ed, so no dwarf_dealloc()
484*7fd79137SRobert Mustacchi DW_DLA_STRING should be applied to it.
485*7fd79137SRobert Mustacchi
486*7fd79137SRobert Mustacchi */
487*7fd79137SRobert Mustacchi int
dwarf_global_name_offsets(Dwarf_Global global,char ** ret_name,Dwarf_Off * die_offset,Dwarf_Off * cu_die_offset,Dwarf_Error * error)488*7fd79137SRobert Mustacchi dwarf_global_name_offsets(Dwarf_Global global,
489*7fd79137SRobert Mustacchi char **ret_name,
490*7fd79137SRobert Mustacchi Dwarf_Off * die_offset,
491*7fd79137SRobert Mustacchi Dwarf_Off * cu_die_offset,
492*7fd79137SRobert Mustacchi Dwarf_Error * error)
493*7fd79137SRobert Mustacchi {
494*7fd79137SRobert Mustacchi Dwarf_Global_Context con = 0;
495*7fd79137SRobert Mustacchi Dwarf_Debug dbg = 0;
496*7fd79137SRobert Mustacchi Dwarf_Off off = 0;
497*7fd79137SRobert Mustacchi
498*7fd79137SRobert Mustacchi if (global == NULL) {
499*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
500*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
501*7fd79137SRobert Mustacchi }
502*7fd79137SRobert Mustacchi
503*7fd79137SRobert Mustacchi con = global->gl_context;
504*7fd79137SRobert Mustacchi
505*7fd79137SRobert Mustacchi if (con == NULL) {
506*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
507*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
508*7fd79137SRobert Mustacchi }
509*7fd79137SRobert Mustacchi
510*7fd79137SRobert Mustacchi off = con->pu_offset_of_cu_header;
511*7fd79137SRobert Mustacchi /* The offset had better not be too close to the end. If it is,
512*7fd79137SRobert Mustacchi _dwarf_length_of_cu_header() will step off the end and therefore
513*7fd79137SRobert Mustacchi must not be used. 10 is a meaningless heuristic, but no CU
514*7fd79137SRobert Mustacchi header is that small so it is safe. An erroneous offset is due
515*7fd79137SRobert Mustacchi to a bug in the tool chain. A bug like this has been seen on
516*7fd79137SRobert Mustacchi IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and
517*7fd79137SRobert Mustacchi with 2 million pubnames entries. */
518*7fd79137SRobert Mustacchi #define MIN_CU_HDR_SIZE 10
519*7fd79137SRobert Mustacchi dbg = con->pu_dbg;
520*7fd79137SRobert Mustacchi if (dbg == NULL) {
521*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
522*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
523*7fd79137SRobert Mustacchi }
524*7fd79137SRobert Mustacchi if (dbg->de_debug_info.dss_size &&
525*7fd79137SRobert Mustacchi ((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info.dss_size)) {
526*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
527*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
528*7fd79137SRobert Mustacchi }
529*7fd79137SRobert Mustacchi #undef MIN_CU_HDR_SIZE
530*7fd79137SRobert Mustacchi if (die_offset != NULL) {
531*7fd79137SRobert Mustacchi *die_offset = global->gl_named_die_offset_within_cu + off;
532*7fd79137SRobert Mustacchi }
533*7fd79137SRobert Mustacchi
534*7fd79137SRobert Mustacchi *ret_name = (char *) global->gl_name;
535*7fd79137SRobert Mustacchi
536*7fd79137SRobert Mustacchi if (cu_die_offset != NULL) {
537*7fd79137SRobert Mustacchi int res = _dwarf_load_debug_info(dbg, error);
538*7fd79137SRobert Mustacchi
539*7fd79137SRobert Mustacchi if (res != DW_DLV_OK) {
540*7fd79137SRobert Mustacchi return res;
541*7fd79137SRobert Mustacchi }
542*7fd79137SRobert Mustacchi /* The offset had better not be too close to the end. If it is,
543*7fd79137SRobert Mustacchi _dwarf_length_of_cu_header() will step off the end and
544*7fd79137SRobert Mustacchi therefore must not be used. 10 is a meaningless heuristic,
545*7fd79137SRobert Mustacchi but no CU header is that small so it is safe. */
546*7fd79137SRobert Mustacchi if ((off + 10) >= dbg->de_debug_info.dss_size) {
547*7fd79137SRobert Mustacchi _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
548*7fd79137SRobert Mustacchi return (DW_DLV_ERROR);
549*7fd79137SRobert Mustacchi }
550*7fd79137SRobert Mustacchi *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off);
551*7fd79137SRobert Mustacchi }
552*7fd79137SRobert Mustacchi
553*7fd79137SRobert Mustacchi
554*7fd79137SRobert Mustacchi return DW_DLV_OK;
555*7fd79137SRobert Mustacchi }
556*7fd79137SRobert Mustacchi
557*7fd79137SRobert Mustacchi /*
558*7fd79137SRobert Mustacchi We have the offset to a CU header.
559*7fd79137SRobert Mustacchi Return thru outFileOffset the offset of the CU DIE.
560*7fd79137SRobert Mustacchi
561*7fd79137SRobert Mustacchi New June, 2001.
562*7fd79137SRobert Mustacchi Used by SGI debuggers.
563*7fd79137SRobert Mustacchi No error is possible.
564*7fd79137SRobert Mustacchi
565*7fd79137SRobert Mustacchi See also dwarf_CU_dieoffset_given_die().
566*7fd79137SRobert Mustacchi */
567*7fd79137SRobert Mustacchi
568*7fd79137SRobert Mustacchi /* ARGSUSED */
569*7fd79137SRobert Mustacchi int
dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,Dwarf_Off in_cu_header_offset,Dwarf_Off * out_cu_die_offset,Dwarf_Error * err)570*7fd79137SRobert Mustacchi dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
571*7fd79137SRobert Mustacchi Dwarf_Off in_cu_header_offset,
572*7fd79137SRobert Mustacchi Dwarf_Off * out_cu_die_offset,
573*7fd79137SRobert Mustacchi Dwarf_Error * err)
574*7fd79137SRobert Mustacchi {
575*7fd79137SRobert Mustacchi Dwarf_Off len =
576*7fd79137SRobert Mustacchi _dwarf_length_of_cu_header(dbg, in_cu_header_offset);
577*7fd79137SRobert Mustacchi
578*7fd79137SRobert Mustacchi Dwarf_Off newoff = in_cu_header_offset + len;
579*7fd79137SRobert Mustacchi
580*7fd79137SRobert Mustacchi *out_cu_die_offset = newoff;
581*7fd79137SRobert Mustacchi return DW_DLV_OK;
582*7fd79137SRobert Mustacchi }
583*7fd79137SRobert Mustacchi /* dwarf_CU_dieoffset_given_die returns
584*7fd79137SRobert Mustacchi the global debug_info section offset of the CU die
585*7fd79137SRobert Mustacchi that is the CU containing the given (passed-in) die.
586*7fd79137SRobert Mustacchi This information makes it possible for a consumer to
587*7fd79137SRobert Mustacchi find and print context information for any die.
588*7fd79137SRobert Mustacchi
589*7fd79137SRobert Mustacchi Use dwarf_offdie() passing in the offset this returns
590*7fd79137SRobert Mustacchi to get a die pointer to the CU die.
591*7fd79137SRobert Mustacchi */
592*7fd79137SRobert Mustacchi int
dwarf_CU_dieoffset_given_die(Dwarf_Die die,Dwarf_Off * return_offset,Dwarf_Error * error)593*7fd79137SRobert Mustacchi dwarf_CU_dieoffset_given_die(Dwarf_Die die,
594*7fd79137SRobert Mustacchi Dwarf_Off* return_offset,
595*7fd79137SRobert Mustacchi Dwarf_Error* error)
596*7fd79137SRobert Mustacchi {
597*7fd79137SRobert Mustacchi Dwarf_Off dieoff = 0;
598*7fd79137SRobert Mustacchi Dwarf_CU_Context cucontext = 0;
599*7fd79137SRobert Mustacchi
600*7fd79137SRobert Mustacchi CHECK_DIE(die, DW_DLV_ERROR);
601*7fd79137SRobert Mustacchi cucontext = die->di_cu_context;
602*7fd79137SRobert Mustacchi dieoff = cucontext->cc_debug_info_offset;
603*7fd79137SRobert Mustacchi /* The following call cannot fail, so no error check. */
604*7fd79137SRobert Mustacchi dwarf_get_cu_die_offset_given_cu_header_offset(
605*7fd79137SRobert Mustacchi cucontext->cc_dbg, dieoff, return_offset,error);
606*7fd79137SRobert Mustacchi return DW_DLV_OK;
607*7fd79137SRobert Mustacchi }
608