diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index c99505fba7..8627aa9c4a 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 01208efc1a..bf1792bf9e 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 b6fe58a4c9..d5b0361181 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 a399789cb7..0c92e629d6 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 e33372de25..1cc4cd10c1 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 875319051a..c8fa603ec7 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 8becf78cce..aea8d36794 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 3aeae70405..07eda12de1 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 fd70cf2c49..29bb3f7cf0 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 a640e4c42c..6769dac9af 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 1f584425a1..8e37298d11 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 518a59e272..ed254fac06 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 8a32795243..ea4620667c 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 e2537d6079..fbd67c657e 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 dc9c0ccad8..0460587755 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 db7c5a4ed6..69d538b4ad 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 b466b5d281..7feb72125a 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 bf7f064ede..34370f98b4 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,