3 Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2.1 of the GNU Lesser General Public License
7 as published by the Free Software Foundation.
9 This program is distributed in the hope that it would be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 Further, this software is distributed without any warranty that it is
14 free of the rightful claim of any third person regarding infringement
15 or the like. Any license provided herein, whether implied or
16 otherwise, applies only to this software file. Patent licenses, if
17 any, provided herein do not apply to combinations of this program with
18 other software, or any other product whatsoever.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this program; if not, write the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
25 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
26 Mountain View, CA 94043, or:
30 For further information regarding this notice, see:
32 http://oss.sgi.com/projects/GenInfo/NoticeExplan
35 /* This code used by SGI-IRIX rqs processing, not needed by
36 any other system or application.
40 #include "libdwarfdefs.h"
46 #include "dwarf_base_types.h"
47 #include "dwarf_alloc.h"
48 #include "dwarf_opaque.h"
49 #include "dwarf_arange.h"
50 #include "dwarf_line.h"
51 #include "dwarf_frame.h"
52 #include <cmplrs/dwarf_addr_finder.h>
53 #include "dwarf_error.h"
55 typedef unsigned long long ull
;
57 static int do_this_die_and_dealloc(Dwarf_Debug dbg
, Dwarf_Die die
,
60 handle_debug_info(Dwarf_Debug dbg
, int *errval
);
62 handle_debug_frame(Dwarf_Debug dbg
, Dwarf_addr_callback_func cb_func
, int *errval
);
64 handle_debug_aranges(Dwarf_Debug dbg
, Dwarf_addr_callback_func cb_func
, int *errval
);
66 handle_debug_line(Dwarf_Debug dbg
, Dwarf_Die cu_die
, Dwarf_addr_callback_func cb_func
, int *errval
);
68 handle_debug_loc(void);
71 static Dwarf_addr_callback_func send_addr_note
;
74 _dwarf_addr_finder(dwarf_elf_handle elf_file_ptr
,
75 Dwarf_addr_callback_func cb_func
, int *dwerr
)
82 int sections_found
= 0;
84 res
= dwarf_elf_init(elf_file_ptr
, DW_DLC_READ
, /* errhand */ 0,
85 /* errarg */ 0, &dbg
, &err
);
86 if (res
== DW_DLV_ERROR
) {
87 int errv
= (int) dwarf_errno(err
);
91 if (res
== DW_DLV_NO_ENTRY
) {
95 send_addr_note
= cb_func
;
97 res
= handle_debug_info(dbg
, &errval
);
102 case DW_DLV_NO_ENTRY
:
107 dwarf_finish(dbg
, &err
);
112 res
= handle_debug_aranges(dbg
, cb_func
, &errval
);
117 case DW_DLV_NO_ENTRY
:
121 dwarf_finish(dbg
, &err
);
125 res
= handle_debug_frame(dbg
, cb_func
, &errval
);
130 case DW_DLV_NO_ENTRY
:
134 dwarf_finish(dbg
, &err
);
139 res
= handle_debug_loc(); /* does nothing */
144 case DW_DLV_NO_ENTRY
:
148 /* IMPOSSIBLE : handle_debug_loc cannot return this */
149 dwarf_finish(dbg
, &err
);
157 res
= dwarf_finish(dbg
, &err
);
158 if (res
== DW_DLV_ERROR
) {
159 *dwerr
= (int) dwarf_errno(err
);
162 if (sections_found
== 0) {
163 return DW_DLV_NO_ENTRY
;
170 Return DW_DLV_OK, ERROR, or NO_ENTRY.
173 handle_debug_info(Dwarf_Debug dbg
, int *errval
)
175 Dwarf_Unsigned nxtoff
= 1;
176 Dwarf_Unsigned hdr_length
;
177 Dwarf_Half version_stamp
;
178 Dwarf_Unsigned abbrev_offset
;
179 Dwarf_Half addr_size
;
181 int terminate_now
= 0;
185 int nres
= DW_DLV_OK
;
188 for (nres
= dwarf_next_cu_header(dbg
, &hdr_length
, &version_stamp
,
190 &addr_size
, &nxtoff
, &err
);
191 terminate_now
== 0 && nres
== DW_DLV_OK
;
192 nres
= dwarf_next_cu_header(dbg
, &hdr_length
, &version_stamp
,
194 &addr_size
, &nxtoff
, &err
)
197 Dwarf_Die curdie
= 0;
199 /* try to get the compilation unit die */
200 sibres
= dwarf_siblingof(dbg
, curdie
, &sibdie
, &err
);
201 if (sibres
== DW_DLV_OK
) {
202 res
= do_this_die_and_dealloc(dbg
, sibdie
, errval
);
206 case DW_DLV_NO_ENTRY
:
212 } else if (sibres
== DW_DLV_ERROR
) {
213 *errval
= (int) dwarf_errno(err
);
221 if (nres
== DW_DLV_ERROR
) {
222 int localerr
= (int) dwarf_errno(err
);
231 might_have_addr
[] = {
236 might_have_locdesc
[] = {
241 DW_AT_data_member_location
,
245 DW_AT_vtable_elem_location
,
249 Return DW_DLV_OK if handling this went ok.
252 handle_attr_addr(Dwarf_Debug dbg
, Dwarf_Die die
, Dwarf_Half attrnum
,
261 Dwarf_Attribute attr
;
263 ares
= dwarf_attr(die
, attrnum
, &attr
, perr
);
264 if (ares
== DW_DLV_OK
) {
265 int formres
= dwarf_whatform(attr
, &form
, perr
);
271 case DW_DLV_NO_ENTRY
: /* impossible. */
277 case DW_FORM_ref_addr
:
279 res
= dwarf_attr_offset(die
, attr
, &offset
, perr
);
280 if (res
== DW_DLV_OK
) {
281 ares
= dwarf_formaddr(attr
, &addr
, perr
);
282 if (ares
== DW_DLV_OK
) {
283 send_addr_note(DW_SECTION_INFO
, offset
, addr
);
284 } else if (ares
== DW_DLV_ERROR
) {
286 } /* no entry: ok. */
288 res
= DW_DLV_ERROR
; /* NO_ENTRY is impossible. */
293 /* surprising! An error? */
297 dwarf_dealloc(dbg
, attr
, DW_DLA_ATTR
);
306 Return DW_DLV_OK if handling this went ok.
309 handle_attr_locdesc(Dwarf_Debug dbg
, Dwarf_Die die
, Dwarf_Half attrnum
,
312 int retval
= DW_DLV_OK
;
313 Dwarf_Attribute attr
;
314 Dwarf_Locdesc
*llbuf
;
318 unsigned int entindx
;
323 ares
= dwarf_attr(die
, attrnum
, &attr
, perr
);
324 if (ares
== DW_DLV_OK
) {
326 int fres
= dwarf_whatform(attr
, &form
, perr
);
328 if (fres
== DW_DLV_OK
) {
333 /* must be location description */
334 res
= dwarf_attr_offset(die
, attr
, &offset
, perr
);
336 if (res
== DW_DLV_OK
) {
338 int lres
= dwarf_loclist(attr
, &llbuf
, &count
, perr
);
339 if (lres
!= DW_DLV_OK
) {
343 /* this cannot happen! */
345 _dwarf_error(dbg
, perr
,
346 DW_DLE_LOCDESC_COUNT_WRONG
);
347 retval
= DW_DLV_ERROR
;
350 for (i
= 0; i
< count
; ++i
) {
351 unsigned int ents
= llbuf
[i
].ld_cents
;
353 locp
= llbuf
[i
].ld_s
;
354 for (entindx
= 0; entindx
< ents
; entindx
++) {
357 llocp
= locp
+ entindx
;
358 if (llocp
->lr_atom
== DW_OP_addr
) {
359 send_addr_note(DW_SECTION_INFO
, offset
+
364 addr is 1 past it. */
372 for (i
= 0; i
< count
; ++i
) {
373 dwarf_dealloc(dbg
, llbuf
[i
].ld_s
,
376 dwarf_dealloc(dbg
, llbuf
, DW_DLA_LOCDESC
);
384 /* must be a const offset in debug_loc */
387 dwarf_dealloc(dbg
, attr
, DW_DLA_ATTR
);
388 } /* else error or no entry */
397 Return DW_DLV_OK, or DW_DLV_ERROR
399 Handle the addrs in a single die.
402 process_this_die_attrs(Dwarf_Debug dbg
, Dwarf_Die newdie
, int *errval
)
406 Dwarf_Half newattrnum
;
412 int doffres
= dwarf_dieoffset(newdie
, &doff
, &err
);
414 if (doffres
!= DW_DLV_OK
) {
415 if (doffres
== DW_DLV_ERROR
) {
416 *errval
= (int) dwarf_errno(err
);
420 tres
= dwarf_tag(newdie
, <ag
, &err
);
421 if (tres
!= DW_DLV_OK
) {
424 if (DW_TAG_compile_unit
== ltag
) {
425 /* because of the way the dwarf_line code works, we do lines
426 only per compile unit. This may turn out to be wrong if
427 we have lines left unconnected to a CU. of course such
428 lines will not, at present, be used by gnome. This is
429 not ideal as coded due to the dwarf_line.c issue. */
430 int lres
= handle_debug_line(dbg
, newdie
, send_addr_note
, errval
);
431 if (lres
== DW_DLV_ERROR
) {
436 for (i
= 0; i
< sizeof(might_have_addr
) / sizeof(int); i
++) {
440 newattrnum
= might_have_addr
[i
];
442 resattr
= dwarf_hasattr(newdie
, newattrnum
, &hasattr
, &err
);
443 if (DW_DLV_OK
== resattr
) {
445 res
= handle_attr_addr(dbg
, newdie
, newattrnum
, &err
);
446 if (res
!= DW_DLV_OK
) {
447 *errval
= (int) dwarf_errno(err
);
452 if (resattr
== DW_DLV_ERROR
) {
453 *errval
= (int) dwarf_errno(err
);
458 for (i
= 0; i
< sizeof(might_have_locdesc
) / sizeof(int); i
++) {
462 newattrnum
= might_have_locdesc
[i
];
464 resattr
= dwarf_hasattr(newdie
, newattrnum
, &hasattr
, &err
);
465 if (DW_DLV_OK
== resattr
) {
468 handle_attr_locdesc(dbg
, newdie
, newattrnum
, &err
);
469 if (res
!= DW_DLV_OK
) {
470 *errval
= (int) dwarf_errno(err
);
475 if (resattr
== DW_DLV_ERROR
) {
476 *errval
= (int) dwarf_errno(err
);
486 Handle siblings as a list,
487 Do children by recursing.
488 Effectively this is walking the tree preorder.
490 This dealloc's any die passed to it, so the
491 caller should not do that dealloc.
492 It seems more logical to have the one causing
493 the alloc to do the dealloc, but that way this
494 routine became a mess.
498 do_this_die_and_dealloc(Dwarf_Debug dbg
, Dwarf_Die die
, int *errval
)
501 Dwarf_Die prevdie
= 0;
502 Dwarf_Die newdie
= die
;
505 int sibres
= DW_DLV_OK
;
506 int tres
= DW_DLV_OK
;
509 while (sibres
== DW_DLV_OK
) {
513 res
= process_this_die_attrs(dbg
, newdie
, errval
);
517 case DW_DLV_NO_ENTRY
:
522 dwarf_dealloc(dbg
, prevdie
, DW_DLA_DIE
);
528 tres
= dwarf_child(newdie
, &ch_die
, &err
);
530 if (tres
== DW_DLV_OK
) {
531 res
= do_this_die_and_dealloc(dbg
, ch_die
, errval
);
535 case DW_DLV_NO_ENTRY
:
540 dwarf_dealloc(dbg
, prevdie
, DW_DLA_DIE
);
545 } else if (tres
== DW_DLV_ERROR
) {
547 *errval
= (int) dwarf_errno(err
);
549 dwarf_dealloc(dbg
, prevdie
, DW_DLA_DIE
);
552 dwarf_dealloc(dbg
, err
, DW_DLA_ERROR
);
554 } /* else was NO ENTRY */
557 sibres
= dwarf_siblingof(dbg
, newdie
, &sibdie
, &err
);
559 dwarf_dealloc(dbg
, prevdie
, DW_DLA_DIE
);
565 if (sibres
== DW_DLV_NO_ENTRY
) {
569 *errval
= (int) dwarf_errno(err
);
571 dwarf_dealloc(dbg
, prevdie
, DW_DLA_DIE
);
574 dwarf_dealloc(dbg
, err
, DW_DLA_ERROR
);
581 handle_debug_frame(Dwarf_Debug dbg
, Dwarf_addr_callback_func cb_func
,
584 int retval
= DW_DLV_OK
;
587 Dwarf_Addr
*addrlist
;
588 Dwarf_Off
*offsetlist
;
593 _dwarf_frame_address_offsets(dbg
, &addrlist
, &offsetlist
,
595 if (res
== DW_DLV_OK
) {
596 for (i
= 0; i
< count
; i
++) {
597 cb_func(DW_SECTION_FRAME
, offsetlist
[i
], addrlist
[i
]);
599 dwarf_dealloc(dbg
, offsetlist
, DW_DLA_ADDR
);
600 dwarf_dealloc(dbg
, addrlist
, DW_DLA_ADDR
);
601 } else if (res
== DW_DLV_NO_ENTRY
) {
604 *errval
= (int) dwarf_errno(err
);
605 retval
= DW_DLV_ERROR
;
611 handle_debug_aranges(Dwarf_Debug dbg
, Dwarf_addr_callback_func cb_func
,
614 int retval
= DW_DLV_OK
;
622 _dwarf_get_aranges_addr_offsets(dbg
, &aranges
, &offsets
, &count
,
624 if (retval
== DW_DLV_OK
) {
626 retval
= DW_DLV_NO_ENTRY
;
628 for (indx
= 0; indx
< count
; indx
++) {
629 cb_func(DW_SECTION_ARANGES
, offsets
[indx
],
633 dwarf_dealloc(dbg
, aranges
, DW_DLA_ADDR
);
634 dwarf_dealloc(dbg
, offsets
, DW_DLA_ADDR
);
635 } else if (retval
== DW_DLV_NO_ENTRY
) {
638 *errval
= (int) dwarf_errno(err
);
639 retval
= DW_DLV_ERROR
;
644 handle_debug_line(Dwarf_Debug dbg
, Dwarf_Die cu_die
,
645 Dwarf_addr_callback_func cb_func
, int *errval
)
647 int retval
= DW_DLV_OK
;
650 Dwarf_Addr
*addrlist
;
651 Dwarf_Off
*offsetlist
;
652 Dwarf_Unsigned count
;
656 _dwarf_line_address_offsets(dbg
, cu_die
, &addrlist
, &offsetlist
,
658 if (res
== DW_DLV_OK
) {
659 for (i
= 0; i
< count
; i
++) {
660 cb_func(DW_SECTION_LINE
, offsetlist
[i
], addrlist
[i
]);
663 dwarf_dealloc(dbg
, offsetlist
, DW_DLA_ADDR
);
664 dwarf_dealloc(dbg
, addrlist
, DW_DLA_ADDR
);
665 } else if (res
== DW_DLV_NO_ENTRY
) {
668 *errval
= (int) dwarf_errno(err
);
669 retval
= DW_DLV_ERROR
;
675 We need to add support for this. Currently we do not
676 generate this section.
680 handle_debug_loc(void)
682 int retval
= DW_DLV_NO_ENTRY
;