* 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:
parent
3aef2284c6
commit
b6807d988a
8 changed files with 359 additions and 16 deletions
|
@ -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
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
144
gdb/dwarf2read.c
144
gdb/dwarf2read.c
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
22
gdb/testsuite/gdb.dwarf2/implptrconst.c
Normal file
22
gdb/testsuite/gdb.dwarf2/implptrconst.c
Normal 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;
|
||||
}
|
103
gdb/testsuite/gdb.dwarf2/implptrconst.exp
Normal file
103
gdb/testsuite/gdb.dwarf2/implptrconst.exp
Normal 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'"
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue