From: Pedro Alves Date: Wed, 28 Mar 2012 18:30:01 +0000 (+0000) Subject: 2012-03-28 Pedro Alves X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c14dfd32064a2213d57d8ef551a9c64841e61032;p=binutils-gdb.git 2012-03-28 Pedro Alves * linux-ia64-low.c (ia64_regmap): Map IA64_EC_REGNUM to PT_AR_EC. (IA64_GR0_REGNUM, IA64_FR0_REGNUM) (IA64_FR1_REGNUM): New defines. (ia64_fetch_register): New. (the_low_target): Install it. * linux-low.h (struct linux_target_ops) : New field. * linux-low.c (linux_fetch_registers): Try the the_low_target.fetch_register hook first. * linux-arm-low.c (the_low_target): Adjust. * linux-bfin-low.c (the_low_target): Adjust. * linux-cris-low.c (the_low_target): Adjust. * linux-crisv32-low.c (the_low_target): Adjust. * linux-m32r-low.c (the_low_target): Adjust. * linux-m68k-low.c (the_low_target): Adjust. * linux-mips-low.c (the_low_target): Adjust. * linux-ppc-low.c (the_low_target): Adjust. * linux-s390-low.c (the_low_target): Adjust. * linux-sh-low.c (the_low_target): Adjust. * linux-sparc-low.c (the_low_target): Adjust. * linux-tic6x-low.c (the_low_target): Adjust. * linux-x86-low.c (the_low_target): Adjust. * linux-xtensa-low.c (the_low_target): Adjust. --- diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index c99505fba7e..8627aa9c4a7 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,30 @@ +2012-03-28 Pedro Alves + + * linux-ia64-low.c (ia64_regmap): Map IA64_EC_REGNUM to PT_AR_EC. + (IA64_GR0_REGNUM, IA64_FR0_REGNUM) + (IA64_FR1_REGNUM): New defines. + (ia64_fetch_register): New. + (the_low_target): Install it. + * linux-low.h (struct linux_target_ops) : New + field. + * linux-low.c (linux_fetch_registers): Try the + the_low_target.fetch_register hook first. + + * linux-arm-low.c (the_low_target): Adjust. + * linux-bfin-low.c (the_low_target): Adjust. + * linux-cris-low.c (the_low_target): Adjust. + * linux-crisv32-low.c (the_low_target): Adjust. + * linux-m32r-low.c (the_low_target): Adjust. + * linux-m68k-low.c (the_low_target): Adjust. + * linux-mips-low.c (the_low_target): Adjust. + * linux-ppc-low.c (the_low_target): Adjust. + * linux-s390-low.c (the_low_target): Adjust. + * linux-sh-low.c (the_low_target): Adjust. + * linux-sparc-low.c (the_low_target): Adjust. + * linux-tic6x-low.c (the_low_target): Adjust. + * linux-x86-low.c (the_low_target): Adjust. + * linux-xtensa-low.c (the_low_target): Adjust. + 2012-03-26 Pedro Alves * server.c (handle_qxfer_libraries): Don't bail early if diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index 01208efc1ab..bf1792bf9e0 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -837,6 +837,7 @@ struct linux_target_ops the_low_target = { NULL, arm_cannot_fetch_register, arm_cannot_store_register, + NULL, /* fetch_register */ arm_get_pc, arm_set_pc, diff --git a/gdb/gdbserver/linux-bfin-low.c b/gdb/gdbserver/linux-bfin-low.c index b6fe58a4c95..d5b0361181c 100644 --- a/gdb/gdbserver/linux-bfin-low.c +++ b/gdb/gdbserver/linux-bfin-low.c @@ -97,6 +97,7 @@ struct linux_target_ops the_low_target = { NULL, bfin_cannot_fetch_register, bfin_cannot_store_register, + NULL, /* fetch_register */ bfin_get_pc, bfin_set_pc, bfin_breakpoint, diff --git a/gdb/gdbserver/linux-cris-low.c b/gdb/gdbserver/linux-cris-low.c index a399789cb71..0c92e629d67 100644 --- a/gdb/gdbserver/linux-cris-low.c +++ b/gdb/gdbserver/linux-cris-low.c @@ -115,6 +115,7 @@ struct linux_target_ops the_low_target = { NULL, cris_cannot_fetch_register, cris_cannot_store_register, + NULL, /* fetch_register */ cris_get_pc, cris_set_pc, (const unsigned char *) &cris_breakpoint, diff --git a/gdb/gdbserver/linux-crisv32-low.c b/gdb/gdbserver/linux-crisv32-low.c index e33372de257..1cc4cd10c18 100644 --- a/gdb/gdbserver/linux-crisv32-low.c +++ b/gdb/gdbserver/linux-crisv32-low.c @@ -377,6 +377,7 @@ struct linux_target_ops the_low_target = { NULL, NULL, NULL, + NULL, /* fetch_register */ cris_get_pc, cris_set_pc, (const unsigned char *) &cris_breakpoint, diff --git a/gdb/gdbserver/linux-ia64-low.c b/gdb/gdbserver/linux-ia64-low.c index 875319051ad..c8fa603ec7d 100644 --- a/gdb/gdbserver/linux-ia64-low.c +++ b/gdb/gdbserver/linux-ia64-low.c @@ -256,7 +256,7 @@ static int ia64_regmap[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, PT_AR_PFS, PT_AR_LC, - -1, /* Not available: EC, the Epilog Count register */ + PT_AR_EC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -278,6 +278,48 @@ ia64_cannot_fetch_register (int regno) return 0; } +/* GDB register numbers. */ +#define IA64_GR0_REGNUM 0 +#define IA64_FR0_REGNUM 128 +#define IA64_FR1_REGNUM 129 + +static int +ia64_fetch_register (struct regcache *regcache, int regnum) +{ + /* r0 cannot be fetched but is always zero. */ + if (regnum == IA64_GR0_REGNUM) + { + const gdb_byte zero[8] = { 0 }; + + gdb_assert (sizeof (zero) == register_size (regnum)); + supply_register (regcache, regnum, zero); + return 1; + } + + /* fr0 cannot be fetched but is always zero. */ + if (regnum == IA64_FR0_REGNUM) + { + const gdb_byte f_zero[16] = { 0 }; + + gdb_assert (sizeof (f_zero) == register_size (regnum)); + supply_register (regcache, regnum, f_zero); + return 1; + } + + /* fr1 cannot be fetched but is always one (1.0). */ + if (regnum == IA64_FR1_REGNUM) + { + const gdb_byte f_one[16] = + { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; + + gdb_assert (sizeof (f_one) == register_size (regnum)); + supply_register (regcache, regnum, f_one); + return 1; + } + + return 0; +} + struct linux_target_ops the_low_target = { init_registers_ia64, ia64_num_regs, @@ -285,4 +327,5 @@ struct linux_target_ops the_low_target = { NULL, ia64_cannot_fetch_register, ia64_cannot_store_register, + ia64_fetch_register, }; diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 8becf78ccea..aea8d367943 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -4271,11 +4271,19 @@ linux_fetch_registers (struct regcache *regcache, int regno) if (regno == -1) { + if (the_low_target.fetch_register != NULL) + for (regno = 0; regno < the_low_target.num_regs; regno++) + (*the_low_target.fetch_register) (regcache, regno); + all = regsets_fetch_inferior_registers (regcache); - usr_fetch_inferior_registers (regcache, regno, all); + usr_fetch_inferior_registers (regcache, -1, all); } else { + if (the_low_target.fetch_register != NULL + && (*the_low_target.fetch_register) (regcache, regno)) + return; + use_regsets = linux_register_in_regsets (regno); if (use_regsets) all = regsets_fetch_inferior_registers (regcache); diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index 3aeae704055..07eda12de16 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -81,6 +81,14 @@ struct linux_target_ops store the register, and 2 if failure to store the register is acceptable. */ int (*cannot_store_register) (int); + + /* Hook to fetch a register in some non-standard way. Used for + example by backends that have read-only registers with hardcoded + values (e.g., IA64's gr0/fr0/fr1). Returns true if register + REGNO was supplied, false if not, and we should fallback to the + standard ptrace methods. */ + int (*fetch_register) (struct regcache *regcache, int regno); + CORE_ADDR (*get_pc) (struct regcache *regcache); void (*set_pc) (struct regcache *regcache, CORE_ADDR newpc); const unsigned char *breakpoint; diff --git a/gdb/gdbserver/linux-m32r-low.c b/gdb/gdbserver/linux-m32r-low.c index fd70cf2c499..29bb3f7cf01 100644 --- a/gdb/gdbserver/linux-m32r-low.c +++ b/gdb/gdbserver/linux-m32r-low.c @@ -94,6 +94,7 @@ struct linux_target_ops the_low_target = { NULL, m32r_cannot_fetch_register, m32r_cannot_store_register, + NULL, /* fetch_register */ m32r_get_pc, m32r_set_pc, (const unsigned char *) &m32r_breakpoint, diff --git a/gdb/gdbserver/linux-m68k-low.c b/gdb/gdbserver/linux-m68k-low.c index a640e4c42c2..6769dac9afa 100644 --- a/gdb/gdbserver/linux-m68k-low.c +++ b/gdb/gdbserver/linux-m68k-low.c @@ -182,6 +182,7 @@ struct linux_target_ops the_low_target = { NULL, m68k_cannot_fetch_register, m68k_cannot_store_register, + NULL, /* fetch_register */ m68k_get_pc, m68k_set_pc, m68k_breakpoint, diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c index 1f584425a14..8e37298d118 100644 --- a/gdb/gdbserver/linux-mips-low.c +++ b/gdb/gdbserver/linux-mips-low.c @@ -430,6 +430,7 @@ struct linux_target_ops the_low_target = { NULL, mips_cannot_fetch_register, mips_cannot_store_register, + NULL, /* fetch_register */ mips_get_pc, mips_set_pc, (const unsigned char *) &mips_breakpoint, diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c index 518a59e2720..ed254fac067 100644 --- a/gdb/gdbserver/linux-ppc-low.c +++ b/gdb/gdbserver/linux-ppc-low.c @@ -613,6 +613,7 @@ struct linux_target_ops the_low_target = { NULL, ppc_cannot_fetch_register, ppc_cannot_store_register, + NULL, /* fetch_register */ ppc_get_pc, ppc_set_pc, (const unsigned char *) &ppc_breakpoint, diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index 8a327952434..ea4620667cf 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -464,6 +464,7 @@ struct linux_target_ops the_low_target = { NULL, s390_cannot_fetch_register, s390_cannot_store_register, + NULL, /* fetch_register */ s390_get_pc, s390_set_pc, s390_breakpoint, diff --git a/gdb/gdbserver/linux-sh-low.c b/gdb/gdbserver/linux-sh-low.c index e2537d60796..fbd67c657ee 100644 --- a/gdb/gdbserver/linux-sh-low.c +++ b/gdb/gdbserver/linux-sh-low.c @@ -115,6 +115,7 @@ struct linux_target_ops the_low_target = { NULL, sh_cannot_fetch_register, sh_cannot_store_register, + NULL, /* fetch_register */ sh_get_pc, sh_set_pc, (const unsigned char *) &sh_breakpoint, diff --git a/gdb/gdbserver/linux-sparc-low.c b/gdb/gdbserver/linux-sparc-low.c index dc9c0ccad88..04605877553 100644 --- a/gdb/gdbserver/linux-sparc-low.c +++ b/gdb/gdbserver/linux-sparc-low.c @@ -284,6 +284,7 @@ struct linux_target_ops the_low_target = { NULL, sparc_cannot_fetch_register, sparc_cannot_store_register, + NULL, /* fetch_register */ sparc_get_pc, /* No sparc_set_pc is needed. */ NULL, diff --git a/gdb/gdbserver/linux-tic6x-low.c b/gdb/gdbserver/linux-tic6x-low.c index db7c5a4ed62..69d538b4ad5 100644 --- a/gdb/gdbserver/linux-tic6x-low.c +++ b/gdb/gdbserver/linux-tic6x-low.c @@ -324,6 +324,7 @@ struct linux_target_ops the_low_target = { NULL, tic6x_cannot_fetch_register, tic6x_cannot_store_register, + NULL, /* fetch_register */ tic6x_get_pc, tic6x_set_pc, (const unsigned char *) &tic6x_breakpoint, diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index b466b5d281e..7feb72125ad 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -2969,6 +2969,7 @@ struct linux_target_ops the_low_target = NULL, NULL, NULL, + NULL, /* fetch_register */ x86_get_pc, x86_set_pc, x86_breakpoint, diff --git a/gdb/gdbserver/linux-xtensa-low.c b/gdb/gdbserver/linux-xtensa-low.c index bf7f064eded..34370f98b4c 100644 --- a/gdb/gdbserver/linux-xtensa-low.c +++ b/gdb/gdbserver/linux-xtensa-low.c @@ -183,6 +183,7 @@ struct linux_target_ops the_low_target = { NULL, 0, 0, + NULL, /* fetch_register */ xtensa_get_pc, xtensa_set_pc, xtensa_breakpoint,