* dwarf2loc.c (read_pieced_value): Work properly when 'v' has an
	offset.
	(write_pieced_value): Likewise.
gdb/testsuite
	* gdb.dwarf2.pieces.exp: New file.
	* gdb.dwarf2.pieces.S: New file.
	* gdb.dwarf2.pieces.c: New file.
This commit is contained in:
Tom Tromey 2010-05-21 20:39:50 +00:00
parent 90e7c2c53d
commit afd74c5ff7
6 changed files with 1931 additions and 27 deletions

View File

@ -1,3 +1,9 @@
2010-05-21 Tom Tromey <tromey@redhat.com>
* dwarf2loc.c (read_pieced_value): Work properly when 'v' has an
offset.
(write_pieced_value): Likewise.
2010-05-21 Pierre Muller <muller@ics.u-strasbg.fr>
* dwarf2read.c (process_die): Also allow DW_TAG_const_type

View File

@ -264,14 +264,46 @@ read_pieced_value (struct value *v)
{
int i;
long offset = 0;
ULONGEST bytes_to_skip;
gdb_byte *contents;
struct piece_closure *c = (struct piece_closure *) value_computed_closure (v);
struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (v));
size_t type_len;
if (value_type (v) != value_enclosing_type (v))
internal_error (__FILE__, __LINE__,
_("Should not be able to create a lazy value with "
"an enclosing type"));
contents = value_contents_raw (v);
for (i = 0; i < c->n_pieces; i++)
bytes_to_skip = value_offset (v);
type_len = TYPE_LENGTH (value_type (v));
for (i = 0; i < c->n_pieces && offset < type_len; i++)
{
struct dwarf_expr_piece *p = &c->pieces[i];
size_t this_size;
long dest_offset, source_offset;
if (bytes_to_skip > 0 && bytes_to_skip >= p->size)
{
bytes_to_skip -= p->size;
continue;
}
this_size = p->size;
if (this_size > type_len - offset)
this_size = type_len - offset;
if (bytes_to_skip > 0)
{
dest_offset = 0;
source_offset = bytes_to_skip;
this_size -= bytes_to_skip;
bytes_to_skip = 0;
}
else
{
dest_offset = offset;
source_offset = 0;
}
switch (p->location)
{
@ -280,17 +312,17 @@ read_pieced_value (struct value *v)
struct gdbarch *arch = get_frame_arch (frame);
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch,
p->v.expr.value);
int reg_offset = 0;
int reg_offset = source_offset;
if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
&& p->size < register_size (arch, gdb_regnum))
&& this_size < register_size (arch, gdb_regnum))
/* Big-endian, and we want less than full size. */
reg_offset = register_size (arch, gdb_regnum) - p->size;
reg_offset = register_size (arch, gdb_regnum) - this_size;
if (gdb_regnum != -1)
{
get_frame_register_bytes (frame, gdb_regnum, reg_offset,
p->size, contents + offset);
this_size, contents + dest_offset);
}
else
{
@ -302,38 +334,60 @@ read_pieced_value (struct value *v)
case DWARF_VALUE_MEMORY:
if (p->v.expr.in_stack_memory)
read_stack (p->v.expr.value, contents + offset, p->size);
read_stack (p->v.expr.value + source_offset,
contents + dest_offset, this_size);
else
read_memory (p->v.expr.value, contents + offset, p->size);
read_memory (p->v.expr.value + source_offset,
contents + dest_offset, this_size);
break;
case DWARF_VALUE_STACK:
{
struct gdbarch *gdbarch = get_type_arch (value_type (v));
size_t n = p->size;
size_t n = this_size;
if (n > c->addr_size)
n = c->addr_size;
store_unsigned_integer (contents + offset, n,
gdbarch_byte_order (gdbarch),
p->v.expr.value);
if (n > c->addr_size - source_offset)
n = (c->addr_size >= source_offset
? c->addr_size - source_offset
: 0);
if (n == 0)
{
/* Nothing. */
}
else if (source_offset == 0)
store_unsigned_integer (contents + dest_offset, n,
gdbarch_byte_order (gdbarch),
p->v.expr.value);
else
{
gdb_byte bytes[sizeof (ULONGEST)];
store_unsigned_integer (bytes, n + source_offset,
gdbarch_byte_order (gdbarch),
p->v.expr.value);
memcpy (contents + dest_offset, bytes + source_offset, n);
}
}
break;
case DWARF_VALUE_LITERAL:
{
size_t n = p->size;
size_t n = this_size;
if (n > p->v.literal.length)
n = p->v.literal.length;
memcpy (contents + offset, p->v.literal.data, n);
if (n > p->v.literal.length - source_offset)
n = (p->v.literal.length >= source_offset
? p->v.literal.length - source_offset
: 0);
if (n != 0)
memcpy (contents + dest_offset,
p->v.literal.data + source_offset, n);
}
break;
default:
internal_error (__FILE__, __LINE__, _("invalid location type"));
}
offset += p->size;
offset += this_size;
}
}
@ -342,9 +396,11 @@ write_pieced_value (struct value *to, struct value *from)
{
int i;
long offset = 0;
gdb_byte *contents;
ULONGEST bytes_to_skip;
const gdb_byte *contents;
struct piece_closure *c = (struct piece_closure *) value_computed_closure (to);
struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (to));
size_t type_len;
if (frame == NULL)
{
@ -352,10 +408,35 @@ write_pieced_value (struct value *to, struct value *from)
return;
}
contents = value_contents_raw (from);
for (i = 0; i < c->n_pieces; i++)
contents = value_contents (from);
bytes_to_skip = value_offset (to);
type_len = TYPE_LENGTH (value_type (to));
for (i = 0; i < c->n_pieces && offset < type_len; i++)
{
struct dwarf_expr_piece *p = &c->pieces[i];
size_t this_size;
long dest_offset, source_offset;
if (bytes_to_skip > 0 && bytes_to_skip >= p->size)
{
bytes_to_skip -= p->size;
continue;
}
this_size = p->size;
if (this_size > type_len - offset)
this_size = type_len - offset;
if (bytes_to_skip > 0)
{
dest_offset = bytes_to_skip;
source_offset = 0;
this_size -= bytes_to_skip;
bytes_to_skip = 0;
}
else
{
dest_offset = 0;
source_offset = offset;
}
switch (p->location)
{
@ -363,17 +444,17 @@ write_pieced_value (struct value *to, struct value *from)
{
struct gdbarch *arch = get_frame_arch (frame);
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.expr.value);
int reg_offset = 0;
int reg_offset = dest_offset;
if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
&& p->size < register_size (arch, gdb_regnum))
&& this_size <= register_size (arch, gdb_regnum))
/* Big-endian, and we want less than full size. */
reg_offset = register_size (arch, gdb_regnum) - p->size;
reg_offset = register_size (arch, gdb_regnum) - this_size;
if (gdb_regnum != -1)
{
put_frame_register_bytes (frame, gdb_regnum, reg_offset,
p->size, contents + offset);
this_size, contents + source_offset);
}
else
{
@ -383,13 +464,14 @@ write_pieced_value (struct value *to, struct value *from)
}
break;
case DWARF_VALUE_MEMORY:
write_memory (p->v.expr.value, contents + offset, p->size);
write_memory (p->v.expr.value + dest_offset,
contents + source_offset, this_size);
break;
default:
set_value_optimized_out (to, 1);
return;
}
offset += p->size;
offset += this_size;
}
}

View File

@ -1,3 +1,9 @@
2010-05-21 Tom Tromey <tromey@redhat.com>
* gdb.dwarf2.pieces.exp: New file.
* gdb.dwarf2.pieces.S: New file.
* gdb.dwarf2.pieces.c: New file.
2010-05-20 Pedro Alves <pedro@codesourcery.com>
Joel Brobecker <brobecker@adacore.com>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
/* Copyright (C) 2010 Free Software Foundation, Inc.
This file is part of GDB.
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/>. */
/* The original program corresponding to pieces.S.
This came from https://bugzilla.redhat.com/show_bug.cgi?id=589467
Note that it is not ever compiled, pieces.S is used instead.
However, it is used to extract breakpoint line numbers. */
struct A { int i; int j; };
struct B { int : 4; int i : 12; int j : 12; int : 4; };
__attribute__((noinline)) void
bar (int x)
{
asm volatile ("" : : "r" (x) : "memory");
}
__attribute__((noinline)) int
f1 (int k)
{
struct A a = { 4, k + 6 };
asm ("" : "+r" (a.i));
a.j++;
bar (a.i); /* { dg-final { gdb-test 20 "a.i" "4" } } */
bar (a.j); /* { dg-final { gdb-test 20 "a.j" "14" } } */
return a.i + a.j; /* f1 breakpoint */
}
__attribute__((noinline)) int
f2 (int k)
{
int a[2] = { 4, k + 6 };
asm ("" : "+r" (a[0]));
a[1]++;
bar (a[0]); /* { dg-final { gdb-test 31 "a\[0\]" "4" } } */
bar (a[1]); /* { dg-final { gdb-test 31 "a\[1\]" "14" } } */
return a[0] + a[1]; /* f2 breakpoint */
}
__attribute__((noinline)) int
f3 (int k)
{
struct B a = { 4, k + 6 };
asm ("" : "+r" (a.i));
a.j++;
bar (a.i); /* { dg-final { gdb-test 42 "a.i" "4" } } */
bar (a.j); /* { dg-final { gdb-test 42 "a.j" "14" } } */
return a.i + a.j; /* f3 breakpoint */
}
__attribute__((noinline)) int
f4 (int k)
{
int a[2] = { k, k };
asm ("" : "+r" (a[0]));
a[1]++;
bar (a[0]);
bar (a[1]);
return a[0] + a[1]; /* f4 breakpoint */
}
__attribute__((noinline)) int
f5 (int k)
{
struct A a = { k, k };
asm ("" : "+r" (a.i));
a.j++;
bar (a.i);
bar (a.j);
return a.i + a.j; /* f5 breakpoint */
}
int
main (void)
{
int k;
asm ("" : "=r" (k) : "0" (7));
f1 (k);
f2 (k);
f3 (k);
f4 (k);
f5 (k);
return 0;
}

View File

@ -0,0 +1,57 @@
# Copyright 2010 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 some DWARF piece operators.
# 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
}
# This test can only be run on x86 targets.
if {![istarget i?86-*]} {
return 0
}
set testfile "pieces"
set srcfile ${testfile}.S
set csrcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}.x
if {[prepare_for_testing ${testfile}.exp ${testfile}.x $srcfile]} {
return -1
}
if ![runto_main] {
return -1
}
# Function f1 tests a particular gdb bug involving DW_OP_piece.
proc pieces_test_f1 {} {
global csrcfile
set line [gdb_get_line_number "f1 breakpoint" $csrcfile]
gdb_test "break pieces.c:$line" "Breakpoint 2.*" \
"set f1 breakpoint for pieces"
gdb_continue_to_breakpoint "continue to f1 breakpoint for pieces"
gdb_test "print a" " = {i = 4, j = 14}" "print a in pieces:f1"
gdb_test "print a.j" " = 14" "print a.j in pieces:f1"
}
pieces_test_f1