gdb/
Fix PR 10640. * dwarf2-frame.c (no_dwarf_call): New function. (execute_stack_op): Set CTX->DWARF_CALL. * dwarf2expr.c (execute_stack_op) <DW_OP_call2, DW_OP_call4>: New. * dwarf2expr.h (struct dwarf_expr_context) <dwarf_call>: New. (struct dwarf_expr_context) <get_subr>: Remove the #if0-ed field. * dwarf2loc.c (per_cu_dwarf_call, dwarf_expr_dwarf_call): New functions. (dwarf2_evaluate_loc_desc): Initialize CTX->DWARF_CALL. (needs_frame_dwarf_call): New function. (dwarf2_loc_desc_needs_frame): Initialize CTX->DWARF_CALL. * dwarf2read.c (follow_die_offset): Based on former follow_die_ref. Update the comment. Move variables die, offset and error call to ... (follow_die_ref): ... a new function. (dwarf2_fetch_die_location_block): New function. * dwarf2loc.h (dwarf2_fetch_die_location_block): New prototype. gdb/testsuite/ Test PR 10640. * gdb.dwarf2/dw2-op-call.exp, gdb.dwarf2/dw2-op-call.S: New.
This commit is contained in:
parent
17ea53c331
commit
5c631832c1
10 changed files with 315 additions and 22 deletions
|
@ -1,3 +1,21 @@
|
|||
2010-06-07 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
Fix PR 10640.
|
||||
* dwarf2-frame.c (no_dwarf_call): New function.
|
||||
(execute_stack_op): Set CTX->DWARF_CALL.
|
||||
* dwarf2expr.c (execute_stack_op) <DW_OP_call2, DW_OP_call4>: New.
|
||||
* dwarf2expr.h (struct dwarf_expr_context) <dwarf_call>: New.
|
||||
(struct dwarf_expr_context) <get_subr>: Remove the #if0-ed field.
|
||||
* dwarf2loc.c (per_cu_dwarf_call, dwarf_expr_dwarf_call): New functions.
|
||||
(dwarf2_evaluate_loc_desc): Initialize CTX->DWARF_CALL.
|
||||
(needs_frame_dwarf_call): New function.
|
||||
(dwarf2_loc_desc_needs_frame): Initialize CTX->DWARF_CALL.
|
||||
* dwarf2read.c (follow_die_offset): Based on former follow_die_ref.
|
||||
Update the comment. Move variables die, offset and error call to ...
|
||||
(follow_die_ref): ... a new function.
|
||||
(dwarf2_fetch_die_location_block): New function.
|
||||
* dwarf2loc.h (dwarf2_fetch_die_location_block): New prototype.
|
||||
|
||||
2010-06-07 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* dwarf2loc.c (struct dwarf_expr_baton) Replace objfile by per_cu.
|
||||
|
|
|
@ -328,6 +328,15 @@ no_get_tls_address (void *baton, CORE_ADDR offset)
|
|||
_("Support for DW_OP_GNU_push_tls_address is unimplemented"));
|
||||
}
|
||||
|
||||
/* Helper function for execute_stack_op. */
|
||||
|
||||
static void
|
||||
no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
|
||||
{
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("Support for DW_OP_call* is invalid in CFI"));
|
||||
}
|
||||
|
||||
/* Execute the required actions for both the DW_CFA_restore and
|
||||
DW_CFA_restore_extended instructions. */
|
||||
static void
|
||||
|
@ -378,6 +387,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
|
|||
ctx->get_frame_base = no_get_frame_base;
|
||||
ctx->get_frame_cfa = no_get_frame_cfa;
|
||||
ctx->get_tls_address = no_get_tls_address;
|
||||
ctx->dwarf_call = no_dwarf_call;
|
||||
|
||||
dwarf_expr_push (ctx, initial, initial_in_stack_memory);
|
||||
dwarf_expr_eval (ctx, exp, len);
|
||||
|
|
|
@ -911,6 +911,18 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
ctx->initialized = 0;
|
||||
goto no_push;
|
||||
|
||||
case DW_OP_call2:
|
||||
result = extract_unsigned_integer (op_ptr, 2, byte_order);
|
||||
op_ptr += 2;
|
||||
ctx->dwarf_call (ctx, result);
|
||||
goto no_push;
|
||||
|
||||
case DW_OP_call4:
|
||||
result = extract_unsigned_integer (op_ptr, 4, byte_order);
|
||||
op_ptr += 4;
|
||||
ctx->dwarf_call (ctx, result);
|
||||
goto no_push;
|
||||
|
||||
default:
|
||||
error (_("Unhandled dwarf expression opcode 0x%x"), op);
|
||||
}
|
||||
|
|
|
@ -97,15 +97,14 @@ struct dwarf_expr_context
|
|||
DW_OP_GNU_push_tls_address. */
|
||||
CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset);
|
||||
|
||||
/* Execute DW_AT_location expression for the DWARF expression subroutine in
|
||||
the DIE at DIE_OFFSET in the CU from CTX. Do not touch STACK while it
|
||||
being passed to and returned from the called DWARF subroutine. */
|
||||
void (*dwarf_call) (struct dwarf_expr_context *ctx, size_t die_offset);
|
||||
|
||||
#if 0
|
||||
/* Not yet implemented. */
|
||||
|
||||
/* Return the location expression for the dwarf expression
|
||||
subroutine in the die at OFFSET in the current compilation unit.
|
||||
The result must be live until the current expression evaluation
|
||||
is complete. */
|
||||
unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length);
|
||||
|
||||
/* Return the `object address' for DW_OP_push_object_address. */
|
||||
CORE_ADDR (*get_object_address) (void *baton);
|
||||
#endif
|
||||
|
|
|
@ -232,6 +232,33 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
|
|||
return target_translate_tls_address (objfile, offset);
|
||||
}
|
||||
|
||||
/* Call DWARF subroutine from DW_AT_location of DIE at DIE_OFFSET in current CU
|
||||
(as is PER_CU). State of the CTX is not affected by the call and return. */
|
||||
|
||||
static void
|
||||
per_cu_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset,
|
||||
struct dwarf2_per_cu_data *per_cu)
|
||||
{
|
||||
struct dwarf2_locexpr_baton block;
|
||||
|
||||
block = dwarf2_fetch_die_location_block (die_offset, per_cu);
|
||||
|
||||
/* DW_OP_call_ref is currently not supported. */
|
||||
gdb_assert (block.per_cu == per_cu);
|
||||
|
||||
dwarf_expr_eval (ctx, block.data, block.size);
|
||||
}
|
||||
|
||||
/* Helper interface of per_cu_dwarf_call for dwarf2_evaluate_loc_desc. */
|
||||
|
||||
static void
|
||||
dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
|
||||
{
|
||||
struct dwarf_expr_baton *debaton = ctx->baton;
|
||||
|
||||
return per_cu_dwarf_call (ctx, die_offset, debaton->per_cu);
|
||||
}
|
||||
|
||||
struct piece_closure
|
||||
{
|
||||
/* Reference count. */
|
||||
|
@ -815,6 +842,7 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
|
|||
ctx->get_frame_base = dwarf_expr_frame_base;
|
||||
ctx->get_frame_cfa = dwarf_expr_frame_cfa;
|
||||
ctx->get_tls_address = dwarf_expr_tls_address;
|
||||
ctx->dwarf_call = dwarf_expr_dwarf_call;
|
||||
|
||||
dwarf_expr_eval (ctx, data, size);
|
||||
if (ctx->num_pieces > 0)
|
||||
|
@ -962,6 +990,16 @@ needs_frame_tls_address (void *baton, CORE_ADDR offset)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Helper interface of per_cu_dwarf_call for dwarf2_loc_desc_needs_frame. */
|
||||
|
||||
static void
|
||||
needs_frame_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
|
||||
{
|
||||
struct needs_frame_baton *nf_baton = ctx->baton;
|
||||
|
||||
return per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu);
|
||||
}
|
||||
|
||||
/* Return non-zero iff the location expression at DATA (length SIZE)
|
||||
requires a frame to evaluate. */
|
||||
|
||||
|
@ -988,6 +1026,7 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size,
|
|||
ctx->get_frame_base = needs_frame_frame_base;
|
||||
ctx->get_frame_cfa = needs_frame_frame_cfa;
|
||||
ctx->get_tls_address = needs_frame_tls_address;
|
||||
ctx->dwarf_call = needs_frame_dwarf_call;
|
||||
|
||||
dwarf_expr_eval (ctx, data, size);
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu);
|
|||
/* Return the offset size given in the compilation unit header for CU. */
|
||||
int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *cu);
|
||||
|
||||
struct dwarf2_locexpr_baton dwarf2_fetch_die_location_block
|
||||
(unsigned int offset, struct dwarf2_per_cu_data *per_cu);
|
||||
|
||||
/* The symbol location baton types used by the DWARF-2 reader (i.e.
|
||||
SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). "struct
|
||||
dwarf2_locexpr_baton" is for a symbol with a single location
|
||||
|
|
|
@ -10736,30 +10736,25 @@ follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
|
|||
return die;
|
||||
}
|
||||
|
||||
/* Follow reference attribute ATTR of SRC_DIE.
|
||||
On entry *REF_CU is the CU of SRC_DIE.
|
||||
/* Follow reference OFFSET.
|
||||
On entry *REF_CU is the CU of source DIE referencing OFFSET.
|
||||
On exit *REF_CU is the CU of the result. */
|
||||
|
||||
static struct die_info *
|
||||
follow_die_ref (struct die_info *src_die, struct attribute *attr,
|
||||
struct dwarf2_cu **ref_cu)
|
||||
follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu)
|
||||
{
|
||||
struct die_info *die;
|
||||
unsigned int offset;
|
||||
struct die_info temp_die;
|
||||
struct dwarf2_cu *target_cu, *cu = *ref_cu;
|
||||
|
||||
gdb_assert (cu->per_cu != NULL);
|
||||
|
||||
offset = dwarf2_get_ref_die_offset (attr);
|
||||
|
||||
if (cu->per_cu->from_debug_types)
|
||||
{
|
||||
/* .debug_types CUs cannot reference anything outside their CU.
|
||||
If they need to, they have to reference a signatured type via
|
||||
DW_FORM_sig8. */
|
||||
if (! offset_in_cu_p (&cu->header, offset))
|
||||
goto not_found;
|
||||
return NULL;
|
||||
target_cu = cu;
|
||||
}
|
||||
else if (! offset_in_cu_p (&cu->header, offset))
|
||||
|
@ -10779,15 +10774,67 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
|
|||
|
||||
*ref_cu = target_cu;
|
||||
temp_die.offset = offset;
|
||||
die = htab_find_with_hash (target_cu->die_hash, &temp_die, offset);
|
||||
if (die)
|
||||
return die;
|
||||
return htab_find_with_hash (target_cu->die_hash, &temp_die, offset);
|
||||
}
|
||||
|
||||
not_found:
|
||||
/* Follow reference attribute ATTR of SRC_DIE.
|
||||
On entry *REF_CU is the CU of SRC_DIE.
|
||||
On exit *REF_CU is the CU of the result. */
|
||||
|
||||
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
|
||||
"at 0x%x [in module %s]"),
|
||||
offset, src_die->offset, cu->objfile->name);
|
||||
static struct die_info *
|
||||
follow_die_ref (struct die_info *src_die, struct attribute *attr,
|
||||
struct dwarf2_cu **ref_cu)
|
||||
{
|
||||
unsigned int offset = dwarf2_get_ref_die_offset (attr);
|
||||
struct dwarf2_cu *cu = *ref_cu;
|
||||
struct die_info *die;
|
||||
|
||||
die = follow_die_offset (offset, ref_cu);
|
||||
if (!die)
|
||||
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
|
||||
"at 0x%x [in module %s]"),
|
||||
offset, src_die->offset, cu->objfile->name);
|
||||
|
||||
return die;
|
||||
}
|
||||
|
||||
/* Return DWARF block and its CU referenced by OFFSET at PER_CU. Returned
|
||||
value is intended for DW_OP_call*. */
|
||||
|
||||
struct dwarf2_locexpr_baton
|
||||
dwarf2_fetch_die_location_block (unsigned int offset,
|
||||
struct dwarf2_per_cu_data *per_cu)
|
||||
{
|
||||
struct dwarf2_cu *cu = per_cu->cu;
|
||||
struct die_info *die;
|
||||
struct attribute *attr;
|
||||
struct dwarf2_locexpr_baton retval;
|
||||
|
||||
die = follow_die_offset (offset, &cu);
|
||||
if (!die)
|
||||
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
|
||||
offset, per_cu->cu->objfile->name);
|
||||
|
||||
attr = dwarf2_attr (die, DW_AT_location, cu);
|
||||
if (!attr)
|
||||
{
|
||||
/* DWARF: "If there is no such attribute, then there is no effect.". */
|
||||
|
||||
retval.data = NULL;
|
||||
retval.size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!attr_form_is_block (attr))
|
||||
error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
|
||||
"is neither DW_FORM_block* nor DW_FORM_exprloc"),
|
||||
offset, per_cu->cu->objfile->name);
|
||||
|
||||
retval.data = DW_BLOCK (attr)->data;
|
||||
retval.size = DW_BLOCK (attr)->size;
|
||||
}
|
||||
retval.per_cu = cu->per_cu;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Follow the signature attribute ATTR in SRC_DIE.
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2010-06-07 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
Test PR 10640.
|
||||
* gdb.dwarf2/dw2-op-call.exp, gdb.dwarf2/dw2-op-call.S: New.
|
||||
|
||||
2010-06-07 Sami Wagiaalla <swagiaal@redhat.com>
|
||||
|
||||
* gdb.cp/koenig.exp: Test for ADL operators.
|
||||
|
|
119
gdb/testsuite/gdb.dwarf2/dw2-op-call.S
Normal file
119
gdb/testsuite/gdb.dwarf2/dw2-op-call.S
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2009 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Test DW_OP_call2 and DW_OP_call4, PR gdb/10640. */
|
||||
|
||||
.section .data
|
||||
array1: .2byte 1
|
||||
array2: .2byte 2
|
||||
array3: .2byte 3
|
||||
|
||||
.section .debug_info
|
||||
.Lcu1_begin:
|
||||
/* CU header */
|
||||
.4byte .Lcu1_end - .Lcu1_start /* Length of Compilation Unit */
|
||||
.Lcu1_start:
|
||||
.2byte 2 /* DWARF Version */
|
||||
.4byte .Labbrev1_begin /* Offset into abbrev section */
|
||||
.byte 4 /* Pointer size */
|
||||
|
||||
/* CU die */
|
||||
.uleb128 1 /* Abbrev: DW_TAG_compile_unit */
|
||||
.ascii "file1.txt\0" /* DW_AT_name */
|
||||
.ascii "GNU C 3.3.3\0" /* DW_AT_producer */
|
||||
.byte 2 /* DW_LANG_C (C) */
|
||||
|
||||
.L2byte_type:
|
||||
.uleb128 2 /* Abbrev: DW_TAG_base_type */
|
||||
.ascii "2byte\0" /* DW_AT_name */
|
||||
.byte 2 /* DW_AT_byte_size */
|
||||
.byte 7 /* DW_AT_encoding: DW_ATE_unsigned */
|
||||
|
||||
.Larray1:
|
||||
.uleb128 3 /* Abbrev: DW_TAG_variable */
|
||||
.ascii "array1\0" /* DW_AT_name */
|
||||
.4byte .L2byte_type-.Lcu1_begin /* DW_AT_type */
|
||||
.byte 2f - 1f /* DW_AT_location */
|
||||
1: .byte 3 /* DW_OP_addr */
|
||||
.4byte array /* <addr> */
|
||||
2:
|
||||
|
||||
.uleb128 3 /* Abbrev: DW_TAG_variable */
|
||||
.ascii "array2\0" /* DW_AT_name */
|
||||
.4byte .L2byte_type-.Lcu1_begin /* DW_AT_type */
|
||||
.byte 2f - 1f /* DW_AT_location */
|
||||
1: .byte 0x98 /* DW_OP_call2 */
|
||||
.2byte .Larray1-.Lcu1_begin /* <current CU offset> */
|
||||
.byte 0x23 /* DW_OP_plus_uconst */
|
||||
.uleb128 array2-array1 /* <uconst> */
|
||||
2:
|
||||
|
||||
.uleb128 3 /* Abbrev: DW_TAG_variable */
|
||||
.ascii "array3\0" /* DW_AT_name */
|
||||
.4byte .L2byte_type-.Lcu1_begin /* DW_AT_type */
|
||||
.byte 2f - 1f /* DW_AT_location */
|
||||
1: .byte 0x99 /* DW_OP_call4 */
|
||||
.4byte .Larray1-.Lcu1_begin /* <current CU offset> */
|
||||
.byte 0x23 /* DW_OP_plus_uconst */
|
||||
.uleb128 array3-array1 /* <uconst> */
|
||||
2:
|
||||
|
||||
.byte 0 /* End of children of CU */
|
||||
|
||||
.Lcu1_end:
|
||||
|
||||
/* Abbrev table */
|
||||
.section .debug_abbrev
|
||||
.Labbrev1_begin:
|
||||
.uleb128 1 /* Abbrev code */
|
||||
.uleb128 0x11 /* DW_TAG_compile_unit */
|
||||
.byte 1 /* has_children */
|
||||
.uleb128 0x3 /* DW_AT_name */
|
||||
.uleb128 0x8 /* DW_FORM_string */
|
||||
.uleb128 0x25 /* DW_AT_producer */
|
||||
.uleb128 0x8 /* DW_FORM_string */
|
||||
.uleb128 0x13 /* DW_AT_language */
|
||||
.uleb128 0xb /* DW_FORM_data1 */
|
||||
.byte 0x0 /* Terminator */
|
||||
.byte 0x0 /* Terminator */
|
||||
|
||||
.uleb128 2 /* Abbrev code */
|
||||
.uleb128 0x24 /* DW_TAG_base_type */
|
||||
.byte 0 /* has_children */
|
||||
.uleb128 0x3 /* DW_AT_name */
|
||||
.uleb128 0x8 /* DW_FORM_string */
|
||||
.uleb128 0xb /* DW_AT_byte_size */
|
||||
.uleb128 0xb /* DW_FORM_data1 */
|
||||
.uleb128 0x3e /* DW_AT_encoding */
|
||||
.uleb128 0xb /* DW_FORM_data1 */
|
||||
.byte 0x0 /* Terminator */
|
||||
.byte 0x0 /* Terminator */
|
||||
|
||||
.uleb128 3 /* Abbrev code */
|
||||
.uleb128 0x34 /* DW_TAG_variable */
|
||||
.byte 0 /* has_children */
|
||||
.uleb128 0x3 /* DW_AT_name */
|
||||
.uleb128 0x8 /* DW_FORM_string */
|
||||
.uleb128 0x49 /* DW_AT_type */
|
||||
.uleb128 0x13 /* DW_FORM_ref4 */
|
||||
.uleb128 0x2 /* DW_AT_location */
|
||||
.uleb128 0xa /* DW_FORM_block1 */
|
||||
.byte 0x0 /* Terminator */
|
||||
.byte 0x0 /* Terminator */
|
||||
|
||||
.byte 0x0 /* Terminator */
|
||||
.byte 0x0 /* Terminator */
|
41
gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
Normal file
41
gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Copyright 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test DW_OP_call2 and DW_OP_call4, PR gdb/10640.
|
||||
|
||||
# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
# For now pick a sampling of likely targets.
|
||||
if {![istarget *-*-linux*]
|
||||
&& ![istarget *-*-gnu*]
|
||||
&& ![istarget *-*-elf*]
|
||||
&& ![istarget *-*-openbsd*]
|
||||
&& ![istarget arm-*-eabi*]
|
||||
&& ![istarget powerpc-*-eabi*]} {
|
||||
return 0
|
||||
}
|
||||
|
||||
set testfile "dw2-op-call"
|
||||
set srcfile ${testfile}.S
|
||||
set executable ${testfile}.x
|
||||
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${executable}" object {nodebug}] != "" } {
|
||||
return -1
|
||||
}
|
||||
|
||||
clean_restart $executable
|
||||
|
||||
gdb_test "p array1" " = 1"
|
||||
gdb_test "p array2" " = 2" "array2 using DW_OP_call2"
|
||||
gdb_test "p array3" " = 3" "array3 using DW_OP_call4"
|
Loading…
Add table
Reference in a new issue