gdb/gdbserver/
* regcache.c (init_register_cache): Initialize regcache->register_status. (free_register_cache): Release regcache->register_status. (regcache_cpy): Copy register_status. (registers_to_string): Print 'x's for unavailable registers. (supply_register): Mark the register's status valid or unavailable, depending on whether a buffer was passed in or not. (supply_register_zeroed): New. (supply_regblock): Mark the registers' status valid or unavailable, depending on whether a buffer was passed in or not. * regcache.h (REG_UNAVAILABLE, REG_VALID): New defines. (struct regcache): New `register_status' field. (supply_register_zeroed): Declare. * i387-fp.c (i387_xsave_to_cache): Zero out registers using supply_register_zeroed, rather than passing a NULL buffer to supply_register. * tracepoint.c (fetch_traceframe_registers): Update comment.
This commit is contained in:
parent
85724a0e60
commit
1c79eb8a7d
|
@ -1,3 +1,23 @@
|
||||||
|
2011-01-28 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
|
* regcache.c (init_register_cache): Initialize
|
||||||
|
regcache->register_status.
|
||||||
|
(free_register_cache): Release regcache->register_status.
|
||||||
|
(regcache_cpy): Copy register_status.
|
||||||
|
(registers_to_string): Print 'x's for unavailable registers.
|
||||||
|
(supply_register): Mark the register's status valid or
|
||||||
|
unavailable, depending on whether a buffer was passed in or not.
|
||||||
|
(supply_register_zeroed): New.
|
||||||
|
(supply_regblock): Mark the registers' status valid or
|
||||||
|
unavailable, depending on whether a buffer was passed in or not.
|
||||||
|
* regcache.h (REG_UNAVAILABLE, REG_VALID): New defines.
|
||||||
|
(struct regcache): New `register_status' field.
|
||||||
|
(supply_register_zeroed): Declare.
|
||||||
|
* i387-fp.c (i387_xsave_to_cache): Zero out registers using
|
||||||
|
supply_register_zeroed, rather than passing a NULL buffer to
|
||||||
|
supply_register.
|
||||||
|
* tracepoint.c (fetch_traceframe_registers): Update comment.
|
||||||
|
|
||||||
2011-01-28 Pedro Alves <pedro@codesourcery.com>
|
2011-01-28 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
* i387-fp.c (i387_xsave_to_cache): Make passing NULL as register
|
* i387-fp.c (i387_xsave_to_cache): Make passing NULL as register
|
||||||
|
|
|
@ -482,7 +482,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||||
if ((clear_bv & I386_XSTATE_X87) != 0)
|
if ((clear_bv & I386_XSTATE_X87) != 0)
|
||||||
{
|
{
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
supply_register (regcache, i + st0_regnum, NULL);
|
supply_register_zeroed (regcache, i + st0_regnum);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -499,7 +499,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||||
if ((clear_bv & I386_XSTATE_SSE))
|
if ((clear_bv & I386_XSTATE_SSE))
|
||||||
{
|
{
|
||||||
for (i = 0; i < num_xmm_registers; i++)
|
for (i = 0; i < num_xmm_registers; i++)
|
||||||
supply_register (regcache, i + xmm0_regnum, NULL);
|
supply_register_zeroed (regcache, i + xmm0_regnum);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -516,7 +516,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||||
if ((clear_bv & I386_XSTATE_AVX) != 0)
|
if ((clear_bv & I386_XSTATE_AVX) != 0)
|
||||||
{
|
{
|
||||||
for (i = 0; i < num_xmm_registers; i++)
|
for (i = 0; i < num_xmm_registers; i++)
|
||||||
supply_register (regcache, i + ymm0h_regnum, NULL);
|
supply_register_zeroed (regcache, i + ymm0h_regnum);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,6 +98,8 @@ init_register_cache (struct regcache *regcache, unsigned char *regbuf)
|
||||||
garbage. */
|
garbage. */
|
||||||
regcache->registers = xcalloc (1, register_bytes);
|
regcache->registers = xcalloc (1, register_bytes);
|
||||||
regcache->registers_owned = 1;
|
regcache->registers_owned = 1;
|
||||||
|
regcache->register_status = xcalloc (1, num_registers);
|
||||||
|
gdb_assert (REG_UNAVAILABLE == 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#else
|
#else
|
||||||
|
@ -108,6 +110,9 @@ init_register_cache (struct regcache *regcache, unsigned char *regbuf)
|
||||||
{
|
{
|
||||||
regcache->registers = regbuf;
|
regcache->registers = regbuf;
|
||||||
regcache->registers_owned = 0;
|
regcache->registers_owned = 0;
|
||||||
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
regcache->register_status = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
regcache->registers_valid = 0;
|
regcache->registers_valid = 0;
|
||||||
|
@ -136,6 +141,7 @@ free_register_cache (struct regcache *regcache)
|
||||||
{
|
{
|
||||||
if (regcache->registers_owned)
|
if (regcache->registers_owned)
|
||||||
free (regcache->registers);
|
free (regcache->registers);
|
||||||
|
free (regcache->register_status);
|
||||||
free (regcache);
|
free (regcache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,6 +152,10 @@ void
|
||||||
regcache_cpy (struct regcache *dst, struct regcache *src)
|
regcache_cpy (struct regcache *dst, struct regcache *src)
|
||||||
{
|
{
|
||||||
memcpy (dst->registers, src->registers, register_bytes);
|
memcpy (dst->registers, src->registers, register_bytes);
|
||||||
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
if (dst->register_status != NULL && src->register_status != NULL)
|
||||||
|
memcpy (dst->register_status, src->register_status, num_registers);
|
||||||
|
#endif
|
||||||
dst->registers_valid = src->registers_valid;
|
dst->registers_valid = src->registers_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,8 +219,23 @@ void
|
||||||
registers_to_string (struct regcache *regcache, char *buf)
|
registers_to_string (struct regcache *regcache, char *buf)
|
||||||
{
|
{
|
||||||
unsigned char *registers = regcache->registers;
|
unsigned char *registers = regcache->registers;
|
||||||
|
int i;
|
||||||
|
|
||||||
convert_int_to_ascii (registers, buf, register_bytes);
|
for (i = 0; i < num_registers; i++)
|
||||||
|
{
|
||||||
|
if (regcache->register_status[i] == REG_VALID)
|
||||||
|
{
|
||||||
|
convert_int_to_ascii (registers, buf, register_size (i));
|
||||||
|
buf += register_size (i) * 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset (buf, 'x', register_size (i) * 2);
|
||||||
|
buf += register_size (i) * 2;
|
||||||
|
}
|
||||||
|
registers += register_size (i);
|
||||||
|
}
|
||||||
|
*buf = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -273,22 +298,74 @@ register_data (struct regcache *regcache, int n, int fetch)
|
||||||
return regcache->registers + (reg_defs[n].offset / 8);
|
return regcache->registers + (reg_defs[n].offset / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Supply register N, whose contents are stored in BUF, to REGCACHE.
|
||||||
|
If BUF is NULL, the register's value is recorded as
|
||||||
|
unavailable. */
|
||||||
|
|
||||||
void
|
void
|
||||||
supply_register (struct regcache *regcache, int n, const void *buf)
|
supply_register (struct regcache *regcache, int n, const void *buf)
|
||||||
{
|
{
|
||||||
if (buf)
|
if (buf)
|
||||||
memcpy (register_data (regcache, n, 0), buf, register_size (n));
|
{
|
||||||
|
memcpy (register_data (regcache, n, 0), buf, register_size (n));
|
||||||
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
if (regcache->register_status != NULL)
|
||||||
|
regcache->register_status[n] = REG_VALID;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
memset (register_data (regcache, n, 0), 0, register_size (n));
|
{
|
||||||
|
memset (register_data (regcache, n, 0), 0, register_size (n));
|
||||||
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
if (regcache->register_status != NULL)
|
||||||
|
regcache->register_status[n] = REG_UNAVAILABLE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Supply register N with value zero to REGCACHE. */
|
||||||
|
|
||||||
|
void
|
||||||
|
supply_register_zeroed (struct regcache *regcache, int n)
|
||||||
|
{
|
||||||
|
memset (register_data (regcache, n, 0), 0, register_size (n));
|
||||||
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
if (regcache->register_status != NULL)
|
||||||
|
regcache->register_status[n] = REG_VALID;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Supply the whole register set whose contents are stored in BUF, to
|
||||||
|
REGCACHE. If BUF is NULL, all the registers' values are recorded
|
||||||
|
as unavailable. */
|
||||||
|
|
||||||
void
|
void
|
||||||
supply_regblock (struct regcache *regcache, const void *buf)
|
supply_regblock (struct regcache *regcache, const void *buf)
|
||||||
{
|
{
|
||||||
if (buf)
|
if (buf)
|
||||||
memcpy (regcache->registers, buf, register_bytes);
|
{
|
||||||
|
memcpy (regcache->registers, buf, register_bytes);
|
||||||
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_registers; i++)
|
||||||
|
regcache->register_status[i] = REG_VALID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
memset (regcache->registers, 0, register_bytes);
|
{
|
||||||
|
memset (regcache->registers, 0, register_bytes);
|
||||||
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_registers; i++)
|
||||||
|
regcache->register_status[i] = REG_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef IN_PROCESS_AGENT
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
|
|
@ -23,15 +23,31 @@
|
||||||
struct inferior_list_entry;
|
struct inferior_list_entry;
|
||||||
struct thread_info;
|
struct thread_info;
|
||||||
|
|
||||||
|
/* The register exists, it has a value, but we don't know what it is.
|
||||||
|
Used when inspecting traceframes. */
|
||||||
|
#define REG_UNAVAILABLE 0
|
||||||
|
|
||||||
|
/* We know the register's value (and we have it cached). */
|
||||||
|
#define REG_VALID 1
|
||||||
|
|
||||||
/* The data for the register cache. Note that we have one per
|
/* The data for the register cache. Note that we have one per
|
||||||
inferior; this is primarily for simplicity, as the performance
|
inferior; this is primarily for simplicity, as the performance
|
||||||
benefit is minimal. */
|
benefit is minimal. */
|
||||||
|
|
||||||
struct regcache
|
struct regcache
|
||||||
{
|
{
|
||||||
|
/* Whether the REGISTERS buffer's contents are valid. If false, we
|
||||||
|
haven't fetched the registers from the target yet. Not that this
|
||||||
|
register cache is _not_ pass-through, unlike GDB's. Note that
|
||||||
|
"valid" here is unrelated to whether the registers are available
|
||||||
|
in a traceframe. For that, check REGISTER_STATUS below. */
|
||||||
int registers_valid;
|
int registers_valid;
|
||||||
int registers_owned;
|
int registers_owned;
|
||||||
unsigned char *registers;
|
unsigned char *registers;
|
||||||
|
#ifndef IN_PROCESS_AGENT
|
||||||
|
/* One of REG_UNAVAILBLE or REG_VALID. */
|
||||||
|
unsigned char *register_status;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct regcache *init_register_cache (struct regcache *regcache,
|
struct regcache *init_register_cache (struct regcache *regcache,
|
||||||
|
@ -84,6 +100,8 @@ extern const char *gdbserver_xmltarget;
|
||||||
|
|
||||||
void supply_register (struct regcache *regcache, int n, const void *buf);
|
void supply_register (struct regcache *regcache, int n, const void *buf);
|
||||||
|
|
||||||
|
void supply_register_zeroed (struct regcache *regcache, int n);
|
||||||
|
|
||||||
void supply_register_by_name (struct regcache *regcache,
|
void supply_register_by_name (struct regcache *regcache,
|
||||||
const char *name, const void *buf);
|
const char *name, const void *buf);
|
||||||
|
|
||||||
|
|
|
@ -4840,8 +4840,7 @@ fetch_traceframe_registers (int tfnum, struct regcache *regcache, int regnum)
|
||||||
dataptr = traceframe_find_regblock (tframe, tfnum);
|
dataptr = traceframe_find_regblock (tframe, tfnum);
|
||||||
if (dataptr == NULL)
|
if (dataptr == NULL)
|
||||||
{
|
{
|
||||||
/* We don't like making up numbers, but GDB has all manner of
|
/* Mark registers unavailable. */
|
||||||
troubles when the target says there are no registers. */
|
|
||||||
supply_regblock (regcache, NULL);
|
supply_regblock (regcache, NULL);
|
||||||
|
|
||||||
/* We can generally guess at a PC, although this will be
|
/* We can generally guess at a PC, although this will be
|
||||||
|
|
Loading…
Reference in New Issue