summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdwarf/common/dwarf_addr_finder.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdwarf/common/dwarf_addr_finder.c')
-rw-r--r--usr/src/lib/libdwarf/common/dwarf_addr_finder.c685
1 files changed, 0 insertions, 685 deletions
diff --git a/usr/src/lib/libdwarf/common/dwarf_addr_finder.c b/usr/src/lib/libdwarf/common/dwarf_addr_finder.c
deleted file mode 100644
index 2fadefc1ea..0000000000
--- a/usr/src/lib/libdwarf/common/dwarf_addr_finder.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
-
- Copyright (C) 2000-2004 Silicon Graphics, Inc. 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.
-
- Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
- Mountain View, CA 94043, or:
-
- http://www.sgi.com
-
- For further information regarding this notice, see:
-
- http://oss.sgi.com/projects/GenInfo/NoticeExplan
-
-*/
-/* This code used by SGI-IRIX rqs processing, not needed by
- any other system or application.
-*/
-
-#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);
-
-
-static Dwarf_addr_callback_func send_addr_note;
-
-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;
- Dwarf_Half version_stamp;
- Dwarf_Unsigned abbrev_offset;
- Dwarf_Half addr_size;
- Dwarf_Error err;
- int terminate_now = 0;
- int res = 0;
- Dwarf_Die sibdie;
- int sibres;
- 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 int
- might_have_addr[] = {
- DW_AT_high_pc,
- DW_AT_low_pc,
-};
-static 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.
-*/
-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;
- Dwarf_Addr addr;
- Dwarf_Half form;
- int ares;
-
- 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_ref_addr:
- 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 {
- res = DW_DLV_ERROR; /* NO_ENTRY is impossible. */
- }
- break;
-
- default:
- /* surprising! 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;
- Dwarf_Locdesc *llbuf;
- Dwarf_Signed i;
- Dwarf_Off offset;
- Dwarf_Loc *locp;
- unsigned int entindx;
- int res;
- int ares;
-
-
- 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;
- Dwarf_Half i;
- Dwarf_Half newattrnum;
- int res;
- int tres;
- Dwarf_Half ltag;
-
- Dwarf_Off doff;
- 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, &ltag, &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;
- Dwarf_Bool hasattr;
-
- 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;
- Dwarf_Bool hasattr;
-
- 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;
-
- 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;
- Dwarf_Error err;
- Dwarf_Addr *addrlist;
- Dwarf_Off *offsetlist;
- Dwarf_Signed count;
- int i;
-
- 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;
- Dwarf_Addr *aranges;
- Dwarf_Signed count;
- int indx;
- Dwarf_Off *offsets;
-
- 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;
- Dwarf_Error err;
- Dwarf_Addr *addrlist;
- Dwarf_Off *offsetlist;
- Dwarf_Unsigned count;
- Dwarf_Unsigned i;
-
- 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;
-}