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 | 1353 |
1 files changed, 757 insertions, 596 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_loc.c b/usr/src/tools/ctf/dwarf/common/dwarf_loc.c index b8f75b90e2..f28b27b630 100644 --- a/usr/src/tools/ctf/dwarf/common/dwarf_loc.c +++ b/usr/src/tools/ctf/dwarf/common/dwarf_loc.c @@ -1,6 +1,7 @@ /* - Copyright (C) 2000,2003 Silicon Graphics, Inc. All Rights Reserved. + 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 @@ -19,10 +20,10 @@ 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. - Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, Mountain View, CA 94043, or: http://www.sgi.com @@ -32,13 +33,20 @@ 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, @@ -54,39 +62,43 @@ */ static Dwarf_Locdesc * _dwarf_get_locdesc(Dwarf_Debug dbg, - Dwarf_Block * loc_block, - Dwarf_Addr lowpc, - Dwarf_Addr highpc, Dwarf_Error * error) + 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; + Dwarf_Unsigned loc_len = 0; /* Sweeps the block containing the location expression. */ - Dwarf_Small *loc_ptr; + Dwarf_Small *loc_ptr = 0; /* Current location operator. */ - Dwarf_Small atom; + Dwarf_Small atom = 0; /* Offset of current operator from start of block. */ - Dwarf_Unsigned offset; + 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, prev_loc, head_loc = NULL; + 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; + Dwarf_Unsigned op_count = 0; /* Contiguous block of Dwarf_Loc's for Dwarf_Locdesc. */ - Dwarf_Loc *block_loc; + Dwarf_Loc *block_loc = 0; /* Dwarf_Locdesc pointer to be returned. */ - Dwarf_Locdesc *locdesc; + Dwarf_Locdesc *locdesc = 0; - Dwarf_Word leb128_length; - Dwarf_Unsigned i; + Dwarf_Word leb128_length = 0; + Dwarf_Unsigned i = 0; /* ***** BEGIN CODE ***** */ @@ -97,341 +109,396 @@ _dwarf_get_locdesc(Dwarf_Debug dbg, 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, dbg->de_pointer_size); - loc_ptr += dbg->de_pointer_size; - offset += dbg->de_pointer_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; - 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); - 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); - 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; - - 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; - } + 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); + (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); + _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); + (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); + (Dwarf_Locdesc *) _dwarf_get_alloc(dbg, DW_DLA_LOCDESC, 1); if (locdesc == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (NULL); + _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (NULL); } locdesc->ld_cents = op_count; @@ -453,52 +520,53 @@ _dwarf_get_locdesc(Dwarf_Debug dbg, static int _dwarf_read_loc_section(Dwarf_Debug dbg, - Dwarf_Block * return_block, - Dwarf_Addr * lowpc, Dwarf_Addr * hipc, - Dwarf_Off sec_offset, Dwarf_Error * error) + 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 + sec_offset; - int address_size = dbg->de_pointer_size; + 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); + 2 * address_size + sizeof(Dwarf_Half); - if (sec_offset >= dbg->de_debug_loc_size) { - /* We're at the end. No more present. */ - return DW_DLV_NO_ENTRY; + 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_size) { - _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); - return DW_DLV_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); + 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); + /* 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); + /* 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_size) { - _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); - return DW_DLV_ERROR; - } + 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; @@ -508,37 +576,37 @@ _dwarf_read_loc_section(Dwarf_Debug dbg, 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; + ((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, - int *loclist_count, Dwarf_Error * error) + 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, error); - - if (res != DW_DLV_OK) { - return res; - } - offset = b.bl_len + b.bl_section_offset; - if (lowpc == 0 && highpc == 0) { - break; - } - count++; + 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; @@ -548,35 +616,36 @@ _dwarf_get_loclist_count(Dwarf_Debug dbg, */ static int _dwarf_setup_loc(Dwarf_Attribute attr, - Dwarf_Debug * dbg_ret, - Dwarf_Half * form_ret, Dwarf_Error * error) + 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; + int blkres = DW_DLV_ERROR; if (attr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ATTR_NULL); - return (DW_DLV_ERROR); + _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); + _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); + _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; + _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD); + return blkres; } *form_ret = form; - return DW_DLV_OK; } @@ -584,24 +653,20 @@ _dwarf_setup_loc(Dwarf_Attribute attr, */ static int _dwarf_get_loclist_header_start(Dwarf_Debug dbg, - Dwarf_Attribute attr, - Dwarf_Unsigned * loclist_offset, - Dwarf_Error * error) + Dwarf_Attribute attr, + Dwarf_Unsigned * loclist_offset, + Dwarf_Error * error) { - int secload = 0; int blkres = dwarf_formudata(attr, loclist_offset, error); - if (blkres != DW_DLV_OK) { - return (blkres); + return (blkres); } - if (!dbg->de_debug_loc) { - secload = _dwarf_load_section(dbg, - dbg->de_debug_loc_index, - &dbg->de_debug_loc, error); - if (secload != DW_DLV_OK) { - return secload; - } + 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; } @@ -614,23 +679,22 @@ 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[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. - + 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_Locdesc *** llbuf_out, + Dwarf_Signed * listlen_out, Dwarf_Error * error) { Dwarf_Debug dbg; @@ -650,110 +714,123 @@ dwarf_loclist_n(Dwarf_Attribute attr, Dwarf_Addr highpc = 0; Dwarf_Signed listlen = 0; Dwarf_Locdesc **llbuf = 0; + Dwarf_CU_Context cucontext = 0; + unsigned address_size = 0; - int blkres; - int setup_res; + int blkres = DW_DLV_ERROR; + int setup_res = DW_DLV_ERROR; /* ***** BEGIN CODE ***** */ - setup_res = _dwarf_setup_loc(attr, &dbg, &form, error); + setup_res = _dwarf_setup_loc(attr, &dbg,&cucontext, &form, error); if (setup_res != DW_DLV_OK) { - return setup_res; + 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 (form == DW_FORM_data4 || form == DW_FORM_data8) { - - /* A reference to .debug_loc, with an offset in .debug_loc of a - loclist */ - Dwarf_Unsigned loclist_offset = 0; - int off_res; - int count_res; - 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, - &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, error); - if (blkres != DW_DLV_OK) { - _dwarf_cleanup_llbuf(dbg, llbuf, lli); - return (blkres); - } - locdesc = _dwarf_get_locdesc(dbg, &loc_block, - 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; - } + 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, - 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; + 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; @@ -761,27 +838,27 @@ dwarf_loclist_n(Dwarf_Attribute attr, 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 + 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. + 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_Locdesc ** llbuf, + Dwarf_Signed * listlen, Dwarf_Error * error) { Dwarf_Debug dbg; - /* - Dwarf_Attribute that describes the DW_AT_location in die, if + /* Dwarf_Attribute that describes the DW_AT_location in die, if present. */ Dwarf_Attribute loc_attr = attr; @@ -794,68 +871,151 @@ dwarf_loclist(Dwarf_Attribute attr, Dwarf_Half form = 0; Dwarf_Addr lowpc = 0; Dwarf_Addr highpc = 0; + Dwarf_CU_Context cucontext = 0; + unsigned address_size = 0; - int blkres; - int setup_res; + int blkres = DW_DLV_ERROR; + int setup_res = DW_DLV_ERROR; /* ***** BEGIN CODE ***** */ - setup_res = _dwarf_setup_loc(attr, &dbg, &form, error); + setup_res = _dwarf_setup_loc(attr, &dbg, &cucontext, &form, error); if (setup_res != DW_DLV_OK) { - return setup_res; + 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 (form == DW_FORM_data4 || form == DW_FORM_data8) { + 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 */ + } - /* A reference to .debug_loc, with an offset in .debug_loc of a - loclist */ - Dwarf_Unsigned loclist_offset = 0; - int off_res; + /* 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); + } - off_res = _dwarf_get_loclist_header_start(dbg, - attr, &loclist_offset, - error); - if (off_res != DW_DLV_OK) { - return off_res; - } + *llbuf = locdesc; + *listlen = 1; + return (DW_DLV_OK); +} - /* With dwarf_loclist, just read a single entry */ - blkres = _dwarf_read_loc_section(dbg, &loc_block, - &lowpc, - &highpc, - loclist_offset, error); - if (blkres != DW_DLV_OK) { - return (blkres); - } +/* + 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); - } 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 */ - } + 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. FIXME: doing this once - is wrong, needs to handle low/hi pc sets. */ - locdesc = _dwarf_get_locdesc(dbg, &loc_block, lowpc, highpc, error); + 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); + /* low level error already set: let it be passed back */ + return (DW_DLV_ERROR); } *llbuf = locdesc; @@ -866,47 +1026,48 @@ dwarf_loclist(Dwarf_Attribute attr, /* 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_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; - Dwarf_Addr highpc; - int res; - - if (!dbg->de_debug_loc) { - int secload = _dwarf_load_section(dbg, - dbg->de_debug_loc_index, - &dbg->de_debug_loc, - error); - - if (secload != DW_DLV_OK) { - return secload; - } + 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, error); + &b, &lowpc, &highpc, offset, + address_size,error); if (res != DW_DLV_OK) { - return res; + 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; +} - -} |
