diff options
-rw-r--r-- | gdb/ChangeLog | 16 | ||||
-rw-r--r-- | gdb/ax-gdb.c | 4 | ||||
-rw-r--r-- | gdb/ax-general.c | 77 | ||||
-rw-r--r-- | gdb/gdbarch.c | 66 | ||||
-rw-r--r-- | gdb/gdbarch.h | 20 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 10 | ||||
-rw-r--r-- | gdb/mips-tdep.c | 48 |
7 files changed, 214 insertions, 27 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5beba9a..6508a66 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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. diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index e01f359..ab6b829 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -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); diff --git a/gdb/ax-general.c b/gdb/ax-general.c index ab4591f..e1269e6 100644 --- a/gdb/ax-general.c +++ b/gdb/ax-general.c @@ -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; + + /* 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); } - - ax->reg_mask[byte] |= 1 << (reg % 8); } /* Given an agent expression AX, fill in requirements and other descriptive diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 78e5c48..6921f64 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -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 */ @@ -761,6 +767,18 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *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)); fprintf_unfiltered (file, @@ -1741,6 +1759,54 @@ set_gdbarch_num_pseudo_regs (struct gdbarch *gdbarch, } 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) { gdb_assert (gdbarch != NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 443e1d5..4017f48 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -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). diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 5b66116..fe3a8d3 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -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. diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index e6df5f5..9b384ac 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -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); |