mirror of
https://github.com/davea42/libdwarf-code.git
synced 2025-10-23 18:58:26 +08:00

Dwarf_Error* and with mistakes treating DW_DLV_NO_ENTRY as if it were DW_DLV_ERROR. * dwarf_form.c: Only do dwarf_errno(*error) when error is non-null. * dwarf_macro5.c, dwarf_query.c, dwarf_ranges.c: Avoid the possibility of doing dwarf_errno(*error) when error is null. * dwarf_util.c(_dwarf_error_mv_s_to_t): Added code to ensure that nothing crash-worthy happens even if a future internal caller calls it with one or more NULL arguments. * libdwarf2.1.mm: Added a few words about Error Handling in general to clarify earlier wording (earlier wording was not as explicit as it should have been). * libdwarf2.1.pdf: Regenerated. Version 2.45 * dwarf_sort_line.c: Though no longer built or used, added an initializer to a local variable for correctness.
674 lines
19 KiB
C
674 lines
19 KiB
C
/*
|
|
|
|
Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
|
|
Portions Copyright 2011 David Anderson. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of version 2.1 of the GNU Lesser General Public License
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it would be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
Further, this software is distributed without any warranty that it is
|
|
free of the rightful claim of any third person regarding infringement
|
|
or the like. Any license provided herein, whether implied or
|
|
otherwise, applies only to this software file. Patent licenses, if
|
|
any, provided herein do not apply to combinations of this program with
|
|
other software, or any other product whatsoever.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this program; if not, write the Free Software
|
|
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
|
USA.
|
|
|
|
*/
|
|
/* This code used by SGI-IRIX rqs processing, not needed by
|
|
any other system or application.
|
|
The 'We need' and 'FIX' here are left in for historical
|
|
interest, the code is not really used in the public libdwarf
|
|
or applications.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "libdwarfdefs.h"
|
|
#ifdef HAVE_ELF_H
|
|
#include <elf.h>
|
|
#endif
|
|
#include <dwarf.h>
|
|
#include <libdwarf.h>
|
|
#include "dwarf_base_types.h"
|
|
#include "dwarf_alloc.h"
|
|
#include "dwarf_opaque.h"
|
|
#include "dwarf_arange.h"
|
|
#include "dwarf_line.h"
|
|
#include "dwarf_frame.h"
|
|
#include <cmplrs/dwarf_addr_finder.h>
|
|
#include "dwarf_error.h"
|
|
|
|
typedef unsigned long long ull;
|
|
|
|
static int do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die,
|
|
int *errval);
|
|
static int handle_debug_info(Dwarf_Debug dbg, int *errval);
|
|
static int handle_debug_frame(Dwarf_Debug dbg,
|
|
Dwarf_addr_callback_func cb_func, int *errval);
|
|
static int handle_debug_aranges(Dwarf_Debug dbg,
|
|
Dwarf_addr_callback_func cb_func, int *errval);
|
|
static int handle_debug_line(Dwarf_Debug dbg,
|
|
Dwarf_Die cu_die, Dwarf_addr_callback_func cb_func, int *errval);
|
|
static int handle_debug_loc(void);
|
|
|
|
|
|
/* A static variable is not thread-safe, but this is only
|
|
used by SGI-internal software which is single-threaded
|
|
so the static variable is safe.
|
|
*/
|
|
static Dwarf_addr_callback_func send_addr_note;
|
|
|
|
/* A function which should probably not be used outside
|
|
of SGI. Intended to be used by executable and
|
|
shared-library post-processor software.
|
|
*/
|
|
int
|
|
_dwarf_addr_finder(dwarf_elf_handle elf_file_ptr,
|
|
Dwarf_addr_callback_func cb_func, int *dwerr)
|
|
{
|
|
|
|
Dwarf_Error err = 0;
|
|
Dwarf_Debug dbg = 0;
|
|
int res = 0;
|
|
int errval = 0;
|
|
int sections_found = 0;
|
|
|
|
res = dwarf_elf_init(elf_file_ptr, DW_DLC_READ, /* errhand */ 0,
|
|
/* errarg */ 0, &dbg, &err);
|
|
if (res == DW_DLV_ERROR) {
|
|
int errv = (int) dwarf_errno(err);
|
|
return errv;
|
|
}
|
|
if (res == DW_DLV_NO_ENTRY) {
|
|
return res;
|
|
}
|
|
send_addr_note = cb_func;
|
|
res = handle_debug_info(dbg, &errval);
|
|
switch (res) {
|
|
case DW_DLV_OK:
|
|
++sections_found;
|
|
break;
|
|
case DW_DLV_NO_ENTRY:
|
|
|
|
break;
|
|
default:
|
|
case DW_DLV_ERROR:
|
|
dwarf_finish(dbg, &err);
|
|
*dwerr = errval;
|
|
return res;
|
|
}
|
|
|
|
res = handle_debug_aranges(dbg, cb_func, &errval);
|
|
switch (res) {
|
|
case DW_DLV_OK:
|
|
++sections_found;
|
|
break;
|
|
case DW_DLV_NO_ENTRY:
|
|
break;
|
|
default:
|
|
case DW_DLV_ERROR:
|
|
dwarf_finish(dbg, &err);
|
|
*dwerr = errval;
|
|
return res;
|
|
}
|
|
res = handle_debug_frame(dbg, cb_func, &errval);
|
|
switch (res) {
|
|
case DW_DLV_OK:
|
|
++sections_found;
|
|
break;
|
|
case DW_DLV_NO_ENTRY:
|
|
break;
|
|
default:
|
|
case DW_DLV_ERROR:
|
|
dwarf_finish(dbg, &err);
|
|
*dwerr = errval;
|
|
return res;
|
|
}
|
|
|
|
res = handle_debug_loc(); /* does nothing */
|
|
switch (res) {
|
|
case DW_DLV_OK:
|
|
++sections_found;
|
|
break;
|
|
case DW_DLV_NO_ENTRY:
|
|
break;
|
|
default:
|
|
case DW_DLV_ERROR:
|
|
/* IMPOSSIBLE : handle_debug_loc cannot return this */
|
|
dwarf_finish(dbg, &err);
|
|
*dwerr = errval;
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
*dwerr = 0;
|
|
res = dwarf_finish(dbg, &err);
|
|
if (res == DW_DLV_ERROR) {
|
|
*dwerr = (int) dwarf_errno(err);
|
|
return DW_DLV_ERROR;
|
|
}
|
|
if (sections_found == 0) {
|
|
return DW_DLV_NO_ENTRY;
|
|
}
|
|
return DW_DLV_OK;
|
|
|
|
}
|
|
|
|
/* Return DW_DLV_OK, ERROR, or NO_ENTRY. */
|
|
static int
|
|
handle_debug_info(Dwarf_Debug dbg, int *errval)
|
|
{
|
|
Dwarf_Unsigned nxtoff = 1;
|
|
Dwarf_Unsigned hdr_length = 0;
|
|
Dwarf_Half version_stamp = 0;
|
|
Dwarf_Unsigned abbrev_offset = 0;
|
|
Dwarf_Half addr_size = 0;
|
|
Dwarf_Error err = 0;
|
|
int terminate_now = 0;
|
|
int res = 0;
|
|
Dwarf_Die sibdie = 0;
|
|
int sibres = 0;
|
|
int nres = DW_DLV_OK;
|
|
|
|
|
|
for (nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
|
|
&abbrev_offset,
|
|
&addr_size, &nxtoff, &err);
|
|
terminate_now == 0 && nres == DW_DLV_OK;
|
|
nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
|
|
&abbrev_offset,
|
|
&addr_size, &nxtoff, &err)) {
|
|
|
|
Dwarf_Die curdie = 0;
|
|
|
|
/* Try to get the compilation unit die */
|
|
sibres = dwarf_siblingof(dbg, curdie, &sibdie, &err);
|
|
if (sibres == DW_DLV_OK) {
|
|
res = do_this_die_and_dealloc(dbg, sibdie, errval);
|
|
switch (res) {
|
|
case DW_DLV_OK:
|
|
break;
|
|
case DW_DLV_NO_ENTRY:
|
|
break;
|
|
default:
|
|
case DW_DLV_ERROR:
|
|
return DW_DLV_ERROR;
|
|
}
|
|
} else if (sibres == DW_DLV_ERROR) {
|
|
*errval = (int) dwarf_errno(err);
|
|
return DW_DLV_ERROR;
|
|
} else {
|
|
/* NO ENTRY! */
|
|
/* impossible? */
|
|
}
|
|
|
|
}
|
|
if (nres == DW_DLV_ERROR) {
|
|
int localerr = (int) dwarf_errno(err);
|
|
|
|
*errval = localerr;
|
|
return DW_DLV_ERROR;
|
|
}
|
|
return DW_DLV_OK;
|
|
}
|
|
|
|
static const int
|
|
might_have_addr[] = {
|
|
DW_AT_high_pc,
|
|
DW_AT_low_pc,
|
|
};
|
|
static const int might_have_locdesc[] = {
|
|
DW_AT_segment,
|
|
DW_AT_return_addr,
|
|
DW_AT_frame_base,
|
|
DW_AT_static_link,
|
|
DW_AT_data_member_location,
|
|
DW_AT_string_length,
|
|
DW_AT_location,
|
|
DW_AT_use_location,
|
|
DW_AT_vtable_elem_location,
|
|
};
|
|
|
|
/* Return DW_DLV_OK if handling this went ok.
|
|
For any FORM except DW_FORM_addr we do nothing
|
|
and return DW_DLV_OK.
|
|
For DW_FORM_ref_addr (the offset in .debug_info
|
|
of an address) we don't need to do anything
|
|
as the offsets in .debug_info do not change.
|
|
*/
|
|
static int
|
|
handle_attr_addr(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum,
|
|
Dwarf_Error * perr)
|
|
{
|
|
int res = DW_DLV_OK;
|
|
Dwarf_Off offset = 0;
|
|
Dwarf_Addr addr = 0;
|
|
Dwarf_Half form = 0;
|
|
int ares = 0;
|
|
|
|
Dwarf_Attribute attr;
|
|
|
|
ares = dwarf_attr(die, attrnum, &attr, perr);
|
|
if (ares == DW_DLV_OK) {
|
|
int formres = dwarf_whatform(attr, &form, perr);
|
|
|
|
switch (formres) {
|
|
case DW_DLV_OK:
|
|
break;
|
|
case DW_DLV_ERROR:
|
|
case DW_DLV_NO_ENTRY: /* impossible. */
|
|
return formres;
|
|
|
|
}
|
|
|
|
switch (form) {
|
|
case DW_FORM_addr:
|
|
res = dwarf_attr_offset(die, attr, &offset, perr);
|
|
if (res == DW_DLV_OK) {
|
|
ares = dwarf_formaddr(attr, &addr, perr);
|
|
if (ares == DW_DLV_OK) {
|
|
send_addr_note(DW_SECTION_INFO, offset, addr);
|
|
} else if (ares == DW_DLV_ERROR) {
|
|
return ares;
|
|
}
|
|
/* no entry: ok. */
|
|
} else {
|
|
/* NO_ENTRY is impossible. */
|
|
res = DW_DLV_ERROR;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
/* Surprising FORM. An error? */
|
|
/* Do nothing */
|
|
;
|
|
}
|
|
dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
|
|
} else {
|
|
res = ares;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/* Return DW_DLV_OK if handling this went ok. */
|
|
static int
|
|
handle_attr_locdesc(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum,
|
|
Dwarf_Error * perr)
|
|
{
|
|
int retval = DW_DLV_OK;
|
|
Dwarf_Attribute attr = 0;
|
|
Dwarf_Locdesc *llbuf = 0;
|
|
Dwarf_Signed i = 0;
|
|
Dwarf_Off offset = 0;
|
|
Dwarf_Loc *locp = 0;
|
|
unsigned int entindx = 0;
|
|
int res = 0;
|
|
int ares = 0;
|
|
|
|
|
|
ares = dwarf_attr(die, attrnum, &attr, perr);
|
|
if (ares == DW_DLV_OK) {
|
|
Dwarf_Half form;
|
|
int fres = dwarf_whatform(attr, &form, perr);
|
|
|
|
if (fres == DW_DLV_OK) {
|
|
switch (form) {
|
|
case DW_FORM_block1:
|
|
case DW_FORM_block2:
|
|
case DW_FORM_block4:
|
|
/* must be location description */
|
|
res = dwarf_attr_offset(die, attr, &offset, perr);
|
|
llbuf = 0;
|
|
if (res == DW_DLV_OK) {
|
|
Dwarf_Signed count;
|
|
int lres = dwarf_loclist(attr, &llbuf, &count, perr);
|
|
if (lres != DW_DLV_OK) {
|
|
return lres;
|
|
}
|
|
if (count != 1) {
|
|
/* this cannot happen! */
|
|
/* perr? */
|
|
_dwarf_error(dbg, perr,
|
|
DW_DLE_LOCDESC_COUNT_WRONG);
|
|
retval = DW_DLV_ERROR;
|
|
return retval;
|
|
}
|
|
for (i = 0; i < count; ++i) {
|
|
unsigned int ents = llbuf[i].ld_cents;
|
|
|
|
locp = llbuf[i].ld_s;
|
|
for (entindx = 0; entindx < ents; entindx++) {
|
|
Dwarf_Loc *llocp;
|
|
|
|
llocp = locp + entindx;
|
|
if (llocp->lr_atom == DW_OP_addr) {
|
|
send_addr_note(DW_SECTION_INFO, offset +
|
|
llocp->lr_offset + 1
|
|
/* The offset is the
|
|
offset of the atom,
|
|
** and we know the
|
|
addr is 1 past it. */
|
|
, llocp->lr_number);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (count > 0) {
|
|
for (i = 0; i < count; ++i) {
|
|
dwarf_dealloc(dbg, llbuf[i].ld_s,
|
|
DW_DLA_LOC_BLOCK);
|
|
}
|
|
dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
|
|
}
|
|
} else {
|
|
retval = res;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
/* must be a const offset in debug_loc */
|
|
; /* do nothing */
|
|
}
|
|
dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
|
|
} /* else error or no entry */
|
|
retval = fres;
|
|
} else {
|
|
retval = ares;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
/* Return DW_DLV_OK, or DW_DLV_ERROR
|
|
|
|
Handle the addrs in a single die. */
|
|
static int
|
|
process_this_die_attrs(Dwarf_Debug dbg, Dwarf_Die newdie, int *errval)
|
|
{
|
|
Dwarf_Error err = 0;
|
|
Dwarf_Half i = 0;
|
|
Dwarf_Half newattrnum = 0;
|
|
int res = 0;
|
|
int tres = 0;
|
|
Dwarf_Half ltag = 0;
|
|
Dwarf_Off doff = 0;
|
|
|
|
int doffres = dwarf_dieoffset(newdie, &doff, &err);
|
|
if (doffres != DW_DLV_OK) {
|
|
if (doffres == DW_DLV_ERROR) {
|
|
*errval = (int) dwarf_errno(err);
|
|
}
|
|
return doffres;
|
|
}
|
|
tres = dwarf_tag(newdie, <ag, &err);
|
|
if (tres != DW_DLV_OK) {
|
|
return tres;
|
|
}
|
|
if (DW_TAG_compile_unit == ltag) {
|
|
/* Because of the way the dwarf_line code works, we do lines
|
|
only per compile unit. This may turn out to be wrong if
|
|
we have lines left unconnected to a CU. of course such
|
|
lines will not, at present, be used by gnome. This is
|
|
not ideal as coded due to the dwarf_line.c issue. */
|
|
int lres = handle_debug_line(dbg, newdie, send_addr_note, errval);
|
|
if (lres == DW_DLV_ERROR) {
|
|
return lres;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < sizeof(might_have_addr) / sizeof(int); i++) {
|
|
int resattr = 0;
|
|
Dwarf_Bool hasattr = 0;
|
|
|
|
newattrnum = might_have_addr[i];
|
|
err = 0;
|
|
resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
|
|
if (DW_DLV_OK == resattr) {
|
|
if (hasattr) {
|
|
res = handle_attr_addr(dbg, newdie, newattrnum, &err);
|
|
if (res != DW_DLV_OK) {
|
|
*errval = (int) dwarf_errno(err);
|
|
return DW_DLV_ERROR;
|
|
}
|
|
}
|
|
} else {
|
|
if (resattr == DW_DLV_ERROR) {
|
|
*errval = (int) dwarf_errno(err);
|
|
return resattr;
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < sizeof(might_have_locdesc) / sizeof(int); i++) {
|
|
int resattr = 0;
|
|
Dwarf_Bool hasattr = 0;
|
|
|
|
newattrnum = might_have_locdesc[i];
|
|
err = 0;
|
|
resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
|
|
if (DW_DLV_OK == resattr) {
|
|
if (hasattr) {
|
|
res =
|
|
handle_attr_locdesc(dbg, newdie, newattrnum, &err);
|
|
if (res != DW_DLV_OK) {
|
|
*errval = (int) dwarf_errno(err);
|
|
return DW_DLV_ERROR;
|
|
}
|
|
}
|
|
} else {
|
|
if (resattr == DW_DLV_ERROR) {
|
|
*errval = (int) dwarf_errno(err);
|
|
return resattr;
|
|
}
|
|
}
|
|
}
|
|
|
|
return DW_DLV_OK;
|
|
}
|
|
|
|
/* Handle siblings as a list,
|
|
Do children by recursing.
|
|
Effectively this is walking the tree preorder.
|
|
|
|
This dealloc's any die passed to it, so the
|
|
caller should not do that dealloc.
|
|
It seems more logical to have the one causing
|
|
the alloc to do the dealloc, but that way this
|
|
routine became a mess.
|
|
*/
|
|
static int
|
|
do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, int *errval)
|
|
{
|
|
|
|
Dwarf_Die prevdie = 0;
|
|
Dwarf_Die newdie = die;
|
|
Dwarf_Error err = 0;
|
|
int res = 0;
|
|
int sibres = DW_DLV_OK;
|
|
int tres = DW_DLV_OK;
|
|
Dwarf_Die sibdie = 0;
|
|
|
|
while (sibres == DW_DLV_OK) {
|
|
Dwarf_Die ch_die;
|
|
|
|
|
|
res = process_this_die_attrs(dbg, newdie, errval);
|
|
switch (res) {
|
|
case DW_DLV_OK:
|
|
break;
|
|
case DW_DLV_NO_ENTRY:
|
|
break;
|
|
default:
|
|
case DW_DLV_ERROR:
|
|
if (prevdie) {
|
|
dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
|
|
prevdie = 0;
|
|
}
|
|
return DW_DLV_ERROR;
|
|
}
|
|
|
|
tres = dwarf_child(newdie, &ch_die, &err);
|
|
|
|
if (tres == DW_DLV_OK) {
|
|
res = do_this_die_and_dealloc(dbg, ch_die, errval);
|
|
switch (res) {
|
|
case DW_DLV_OK:
|
|
break;
|
|
case DW_DLV_NO_ENTRY:
|
|
break;
|
|
default:
|
|
case DW_DLV_ERROR:
|
|
if (prevdie) {
|
|
dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
|
|
prevdie = 0;
|
|
}
|
|
return DW_DLV_ERROR;
|
|
}
|
|
} else if (tres == DW_DLV_ERROR) {
|
|
/* An error! */
|
|
*errval = (int) dwarf_errno(err);
|
|
if (prevdie) {
|
|
dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
|
|
prevdie = 0;
|
|
}
|
|
dwarf_dealloc(dbg, err, DW_DLA_ERROR);
|
|
return DW_DLV_ERROR;
|
|
} /* else was NO ENTRY */
|
|
prevdie = newdie;
|
|
sibdie = 0;
|
|
sibres = dwarf_siblingof(dbg, newdie, &sibdie, &err);
|
|
if (prevdie) {
|
|
dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
|
|
prevdie = 0;
|
|
}
|
|
newdie = sibdie;
|
|
|
|
}
|
|
if (sibres == DW_DLV_NO_ENTRY) {
|
|
return DW_DLV_OK;
|
|
}
|
|
/* error. */
|
|
*errval = (int) dwarf_errno(err);
|
|
if (prevdie) {
|
|
dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
|
|
prevdie = 0;
|
|
}
|
|
dwarf_dealloc(dbg, err, DW_DLA_ERROR);
|
|
return DW_DLV_ERROR;
|
|
|
|
}
|
|
|
|
|
|
static int
|
|
handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
|
|
int *errval)
|
|
{
|
|
int retval = DW_DLV_OK;
|
|
int res = 0;
|
|
Dwarf_Error err = 0;
|
|
Dwarf_Addr *addrlist = 0;
|
|
Dwarf_Off *offsetlist = 0;
|
|
Dwarf_Signed count = 0;
|
|
int i = 0;
|
|
|
|
res = _dwarf_frame_address_offsets(dbg, &addrlist,
|
|
&offsetlist, &count, &err);
|
|
if (res == DW_DLV_OK) {
|
|
for (i = 0; i < count; i++) {
|
|
cb_func(DW_SECTION_FRAME, offsetlist[i], addrlist[i]);
|
|
}
|
|
dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
|
|
dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
|
|
} else if (res == DW_DLV_NO_ENTRY) {
|
|
retval = res;
|
|
} else {
|
|
*errval = (int) dwarf_errno(err);
|
|
retval = DW_DLV_ERROR;
|
|
}
|
|
return retval;
|
|
|
|
}
|
|
static int
|
|
handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
|
|
int *errval)
|
|
{
|
|
int retval = DW_DLV_OK;
|
|
Dwarf_Error err = 0;
|
|
Dwarf_Addr *aranges = 0;
|
|
Dwarf_Signed count = 0;
|
|
int indx = 0;
|
|
Dwarf_Off *offsets = 0;
|
|
|
|
retval =
|
|
_dwarf_get_aranges_addr_offsets(dbg, &aranges, &offsets, &count,
|
|
&err);
|
|
if (retval == DW_DLV_OK) {
|
|
if (count == 0) {
|
|
retval = DW_DLV_NO_ENTRY;
|
|
} else {
|
|
for (indx = 0; indx < count; indx++) {
|
|
cb_func(DW_SECTION_ARANGES, offsets[indx],
|
|
aranges[indx]);
|
|
}
|
|
}
|
|
dwarf_dealloc(dbg, aranges, DW_DLA_ADDR);
|
|
dwarf_dealloc(dbg, offsets, DW_DLA_ADDR);
|
|
} else if (retval == DW_DLV_NO_ENTRY) {
|
|
; /* do nothing */
|
|
} else {
|
|
*errval = (int) dwarf_errno(err);
|
|
retval = DW_DLV_ERROR;
|
|
}
|
|
return retval;
|
|
}
|
|
static int
|
|
handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die,
|
|
Dwarf_addr_callback_func cb_func, int *errval)
|
|
{
|
|
int retval = DW_DLV_OK;
|
|
int res = 0;
|
|
Dwarf_Error err = 0;
|
|
Dwarf_Addr *addrlist = 0;
|
|
Dwarf_Off *offsetlist = 0;
|
|
Dwarf_Unsigned count = 0;
|
|
Dwarf_Unsigned i = 0;
|
|
|
|
res = _dwarf_line_address_offsets(dbg, cu_die, &addrlist,
|
|
&offsetlist, &count, &err);
|
|
if (res == DW_DLV_OK) {
|
|
for (i = 0; i < count; i++) {
|
|
cb_func(DW_SECTION_LINE, offsetlist[i], addrlist[i]);
|
|
|
|
}
|
|
dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
|
|
dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
|
|
} else if (res == DW_DLV_NO_ENTRY) {
|
|
retval = res;
|
|
} else {
|
|
*errval = (int) dwarf_errno(err);
|
|
retval = DW_DLV_ERROR;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
/* We need to add support for this. Currently we do not
|
|
generate this section.
|
|
FIX!
|
|
*/
|
|
static int
|
|
handle_debug_loc(void)
|
|
{
|
|
int retval = DW_DLV_NO_ENTRY;
|
|
|
|
return retval;
|
|
}
|