diff options
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common/dwarf_loc.c')
-rw-r--r-- | usr/src/tools/ctf/dwarf/common/dwarf_loc.c | 1073 |
1 files changed, 0 insertions, 1073 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_loc.c b/usr/src/tools/ctf/dwarf/common/dwarf_loc.c deleted file mode 100644 index f28b27b630..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_loc.c +++ /dev/null @@ -1,1073 +0,0 @@ -/* - - Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 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. - - 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 - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include "dwarf_loc.h" -#include <stdio.h> /* for debugging only. */ -#include <sys/types.h> - -/* - Given a Dwarf_Block that represents a location expression, - this function returns a pointer to a Dwarf_Locdesc struct - that has its ld_cents field set to the number of location - operators in the block, and its ld_s field pointing to a - contiguous block of Dwarf_Loc structs. However, the - ld_lopc and ld_hipc values are uninitialized. Returns - NULL on error. This function assumes that the length of - the block is greater than 0. Zero length location expressions - to represent variables that have been optimized away are - handled in the calling function. -*/ -static Dwarf_Locdesc * -_dwarf_get_locdesc(Dwarf_Debug dbg, - Dwarf_Block * loc_block, - Dwarf_Half address_size, - Dwarf_Addr lowpc, - Dwarf_Addr highpc, - Dwarf_Error * error) -{ - /* Size of the block containing the location expression. */ - Dwarf_Unsigned loc_len = 0; - - /* Sweeps the block containing the location expression. */ - Dwarf_Small *loc_ptr = 0; - - /* Current location operator. */ - Dwarf_Small atom = 0; - - /* Offset of current operator from start of block. */ - Dwarf_Unsigned offset = 0; - - /* Operands of current location operator. */ - Dwarf_Unsigned operand1, operand2; - - /* Used to chain the Dwarf_Loc_Chain_s structs. */ - Dwarf_Loc_Chain curr_loc = NULL; - Dwarf_Loc_Chain prev_loc = NULL; - Dwarf_Loc_Chain head_loc = NULL; - - /* Count of the number of location operators. */ - Dwarf_Unsigned op_count = 0; - - /* Contiguous block of Dwarf_Loc's for Dwarf_Locdesc. */ - Dwarf_Loc *block_loc = 0; - - /* Dwarf_Locdesc pointer to be returned. */ - Dwarf_Locdesc *locdesc = 0; - - Dwarf_Word leb128_length = 0; - Dwarf_Unsigned i = 0; - - /* ***** BEGIN CODE ***** */ - - loc_len = loc_block->bl_len; - loc_ptr = loc_block->bl_data; - - offset = 0; - op_count = 0; - while (offset < loc_len) { - - operand1 = 0; - operand2 = 0; - op_count++; - - atom = *(Dwarf_Small *) loc_ptr; - loc_ptr++; - offset++; - - curr_loc = - (Dwarf_Loc_Chain) _dwarf_get_alloc(dbg, DW_DLA_LOC_CHAIN, - 1); - if (curr_loc == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - curr_loc->lc_offset = offset; - curr_loc->lc_atom = atom; - switch (atom) { - - case DW_OP_reg0: - case DW_OP_reg1: - case DW_OP_reg2: - case DW_OP_reg3: - case DW_OP_reg4: - case DW_OP_reg5: - case DW_OP_reg6: - case DW_OP_reg7: - case DW_OP_reg8: - case DW_OP_reg9: - case DW_OP_reg10: - case DW_OP_reg11: - case DW_OP_reg12: - case DW_OP_reg13: - case DW_OP_reg14: - case DW_OP_reg15: - case DW_OP_reg16: - case DW_OP_reg17: - case DW_OP_reg18: - case DW_OP_reg19: - case DW_OP_reg20: - case DW_OP_reg21: - case DW_OP_reg22: - case DW_OP_reg23: - case DW_OP_reg24: - case DW_OP_reg25: - case DW_OP_reg26: - case DW_OP_reg27: - case DW_OP_reg28: - case DW_OP_reg29: - case DW_OP_reg30: - case DW_OP_reg31: - break; - - case DW_OP_regx: - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_lit0: - case DW_OP_lit1: - case DW_OP_lit2: - case DW_OP_lit3: - case DW_OP_lit4: - case DW_OP_lit5: - case DW_OP_lit6: - case DW_OP_lit7: - case DW_OP_lit8: - case DW_OP_lit9: - case DW_OP_lit10: - case DW_OP_lit11: - case DW_OP_lit12: - case DW_OP_lit13: - case DW_OP_lit14: - case DW_OP_lit15: - case DW_OP_lit16: - case DW_OP_lit17: - case DW_OP_lit18: - case DW_OP_lit19: - case DW_OP_lit20: - case DW_OP_lit21: - case DW_OP_lit22: - case DW_OP_lit23: - case DW_OP_lit24: - case DW_OP_lit25: - case DW_OP_lit26: - case DW_OP_lit27: - case DW_OP_lit28: - case DW_OP_lit29: - case DW_OP_lit30: - case DW_OP_lit31: - operand1 = atom - DW_OP_lit0; - break; - - case DW_OP_addr: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, - loc_ptr, address_size); - loc_ptr += address_size; - offset += address_size; - break; - - case DW_OP_const1u: - operand1 = *(Dwarf_Small *) loc_ptr; - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_const1s: - operand1 = *(Dwarf_Sbyte *) loc_ptr; - SIGN_EXTEND(operand1,1); - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_const2u: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); - loc_ptr = loc_ptr + 2; - offset = offset + 2; - break; - - case DW_OP_const2s: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); - SIGN_EXTEND(operand1,2); - loc_ptr = loc_ptr + 2; - offset = offset + 2; - break; - - case DW_OP_const4u: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); - loc_ptr = loc_ptr + 4; - offset = offset + 4; - break; - - case DW_OP_const4s: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); - SIGN_EXTEND(operand1,4); - loc_ptr = loc_ptr + 4; - offset = offset + 4; - break; - - case DW_OP_const8u: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8); - loc_ptr = loc_ptr + 8; - offset = offset + 8; - break; - - case DW_OP_const8s: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8); - loc_ptr = loc_ptr + 8; - offset = offset + 8; - break; - - case DW_OP_constu: - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_consts: - operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_fbreg: - operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_bregx: - /* uleb reg num followed by sleb offset */ - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - - operand2 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_dup: - case DW_OP_drop: - break; - - case DW_OP_pick: - operand1 = *(Dwarf_Small *) loc_ptr; - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_over: - case DW_OP_swap: - case DW_OP_rot: - case DW_OP_deref: - break; - - case DW_OP_deref_size: - operand1 = *(Dwarf_Small *) loc_ptr; - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_xderef: - break; - - case DW_OP_xderef_size: - operand1 = *(Dwarf_Small *) loc_ptr; - loc_ptr = loc_ptr + 1; - offset = offset + 1; - break; - - case DW_OP_abs: - case DW_OP_and: - case DW_OP_div: - case DW_OP_minus: - case DW_OP_mod: - case DW_OP_mul: - case DW_OP_neg: - case DW_OP_not: - case DW_OP_or: - case DW_OP_plus: - break; - - case DW_OP_plus_uconst: - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_shl: - case DW_OP_shr: - case DW_OP_shra: - case DW_OP_xor: - break; - - case DW_OP_le: - case DW_OP_ge: - case DW_OP_eq: - case DW_OP_lt: - case DW_OP_gt: - case DW_OP_ne: - break; - - case DW_OP_skip: - case DW_OP_bra: - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); - loc_ptr = loc_ptr + 2; - offset = offset + 2; - break; - - case DW_OP_piece: - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - - case DW_OP_nop: - break; - case DW_OP_push_object_address: /* DWARF3 */ - break; - case DW_OP_call2: /* DWARF3 */ - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2); - loc_ptr = loc_ptr + 2; - offset = offset + 2; - break; - - case DW_OP_call4: /* DWARF3 */ - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4); - loc_ptr = loc_ptr + 4; - offset = offset + 4; - break; - case DW_OP_call_ref: /* DWARF3 */ - READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, - dbg->de_length_size); - loc_ptr = loc_ptr + dbg->de_length_size; - offset = offset + dbg->de_length_size; - break; - - case DW_OP_form_tls_address: /* DWARF3f */ - break; - case DW_OP_call_frame_cfa: /* DWARF3f */ - break; - case DW_OP_bit_piece: /* DWARF3f */ - /* uleb size in bits followed by uleb offset in bits */ - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - - operand2 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - break; - case DW_OP_implicit_value: /* DWARF4 */ - /* uleb length of value bytes followed by that - number of bytes of the value. */ - operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length); - loc_ptr = loc_ptr + leb128_length; - offset = offset + leb128_length; - - /* Second operand is block of 'operand1' bytes of stuff. */ - /* This using the second operand as a pointer - is quite ugly. */ - /* This gets an ugly compiler warning. Sorry. */ - operand2 = (Dwarf_Unsigned)(uintptr_t)loc_ptr; - offset = offset + operand1; - loc_ptr = loc_ptr + operand1; - break; - case DW_OP_stack_value: /* DWARF4 */ - break; - - - default: - _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD); - return (NULL); - } - - - curr_loc->lc_number = operand1; - curr_loc->lc_number2 = operand2; - - if (head_loc == NULL) - head_loc = prev_loc = curr_loc; - else { - prev_loc->lc_next = curr_loc; - prev_loc = curr_loc; - } - } - - block_loc = - (Dwarf_Loc *) _dwarf_get_alloc(dbg, DW_DLA_LOC_BLOCK, op_count); - if (block_loc == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - - curr_loc = head_loc; - for (i = 0; i < op_count; i++) { - (block_loc + i)->lr_atom = curr_loc->lc_atom; - (block_loc + i)->lr_number = curr_loc->lc_number; - (block_loc + i)->lr_number2 = curr_loc->lc_number2; - (block_loc + i)->lr_offset = curr_loc->lc_offset; - - prev_loc = curr_loc; - curr_loc = curr_loc->lc_next; - dwarf_dealloc(dbg, prev_loc, DW_DLA_LOC_CHAIN); - } - - locdesc = - (Dwarf_Locdesc *) _dwarf_get_alloc(dbg, DW_DLA_LOCDESC, 1); - if (locdesc == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); - } - - locdesc->ld_cents = op_count; - locdesc->ld_s = block_loc; - locdesc->ld_from_loclist = loc_block->bl_from_loclist; - locdesc->ld_section_offset = loc_block->bl_section_offset; - locdesc->ld_lopc = lowpc; - locdesc->ld_hipc = highpc; - - return (locdesc); -} - -/* Using a loclist offset to get the in-memory - address of .debug_loc data to read, returns the loclist - 'header' info in return_block. -*/ - -#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff) - -static int -_dwarf_read_loc_section(Dwarf_Debug dbg, - Dwarf_Block * return_block, - Dwarf_Addr * lowpc, Dwarf_Addr * hipc, - Dwarf_Off sec_offset, - Dwarf_Half address_size, - Dwarf_Error * error) -{ - Dwarf_Small *beg = dbg->de_debug_loc.dss_data + sec_offset; - - Dwarf_Addr start_addr = 0; - Dwarf_Addr end_addr = 0; - Dwarf_Half exprblock_size = 0; - Dwarf_Unsigned exprblock_off = - 2 * address_size + sizeof(Dwarf_Half); - - if (sec_offset >= dbg->de_debug_loc.dss_size) { - /* We're at the end. No more present. */ - return DW_DLV_NO_ENTRY; - } - - /* If it goes past end, error */ - if (exprblock_off > dbg->de_debug_loc.dss_size) { - _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); - return DW_DLV_ERROR; - } - - READ_UNALIGNED(dbg, start_addr, Dwarf_Addr, beg, address_size); - READ_UNALIGNED(dbg, end_addr, Dwarf_Addr, - beg + address_size, address_size); - if (start_addr == 0 && end_addr == 0) { - /* If start_addr and end_addr are 0, it's the end and no - exprblock_size field follows. */ - exprblock_size = 0; - exprblock_off -= sizeof(Dwarf_Half); - } else if (start_addr == MAX_ADDR) { - /* end address is a base address, no exprblock_size field here - either */ - exprblock_size = 0; - exprblock_off -= sizeof(Dwarf_Half); - } else { - - READ_UNALIGNED(dbg, exprblock_size, Dwarf_Half, - beg + 2 * address_size, sizeof(Dwarf_Half)); - /* exprblock_size can be zero, means no expression */ - if ((exprblock_off + exprblock_size) > dbg->de_debug_loc.dss_size) { - _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); - return DW_DLV_ERROR; - } - } -#undef MAX_ADDR - *lowpc = start_addr; - *hipc = end_addr; - - return_block->bl_len = exprblock_size; - return_block->bl_from_loclist = 1; - return_block->bl_data = beg + exprblock_off; - return_block->bl_section_offset = - ((Dwarf_Small *) return_block->bl_data) - dbg->de_debug_loc.dss_data; - - return DW_DLV_OK; - -} -static int -_dwarf_get_loclist_count(Dwarf_Debug dbg, - Dwarf_Off loclist_offset, - Dwarf_Half address_size, - int *loclist_count, Dwarf_Error * error) -{ - int count = 0; - Dwarf_Off offset = loclist_offset; - - - for (;;) { - Dwarf_Block b; - Dwarf_Addr lowpc; - Dwarf_Addr highpc; - int res = _dwarf_read_loc_section(dbg, &b, - &lowpc, &highpc, - offset, address_size,error); - - if (res != DW_DLV_OK) { - return res; - } - offset = b.bl_len + b.bl_section_offset; - if (lowpc == 0 && highpc == 0) { - break; - } - count++; - } - *loclist_count = count; - return DW_DLV_OK; -} - -/* Helper routine to avoid code duplication. -*/ -static int -_dwarf_setup_loc(Dwarf_Attribute attr, - Dwarf_Debug * dbg_ret, - Dwarf_CU_Context *cucontext_ret, - Dwarf_Half * form_ret, Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Half form = 0; - int blkres = DW_DLV_ERROR; - - if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); - } - if (attr->ar_cu_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT); - return (DW_DLV_ERROR); - } - *cucontext_ret = attr->ar_cu_context; - - dbg = attr->ar_cu_context->cc_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); - return (DW_DLV_ERROR); - } - *dbg_ret = dbg; - blkres = dwarf_whatform(attr, &form, error); - if (blkres != DW_DLV_OK) { - _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD); - return blkres; - } - *form_ret = form; - return DW_DLV_OK; -} - -/* Helper routine to avoid code duplication. -*/ -static int -_dwarf_get_loclist_header_start(Dwarf_Debug dbg, - Dwarf_Attribute attr, - Dwarf_Unsigned * loclist_offset, - Dwarf_Error * error) -{ - int blkres = dwarf_formudata(attr, loclist_offset, error); - if (blkres != DW_DLV_OK) { - return (blkres); - } - - if (!dbg->de_debug_loc.dss_data) { - int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error); - if (secload != DW_DLV_OK) { - return secload; - } - } - return DW_DLV_OK; -} - -/* When llbuf (see dwarf_loclist_n) is partially set up - and an error is encountered, tear it down as it - won't be used. -*/ -static void -_dwarf_cleanup_llbuf(Dwarf_Debug dbg, Dwarf_Locdesc ** llbuf, int count) -{ - int i; - for (i = 0; i < count; ++i) { - dwarf_dealloc(dbg, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK); - dwarf_dealloc(dbg, llbuf[i], DW_DLA_LOCDESC); - } - dwarf_dealloc(dbg, llbuf, DW_DLA_LIST); -} - -/* - Handles simple location entries and loclists. - Returns all the Locdesc's thru llbuf. - -*/ -int -dwarf_loclist_n(Dwarf_Attribute attr, - Dwarf_Locdesc *** llbuf_out, - Dwarf_Signed * listlen_out, Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - /* - Dwarf_Attribute that describes the DW_AT_location in die, if - present. */ - Dwarf_Attribute loc_attr = attr; - - /* Dwarf_Block that describes a single location expression. */ - Dwarf_Block loc_block; - - /* A pointer to the current Dwarf_Locdesc read. */ - Dwarf_Locdesc *locdesc = 0; - - Dwarf_Half form = 0; - Dwarf_Addr lowpc = 0; - Dwarf_Addr highpc = 0; - Dwarf_Signed listlen = 0; - Dwarf_Locdesc **llbuf = 0; - Dwarf_CU_Context cucontext = 0; - unsigned address_size = 0; - - int blkres = DW_DLV_ERROR; - int setup_res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - setup_res = _dwarf_setup_loc(attr, &dbg,&cucontext, &form, error); - if (setup_res != DW_DLV_OK) { - return setup_res; - } - address_size = cucontext->cc_address_size; - /* If this is a form_block then it's a location expression. If it's - DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */ - if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP || - cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) && - (form == DW_FORM_data4 || form == DW_FORM_data8)) || - (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 && - form == DW_FORM_sec_offset)) - { - - - /* A reference to .debug_loc, with an offset in .debug_loc of a - loclist */ - Dwarf_Unsigned loclist_offset = 0; - int off_res = DW_DLV_ERROR; - int count_res = DW_DLV_ERROR; - int loclist_count; - int lli; - - off_res = _dwarf_get_loclist_header_start(dbg, - attr, &loclist_offset, - error); - if (off_res != DW_DLV_OK) { - return off_res; - } - count_res = _dwarf_get_loclist_count(dbg, loclist_offset, - address_size, - &loclist_count, error); - listlen = loclist_count; - if (count_res != DW_DLV_OK) { - return count_res; - } - if (loclist_count == 0) { - return DW_DLV_NO_ENTRY; - } - - llbuf = (Dwarf_Locdesc **) - _dwarf_get_alloc(dbg, DW_DLA_LIST, loclist_count); - if (!llbuf) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - for (lli = 0; lli < loclist_count; ++lli) { - blkres = _dwarf_read_loc_section(dbg, &loc_block, - &lowpc, - &highpc, - loclist_offset, - address_size, - error); - if (blkres != DW_DLV_OK) { - _dwarf_cleanup_llbuf(dbg, llbuf, lli); - return (blkres); - } - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - address_size, - lowpc, highpc, error); - if (locdesc == NULL) { - _dwarf_cleanup_llbuf(dbg, llbuf, lli); - /* low level error already set: let it be passed back */ - return (DW_DLV_ERROR); - } - llbuf[lli] = locdesc; - - /* Now get to next loclist entry offset. */ - loclist_offset = loc_block.bl_section_offset + - loc_block.bl_len; - } - - - } else { - Dwarf_Block *tblock = 0; - - blkres = dwarf_formblock(loc_attr, &tblock, error); - if (blkres != DW_DLV_OK) { - return (blkres); - } - loc_block = *tblock; - /* We copied tblock contents to the stack var, so can dealloc - tblock now. Avoids leaks. */ - dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK); - listlen = 1; /* One by definition of a location entry. */ - lowpc = 0; /* HACK */ - highpc = (Dwarf_Unsigned) (-1LL); /* HACK */ - - /* An empty location description (block length 0) means the - code generator emitted no variable, the variable was not - generated, it was unused or perhaps never tested after being - set. Dwarf2, section 2.4.1 In other words, it is not an - error, and we don't test for block length 0 specially here. */ - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - address_size, - lowpc, highpc, error); - if (locdesc == NULL) { - /* low level error already set: let it be passed back */ - return (DW_DLV_ERROR); - } - llbuf = (Dwarf_Locdesc **) - _dwarf_get_alloc(dbg, DW_DLA_LIST, listlen); - if (!llbuf) { - /* Free the locdesc we allocated but won't use. */ - dwarf_dealloc(dbg, locdesc, DW_DLA_LOCDESC); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - llbuf[0] = locdesc; - } - - *llbuf_out = llbuf; - *listlen_out = listlen; - return (DW_DLV_OK); -} - - -/* - Handles only a location expression. - If called on a loclist, just returns one of those. - Cannot not handle a real loclist. - It returns the location expression as a loclist with - a single entry. - See dwarf_loclist_n() which handles any number - of location list entries. - - This is the original definition, and it simply - does not work for loclists. Kept for compatibility. -*/ -int -dwarf_loclist(Dwarf_Attribute attr, - Dwarf_Locdesc ** llbuf, - Dwarf_Signed * listlen, Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - /* Dwarf_Attribute that describes the DW_AT_location in die, if - present. */ - Dwarf_Attribute loc_attr = attr; - - /* Dwarf_Block that describes a single location expression. */ - Dwarf_Block loc_block; - - /* A pointer to the current Dwarf_Locdesc read. */ - Dwarf_Locdesc *locdesc = 0; - - Dwarf_Half form = 0; - Dwarf_Addr lowpc = 0; - Dwarf_Addr highpc = 0; - Dwarf_CU_Context cucontext = 0; - unsigned address_size = 0; - - int blkres = DW_DLV_ERROR; - int setup_res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - setup_res = _dwarf_setup_loc(attr, &dbg, &cucontext, &form, error); - if (setup_res != DW_DLV_OK) { - return setup_res; - } - address_size = cucontext->cc_address_size; - /* If this is a form_block then it's a location expression. If it's - DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */ - if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP || - cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) && - (form == DW_FORM_data4 || form == DW_FORM_data8)) || - (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 && - form == DW_FORM_sec_offset)) - { - - /* A reference to .debug_loc, with an offset in .debug_loc of a - loclist */ - Dwarf_Unsigned loclist_offset = 0; - int off_res = DW_DLV_ERROR; - - off_res = _dwarf_get_loclist_header_start(dbg, - attr, &loclist_offset, - error); - if (off_res != DW_DLV_OK) { - return off_res; - } - - /* With dwarf_loclist, just read a single entry */ - blkres = _dwarf_read_loc_section(dbg, &loc_block, - &lowpc, - &highpc, - loclist_offset, - address_size, - error); - if (blkres != DW_DLV_OK) { - return (blkres); - } - } else { - Dwarf_Block *tblock = 0; - - blkres = dwarf_formblock(loc_attr, &tblock, error); - if (blkres != DW_DLV_OK) { - return (blkres); - } - loc_block = *tblock; - /* We copied tblock contents to the stack var, so can dealloc - tblock now. Avoids leaks. */ - dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK); - lowpc = 0; /* HACK */ - highpc = (Dwarf_Unsigned) (-1LL); /* HACK */ - } - - /* An empty location description (block length 0) means the code - generator emitted no variable, the variable was not generated, - it was unused or perhaps never tested after being set. Dwarf2, - section 2.4.1 In other words, it is not an error, and we don't - test for block length 0 specially here. - See *dwarf_loclist_n() which handles the general case, this case - handles only a single location expression. */ - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - address_size, - lowpc, highpc, error); - if (locdesc == NULL) { - /* low level error already set: let it be passed back */ - return (DW_DLV_ERROR); - } - - *llbuf = locdesc; - *listlen = 1; - return (DW_DLV_OK); -} - - - -/* - Handles only a location expression. - It returns the location expression as a loclist with - a single entry. - - Usable to access dwarf expressions from any source, but - specifically from - DW_CFA_def_cfa_expression - DW_CFA_expression - DW_CFA_val_expression - - expression_in must point to a valid dwarf expression - set of bytes of length expression_length. Not - a DW_FORM_block*, just the expression bytes. - - If the address_size != de_pointer_size this will not work - right. FIXME. -*/ -int -dwarf_loclist_from_expr(Dwarf_Debug dbg, - Dwarf_Ptr expression_in, - Dwarf_Unsigned expression_length, - Dwarf_Locdesc ** llbuf, - Dwarf_Signed * listlen, Dwarf_Error * error) -{ - int res = 0; - Dwarf_Half addr_size = dbg->de_pointer_size; - res = dwarf_loclist_from_expr_a(dbg,expression_in, - expression_length, addr_size,llbuf,listlen,error); - return res; -} -/* New April 27 2009. Adding addr_size argument for the rare - * cases where an object has CUs with a different address_size. */ -int -dwarf_loclist_from_expr_a(Dwarf_Debug dbg, - Dwarf_Ptr expression_in, - Dwarf_Unsigned expression_length, - Dwarf_Half addr_size, - Dwarf_Locdesc ** llbuf, - Dwarf_Signed * listlen, Dwarf_Error * error) -{ - /* Dwarf_Block that describes a single location expression. */ - Dwarf_Block loc_block; - - /* A pointer to the current Dwarf_Locdesc read. */ - Dwarf_Locdesc *locdesc = 0; - Dwarf_Addr lowpc = 0; - Dwarf_Addr highpc = (Dwarf_Unsigned) (-1LL); - - memset(&loc_block,0,sizeof(loc_block)); - loc_block.bl_len = expression_length; - loc_block.bl_data = expression_in; - loc_block.bl_from_loclist = 0; /* Not from loclist. */ - loc_block.bl_section_offset = 0; /* Fake. Not meaningful. */ - - /* An empty location description (block length 0) means the code - generator emitted no variable, the variable was not generated, - it was unused or perhaps never tested after being set. Dwarf2, - section 2.4.1 In other words, it is not an error, and we don't - test for block length 0 specially here. */ - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - addr_size,lowpc, highpc, error); - if (locdesc == NULL) { - /* low level error already set: let it be passed back */ - return (DW_DLV_ERROR); - } - - *llbuf = locdesc; - *listlen = 1; - return (DW_DLV_OK); -} - -/* Usable to read a single loclist or to read a block of them - or to read an entire section's loclists. - - It's broken because it's not safe to read a loclist entry - when we do not know the address size (in any object where - address size can vary by compilation unit). -*/ - - /*ARGSUSED*/ int -dwarf_get_loclist_entry(Dwarf_Debug dbg, - Dwarf_Unsigned offset, - Dwarf_Addr * hipc_offset, - Dwarf_Addr * lopc_offset, - Dwarf_Ptr * data, - Dwarf_Unsigned * entry_len, - Dwarf_Unsigned * next_entry, - Dwarf_Error * error) -{ - Dwarf_Block b; - Dwarf_Addr lowpc = 0; - Dwarf_Addr highpc = 0; - Dwarf_Half address_size = 0; - int res = DW_DLV_ERROR; - - if (!dbg->de_debug_loc.dss_data) { - int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error); - if (secload != DW_DLV_OK) { - return secload; - } - } - - /* FIXME: address_size is not necessarily the same in every frame. */ - address_size = dbg->de_pointer_size; - res = _dwarf_read_loc_section(dbg, - &b, &lowpc, &highpc, offset, - address_size,error); - if (res != DW_DLV_OK) { - return res; - } - *hipc_offset = highpc; - *lopc_offset = lowpc; - *entry_len = b.bl_len; - *data = b.bl_data; - *next_entry = b.bl_len + b.bl_section_offset; - return DW_DLV_OK; -} - - |