* amd64-tdep.c (amd64_pseudo_register_read_value): Rename
	from amd64_pseudo_register_read.  Change arguments.  Call
	mark_value_bytes_unavailable when needed.
	(amd64_init_abi): Use set_gdbarch_pseudo_register_read_value, not
	set_gdbarch_pseudo_register_read.
	* sentinel-frame.c (sentinel_frame_prev_register): Use
	regcache_cooked_read_value.
	* regcache.h (regcache_cooked_read_value): Declare.
	* regcache.c (regcache_cooked_read_value): New function.
	(regcache_cooked_read): Call
	gdbarch_pseudo_register_read_value if available.
	* i386-tdep.h (i386_pseudo_register_read_value): Declare.
	(i386_pseudo_register_read): Remove.
	* i386-tdep.c (i386_pseudo_register_read_into_value): Rename from
	i386_pseudo_register_read.  Change arguments.  Call
	mark_value_bytes_unavailable when needed.
	(i386_pseudo_register_read_value): New function.
	(i386_gdbarch_init): Call set_gdbarch_pseudo_register_read_value,
	not set_gdbarch_pseudo_register_read.
	* gdbarch.sh (pseudo_register_read_value): New method.
	* gdbarch.c, gdbarch.h: Rebuild.
	* findvar.c (value_from_register): Call get_frame_register_value.
gdb/testsuite
	* gdb.dwarf2/typeddwarf.c: XFAIL 'z' on x86-64.
	* gdb.dwarf2/typeddwarf.exp (xfail-gdb-test): Add arch_pattern
	argument.
	* gdb.dwarf2/typeddwarf-amd64.S: New file.
This commit is contained in:
Tom Tromey 2011-07-22 15:31:52 +00:00
parent 26ac12805d
commit 3543a589b2
15 changed files with 1818 additions and 61 deletions

View File

@ -1,3 +1,28 @@
2011-07-22 Tom Tromey <tromey@redhat.com>
* amd64-tdep.c (amd64_pseudo_register_read_value): Rename
from amd64_pseudo_register_read. Change arguments. Call
mark_value_bytes_unavailable when needed.
(amd64_init_abi): Use set_gdbarch_pseudo_register_read_value, not
set_gdbarch_pseudo_register_read.
* sentinel-frame.c (sentinel_frame_prev_register): Use
regcache_cooked_read_value.
* regcache.h (regcache_cooked_read_value): Declare.
* regcache.c (regcache_cooked_read_value): New function.
(regcache_cooked_read): Call
gdbarch_pseudo_register_read_value if available.
* i386-tdep.h (i386_pseudo_register_read_value): Declare.
(i386_pseudo_register_read): Remove.
* i386-tdep.c (i386_pseudo_register_read_into_value): Rename from
i386_pseudo_register_read. Change arguments. Call
mark_value_bytes_unavailable when needed.
(i386_pseudo_register_read_value): New function.
(i386_gdbarch_init): Call set_gdbarch_pseudo_register_read_value,
not set_gdbarch_pseudo_register_read.
* gdbarch.sh (pseudo_register_read_value): New method.
* gdbarch.c, gdbarch.h: Rebuild.
* findvar.c (value_from_register): Call get_frame_register_value.
2011-07-22 Phil Muldoon <pmuldoon@redhat.com>
* event-top.c (cli_command_loop): Use get_prompt, get_suffix,

View File

@ -275,14 +275,21 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
return i386_pseudo_register_name (gdbarch, regnum);
}
static enum register_status
amd64_pseudo_register_read (struct gdbarch *gdbarch,
struct regcache *regcache,
int regnum, gdb_byte *buf)
static struct value *
amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
struct regcache *regcache,
int regnum)
{
gdb_byte raw_buf[MAX_REGISTER_SIZE];
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum register_status status;
struct value *result_value;
gdb_byte *buf;
result_value = allocate_value (register_type (gdbarch, regnum));
VALUE_LVAL (result_value) = lval_register;
VALUE_REGNUM (result_value) = regnum;
buf = value_contents_raw (result_value);
if (i386_byte_regnum_p (gdbarch, regnum))
{
@ -297,15 +304,19 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch,
raw_buf);
if (status == REG_VALID)
memcpy (buf, raw_buf + 1, 1);
else
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
}
else
{
status = regcache_raw_read (regcache, gpnum, raw_buf);
if (status == REG_VALID)
memcpy (buf, raw_buf, 1);
else
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
}
return status;
}
else if (i386_dword_regnum_p (gdbarch, regnum))
{
@ -314,11 +325,15 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch,
status = regcache_raw_read (regcache, gpnum, raw_buf);
if (status == REG_VALID)
memcpy (buf, raw_buf, 4);
return status;
else
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
}
else
return i386_pseudo_register_read (gdbarch, regcache, regnum, buf);
i386_pseudo_register_read_into_value (gdbarch, regcache, regnum,
result_value);
return result_value;
}
static void
@ -2494,8 +2509,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Avoid wiring in the MMX registers for now. */
tdep->num_mmx_regs = 0;
set_gdbarch_pseudo_register_read (gdbarch,
amd64_pseudo_register_read);
set_gdbarch_pseudo_register_read_value (gdbarch,
amd64_pseudo_register_read_value);
set_gdbarch_pseudo_register_write (gdbarch,
amd64_pseudo_register_write);

View File

@ -625,10 +625,11 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
struct gdbarch *gdbarch = get_frame_arch (frame);
struct type *type1 = check_typedef (type);
struct value *v;
int optim, unavail, ok;
if (gdbarch_convert_register_p (gdbarch, regnum, type1))
{
int optim, unavail, ok;
/* The ISA/ABI need to something weird when obtaining the
specified value from this register. It might need to
re-order non-adjacent, starting with REGNUM (see MIPS and
@ -643,26 +644,27 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
ok = gdbarch_register_to_value (gdbarch, frame, regnum, type1,
value_contents_raw (v), &optim,
&unavail);
if (!ok)
{
if (optim)
set_value_optimized_out (v, 1);
if (unavail)
mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
}
}
else
{
int len = TYPE_LENGTH (type);
struct value *v2;
/* Construct the value. */
v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
/* Get the data. */
ok = get_frame_register_bytes (frame, regnum, value_offset (v), len,
value_contents_raw (v),
&optim, &unavail);
}
v2 = get_frame_register_value (frame, regnum);
if (!ok)
{
if (optim)
set_value_optimized_out (v, 1);
if (unavail)
mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
value_contents_copy (v, 0, v2, value_offset (v), len);
}
return v;

View File

@ -161,6 +161,7 @@ struct gdbarch
gdbarch_write_pc_ftype *write_pc;
gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer;
gdbarch_pseudo_register_read_ftype *pseudo_register_read;
gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value;
gdbarch_pseudo_register_write_ftype *pseudo_register_write;
int num_regs;
int num_pseudo_regs;
@ -313,6 +314,7 @@ struct gdbarch startup_gdbarch =
0, /* write_pc */
legacy_virtual_frame_pointer, /* virtual_frame_pointer */
0, /* pseudo_register_read */
0, /* pseudo_register_read_value */
0, /* pseudo_register_write */
0, /* num_regs */
0, /* num_pseudo_regs */
@ -594,6 +596,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of write_pc, has predicate. */
/* Skip verify of virtual_frame_pointer, invalid_p == 0 */
/* Skip verify of pseudo_register_read, has predicate. */
/* Skip verify of pseudo_register_read_value, has predicate. */
/* Skip verify of pseudo_register_write, has predicate. */
if (gdbarch->num_regs == -1)
fprintf_unfiltered (log, "\n\tnum_regs");
@ -1084,6 +1087,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
fprintf_unfiltered (file,
"gdbarch_dump: pseudo_register_read = <%s>\n",
host_address_to_string (gdbarch->pseudo_register_read));
fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_pseudo_register_read_value_p() = %d\n",
gdbarch_pseudo_register_read_value_p (gdbarch));
fprintf_unfiltered (file,
"gdbarch_dump: pseudo_register_read_value = <%s>\n",
host_address_to_string (gdbarch->pseudo_register_read_value));
fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_pseudo_register_write_p() = %d\n",
gdbarch_pseudo_register_write_p (gdbarch));
@ -1699,6 +1708,30 @@ set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch,
gdbarch->pseudo_register_read = pseudo_register_read;
}
int
gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
return gdbarch->pseudo_register_read_value != NULL;
}
struct value *
gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->pseudo_register_read_value != NULL);
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_pseudo_register_read_value called\n");
return gdbarch->pseudo_register_read_value (gdbarch, regcache, cookednum);
}
void
set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch,
gdbarch_pseudo_register_read_value_ftype pseudo_register_read_value)
{
gdbarch->pseudo_register_read_value = pseudo_register_read_value;
}
int
gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch)
{

View File

@ -216,6 +216,17 @@ typedef enum register_status (gdbarch_pseudo_register_read_ftype) (struct gdbarc
extern enum register_status gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_ftype *pseudo_register_read);
/* Read a register into a new struct value. If the register is wholly
or partly unavailable, this should call mark_value_bytes_unavailable
as appropriate. If this is defined, then pseudo_register_read will
never be called. */
extern int gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch);
typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum);
extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum);
extern void set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value);
extern int gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch);
typedef void (gdbarch_pseudo_register_write_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf);

View File

@ -418,6 +418,11 @@ F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
m:void:virtual_frame_pointer:CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset:pc, frame_regnum, frame_offset:0:legacy_virtual_frame_pointer::0
#
M:enum register_status:pseudo_register_read:struct regcache *regcache, int cookednum, gdb_byte *buf:regcache, cookednum, buf
# Read a register into a new struct value. If the register is wholly
# or partly unavailable, this should call mark_value_bytes_unavailable
# as appropriate. If this is defined, then pseudo_register_read will
# never be called.
M:struct value *:pseudo_register_read_value:struct regcache *regcache, int cookednum:regcache, cookednum
M:void:pseudo_register_write:struct regcache *regcache, int cookednum, const gdb_byte *buf:regcache, cookednum, buf
#
v:int:num_regs:::0:-1

View File

@ -2780,12 +2780,19 @@ i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
return (I387_ST0_REGNUM (tdep) + fpreg);
}
enum register_status
i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
int regnum, gdb_byte *buf)
/* A helper function for us by i386_pseudo_register_read_value and
amd64_pseudo_register_read_value. It does all the work but reads
the data into an already-allocated value. */
void
i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
struct regcache *regcache,
int regnum,
struct value *result_value)
{
gdb_byte raw_buf[MAX_REGISTER_SIZE];
enum register_status status;
gdb_byte *buf = value_contents_raw (result_value);
if (i386_mmx_regnum_p (gdbarch, regnum))
{
@ -2794,8 +2801,10 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
/* Extract (always little endian). */
status = regcache_raw_read (regcache, fpnum, raw_buf);
if (status != REG_VALID)
return status;
memcpy (buf, raw_buf, register_size (gdbarch, regnum));
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
else
memcpy (buf, raw_buf, register_size (gdbarch, regnum));
}
else
{
@ -2810,15 +2819,17 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
I387_XMM0_REGNUM (tdep) + regnum,
raw_buf);
if (status != REG_VALID)
return status;
memcpy (buf, raw_buf, 16);
mark_value_bytes_unavailable (result_value, 0, 16);
else
memcpy (buf, raw_buf, 16);
/* Read upper 128bits. */
status = regcache_raw_read (regcache,
tdep->ymm0h_regnum + regnum,
raw_buf);
if (status != REG_VALID)
return status;
memcpy (buf + 16, raw_buf, 16);
mark_value_bytes_unavailable (result_value, 16, 32);
else
memcpy (buf + 16, raw_buf, 16);
}
else if (i386_word_regnum_p (gdbarch, regnum))
{
@ -2827,8 +2838,10 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
/* Extract (always little endian). */
status = regcache_raw_read (regcache, gpnum, raw_buf);
if (status != REG_VALID)
return status;
memcpy (buf, raw_buf, 2);
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
else
memcpy (buf, raw_buf, 2);
}
else if (i386_byte_regnum_p (gdbarch, regnum))
{
@ -2841,8 +2854,9 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
upper registers. */
status = regcache_raw_read (regcache, gpnum % 4, raw_buf);
if (status != REG_VALID)
return status;
if (gpnum >= 4)
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
else if (gpnum >= 4)
memcpy (buf, raw_buf + 1, 1);
else
memcpy (buf, raw_buf, 1);
@ -2850,8 +2864,22 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
else
internal_error (__FILE__, __LINE__, _("invalid regnum"));
}
}
return REG_VALID;
static struct value *
i386_pseudo_register_read_value (struct gdbarch *gdbarch,
struct regcache *regcache,
int regnum)
{
struct value *result;
result = allocate_value (register_type (gdbarch, regnum));
VALUE_LVAL (result) = lval_register;
VALUE_REGNUM (result) = regnum;
i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, result);
return result;
}
void
@ -7333,7 +7361,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
frame_base_set_default (gdbarch, &i386_frame_base);
/* Pseudo registers may be changed by amd64_init_abi. */
set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
set_gdbarch_pseudo_register_read_value (gdbarch,
i386_pseudo_register_read_value);
set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
set_tdesc_pseudo_register_type (gdbarch, i386_pseudo_register_type);

View File

@ -311,10 +311,11 @@ extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum);
extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch,
int regnum);
extern enum register_status i386_pseudo_register_read (struct gdbarch *gdbarch,
struct regcache *regcache,
int regnum,
gdb_byte *buf);
extern void i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
struct regcache *regcache,
int regnum,
struct value *result);
extern void i386_pseudo_register_write (struct gdbarch *gdbarch,
struct regcache *regcache,
int regnum, const gdb_byte *buf);

View File

@ -709,11 +709,66 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
return regcache->register_status[regnum];
}
else if (gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
{
struct value *mark, *computed;
enum register_status result = REG_VALID;
mark = value_mark ();
computed = gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
regcache, regnum);
if (value_entirely_available (computed))
memcpy (buf, value_contents_raw (computed),
regcache->descr->sizeof_register[regnum]);
else
{
memset (buf, 0, regcache->descr->sizeof_register[regnum]);
result = REG_UNAVAILABLE;
}
value_free_to_mark (mark);
return result;
}
else
return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
regnum, buf);
}
struct value *
regcache_cooked_read_value (struct regcache *regcache, int regnum)
{
gdb_assert (regnum >= 0);
gdb_assert (regnum < regcache->descr->nr_cooked_registers);
if (regnum < regcache->descr->nr_raw_registers
|| (regcache->readonly_p
&& regcache->register_status[regnum] != REG_UNKNOWN)
|| !gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
{
struct value *result;
result = allocate_value (register_type (regcache->descr->gdbarch,
regnum));
VALUE_LVAL (result) = lval_register;
VALUE_REGNUM (result) = regnum;
/* It is more efficient in general to do this delegation in this
direction than in the other one, even though the value-based
API is preferred. */
if (regcache_cooked_read (regcache, regnum,
value_contents_raw (result)) == REG_UNAVAILABLE)
mark_value_bytes_unavailable (result, 0,
TYPE_LENGTH (value_type (result)));
return result;
}
else
return gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
regcache, regnum);
}
enum register_status
regcache_cooked_read_signed (struct regcache *regcache, int regnum,
LONGEST *val)

View File

@ -104,6 +104,12 @@ enum register_status regcache_cooked_read (struct regcache *regcache,
void regcache_cooked_write (struct regcache *regcache, int rawnum,
const gdb_byte *buf);
/* Read register REGNUM from REGCACHE and return a new value. This
will call mark_value_bytes_unavailable as appropriate. */
struct value *regcache_cooked_read_value (struct regcache *regcache,
int regnum);
/* Read a register as a signed/unsigned quantity. */
extern enum register_status
regcache_cooked_read_signed (struct regcache *regcache,

View File

@ -48,25 +48,12 @@ sentinel_frame_prev_register (struct frame_info *this_frame,
void **this_prologue_cache,
int regnum)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct frame_unwind_cache *cache = *this_prologue_cache;
struct value *value;
struct type *regtype = register_type (gdbarch, regnum);
/* Return the actual value. */
value = allocate_value (regtype);
VALUE_LVAL (value) = lval_register;
VALUE_REGNUM (value) = regnum;
value = regcache_cooked_read_value (cache->regcache, regnum);
VALUE_FRAME_ID (value) = get_frame_id (this_frame);
/* Use the regcache_cooked_read() method so that it, on the fly,
constructs either a raw or pseudo register from the raw
register cache. */
if (regcache_cooked_read (cache->regcache,
regnum,
value_contents_raw (value)) == REG_UNAVAILABLE)
mark_value_bytes_unavailable (value, 0, TYPE_LENGTH (regtype));
return value;
}

View File

@ -1,3 +1,10 @@
2011-07-22 Tom Tromey <tromey@redhat.com>
* gdb.dwarf2/typeddwarf.c: XFAIL 'z' on x86-64.
* gdb.dwarf2/typeddwarf.exp (xfail-gdb-test): Add arch_pattern
argument.
* gdb.dwarf2/typeddwarf-amd64.S: New file.
2011-07-21 Matt Rice <ratmice@gmail.com>
* gdb.threads/Makefile.in: Avoid globbing corethreads.exp

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ f1 (double a, double b, double c, float d, float e, int f, unsigned int g, long
double w = d / 4.0; /* { dg-final { gdb-test 29 "w" "1" } } */
double x = a + b + 1.0; /* { dg-final { gdb-test 29 "x" "4" } } */
double y = b + c + 2.0; /* { dg-final { gdb-test 29 "y" "7" } } */
float z = d + e + 3.0f; /* { dg-final { gdb-test 29 "z" "12" } } */
float z = d + e + 3.0f; /* { dg-final { xfail-gdb-test 29 "z" "12" "x86_64-*-*"} } */
vv++;
}

View File

@ -22,12 +22,16 @@ if ![dwarf2_support] {
return 0
}
# This test can only be run on x86 targets.
if { ![is_x86_like_target] } {
# This test can only be run on x86 and amd64 targets.
if { [is_x86_like_target] } {
set sfile ${test}.S
} elseif {[istarget "x86_64-*-*"]} {
set sfile ${test}-amd64.S
} else {
return 0
}
if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug additional_flags=-nostdlib}] } {
if { [prepare_for_testing "${test}.exp" "${test}" ${sfile} {nodebug additional_flags=-nostdlib}] } {
return -1
}
@ -45,10 +49,19 @@ proc gdb-test {line var value} {
lappend tests($line) [list $var $value 0]
}
proc xfail-gdb-test {line var value} {
# Add an XFAIL'd test. If ARCH_PATTERN is given, and does not match
# the target, then the test is simply added and not XFAIL'd.
proc xfail-gdb-test {line var value {arch_pattern ""}} {
global tests
lappend tests($line) [list $var $value 1]
set flag 1
if {$arch_pattern != ""} {
if {! [istarget $arch_pattern]} {
set flag 0
}
}
lappend tests($line) [list $var $value $flag]
}
proc scan_gdb_tests {} {