* dwarf2loc.c (invalid_synthetic_pointer): Move earlier.

(indirect_pieced_value): Call dwarf2_fetch_constant_bytes
	if needed.
	* dwarf2loc.h (dwarf2_fetch_constant_bytes): Declare.
	* dwarf2read.c (write_constant_as_bytes)
	(dwarf2_fetch_constant_bytes): New functions.
gdb/testsuite
	* gdb.dwarf2/implptrconst.c: New file.
	* gdb.dwarf2/implptrconst.exp: New file.
	* lib/dwarf.exp (Dwarf::_nz_quote): New proc.
	(Dwarf::_handle_DW_FORM): Handle DW_FORM_block1.
	(Dwarf::_location): Handle DW_OP_GNU_implicit_pointer.
This commit is contained in:
Tom Tromey 2013-05-06 19:44:04 +00:00
parent 3aef2284c6
commit b6807d988a
8 changed files with 359 additions and 16 deletions

View File

@ -1,3 +1,12 @@
2013-05-06 Tom Tromey <tromey@redhat.com>
* dwarf2loc.c (invalid_synthetic_pointer): Move earlier.
(indirect_pieced_value): Call dwarf2_fetch_constant_bytes
if needed.
* dwarf2loc.h (dwarf2_fetch_constant_bytes): Declare.
* dwarf2read.c (write_constant_as_bytes)
(dwarf2_fetch_constant_bytes): New functions.
2013-05-06 Tom Tromey <tromey@redhat.com>
* dwarf2read.c (dwarf2_const_value_data): Remove unused

View File

@ -90,6 +90,16 @@ enum debug_loc_kind
DEBUG_LOC_INVALID_ENTRY = -2
};
/* Helper function which throws an error if a synthetic pointer is
invalid. */
static void
invalid_synthetic_pointer (void)
{
error (_("access outside bounds of object "
"referenced via synthetic pointer"));
}
/* Decode the addresses in a non-dwo .debug_loc entry.
A pointer to the next byte to examine is returned in *NEW_PTR.
The encoded low,high addresses are return in *LOW,*HIGH.
@ -2086,9 +2096,37 @@ indirect_pieced_value (struct value *value)
get_frame_address_in_block_wrapper,
frame);
return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame,
baton.data, baton.size, baton.per_cu,
piece->v.ptr.offset + byte_offset);
if (baton.data != NULL)
return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame,
baton.data, baton.size, baton.per_cu,
piece->v.ptr.offset + byte_offset);
{
struct obstack temp_obstack;
struct cleanup *cleanup;
const gdb_byte *bytes;
LONGEST len;
struct value *result;
obstack_init (&temp_obstack);
cleanup = make_cleanup_obstack_free (&temp_obstack);
bytes = dwarf2_fetch_constant_bytes (piece->v.ptr.die, c->per_cu,
&temp_obstack, &len);
if (bytes == NULL)
result = allocate_optimized_out_value (TYPE_TARGET_TYPE (type));
else
{
if (byte_offset < 0
|| byte_offset + TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > len)
invalid_synthetic_pointer ();
bytes += byte_offset;
result = value_from_contents (TYPE_TARGET_TYPE (type), bytes);
}
do_cleanups (cleanup);
return result;
}
}
static void *
@ -2134,16 +2172,6 @@ static const struct lval_funcs pieced_value_funcs = {
free_pieced_value_closure
};
/* Helper function which throws an error if a synthetic pointer is
invalid. */
static void
invalid_synthetic_pointer (void)
{
error (_("access outside bounds of object "
"referenced via synthetic pointer"));
}
/* Virtual method table for dwarf2_evaluate_loc_desc_full below. */
static const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs =

View File

@ -72,6 +72,11 @@ struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_cu_off
CORE_ADDR (*get_frame_pc) (void *baton),
void *baton);
extern const gdb_byte *dwarf2_fetch_constant_bytes (sect_offset,
struct dwarf2_per_cu_data *,
struct obstack *,
LONGEST *);
struct type *dwarf2_get_die_type (cu_offset die_offset,
struct dwarf2_per_cu_data *per_cu);

View File

@ -17765,6 +17765,150 @@ dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
return dwarf2_fetch_die_loc_sect_off (offset, per_cu, get_frame_pc, baton);
}
/* Write a constant of a given type as target-ordered bytes into
OBSTACK. */
static const gdb_byte *
write_constant_as_bytes (struct obstack *obstack,
enum bfd_endian byte_order,
struct type *type,
ULONGEST value,
LONGEST *len)
{
gdb_byte *result;
*len = TYPE_LENGTH (type);
result = obstack_alloc (obstack, *len);
store_unsigned_integer (result, *len, byte_order, value);
return result;
}
/* If the DIE at OFFSET in PER_CU has a DW_AT_const_value, return a
pointer to the constant bytes and set LEN to the length of the
data. If memory is needed, allocate it on OBSTACK. If the DIE
does not have a DW_AT_const_value, return NULL. */
const gdb_byte *
dwarf2_fetch_constant_bytes (sect_offset offset,
struct dwarf2_per_cu_data *per_cu,
struct obstack *obstack,
LONGEST *len)
{
struct dwarf2_cu *cu;
struct die_info *die;
struct attribute *attr;
const gdb_byte *result = NULL;
struct type *type;
LONGEST value;
enum bfd_endian byte_order;
dw2_setup (per_cu->objfile);
if (per_cu->cu == NULL)
load_cu (per_cu);
cu = per_cu->cu;
die = follow_die_offset (offset, per_cu->is_dwz, &cu);
if (!die)
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
offset.sect_off, per_cu->objfile->name);
attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr == NULL)
return NULL;
byte_order = (bfd_big_endian (per_cu->objfile->obfd)
? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE);
switch (attr->form)
{
case DW_FORM_addr:
case DW_FORM_GNU_addr_index:
{
gdb_byte *tem;
*len = cu->header.addr_size;
tem = obstack_alloc (obstack, *len);
store_unsigned_integer (tem, *len, byte_order, DW_ADDR (attr));
result = tem;
}
break;
case DW_FORM_string:
case DW_FORM_strp:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
/* DW_STRING is already allocated on the objfile obstack, point
directly to it. */
result = (const gdb_byte *) DW_STRING (attr);
*len = strlen (DW_STRING (attr));
break;
case DW_FORM_block1:
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_exprloc:
result = DW_BLOCK (attr)->data;
*len = DW_BLOCK (attr)->size;
break;
/* The DW_AT_const_value attributes are supposed to carry the
symbol's value "represented as it would be on the target
architecture." By the time we get here, it's already been
converted to host endianness, so we just need to sign- or
zero-extend it as appropriate. */
case DW_FORM_data1:
type = die_type (die, cu);
result = dwarf2_const_value_data (attr, obstack, cu, &value, 8);
if (result == NULL)
result = write_constant_as_bytes (obstack, byte_order,
type, value, len);
break;
case DW_FORM_data2:
type = die_type (die, cu);
result = dwarf2_const_value_data (attr, obstack, cu, &value, 16);
if (result == NULL)
result = write_constant_as_bytes (obstack, byte_order,
type, value, len);
break;
case DW_FORM_data4:
type = die_type (die, cu);
result = dwarf2_const_value_data (attr, obstack, cu, &value, 32);
if (result == NULL)
result = write_constant_as_bytes (obstack, byte_order,
type, value, len);
break;
case DW_FORM_data8:
type = die_type (die, cu);
result = dwarf2_const_value_data (attr, obstack, cu, &value, 64);
if (result == NULL)
result = write_constant_as_bytes (obstack, byte_order,
type, value, len);
break;
case DW_FORM_sdata:
type = die_type (die, cu);
result = write_constant_as_bytes (obstack, byte_order,
type, DW_SND (attr), len);
break;
case DW_FORM_udata:
type = die_type (die, cu);
result = write_constant_as_bytes (obstack, byte_order,
type, DW_UNSND (attr), len);
break;
default:
complaint (&symfile_complaints,
_("unsupported const value attribute form: '%s'"),
dwarf_form_name (attr->form));
break;
}
return result;
}
/* Return the type of the DIE at DIE_OFFSET in the CU named by
PER_CU. */

View File

@ -1,3 +1,11 @@
2013-05-06 Tom Tromey <tromey@redhat.com>
* gdb.dwarf2/implptrconst.c: New file.
* gdb.dwarf2/implptrconst.exp: New file.
* lib/dwarf.exp (Dwarf::_nz_quote): New proc.
(Dwarf::_handle_DW_FORM): Handle DW_FORM_block1.
(Dwarf::_location): Handle DW_OP_GNU_implicit_pointer.
2013-05-03 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.base/catch-sig.c (main): Raise SIGINT.

View File

@ -0,0 +1,22 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2013 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/>. */
int
main ()
{
return 0;
}

View File

@ -0,0 +1,103 @@
# Copyright 2013 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/>.
load_lib dwarf.exp
# This test can only be run on targets which support DWARF-2 and use gas.
if {![dwarf2_support]} {
return 0
}
if { [skip_cplus_tests] } { continue }
standard_testfile .c implptrconst-dw.S
# Make some DWARF for the test.
set asm_file [standard_output_file $srcfile2]
Dwarf::assemble $asm_file {
cu 0 2 8 {
compile_unit {} {
declare_labels byte_label size_type_label array_label
declare_labels var_label ptr_label
byte_label: base_type {
{name byte}
{encoding @DW_ATE_signed}
{byte_size 1 DW_FORM_sdata}
}
size_type_label: base_type {
{name sizetype}
{encoding @DW_ATE_unsigned}
{byte_size 8 DW_FORM_sdata}
}
array_label: array_type {
{type :$byte_label}
} {
subrange_type {
{type :$size_type_label}
{upper_bound 7 DW_FORM_data1}
}
}
var_label: DW_TAG_variable {
{name b}
{type :$array_label}
{const_value rstuvwxy DW_FORM_block1}
}
ptr_label: pointer_type {
{byte_size 8 DW_FORM_sdata}
{type :$byte_label}
}
DW_TAG_variable {
{name c}
{type :$ptr_label}
{location {
GNU_implicit_pointer $var_label 0
} SPECIAL_expr}
}
}
}
}
if {[gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
object {nodebug}] != ""} {
return -1
}
if {[gdb_compile $asm_file ${binfile}2.o object {nodebug}] != ""} {
return -1
}
if {[gdb_compile [list ${binfile}1.o ${binfile}2.o] \
"${binfile}" executable {}] != ""} {
return -1
}
# We need --readnow because otherwise we never read in the CU we
# created above.
set saved_gdbflags $GDBFLAGS
set GDBFLAGS "$GDBFLAGS -readnow"
clean_restart ${testfile}
set GDBFLAGS $saved_gdbflags
if ![runto_main] {
return -1
}
gdb_test "print *c" " = 114 'r'"

View File

@ -241,6 +241,11 @@ namespace eval Dwarf {
return "\"${string}\\0\""
}
proc _nz_quote {string} {
# For now, no quoting is done.
return "\"${string}\""
}
proc _handle_DW_FORM {form value} {
switch -exact -- $form {
DW_FORM_string {
@ -326,11 +331,19 @@ namespace eval Dwarf {
define_label $l2
}
DW_FORM_block1 {
set len [string length $value]
if {$len > 255} {
error "DW_FORM_block1 length too long"
}
_op .byte $len
_op .ascii [_nz_quote $value]
}
DW_FORM_block2 -
DW_FORM_block4 -
DW_FORM_block -
DW_FORM_block1 -
DW_FORM_ref2 -
DW_FORM_indirect -
@ -591,6 +604,8 @@ namespace eval Dwarf {
# FIXME move docs
proc _location {body} {
variable _constants
variable _cu_label
variable _cu_addr_size
foreach line [split $body \n] {
if {[lindex $line 0] == ""} {
@ -601,8 +616,6 @@ namespace eval Dwarf {
switch -exact -- $opcode {
DW_OP_addr {
variable _cu_addr_size
_op .${_cu_addr_size}byte [lindex $line 1]
}
@ -633,6 +646,17 @@ namespace eval Dwarf {
_op .sleb128 [lindex $line 1]
}
DW_OP_GNU_implicit_pointer {
if {[llength $line] != 3} {
error "usage: DW_OP_GNU_implicit_pointer LABEL OFFSET"
}
# Here label is a section offset.
set label [lindex $line 1]
_op .${_cu_addr_size}byte $label
_op .sleb128 [lindex $line 2]
}
default {
if {[llength $line] > 1} {
error "Unimplemented: operands in location for $opcode"