always read synthetic pointers as signed integers

I see the error message "access outside bounds of object referenced
via synthetic pointer" in the two fails below of mips gdb testing

print d[-2]^M
access outside bounds of object referenced via synthetic pointer^M
(gdb) FAIL: gdb.dwarf2/implptrconst.exp: print d[-2]
(gdb) print/d p[-1]^M
access outside bounds of object referenced via synthetic pointer^M
(gdb) FAIL: gdb.dwarf2/implptrpiece.exp: print/d p[-1]

in the first test, 'd[-2]' is processed by GDB as '* (&d[-2])'.  'd'
is a synthetic pointer, so its value is zero, the address of 'd[-2]'
is -2.  In dwarf2loc.c:indirect_pieced_value,

  /* This is an offset requested by GDB, such as value subscripts.
     However, due to how synthetic pointers are implemented, this is
     always presented to us as a pointer type.  This means we have to
     sign-extend it manually as appropriate.  */
  byte_offset = value_as_address (value);
  if (TYPE_LENGTH (value_type (value)) < sizeof (LONGEST))
    byte_offset = gdb_sign_extend (byte_offset,
				   8 * TYPE_LENGTH (value_type (value)));
  byte_offset += piece->v.ptr.offset;

We know that the value is really an offset instead of address, so the
fix is to extract the value as an (signed) offset.

gdb:

2015-01-08  Pedro Alves  <palves@redhat.com>
	    Yao Qi  <yao@codesourcery.com>

	* dwarf2loc.c (indirect_pieced_value): Don't call
	gdb_sign_extend.  Call extract_signed_integer instead.
	* utils.c (gdb_sign_extend): Remove.
	* utils.h (gdb_sign_extend): Remove declaration.
This commit is contained in:
Yao Qi 2014-12-28 16:12:53 +08:00
parent 3565cf8fed
commit b597c318b8
4 changed files with 19 additions and 27 deletions

View file

@ -1,3 +1,11 @@
2015-01-08 Pedro Alves <palves@redhat.com>
Yao Qi <yao@codesourcery.com>
* dwarf2loc.c (indirect_pieced_value): Don't call
gdb_sign_extend. Call extract_signed_integer instead.
* utils.c (gdb_sign_extend): Remove.
* utils.h (gdb_sign_extend): Remove declaration.
2015-01-07 Pierre Muller <muller@sourceware.org> 2015-01-07 Pierre Muller <muller@sourceware.org>
PR symtab/17811 PR symtab/17811

View file

@ -2012,6 +2012,7 @@ indirect_pieced_value (struct value *value)
int i, bit_offset, bit_length; int i, bit_offset, bit_length;
struct dwarf_expr_piece *piece = NULL; struct dwarf_expr_piece *piece = NULL;
LONGEST byte_offset; LONGEST byte_offset;
enum bfd_endian byte_order;
type = check_typedef (value_type (value)); type = check_typedef (value_type (value));
if (TYPE_CODE (type) != TYPE_CODE_PTR) if (TYPE_CODE (type) != TYPE_CODE_PTR)
@ -2056,11 +2057,16 @@ indirect_pieced_value (struct value *value)
/* This is an offset requested by GDB, such as value subscripts. /* This is an offset requested by GDB, such as value subscripts.
However, due to how synthetic pointers are implemented, this is However, due to how synthetic pointers are implemented, this is
always presented to us as a pointer type. This means we have to always presented to us as a pointer type. This means we have to
sign-extend it manually as appropriate. */ sign-extend it manually as appropriate. Use raw
byte_offset = value_as_address (value); extract_signed_integer directly rather than value_as_address and
if (TYPE_LENGTH (value_type (value)) < sizeof (LONGEST)) sign extend afterwards on architectures that would need it
byte_offset = gdb_sign_extend (byte_offset, (mostly everywhere except MIPS, which has signed addresses) as
8 * TYPE_LENGTH (value_type (value))); the later would go through gdbarch_pointer_to_address and thus
return a CORE_ADDR with high bits set on architectures that
encode address spaces and other things in CORE_ADDR. */
byte_order = gdbarch_byte_order (get_frame_arch (frame));
byte_offset = extract_signed_integer (value_contents (value),
TYPE_LENGTH (type), byte_order);
byte_offset += piece->v.ptr.offset; byte_offset += piece->v.ptr.offset;
gdb_assert (piece); gdb_assert (piece);

View file

@ -3021,23 +3021,6 @@ align_down (ULONGEST v, int n)
return (v & -n); return (v & -n);
} }
/* See utils.h. */
LONGEST
gdb_sign_extend (LONGEST value, int bit)
{
gdb_assert (bit >= 1 && bit <= 8 * sizeof (LONGEST));
if (((value >> (bit - 1)) & 1) != 0)
{
LONGEST signbit = ((LONGEST) 1) << (bit - 1);
value = (value ^ signbit) - signbit;
}
return value;
}
/* Allocation function for the libiberty hash table which uses an /* Allocation function for the libiberty hash table which uses an
obstack. The obstack is passed as DATA. */ obstack. The obstack is passed as DATA. */

View file

@ -340,11 +340,6 @@ extern int myread (int, char *, int);
extern ULONGEST align_up (ULONGEST v, int n); extern ULONGEST align_up (ULONGEST v, int n);
extern ULONGEST align_down (ULONGEST v, int n); extern ULONGEST align_down (ULONGEST v, int n);
/* Sign extend VALUE. BIT is the (1-based) index of the bit in VALUE
to sign-extend. */
extern LONGEST gdb_sign_extend (LONGEST value, int bit);
/* Resource limits used by getrlimit and setrlimit. */ /* Resource limits used by getrlimit and setrlimit. */
enum resource_limit_kind enum resource_limit_kind