xref: /titanic_51/usr/src/lib/libdwarf/common/dwarf_addr_finder.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
1*7fd79137SRobert Mustacchi /*
2*7fd79137SRobert Mustacchi 
3*7fd79137SRobert Mustacchi   Copyright (C) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
4*7fd79137SRobert Mustacchi 
5*7fd79137SRobert Mustacchi   This program is free software; you can redistribute it and/or modify it
6*7fd79137SRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
7*7fd79137SRobert Mustacchi   as published by the Free Software Foundation.
8*7fd79137SRobert Mustacchi 
9*7fd79137SRobert Mustacchi   This program is distributed in the hope that it would be useful, but
10*7fd79137SRobert Mustacchi   WITHOUT ANY WARRANTY; without even the implied warranty of
11*7fd79137SRobert Mustacchi   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12*7fd79137SRobert Mustacchi 
13*7fd79137SRobert Mustacchi   Further, this software is distributed without any warranty that it is
14*7fd79137SRobert Mustacchi   free of the rightful claim of any third person regarding infringement
15*7fd79137SRobert Mustacchi   or the like.  Any license provided herein, whether implied or
16*7fd79137SRobert Mustacchi   otherwise, applies only to this software file.  Patent licenses, if
17*7fd79137SRobert Mustacchi   any, provided herein do not apply to combinations of this program with
18*7fd79137SRobert Mustacchi   other software, or any other product whatsoever.
19*7fd79137SRobert Mustacchi 
20*7fd79137SRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
21*7fd79137SRobert Mustacchi   License along with this program; if not, write the Free Software
22*7fd79137SRobert Mustacchi   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23*7fd79137SRobert Mustacchi   USA.
24*7fd79137SRobert Mustacchi 
25*7fd79137SRobert Mustacchi   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
26*7fd79137SRobert Mustacchi   Mountain View, CA 94043, or:
27*7fd79137SRobert Mustacchi 
28*7fd79137SRobert Mustacchi   http://www.sgi.com
29*7fd79137SRobert Mustacchi 
30*7fd79137SRobert Mustacchi   For further information regarding this notice, see:
31*7fd79137SRobert Mustacchi 
32*7fd79137SRobert Mustacchi   http://oss.sgi.com/projects/GenInfo/NoticeExplan
33*7fd79137SRobert Mustacchi 
34*7fd79137SRobert Mustacchi */
35*7fd79137SRobert Mustacchi /* This code used by SGI-IRIX rqs processing, not needed by
36*7fd79137SRobert Mustacchi    any other system or application.
37*7fd79137SRobert Mustacchi */
38*7fd79137SRobert Mustacchi 
39*7fd79137SRobert Mustacchi #include "config.h"
40*7fd79137SRobert Mustacchi #include "libdwarfdefs.h"
41*7fd79137SRobert Mustacchi #ifdef HAVE_ELF_H
42*7fd79137SRobert Mustacchi #include <elf.h>
43*7fd79137SRobert Mustacchi #endif
44*7fd79137SRobert Mustacchi #include <dwarf.h>
45*7fd79137SRobert Mustacchi #include <libdwarf.h>
46*7fd79137SRobert Mustacchi #include "dwarf_base_types.h"
47*7fd79137SRobert Mustacchi #include "dwarf_alloc.h"
48*7fd79137SRobert Mustacchi #include "dwarf_opaque.h"
49*7fd79137SRobert Mustacchi #include "dwarf_arange.h"
50*7fd79137SRobert Mustacchi #include "dwarf_line.h"
51*7fd79137SRobert Mustacchi #include "dwarf_frame.h"
52*7fd79137SRobert Mustacchi #include <cmplrs/dwarf_addr_finder.h>
53*7fd79137SRobert Mustacchi #include "dwarf_error.h"
54*7fd79137SRobert Mustacchi 
55*7fd79137SRobert Mustacchi typedef unsigned long long ull;
56*7fd79137SRobert Mustacchi 
57*7fd79137SRobert Mustacchi static int do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die,
58*7fd79137SRobert Mustacchi                                    int *errval);
59*7fd79137SRobert Mustacchi static int
60*7fd79137SRobert Mustacchi   handle_debug_info(Dwarf_Debug dbg, int *errval);
61*7fd79137SRobert Mustacchi static int
62*7fd79137SRobert Mustacchi   handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, int *errval);
63*7fd79137SRobert Mustacchi static int
64*7fd79137SRobert Mustacchi   handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, int *errval);
65*7fd79137SRobert Mustacchi static int
66*7fd79137SRobert Mustacchi   handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_addr_callback_func cb_func, int *errval);
67*7fd79137SRobert Mustacchi static int
68*7fd79137SRobert Mustacchi   handle_debug_loc(void);
69*7fd79137SRobert Mustacchi 
70*7fd79137SRobert Mustacchi 
71*7fd79137SRobert Mustacchi static Dwarf_addr_callback_func send_addr_note;
72*7fd79137SRobert Mustacchi 
73*7fd79137SRobert Mustacchi int
74*7fd79137SRobert Mustacchi _dwarf_addr_finder(dwarf_elf_handle elf_file_ptr,
75*7fd79137SRobert Mustacchi                    Dwarf_addr_callback_func cb_func, int *dwerr)
76*7fd79137SRobert Mustacchi {
77*7fd79137SRobert Mustacchi 
78*7fd79137SRobert Mustacchi     Dwarf_Error err = 0;
79*7fd79137SRobert Mustacchi     Dwarf_Debug dbg = 0;
80*7fd79137SRobert Mustacchi     int res = 0;
81*7fd79137SRobert Mustacchi     int errval = 0;
82*7fd79137SRobert Mustacchi     int sections_found = 0;
83*7fd79137SRobert Mustacchi 
84*7fd79137SRobert Mustacchi     res = dwarf_elf_init(elf_file_ptr, DW_DLC_READ, /* errhand */ 0,
85*7fd79137SRobert Mustacchi                          /* errarg */ 0, &dbg, &err);
86*7fd79137SRobert Mustacchi     if (res == DW_DLV_ERROR) {
87*7fd79137SRobert Mustacchi         int errv = (int) dwarf_errno(err);
88*7fd79137SRobert Mustacchi 
89*7fd79137SRobert Mustacchi         return errv;
90*7fd79137SRobert Mustacchi     }
91*7fd79137SRobert Mustacchi     if (res == DW_DLV_NO_ENTRY) {
92*7fd79137SRobert Mustacchi         return res;
93*7fd79137SRobert Mustacchi     }
94*7fd79137SRobert Mustacchi 
95*7fd79137SRobert Mustacchi     send_addr_note = cb_func;
96*7fd79137SRobert Mustacchi 
97*7fd79137SRobert Mustacchi     res = handle_debug_info(dbg, &errval);
98*7fd79137SRobert Mustacchi     switch (res) {
99*7fd79137SRobert Mustacchi     case DW_DLV_OK:
100*7fd79137SRobert Mustacchi         ++sections_found;
101*7fd79137SRobert Mustacchi         break;
102*7fd79137SRobert Mustacchi     case DW_DLV_NO_ENTRY:
103*7fd79137SRobert Mustacchi 
104*7fd79137SRobert Mustacchi         break;
105*7fd79137SRobert Mustacchi     default:
106*7fd79137SRobert Mustacchi     case DW_DLV_ERROR:
107*7fd79137SRobert Mustacchi         dwarf_finish(dbg, &err);
108*7fd79137SRobert Mustacchi         *dwerr = errval;
109*7fd79137SRobert Mustacchi         return res;
110*7fd79137SRobert Mustacchi     }
111*7fd79137SRobert Mustacchi 
112*7fd79137SRobert Mustacchi     res = handle_debug_aranges(dbg, cb_func, &errval);
113*7fd79137SRobert Mustacchi     switch (res) {
114*7fd79137SRobert Mustacchi     case DW_DLV_OK:
115*7fd79137SRobert Mustacchi         ++sections_found;
116*7fd79137SRobert Mustacchi         break;
117*7fd79137SRobert Mustacchi     case DW_DLV_NO_ENTRY:
118*7fd79137SRobert Mustacchi         break;
119*7fd79137SRobert Mustacchi     default:
120*7fd79137SRobert Mustacchi     case DW_DLV_ERROR:
121*7fd79137SRobert Mustacchi         dwarf_finish(dbg, &err);
122*7fd79137SRobert Mustacchi         *dwerr = errval;
123*7fd79137SRobert Mustacchi         return res;
124*7fd79137SRobert Mustacchi     }
125*7fd79137SRobert Mustacchi     res = handle_debug_frame(dbg, cb_func, &errval);
126*7fd79137SRobert Mustacchi     switch (res) {
127*7fd79137SRobert Mustacchi     case DW_DLV_OK:
128*7fd79137SRobert Mustacchi         ++sections_found;
129*7fd79137SRobert Mustacchi         break;
130*7fd79137SRobert Mustacchi     case DW_DLV_NO_ENTRY:
131*7fd79137SRobert Mustacchi         break;
132*7fd79137SRobert Mustacchi     default:
133*7fd79137SRobert Mustacchi     case DW_DLV_ERROR:
134*7fd79137SRobert Mustacchi         dwarf_finish(dbg, &err);
135*7fd79137SRobert Mustacchi         *dwerr = errval;
136*7fd79137SRobert Mustacchi         return res;
137*7fd79137SRobert Mustacchi     }
138*7fd79137SRobert Mustacchi 
139*7fd79137SRobert Mustacchi     res = handle_debug_loc();   /* does nothing */
140*7fd79137SRobert Mustacchi     switch (res) {
141*7fd79137SRobert Mustacchi     case DW_DLV_OK:
142*7fd79137SRobert Mustacchi         ++sections_found;
143*7fd79137SRobert Mustacchi         break;
144*7fd79137SRobert Mustacchi     case DW_DLV_NO_ENTRY:
145*7fd79137SRobert Mustacchi         break;
146*7fd79137SRobert Mustacchi     default:
147*7fd79137SRobert Mustacchi     case DW_DLV_ERROR:
148*7fd79137SRobert Mustacchi         /* IMPOSSIBLE : handle_debug_loc cannot return this */
149*7fd79137SRobert Mustacchi         dwarf_finish(dbg, &err);
150*7fd79137SRobert Mustacchi         *dwerr = errval;
151*7fd79137SRobert Mustacchi         return res;
152*7fd79137SRobert Mustacchi     }
153*7fd79137SRobert Mustacchi 
154*7fd79137SRobert Mustacchi 
155*7fd79137SRobert Mustacchi 
156*7fd79137SRobert Mustacchi     *dwerr = 0;
157*7fd79137SRobert Mustacchi     res = dwarf_finish(dbg, &err);
158*7fd79137SRobert Mustacchi     if (res == DW_DLV_ERROR) {
159*7fd79137SRobert Mustacchi         *dwerr = (int) dwarf_errno(err);
160*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
161*7fd79137SRobert Mustacchi     }
162*7fd79137SRobert Mustacchi     if (sections_found == 0) {
163*7fd79137SRobert Mustacchi         return DW_DLV_NO_ENTRY;
164*7fd79137SRobert Mustacchi     }
165*7fd79137SRobert Mustacchi     return DW_DLV_OK;
166*7fd79137SRobert Mustacchi 
167*7fd79137SRobert Mustacchi }
168*7fd79137SRobert Mustacchi 
169*7fd79137SRobert Mustacchi /*
170*7fd79137SRobert Mustacchi         Return DW_DLV_OK, ERROR, or NO_ENTRY.
171*7fd79137SRobert Mustacchi */
172*7fd79137SRobert Mustacchi static int
173*7fd79137SRobert Mustacchi handle_debug_info(Dwarf_Debug dbg, int *errval)
174*7fd79137SRobert Mustacchi {
175*7fd79137SRobert Mustacchi     Dwarf_Unsigned nxtoff = 1;
176*7fd79137SRobert Mustacchi     Dwarf_Unsigned hdr_length;
177*7fd79137SRobert Mustacchi     Dwarf_Half version_stamp;
178*7fd79137SRobert Mustacchi     Dwarf_Unsigned abbrev_offset;
179*7fd79137SRobert Mustacchi     Dwarf_Half addr_size;
180*7fd79137SRobert Mustacchi     Dwarf_Error err;
181*7fd79137SRobert Mustacchi     int terminate_now = 0;
182*7fd79137SRobert Mustacchi     int res = 0;
183*7fd79137SRobert Mustacchi     Dwarf_Die sibdie;
184*7fd79137SRobert Mustacchi     int sibres;
185*7fd79137SRobert Mustacchi     int nres = DW_DLV_OK;
186*7fd79137SRobert Mustacchi 
187*7fd79137SRobert Mustacchi 
188*7fd79137SRobert Mustacchi     for (nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
189*7fd79137SRobert Mustacchi                                      &abbrev_offset,
190*7fd79137SRobert Mustacchi                                      &addr_size, &nxtoff, &err);
191*7fd79137SRobert Mustacchi          terminate_now == 0 && nres == DW_DLV_OK;
192*7fd79137SRobert Mustacchi          nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
193*7fd79137SRobert Mustacchi                                      &abbrev_offset,
194*7fd79137SRobert Mustacchi                                      &addr_size, &nxtoff, &err)
195*7fd79137SRobert Mustacchi         ) {
196*7fd79137SRobert Mustacchi 
197*7fd79137SRobert Mustacchi         Dwarf_Die curdie = 0;
198*7fd79137SRobert Mustacchi 
199*7fd79137SRobert Mustacchi         /* try to get the compilation unit die */
200*7fd79137SRobert Mustacchi         sibres = dwarf_siblingof(dbg, curdie, &sibdie, &err);
201*7fd79137SRobert Mustacchi         if (sibres == DW_DLV_OK) {
202*7fd79137SRobert Mustacchi             res = do_this_die_and_dealloc(dbg, sibdie, errval);
203*7fd79137SRobert Mustacchi             switch (res) {
204*7fd79137SRobert Mustacchi             case DW_DLV_OK:
205*7fd79137SRobert Mustacchi                 break;
206*7fd79137SRobert Mustacchi             case DW_DLV_NO_ENTRY:
207*7fd79137SRobert Mustacchi                 break;
208*7fd79137SRobert Mustacchi             default:
209*7fd79137SRobert Mustacchi             case DW_DLV_ERROR:
210*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
211*7fd79137SRobert Mustacchi             }
212*7fd79137SRobert Mustacchi         } else if (sibres == DW_DLV_ERROR) {
213*7fd79137SRobert Mustacchi             *errval = (int) dwarf_errno(err);
214*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
215*7fd79137SRobert Mustacchi         } else {
216*7fd79137SRobert Mustacchi             /* NO ENTRY! */
217*7fd79137SRobert Mustacchi             /* impossible? */
218*7fd79137SRobert Mustacchi         }
219*7fd79137SRobert Mustacchi 
220*7fd79137SRobert Mustacchi     }
221*7fd79137SRobert Mustacchi     if (nres == DW_DLV_ERROR) {
222*7fd79137SRobert Mustacchi         int localerr = (int) dwarf_errno(err);
223*7fd79137SRobert Mustacchi 
224*7fd79137SRobert Mustacchi         *errval = localerr;
225*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
226*7fd79137SRobert Mustacchi     }
227*7fd79137SRobert Mustacchi     return DW_DLV_OK;
228*7fd79137SRobert Mustacchi }
229*7fd79137SRobert Mustacchi 
230*7fd79137SRobert Mustacchi static int
231*7fd79137SRobert Mustacchi   might_have_addr[] = {
232*7fd79137SRobert Mustacchi     DW_AT_high_pc,
233*7fd79137SRobert Mustacchi     DW_AT_low_pc,
234*7fd79137SRobert Mustacchi };
235*7fd79137SRobert Mustacchi static int
236*7fd79137SRobert Mustacchi   might_have_locdesc[] = {
237*7fd79137SRobert Mustacchi     DW_AT_segment,
238*7fd79137SRobert Mustacchi     DW_AT_return_addr,
239*7fd79137SRobert Mustacchi     DW_AT_frame_base,
240*7fd79137SRobert Mustacchi     DW_AT_static_link,
241*7fd79137SRobert Mustacchi     DW_AT_data_member_location,
242*7fd79137SRobert Mustacchi     DW_AT_string_length,
243*7fd79137SRobert Mustacchi     DW_AT_location,
244*7fd79137SRobert Mustacchi     DW_AT_use_location,
245*7fd79137SRobert Mustacchi     DW_AT_vtable_elem_location,
246*7fd79137SRobert Mustacchi };
247*7fd79137SRobert Mustacchi 
248*7fd79137SRobert Mustacchi /*
249*7fd79137SRobert Mustacchi         Return DW_DLV_OK if handling this went ok.
250*7fd79137SRobert Mustacchi */
251*7fd79137SRobert Mustacchi static int
252*7fd79137SRobert Mustacchi handle_attr_addr(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum,
253*7fd79137SRobert Mustacchi                  Dwarf_Error * perr)
254*7fd79137SRobert Mustacchi {
255*7fd79137SRobert Mustacchi     int res = DW_DLV_OK;
256*7fd79137SRobert Mustacchi     Dwarf_Off offset;
257*7fd79137SRobert Mustacchi     Dwarf_Addr addr;
258*7fd79137SRobert Mustacchi     Dwarf_Half form;
259*7fd79137SRobert Mustacchi     int ares;
260*7fd79137SRobert Mustacchi 
261*7fd79137SRobert Mustacchi     Dwarf_Attribute attr;
262*7fd79137SRobert Mustacchi 
263*7fd79137SRobert Mustacchi     ares = dwarf_attr(die, attrnum, &attr, perr);
264*7fd79137SRobert Mustacchi     if (ares == DW_DLV_OK) {
265*7fd79137SRobert Mustacchi         int formres = dwarf_whatform(attr, &form, perr);
266*7fd79137SRobert Mustacchi 
267*7fd79137SRobert Mustacchi         switch (formres) {
268*7fd79137SRobert Mustacchi         case DW_DLV_OK:
269*7fd79137SRobert Mustacchi             break;
270*7fd79137SRobert Mustacchi         case DW_DLV_ERROR:
271*7fd79137SRobert Mustacchi         case DW_DLV_NO_ENTRY:   /* impossible. */
272*7fd79137SRobert Mustacchi             return formres;
273*7fd79137SRobert Mustacchi 
274*7fd79137SRobert Mustacchi         }
275*7fd79137SRobert Mustacchi 
276*7fd79137SRobert Mustacchi         switch (form) {
277*7fd79137SRobert Mustacchi         case DW_FORM_ref_addr:
278*7fd79137SRobert Mustacchi         case DW_FORM_addr:
279*7fd79137SRobert Mustacchi             res = dwarf_attr_offset(die, attr, &offset, perr);
280*7fd79137SRobert Mustacchi             if (res == DW_DLV_OK) {
281*7fd79137SRobert Mustacchi                 ares = dwarf_formaddr(attr, &addr, perr);
282*7fd79137SRobert Mustacchi                 if (ares == DW_DLV_OK) {
283*7fd79137SRobert Mustacchi                     send_addr_note(DW_SECTION_INFO, offset, addr);
284*7fd79137SRobert Mustacchi                 } else if (ares == DW_DLV_ERROR) {
285*7fd79137SRobert Mustacchi                     return ares;
286*7fd79137SRobert Mustacchi                 }               /* no entry: ok. */
287*7fd79137SRobert Mustacchi             } else {
288*7fd79137SRobert Mustacchi                 res = DW_DLV_ERROR;     /* NO_ENTRY is impossible. */
289*7fd79137SRobert Mustacchi             }
290*7fd79137SRobert Mustacchi             break;
291*7fd79137SRobert Mustacchi 
292*7fd79137SRobert Mustacchi         default:
293*7fd79137SRobert Mustacchi             /* surprising! An error? */
294*7fd79137SRobert Mustacchi 
295*7fd79137SRobert Mustacchi             ;                   /* do nothing */
296*7fd79137SRobert Mustacchi         }
297*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
298*7fd79137SRobert Mustacchi 
299*7fd79137SRobert Mustacchi     } else {
300*7fd79137SRobert Mustacchi         res = ares;
301*7fd79137SRobert Mustacchi     }
302*7fd79137SRobert Mustacchi     return res;
303*7fd79137SRobert Mustacchi }
304*7fd79137SRobert Mustacchi 
305*7fd79137SRobert Mustacchi /*
306*7fd79137SRobert Mustacchi         Return DW_DLV_OK if handling this went ok.
307*7fd79137SRobert Mustacchi */
308*7fd79137SRobert Mustacchi static int
309*7fd79137SRobert Mustacchi handle_attr_locdesc(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum,
310*7fd79137SRobert Mustacchi                     Dwarf_Error * perr)
311*7fd79137SRobert Mustacchi {
312*7fd79137SRobert Mustacchi     int retval = DW_DLV_OK;
313*7fd79137SRobert Mustacchi     Dwarf_Attribute attr;
314*7fd79137SRobert Mustacchi     Dwarf_Locdesc *llbuf;
315*7fd79137SRobert Mustacchi     Dwarf_Signed i;
316*7fd79137SRobert Mustacchi     Dwarf_Off offset;
317*7fd79137SRobert Mustacchi     Dwarf_Loc *locp;
318*7fd79137SRobert Mustacchi     unsigned int entindx;
319*7fd79137SRobert Mustacchi     int res;
320*7fd79137SRobert Mustacchi     int ares;
321*7fd79137SRobert Mustacchi 
322*7fd79137SRobert Mustacchi 
323*7fd79137SRobert Mustacchi     ares = dwarf_attr(die, attrnum, &attr, perr);
324*7fd79137SRobert Mustacchi     if (ares == DW_DLV_OK) {
325*7fd79137SRobert Mustacchi         Dwarf_Half form;
326*7fd79137SRobert Mustacchi         int fres = dwarf_whatform(attr, &form, perr);
327*7fd79137SRobert Mustacchi 
328*7fd79137SRobert Mustacchi         if (fres == DW_DLV_OK) {
329*7fd79137SRobert Mustacchi             switch (form) {
330*7fd79137SRobert Mustacchi             case DW_FORM_block1:
331*7fd79137SRobert Mustacchi             case DW_FORM_block2:
332*7fd79137SRobert Mustacchi             case DW_FORM_block4:
333*7fd79137SRobert Mustacchi                 /* must be location description */
334*7fd79137SRobert Mustacchi                 res = dwarf_attr_offset(die, attr, &offset, perr);
335*7fd79137SRobert Mustacchi                 llbuf = 0;
336*7fd79137SRobert Mustacchi                 if (res == DW_DLV_OK) {
337*7fd79137SRobert Mustacchi                     Dwarf_Signed count;
338*7fd79137SRobert Mustacchi                     int lres = dwarf_loclist(attr, &llbuf, &count, perr);
339*7fd79137SRobert Mustacchi                     if (lres != DW_DLV_OK) {
340*7fd79137SRobert Mustacchi                         return lres;
341*7fd79137SRobert Mustacchi                     }
342*7fd79137SRobert Mustacchi                     if (count != 1) {
343*7fd79137SRobert Mustacchi                         /* this cannot happen! */
344*7fd79137SRobert Mustacchi                         /* perr? */
345*7fd79137SRobert Mustacchi                         _dwarf_error(dbg, perr,
346*7fd79137SRobert Mustacchi                                      DW_DLE_LOCDESC_COUNT_WRONG);
347*7fd79137SRobert Mustacchi                         retval = DW_DLV_ERROR;
348*7fd79137SRobert Mustacchi                         return retval;
349*7fd79137SRobert Mustacchi                     }
350*7fd79137SRobert Mustacchi                     for (i = 0; i < count; ++i) {
351*7fd79137SRobert Mustacchi                         unsigned int ents = llbuf[i].ld_cents;
352*7fd79137SRobert Mustacchi 
353*7fd79137SRobert Mustacchi                         locp = llbuf[i].ld_s;
354*7fd79137SRobert Mustacchi                         for (entindx = 0; entindx < ents; entindx++) {
355*7fd79137SRobert Mustacchi                             Dwarf_Loc *llocp;
356*7fd79137SRobert Mustacchi 
357*7fd79137SRobert Mustacchi                             llocp = locp + entindx;
358*7fd79137SRobert Mustacchi                             if (llocp->lr_atom == DW_OP_addr) {
359*7fd79137SRobert Mustacchi                                 send_addr_note(DW_SECTION_INFO, offset +
360*7fd79137SRobert Mustacchi                                                llocp->lr_offset + 1
361*7fd79137SRobert Mustacchi                                                /* The offset is the
362*7fd79137SRobert Mustacchi                                                   offset of the atom,
363*7fd79137SRobert Mustacchi                                                   ** and we know the
364*7fd79137SRobert Mustacchi                                                   addr is 1 past it. */
365*7fd79137SRobert Mustacchi                                                , llocp->lr_number);
366*7fd79137SRobert Mustacchi                             }
367*7fd79137SRobert Mustacchi                         }
368*7fd79137SRobert Mustacchi                     }
369*7fd79137SRobert Mustacchi 
370*7fd79137SRobert Mustacchi 
371*7fd79137SRobert Mustacchi                     if (count > 0) {
372*7fd79137SRobert Mustacchi                         for (i = 0; i < count; ++i) {
373*7fd79137SRobert Mustacchi                             dwarf_dealloc(dbg, llbuf[i].ld_s,
374*7fd79137SRobert Mustacchi                                           DW_DLA_LOC_BLOCK);
375*7fd79137SRobert Mustacchi                         }
376*7fd79137SRobert Mustacchi                         dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
377*7fd79137SRobert Mustacchi                     }
378*7fd79137SRobert Mustacchi                 } else {
379*7fd79137SRobert Mustacchi                     retval = res;
380*7fd79137SRobert Mustacchi                 }
381*7fd79137SRobert Mustacchi                 break;
382*7fd79137SRobert Mustacchi 
383*7fd79137SRobert Mustacchi             default:
384*7fd79137SRobert Mustacchi                 /* must be a const offset in debug_loc */
385*7fd79137SRobert Mustacchi                 ;               /* do nothing */
386*7fd79137SRobert Mustacchi             }
387*7fd79137SRobert Mustacchi             dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
388*7fd79137SRobert Mustacchi         }                       /* else error or no entry */
389*7fd79137SRobert Mustacchi         retval = fres;
390*7fd79137SRobert Mustacchi     } else {
391*7fd79137SRobert Mustacchi         retval = ares;
392*7fd79137SRobert Mustacchi     }
393*7fd79137SRobert Mustacchi     return retval;
394*7fd79137SRobert Mustacchi }
395*7fd79137SRobert Mustacchi 
396*7fd79137SRobert Mustacchi /*
397*7fd79137SRobert Mustacchi   Return DW_DLV_OK, or DW_DLV_ERROR
398*7fd79137SRobert Mustacchi 
399*7fd79137SRobert Mustacchi   Handle the addrs in a single die.
400*7fd79137SRobert Mustacchi */
401*7fd79137SRobert Mustacchi static int
402*7fd79137SRobert Mustacchi process_this_die_attrs(Dwarf_Debug dbg, Dwarf_Die newdie, int *errval)
403*7fd79137SRobert Mustacchi {
404*7fd79137SRobert Mustacchi     Dwarf_Error err;
405*7fd79137SRobert Mustacchi     Dwarf_Half i;
406*7fd79137SRobert Mustacchi     Dwarf_Half newattrnum;
407*7fd79137SRobert Mustacchi     int res;
408*7fd79137SRobert Mustacchi     int tres;
409*7fd79137SRobert Mustacchi     Dwarf_Half ltag;
410*7fd79137SRobert Mustacchi 
411*7fd79137SRobert Mustacchi     Dwarf_Off doff;
412*7fd79137SRobert Mustacchi     int doffres = dwarf_dieoffset(newdie, &doff, &err);
413*7fd79137SRobert Mustacchi 
414*7fd79137SRobert Mustacchi     if (doffres != DW_DLV_OK) {
415*7fd79137SRobert Mustacchi         if (doffres == DW_DLV_ERROR) {
416*7fd79137SRobert Mustacchi             *errval = (int) dwarf_errno(err);
417*7fd79137SRobert Mustacchi         }
418*7fd79137SRobert Mustacchi         return doffres;
419*7fd79137SRobert Mustacchi     }
420*7fd79137SRobert Mustacchi     tres = dwarf_tag(newdie, &ltag, &err);
421*7fd79137SRobert Mustacchi     if (tres != DW_DLV_OK) {
422*7fd79137SRobert Mustacchi         return tres;
423*7fd79137SRobert Mustacchi     }
424*7fd79137SRobert Mustacchi     if (DW_TAG_compile_unit == ltag) {
425*7fd79137SRobert Mustacchi         /* because of the way the dwarf_line code works, we do lines
426*7fd79137SRobert Mustacchi            only per compile unit. This may turn out to be wrong if
427*7fd79137SRobert Mustacchi            we have lines left unconnected to a CU. of course such
428*7fd79137SRobert Mustacchi            lines will not, at present, be used by gnome. This is
429*7fd79137SRobert Mustacchi            not ideal as coded due to the dwarf_line.c issue. */
430*7fd79137SRobert Mustacchi         int lres = handle_debug_line(dbg, newdie, send_addr_note, errval);
431*7fd79137SRobert Mustacchi         if (lres == DW_DLV_ERROR) {
432*7fd79137SRobert Mustacchi             return lres;
433*7fd79137SRobert Mustacchi         }
434*7fd79137SRobert Mustacchi     }
435*7fd79137SRobert Mustacchi 
436*7fd79137SRobert Mustacchi     for (i = 0; i < sizeof(might_have_addr) / sizeof(int); i++) {
437*7fd79137SRobert Mustacchi         int resattr;
438*7fd79137SRobert Mustacchi         Dwarf_Bool hasattr;
439*7fd79137SRobert Mustacchi 
440*7fd79137SRobert Mustacchi         newattrnum = might_have_addr[i];
441*7fd79137SRobert Mustacchi         err = 0;
442*7fd79137SRobert Mustacchi         resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
443*7fd79137SRobert Mustacchi         if (DW_DLV_OK == resattr) {
444*7fd79137SRobert Mustacchi             if (hasattr) {
445*7fd79137SRobert Mustacchi                 res = handle_attr_addr(dbg, newdie, newattrnum, &err);
446*7fd79137SRobert Mustacchi                 if (res != DW_DLV_OK) {
447*7fd79137SRobert Mustacchi                     *errval = (int) dwarf_errno(err);
448*7fd79137SRobert Mustacchi                     return DW_DLV_ERROR;
449*7fd79137SRobert Mustacchi                 }
450*7fd79137SRobert Mustacchi             }
451*7fd79137SRobert Mustacchi         } else {
452*7fd79137SRobert Mustacchi             if (resattr == DW_DLV_ERROR) {
453*7fd79137SRobert Mustacchi                 *errval = (int) dwarf_errno(err);
454*7fd79137SRobert Mustacchi                 return resattr;
455*7fd79137SRobert Mustacchi             }
456*7fd79137SRobert Mustacchi         }
457*7fd79137SRobert Mustacchi     }
458*7fd79137SRobert Mustacchi     for (i = 0; i < sizeof(might_have_locdesc) / sizeof(int); i++) {
459*7fd79137SRobert Mustacchi         int resattr;
460*7fd79137SRobert Mustacchi         Dwarf_Bool hasattr;
461*7fd79137SRobert Mustacchi 
462*7fd79137SRobert Mustacchi         newattrnum = might_have_locdesc[i];
463*7fd79137SRobert Mustacchi         err = 0;
464*7fd79137SRobert Mustacchi         resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
465*7fd79137SRobert Mustacchi         if (DW_DLV_OK == resattr) {
466*7fd79137SRobert Mustacchi             if (hasattr) {
467*7fd79137SRobert Mustacchi                 res =
468*7fd79137SRobert Mustacchi                     handle_attr_locdesc(dbg, newdie, newattrnum, &err);
469*7fd79137SRobert Mustacchi                 if (res != DW_DLV_OK) {
470*7fd79137SRobert Mustacchi                     *errval = (int) dwarf_errno(err);
471*7fd79137SRobert Mustacchi                     return DW_DLV_ERROR;
472*7fd79137SRobert Mustacchi                 }
473*7fd79137SRobert Mustacchi             }
474*7fd79137SRobert Mustacchi         } else {
475*7fd79137SRobert Mustacchi             if (resattr == DW_DLV_ERROR) {
476*7fd79137SRobert Mustacchi                 *errval = (int) dwarf_errno(err);
477*7fd79137SRobert Mustacchi                 return resattr;
478*7fd79137SRobert Mustacchi             }
479*7fd79137SRobert Mustacchi         }
480*7fd79137SRobert Mustacchi     }
481*7fd79137SRobert Mustacchi 
482*7fd79137SRobert Mustacchi     return DW_DLV_OK;
483*7fd79137SRobert Mustacchi }
484*7fd79137SRobert Mustacchi 
485*7fd79137SRobert Mustacchi /*
486*7fd79137SRobert Mustacchi         Handle siblings as a list,
487*7fd79137SRobert Mustacchi         Do children by recursing.
488*7fd79137SRobert Mustacchi         Effectively this is walking the tree preorder.
489*7fd79137SRobert Mustacchi 
490*7fd79137SRobert Mustacchi         This dealloc's any die passed to it, so the
491*7fd79137SRobert Mustacchi         caller should not do that dealloc.
492*7fd79137SRobert Mustacchi         It seems more logical to have the one causing
493*7fd79137SRobert Mustacchi         the alloc to do the dealloc, but that way this
494*7fd79137SRobert Mustacchi         routine became a mess.
495*7fd79137SRobert Mustacchi 
496*7fd79137SRobert Mustacchi */
497*7fd79137SRobert Mustacchi static int
498*7fd79137SRobert Mustacchi do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, int *errval)
499*7fd79137SRobert Mustacchi {
500*7fd79137SRobert Mustacchi 
501*7fd79137SRobert Mustacchi     Dwarf_Die prevdie = 0;
502*7fd79137SRobert Mustacchi     Dwarf_Die newdie = die;
503*7fd79137SRobert Mustacchi     Dwarf_Error err = 0;
504*7fd79137SRobert Mustacchi     int res = 0;
505*7fd79137SRobert Mustacchi     int sibres = DW_DLV_OK;
506*7fd79137SRobert Mustacchi     int tres = DW_DLV_OK;
507*7fd79137SRobert Mustacchi     Dwarf_Die sibdie;
508*7fd79137SRobert Mustacchi 
509*7fd79137SRobert Mustacchi     while (sibres == DW_DLV_OK) {
510*7fd79137SRobert Mustacchi         Dwarf_Die ch_die;
511*7fd79137SRobert Mustacchi 
512*7fd79137SRobert Mustacchi 
513*7fd79137SRobert Mustacchi         res = process_this_die_attrs(dbg, newdie, errval);
514*7fd79137SRobert Mustacchi         switch (res) {
515*7fd79137SRobert Mustacchi         case DW_DLV_OK:
516*7fd79137SRobert Mustacchi             break;
517*7fd79137SRobert Mustacchi         case DW_DLV_NO_ENTRY:
518*7fd79137SRobert Mustacchi             break;
519*7fd79137SRobert Mustacchi         default:
520*7fd79137SRobert Mustacchi         case DW_DLV_ERROR:
521*7fd79137SRobert Mustacchi             if (prevdie) {
522*7fd79137SRobert Mustacchi                 dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
523*7fd79137SRobert Mustacchi                 prevdie = 0;
524*7fd79137SRobert Mustacchi             }
525*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
526*7fd79137SRobert Mustacchi         }
527*7fd79137SRobert Mustacchi 
528*7fd79137SRobert Mustacchi         tres = dwarf_child(newdie, &ch_die, &err);
529*7fd79137SRobert Mustacchi 
530*7fd79137SRobert Mustacchi         if (tres == DW_DLV_OK) {
531*7fd79137SRobert Mustacchi             res = do_this_die_and_dealloc(dbg, ch_die, errval);
532*7fd79137SRobert Mustacchi             switch (res) {
533*7fd79137SRobert Mustacchi             case DW_DLV_OK:
534*7fd79137SRobert Mustacchi                 break;
535*7fd79137SRobert Mustacchi             case DW_DLV_NO_ENTRY:
536*7fd79137SRobert Mustacchi                 break;
537*7fd79137SRobert Mustacchi             default:
538*7fd79137SRobert Mustacchi             case DW_DLV_ERROR:
539*7fd79137SRobert Mustacchi                 if (prevdie) {
540*7fd79137SRobert Mustacchi                     dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
541*7fd79137SRobert Mustacchi                     prevdie = 0;
542*7fd79137SRobert Mustacchi                 }
543*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
544*7fd79137SRobert Mustacchi             }
545*7fd79137SRobert Mustacchi         } else if (tres == DW_DLV_ERROR) {
546*7fd79137SRobert Mustacchi             /* An error! */
547*7fd79137SRobert Mustacchi             *errval = (int) dwarf_errno(err);
548*7fd79137SRobert Mustacchi             if (prevdie) {
549*7fd79137SRobert Mustacchi                 dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
550*7fd79137SRobert Mustacchi                 prevdie = 0;
551*7fd79137SRobert Mustacchi             }
552*7fd79137SRobert Mustacchi             dwarf_dealloc(dbg, err, DW_DLA_ERROR);
553*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
554*7fd79137SRobert Mustacchi         }                       /* else was NO ENTRY */
555*7fd79137SRobert Mustacchi         prevdie = newdie;
556*7fd79137SRobert Mustacchi         sibdie = 0;
557*7fd79137SRobert Mustacchi         sibres = dwarf_siblingof(dbg, newdie, &sibdie, &err);
558*7fd79137SRobert Mustacchi         if (prevdie) {
559*7fd79137SRobert Mustacchi             dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
560*7fd79137SRobert Mustacchi             prevdie = 0;
561*7fd79137SRobert Mustacchi         }
562*7fd79137SRobert Mustacchi         newdie = sibdie;
563*7fd79137SRobert Mustacchi 
564*7fd79137SRobert Mustacchi     }
565*7fd79137SRobert Mustacchi     if (sibres == DW_DLV_NO_ENTRY) {
566*7fd79137SRobert Mustacchi         return DW_DLV_OK;
567*7fd79137SRobert Mustacchi     }
568*7fd79137SRobert Mustacchi     /* error. */
569*7fd79137SRobert Mustacchi     *errval = (int) dwarf_errno(err);
570*7fd79137SRobert Mustacchi     if (prevdie) {
571*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
572*7fd79137SRobert Mustacchi         prevdie = 0;
573*7fd79137SRobert Mustacchi     }
574*7fd79137SRobert Mustacchi     dwarf_dealloc(dbg, err, DW_DLA_ERROR);
575*7fd79137SRobert Mustacchi     return DW_DLV_ERROR;
576*7fd79137SRobert Mustacchi 
577*7fd79137SRobert Mustacchi }
578*7fd79137SRobert Mustacchi 
579*7fd79137SRobert Mustacchi 
580*7fd79137SRobert Mustacchi static int
581*7fd79137SRobert Mustacchi handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
582*7fd79137SRobert Mustacchi                    int *errval)
583*7fd79137SRobert Mustacchi {
584*7fd79137SRobert Mustacchi     int retval = DW_DLV_OK;
585*7fd79137SRobert Mustacchi     int res;
586*7fd79137SRobert Mustacchi     Dwarf_Error err;
587*7fd79137SRobert Mustacchi     Dwarf_Addr *addrlist;
588*7fd79137SRobert Mustacchi     Dwarf_Off *offsetlist;
589*7fd79137SRobert Mustacchi     Dwarf_Signed count;
590*7fd79137SRobert Mustacchi     int i;
591*7fd79137SRobert Mustacchi 
592*7fd79137SRobert Mustacchi     res =
593*7fd79137SRobert Mustacchi         _dwarf_frame_address_offsets(dbg, &addrlist, &offsetlist,
594*7fd79137SRobert Mustacchi                                      &count, &err);
595*7fd79137SRobert Mustacchi     if (res == DW_DLV_OK) {
596*7fd79137SRobert Mustacchi         for (i = 0; i < count; i++) {
597*7fd79137SRobert Mustacchi             cb_func(DW_SECTION_FRAME, offsetlist[i], addrlist[i]);
598*7fd79137SRobert Mustacchi         }
599*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
600*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
601*7fd79137SRobert Mustacchi     } else if (res == DW_DLV_NO_ENTRY) {
602*7fd79137SRobert Mustacchi         retval = res;
603*7fd79137SRobert Mustacchi     } else {
604*7fd79137SRobert Mustacchi         *errval = (int) dwarf_errno(err);
605*7fd79137SRobert Mustacchi         retval = DW_DLV_ERROR;
606*7fd79137SRobert Mustacchi     }
607*7fd79137SRobert Mustacchi     return retval;
608*7fd79137SRobert Mustacchi 
609*7fd79137SRobert Mustacchi }
610*7fd79137SRobert Mustacchi static int
611*7fd79137SRobert Mustacchi handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
612*7fd79137SRobert Mustacchi                      int *errval)
613*7fd79137SRobert Mustacchi {
614*7fd79137SRobert Mustacchi     int retval = DW_DLV_OK;
615*7fd79137SRobert Mustacchi     Dwarf_Error err;
616*7fd79137SRobert Mustacchi     Dwarf_Addr *aranges;
617*7fd79137SRobert Mustacchi     Dwarf_Signed count;
618*7fd79137SRobert Mustacchi     int indx;
619*7fd79137SRobert Mustacchi     Dwarf_Off *offsets;
620*7fd79137SRobert Mustacchi 
621*7fd79137SRobert Mustacchi     retval =
622*7fd79137SRobert Mustacchi         _dwarf_get_aranges_addr_offsets(dbg, &aranges, &offsets, &count,
623*7fd79137SRobert Mustacchi                                         &err);
624*7fd79137SRobert Mustacchi     if (retval == DW_DLV_OK) {
625*7fd79137SRobert Mustacchi         if (count == 0) {
626*7fd79137SRobert Mustacchi             retval = DW_DLV_NO_ENTRY;
627*7fd79137SRobert Mustacchi         } else {
628*7fd79137SRobert Mustacchi             for (indx = 0; indx < count; indx++) {
629*7fd79137SRobert Mustacchi                 cb_func(DW_SECTION_ARANGES, offsets[indx],
630*7fd79137SRobert Mustacchi                         aranges[indx]);
631*7fd79137SRobert Mustacchi             }
632*7fd79137SRobert Mustacchi         }
633*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, aranges, DW_DLA_ADDR);
634*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, offsets, DW_DLA_ADDR);
635*7fd79137SRobert Mustacchi     } else if (retval == DW_DLV_NO_ENTRY) {
636*7fd79137SRobert Mustacchi         ;                       /* do nothing */
637*7fd79137SRobert Mustacchi     } else {
638*7fd79137SRobert Mustacchi         *errval = (int) dwarf_errno(err);
639*7fd79137SRobert Mustacchi         retval = DW_DLV_ERROR;
640*7fd79137SRobert Mustacchi     }
641*7fd79137SRobert Mustacchi     return retval;
642*7fd79137SRobert Mustacchi }
643*7fd79137SRobert Mustacchi static int
644*7fd79137SRobert Mustacchi handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die,
645*7fd79137SRobert Mustacchi                   Dwarf_addr_callback_func cb_func, int *errval)
646*7fd79137SRobert Mustacchi {
647*7fd79137SRobert Mustacchi     int retval = DW_DLV_OK;
648*7fd79137SRobert Mustacchi     int res;
649*7fd79137SRobert Mustacchi     Dwarf_Error err;
650*7fd79137SRobert Mustacchi     Dwarf_Addr *addrlist;
651*7fd79137SRobert Mustacchi     Dwarf_Off *offsetlist;
652*7fd79137SRobert Mustacchi     Dwarf_Unsigned count;
653*7fd79137SRobert Mustacchi     Dwarf_Unsigned i;
654*7fd79137SRobert Mustacchi 
655*7fd79137SRobert Mustacchi     res =
656*7fd79137SRobert Mustacchi         _dwarf_line_address_offsets(dbg, cu_die, &addrlist, &offsetlist,
657*7fd79137SRobert Mustacchi                                     &count, &err);
658*7fd79137SRobert Mustacchi     if (res == DW_DLV_OK) {
659*7fd79137SRobert Mustacchi         for (i = 0; i < count; i++) {
660*7fd79137SRobert Mustacchi             cb_func(DW_SECTION_LINE, offsetlist[i], addrlist[i]);
661*7fd79137SRobert Mustacchi 
662*7fd79137SRobert Mustacchi         }
663*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
664*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
665*7fd79137SRobert Mustacchi     } else if (res == DW_DLV_NO_ENTRY) {
666*7fd79137SRobert Mustacchi         retval = res;
667*7fd79137SRobert Mustacchi     } else {
668*7fd79137SRobert Mustacchi         *errval = (int) dwarf_errno(err);
669*7fd79137SRobert Mustacchi         retval = DW_DLV_ERROR;
670*7fd79137SRobert Mustacchi     }
671*7fd79137SRobert Mustacchi     return retval;
672*7fd79137SRobert Mustacchi }
673*7fd79137SRobert Mustacchi 
674*7fd79137SRobert Mustacchi /*
675*7fd79137SRobert Mustacchi         We need to add support for this. Currently we do not
676*7fd79137SRobert Mustacchi         generate this section.
677*7fd79137SRobert Mustacchi         FIX!
678*7fd79137SRobert Mustacchi */
679*7fd79137SRobert Mustacchi static int
680*7fd79137SRobert Mustacchi handle_debug_loc(void)
681*7fd79137SRobert Mustacchi {
682*7fd79137SRobert Mustacchi     int retval = DW_DLV_NO_ENTRY;
683*7fd79137SRobert Mustacchi 
684*7fd79137SRobert Mustacchi     return retval;
685*7fd79137SRobert Mustacchi }
686