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:
Jan Kratochvil 2010-06-07 19:55:33 +00:00
parent 17ea53c331
commit 5c631832c1
10 changed files with 315 additions and 22 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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.

View file

@ -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.

View 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 */

View 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"