2010-12-28 Hui Zhu <teawater@gmail.com>
* gdbarch.sh (ax_pseudo_register_collect, ax_pseudo_register_push_stack): new callbacks. (agent_expr): Forward declare. * gdbarch.h, gdbarch.c: Regenerate. * ax-gdb.c (gen_expr): Remove pseudo-register check code. * ax-general.c (user-regs.h): New include. (ax_reg): Call gdbarch_ax_pseudo_register_push_stack. (ax_reg_mask): Call gdbarch_ax_pseudo_register_collect. * mips-tdep.c (ax.h): New include. (mips_ax_pseudo_register_collect, mips_ax_pseudo_register_push_stack): New functions. (mips_gdbarch_init): Set mips_ax_pseudo_register_collect and mips_ax_pseudo_register_push_stack.
This commit is contained in:
parent
f32bf4a4c9
commit
175ff332d0
7 changed files with 213 additions and 26 deletions
|
@ -1,3 +1,19 @@
|
|||
2010-12-28 Hui Zhu <teawater@gmail.com>
|
||||
|
||||
* gdbarch.sh (ax_pseudo_register_collect,
|
||||
ax_pseudo_register_push_stack): new callbacks.
|
||||
(agent_expr): Forward declare.
|
||||
* gdbarch.h, gdbarch.c: Regenerate.
|
||||
* ax-gdb.c (gen_expr): Remove pseudo-register check code.
|
||||
* ax-general.c (user-regs.h): New include.
|
||||
(ax_reg): Call gdbarch_ax_pseudo_register_push_stack.
|
||||
(ax_reg_mask): Call gdbarch_ax_pseudo_register_collect.
|
||||
* mips-tdep.c (ax.h): New include.
|
||||
(mips_ax_pseudo_register_collect,
|
||||
mips_ax_pseudo_register_push_stack): New functions.
|
||||
(mips_gdbarch_init): Set mips_ax_pseudo_register_collect and
|
||||
mips_ax_pseudo_register_push_stack.
|
||||
|
||||
2010-12-28 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* arm-tdep.c (arm_register_aliases): Remove sp, pc, and fp.
|
||||
|
|
|
@ -1978,10 +1978,6 @@ gen_expr (struct expression *exp, union exp_element **pc,
|
|||
if (reg == -1)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("Register $%s not available"), name);
|
||||
if (reg >= gdbarch_num_regs (exp->gdbarch))
|
||||
error (_("'%s' is a pseudo-register; "
|
||||
"GDB cannot yet trace pseudoregister contents."),
|
||||
name);
|
||||
value->kind = axs_lvalue_register;
|
||||
value->u.reg = reg;
|
||||
value->type = register_type (exp->gdbarch, reg);
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "value.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
#include "user-regs.h"
|
||||
|
||||
static void grow_expr (struct agent_expr *x, int n);
|
||||
|
||||
static void append_const (struct agent_expr *x, LONGEST val, int n);
|
||||
|
@ -272,14 +274,28 @@ ax_const_d (struct agent_expr *x, LONGEST d)
|
|||
void
|
||||
ax_reg (struct agent_expr *x, int reg)
|
||||
{
|
||||
/* Make sure the register number is in range. */
|
||||
if (reg < 0 || reg > 0xffff)
|
||||
error (_("GDB bug: ax-general.c (ax_reg): register number out of range"));
|
||||
grow_expr (x, 3);
|
||||
x->buf[x->len] = aop_reg;
|
||||
x->buf[x->len + 1] = (reg >> 8) & 0xff;
|
||||
x->buf[x->len + 2] = (reg) & 0xff;
|
||||
x->len += 3;
|
||||
if (reg >= gdbarch_num_regs (x->gdbarch))
|
||||
{
|
||||
/* This is a pseudo-register. */
|
||||
if (!gdbarch_ax_pseudo_register_push_stack_p (x->gdbarch))
|
||||
error (_("'%s' is a pseudo-register; "
|
||||
"GDB cannot yet trace its contents."),
|
||||
user_reg_map_regnum_to_name (x->gdbarch, reg));
|
||||
if (gdbarch_ax_pseudo_register_push_stack (x->gdbarch, x, reg))
|
||||
error (_("Trace '%s' failed."),
|
||||
user_reg_map_regnum_to_name (x->gdbarch, reg));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure the register number is in range. */
|
||||
if (reg < 0 || reg > 0xffff)
|
||||
error (_("GDB bug: ax-general.c (ax_reg): register number out of range"));
|
||||
grow_expr (x, 3);
|
||||
x->buf[x->len] = aop_reg;
|
||||
x->buf[x->len + 1] = (reg >> 8) & 0xff;
|
||||
x->buf[x->len + 2] = (reg) & 0xff;
|
||||
x->len += 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assemble code to operate on a trace state variable. */
|
||||
|
@ -413,23 +429,38 @@ ax_print (struct ui_file *f, struct agent_expr *x)
|
|||
void
|
||||
ax_reg_mask (struct agent_expr *ax, int reg)
|
||||
{
|
||||
int byte = reg / 8;
|
||||
|
||||
/* Grow the bit mask if necessary. */
|
||||
if (byte >= ax->reg_mask_len)
|
||||
if (reg >= gdbarch_num_regs (ax->gdbarch))
|
||||
{
|
||||
/* It's not appropriate to double here. This isn't a
|
||||
string buffer. */
|
||||
int new_len = byte + 1;
|
||||
unsigned char *new_reg_mask = xrealloc (ax->reg_mask,
|
||||
new_len * sizeof (ax->reg_mask[0]));
|
||||
memset (new_reg_mask + ax->reg_mask_len, 0,
|
||||
(new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
|
||||
ax->reg_mask_len = new_len;
|
||||
ax->reg_mask = new_reg_mask;
|
||||
/* This is a pseudo-register. */
|
||||
if (!gdbarch_ax_pseudo_register_collect_p (ax->gdbarch))
|
||||
error (_("'%s' is a pseudo-register; "
|
||||
"GDB cannot yet trace its contents."),
|
||||
user_reg_map_regnum_to_name (ax->gdbarch, reg));
|
||||
if (gdbarch_ax_pseudo_register_collect (ax->gdbarch, ax, reg))
|
||||
error (_("Trace '%s' failed."),
|
||||
user_reg_map_regnum_to_name (ax->gdbarch, reg));
|
||||
}
|
||||
else
|
||||
{
|
||||
int byte = reg / 8;
|
||||
|
||||
ax->reg_mask[byte] |= 1 << (reg % 8);
|
||||
/* Grow the bit mask if necessary. */
|
||||
if (byte >= ax->reg_mask_len)
|
||||
{
|
||||
/* It's not appropriate to double here. This isn't a
|
||||
string buffer. */
|
||||
int new_len = byte + 1;
|
||||
unsigned char *new_reg_mask = xrealloc (ax->reg_mask,
|
||||
new_len
|
||||
* sizeof (ax->reg_mask[0]));
|
||||
memset (new_reg_mask + ax->reg_mask_len, 0,
|
||||
(new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
|
||||
ax->reg_mask_len = new_len;
|
||||
ax->reg_mask = new_reg_mask;
|
||||
}
|
||||
|
||||
ax->reg_mask[byte] |= 1 << (reg % 8);
|
||||
}
|
||||
}
|
||||
|
||||
/* Given an agent expression AX, fill in requirements and other descriptive
|
||||
|
|
|
@ -164,6 +164,8 @@ struct gdbarch
|
|||
gdbarch_pseudo_register_write_ftype *pseudo_register_write;
|
||||
int num_regs;
|
||||
int num_pseudo_regs;
|
||||
gdbarch_ax_pseudo_register_collect_ftype *ax_pseudo_register_collect;
|
||||
gdbarch_ax_pseudo_register_push_stack_ftype *ax_pseudo_register_push_stack;
|
||||
int sp_regnum;
|
||||
int pc_regnum;
|
||||
int ps_regnum;
|
||||
|
@ -314,6 +316,8 @@ struct gdbarch startup_gdbarch =
|
|||
0, /* pseudo_register_write */
|
||||
0, /* num_regs */
|
||||
0, /* num_pseudo_regs */
|
||||
0, /* ax_pseudo_register_collect */
|
||||
0, /* ax_pseudo_register_push_stack */
|
||||
-1, /* sp_regnum */
|
||||
-1, /* pc_regnum */
|
||||
-1, /* ps_regnum */
|
||||
|
@ -594,6 +598,8 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
|||
if (gdbarch->num_regs == -1)
|
||||
fprintf_unfiltered (log, "\n\tnum_regs");
|
||||
/* Skip verify of num_pseudo_regs, invalid_p == 0 */
|
||||
/* Skip verify of ax_pseudo_register_collect, has predicate */
|
||||
/* Skip verify of ax_pseudo_register_push_stack, has predicate */
|
||||
/* Skip verify of sp_regnum, invalid_p == 0 */
|
||||
/* Skip verify of pc_regnum, invalid_p == 0 */
|
||||
/* Skip verify of ps_regnum, invalid_p == 0 */
|
||||
|
@ -760,6 +766,18 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
|||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: auto_wide_charset = <%s>\n",
|
||||
host_address_to_string (gdbarch->auto_wide_charset));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: gdbarch_ax_pseudo_register_collect_p() = %d\n",
|
||||
gdbarch_ax_pseudo_register_collect_p (gdbarch));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: ax_pseudo_register_collect = <%s>\n",
|
||||
host_address_to_string (gdbarch->ax_pseudo_register_collect));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: gdbarch_ax_pseudo_register_push_stack_p() = %d\n",
|
||||
gdbarch_ax_pseudo_register_push_stack_p (gdbarch));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: ax_pseudo_register_push_stack = <%s>\n",
|
||||
host_address_to_string (gdbarch->ax_pseudo_register_push_stack));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: believe_pcc_promotion = %s\n",
|
||||
plongest (gdbarch->believe_pcc_promotion));
|
||||
|
@ -1740,6 +1758,54 @@ set_gdbarch_num_pseudo_regs (struct gdbarch *gdbarch,
|
|||
gdbarch->num_pseudo_regs = num_pseudo_regs;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_ax_pseudo_register_collect_p (struct gdbarch *gdbarch)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
return gdbarch->ax_pseudo_register_collect != NULL;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_ax_pseudo_register_collect (struct gdbarch *gdbarch, struct agent_expr *ax, int reg)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->ax_pseudo_register_collect != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_ax_pseudo_register_collect called\n");
|
||||
return gdbarch->ax_pseudo_register_collect (gdbarch, ax, reg);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_ax_pseudo_register_collect (struct gdbarch *gdbarch,
|
||||
gdbarch_ax_pseudo_register_collect_ftype ax_pseudo_register_collect)
|
||||
{
|
||||
gdbarch->ax_pseudo_register_collect = ax_pseudo_register_collect;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_ax_pseudo_register_push_stack_p (struct gdbarch *gdbarch)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
return gdbarch->ax_pseudo_register_push_stack != NULL;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, struct agent_expr *ax, int reg)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->ax_pseudo_register_push_stack != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_ax_pseudo_register_push_stack called\n");
|
||||
return gdbarch->ax_pseudo_register_push_stack (gdbarch, ax, reg);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
|
||||
gdbarch_ax_pseudo_register_push_stack_ftype ax_pseudo_register_push_stack)
|
||||
{
|
||||
gdbarch->ax_pseudo_register_push_stack = ax_pseudo_register_push_stack;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_sp_regnum (struct gdbarch *gdbarch)
|
||||
{
|
||||
|
|
|
@ -53,6 +53,7 @@ struct target_desc;
|
|||
struct displaced_step_closure;
|
||||
struct core_regset_section;
|
||||
struct syscall;
|
||||
struct agent_expr;
|
||||
|
||||
/* The architecture associated with the connection to the target.
|
||||
|
||||
|
@ -232,6 +233,25 @@ extern void set_gdbarch_num_regs (struct gdbarch *gdbarch, int num_regs);
|
|||
extern int gdbarch_num_pseudo_regs (struct gdbarch *gdbarch);
|
||||
extern void set_gdbarch_num_pseudo_regs (struct gdbarch *gdbarch, int num_pseudo_regs);
|
||||
|
||||
/* Assemble agent expression bytecode to collect pseudo-register REG.
|
||||
Return -1 if something goes wrong, 0 otherwise. */
|
||||
|
||||
extern int gdbarch_ax_pseudo_register_collect_p (struct gdbarch *gdbarch);
|
||||
|
||||
typedef int (gdbarch_ax_pseudo_register_collect_ftype) (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
|
||||
extern int gdbarch_ax_pseudo_register_collect (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
|
||||
extern void set_gdbarch_ax_pseudo_register_collect (struct gdbarch *gdbarch, gdbarch_ax_pseudo_register_collect_ftype *ax_pseudo_register_collect);
|
||||
|
||||
/* Assemble agent expression bytecode to push the value of pseudo-register
|
||||
REG on the interpreter stack.
|
||||
Return -1 if something goes wrong, 0 otherwise. */
|
||||
|
||||
extern int gdbarch_ax_pseudo_register_push_stack_p (struct gdbarch *gdbarch);
|
||||
|
||||
typedef int (gdbarch_ax_pseudo_register_push_stack_ftype) (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
|
||||
extern int gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
|
||||
extern void set_gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, gdbarch_ax_pseudo_register_push_stack_ftype *ax_pseudo_register_push_stack);
|
||||
|
||||
/* GDB's standard (or well known) register numbers. These can map onto
|
||||
a real register or a pseudo (computed) register or not be defined at
|
||||
all (-1).
|
||||
|
|
|
@ -427,6 +427,15 @@ v:int:num_regs:::0:-1
|
|||
# combinations of other registers, or they may be computed by GDB.
|
||||
v:int:num_pseudo_regs:::0:0::0
|
||||
|
||||
# Assemble agent expression bytecode to collect pseudo-register REG.
|
||||
# Return -1 if something goes wrong, 0 otherwise.
|
||||
M:int:ax_pseudo_register_collect:struct agent_expr *ax, int reg:ax, reg
|
||||
|
||||
# Assemble agent expression bytecode to push the value of pseudo-register
|
||||
# REG on the interpreter stack.
|
||||
# Return -1 if something goes wrong, 0 otherwise.
|
||||
M:int:ax_pseudo_register_push_stack:struct agent_expr *ax, int reg:ax, reg
|
||||
|
||||
# GDB's standard (or well known) register numbers. These can map onto
|
||||
# a real register or a pseudo (computed) register or not be defined at
|
||||
# all (-1).
|
||||
|
@ -919,6 +928,7 @@ struct target_desc;
|
|||
struct displaced_step_closure;
|
||||
struct core_regset_section;
|
||||
struct syscall;
|
||||
struct agent_expr;
|
||||
|
||||
/* The architecture associated with the connection to the target.
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "dwarf2-frame.h"
|
||||
#include "user-regs.h"
|
||||
#include "valprint.h"
|
||||
#include "ax.h"
|
||||
|
||||
static const struct objfile_data *mips_pdr_data;
|
||||
|
||||
|
@ -616,6 +617,48 @@ mips_pseudo_register_write (struct gdbarch *gdbarch,
|
|||
internal_error (__FILE__, __LINE__, _("bad register size"));
|
||||
}
|
||||
|
||||
static int
|
||||
mips_ax_pseudo_register_collect (struct gdbarch *gdbarch,
|
||||
struct agent_expr *ax, int reg)
|
||||
{
|
||||
int rawnum = reg % gdbarch_num_regs (gdbarch);
|
||||
gdb_assert (reg >= gdbarch_num_regs (gdbarch)
|
||||
&& reg < 2 * gdbarch_num_regs (gdbarch));
|
||||
|
||||
ax_reg_mask (ax, rawnum);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mips_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
|
||||
struct agent_expr *ax, int reg)
|
||||
{
|
||||
int rawnum = reg % gdbarch_num_regs (gdbarch);
|
||||
gdb_assert (reg >= gdbarch_num_regs (gdbarch)
|
||||
&& reg < 2 * gdbarch_num_regs (gdbarch));
|
||||
if (register_size (gdbarch, rawnum) >= register_size (gdbarch, reg))
|
||||
{
|
||||
ax_reg (ax, rawnum);
|
||||
|
||||
if (register_size (gdbarch, rawnum) > register_size (gdbarch, reg))
|
||||
{
|
||||
if (!gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
|
||||
|| gdbarch_byte_order (gdbarch) != BFD_ENDIAN_BIG)
|
||||
{
|
||||
ax_const_l (ax, 32);
|
||||
ax_simple (ax, aop_lsh);
|
||||
}
|
||||
ax_const_l (ax, 32);
|
||||
ax_simple (ax, aop_rsh_signed);
|
||||
}
|
||||
}
|
||||
else
|
||||
internal_error (__FILE__, __LINE__, _("bad register size"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table to translate MIPS16 register field to actual register number. */
|
||||
static int mips16_to_32_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
|
||||
|
||||
|
@ -5933,6 +5976,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read);
|
||||
set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write);
|
||||
|
||||
set_gdbarch_ax_pseudo_register_collect (gdbarch,
|
||||
mips_ax_pseudo_register_collect);
|
||||
set_gdbarch_ax_pseudo_register_push_stack
|
||||
(gdbarch, mips_ax_pseudo_register_push_stack);
|
||||
|
||||
set_gdbarch_elf_make_msymbol_special (gdbarch,
|
||||
mips_elf_make_msymbol_special);
|
||||
|
||||
|
|
Loading…
Reference in a new issue