diff --git a/gdb/configure.ac b/gdb/configure.ac index 680fba0..5263edb 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -924,7 +924,8 @@ AC_CHECK_MEMBERS([struct reg.r_fs, struct reg.r_gs], [], [], # See if provides the PTRACE_GETREGS request. AC_MSG_CHECKING(for PTRACE_GETREGS) AC_CACHE_VAL(gdb_cv_have_ptrace_getregs, -[AC_TRY_COMPILE([#include ], +[AC_TRY_COMPILE([#include + #include ], [PTRACE_GETREGS;], [gdb_cv_have_ptrace_getregs=yes], [gdb_cv_have_ptrace_getregs=no])]) @@ -934,10 +935,81 @@ if test $gdb_cv_have_ptrace_getregs = yes; then [Define if sys/ptrace.h defines the PTRACE_GETREGS request.]) fi +# See if provides the PTRACE_SETREGS request. +AC_MSG_CHECKING(for PTRACE_SETREGS) +AC_CACHE_VAL(gdb_cv_have_ptrace_setregs, +[AC_TRY_COMPILE([#include + #include ], + [PTRACE_SETREGS;], + [gdb_cv_have_ptrace_setregs=yes], + [gdb_cv_have_ptrace_setregs=no])]) +AC_MSG_RESULT($gdb_cv_have_ptrace_setregs) +if test $gdb_cv_have_ptrace_setregs = yes; then + AC_DEFINE(HAVE_PTRACE_SETREGS, 1, + [Define if sys/ptrace.h defines the PTRACE_SETREGS request.]) +fi + +# See if provides the PTRACE_GETREGS64 request. +AC_MSG_CHECKING(for PTRACE_GETREGS64) +AC_CACHE_VAL(gdb_cv_have_ptrace_getregs64, +[AC_TRY_COMPILE([#include + #include ], + [PTRACE_GETREGS64;], + [gdb_cv_have_ptrace_getregs64=yes], + [gdb_cv_have_ptrace_getregs64=no])]) +AC_MSG_RESULT($gdb_cv_have_ptrace_getregs64) +if test $gdb_cv_have_ptrace_getregs64 = yes; then + AC_DEFINE(HAVE_PTRACE_GETREGS64, 1, + [Define if sys/ptrace.h defines the PTRACE_GETREGS64 request.]) +fi + +# See if provides the PTRACE_SETREGS64 request. +AC_MSG_CHECKING(for PTRACE_SETREGS64) +AC_CACHE_VAL(gdb_cv_have_ptrace_setregs64, +[AC_TRY_COMPILE([#include + #include ], + [PTRACE_SETREGS64;], + [gdb_cv_have_ptrace_setregs64=yes], + [gdb_cv_have_ptrace_setregs64=no])]) +AC_MSG_RESULT($gdb_cv_have_ptrace_setregs64) +if test $gdb_cv_have_ptrace_setregs64 = yes; then + AC_DEFINE(HAVE_PTRACE_SETREGS64, 1, + [Define if sys/ptrace.h defines the PTRACE_SETREGS64 request.]) +fi + +# See if provides the PTRACE_GETFPREGS request. +AC_MSG_CHECKING(for PTRACE_GETFPREGS) +AC_CACHE_VAL(gdb_cv_have_ptrace_getfpregs, +[AC_TRY_COMPILE([#include + #include ], + [PTRACE_GETFPREGS;], + [gdb_cv_have_ptrace_getfpregs=yes], + [gdb_cv_have_ptrace_getfpregs=no])]) +AC_MSG_RESULT($gdb_cv_have_ptrace_getfpregs) +if test $gdb_cv_have_ptrace_getfpregs = yes; then + AC_DEFINE(HAVE_PTRACE_GETFPREGS, 1, + [Define if sys/ptrace.h defines the PTRACE_GETFPREGS request.]) +fi + +# See if provides the PTRACE_SETFPREGS request. +AC_MSG_CHECKING(for PTRACE_SETFPREGS) +AC_CACHE_VAL(gdb_cv_have_ptrace_setfpregs, +[AC_TRY_COMPILE([#include + #include ], + [PTRACE_SETFPREGS;], + [gdb_cv_have_ptrace_setfpregs=yes], + [gdb_cv_have_ptrace_setfpregs=no])]) +AC_MSG_RESULT($gdb_cv_have_ptrace_setfpregs) +if test $gdb_cv_have_ptrace_setfpregs = yes; then + AC_DEFINE(HAVE_PTRACE_SETFPREGS, 1, + [Define if sys/ptrace.h defines the PTRACE_SETFPREGS request.]) +fi + # See if provides the PTRACE_GETFPXREGS request. AC_MSG_CHECKING(for PTRACE_GETFPXREGS) AC_CACHE_VAL(gdb_cv_have_ptrace_getfpxregs, -[AC_TRY_COMPILE([#include ], +[AC_TRY_COMPILE([#include + #include ], [PTRACE_GETFPXREGS;], [gdb_cv_have_ptrace_getfpxregs=yes], [gdb_cv_have_ptrace_getfpxregs=no])]) @@ -947,6 +1019,20 @@ if test $gdb_cv_have_ptrace_getfpxregs = yes; then [Define if sys/ptrace.h defines the PTRACE_GETFPXREGS request.]) fi +# See if provides the PTRACE_SETFPXREGS request. +AC_MSG_CHECKING(for PTRACE_SETFPXREGS) +AC_CACHE_VAL(gdb_cv_have_ptrace_setfpxregs, +[AC_TRY_COMPILE([#include + #include ], + [PTRACE_SETFPXREGS;], + [gdb_cv_have_ptrace_setfpxregs=yes], + [gdb_cv_have_ptrace_setfpxregs=no])]) +AC_MSG_RESULT($gdb_cv_have_ptrace_setfpxregs) +if test $gdb_cv_have_ptrace_setfpxregs = yes; then + AC_DEFINE(HAVE_PTRACE_SETFPXREGS, 1, + [Define if sys/ptrace.h defines the PTRACE_SETFPXREGS request.]) +fi + # See if provides the PT_GETDBREGS request. AC_MSG_CHECKING(for PT_GETDBREGS) AC_CACHE_VAL(gdb_cv_have_pt_getdbregs, diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index ed197f1..ffb1e79 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -588,6 +588,70 @@ fetch_altivec_registers (struct regcache *regcache, int tid) supply_vrregset (regcache, ®s); } +static void +fetch_gp_regs (struct regcache *regcache, int tid) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int i; + gdb_gregset_t gregset; + + gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8); + + if (tdep->wordsize == 4) + { +#ifdef HAVE_PTRACE_GETREGS + /* PPC 32-bit. */ + if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0) + perror_with_name (_("Couldn't get general-purpose registers.")); + + supply_gregset (regcache, (const gdb_gregset_t *) &gregset); + return; +#endif /* HAVE_PTRACE_GETREGS */ + } + else if (tdep->wordsize == 8) + { +#ifdef HAVE_PTRACE_GETREGS64 + /* PPC 64-bit. */ + if (ptrace (PTRACE_GETREGS64, tid, 0, (void *) &gregset) < 0) + perror_with_name (_("Couldn't get general-purpose registers.")); + + supply_gregset (regcache, (const gdb_gregset_t *) &gregset); + return; +#endif /* HAVE_PTRACE_GETREGS64 */ + } + + /* If we've hit this point, it doesn't really matter which + architecture we are using. We just need to read the + registers in the "old-fashioned way". */ + for (i = 0; i < ppc_num_gprs; i++) + fetch_register (regcache, tid, tdep->ppc_gp0_regnum + i); +} + +#ifdef HAVE_PTRACE_GETFPREGS + +static void +fetch_fp_regs (struct regcache *regcache, int tid) +{ + gdb_fpregset_t fpregs; + + if (ptrace (PTRACE_GETFPREGS, tid, 0, (void *) &fpregs) < 0) + perror_with_name (_("Couldn't get floating point status")); + + supply_fpregset (regcache, (const gdb_fpregset_t *) &fpregs); +} + +#else /* HAVE_PTRACE_GETFPREGS */ + +static void +fetch_fp_regs (struct regcache *regcache, int tid) +{ + internal_error (__FILE__, __LINE__, + "The function should not be called."); +} + +#endif /* HAVE_PTRACE_GEFPTREGS */ + static void fetch_ppc_registers (struct regcache *regcache, int tid) { @@ -595,11 +659,14 @@ fetch_ppc_registers (struct regcache *regcache, int tid) struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - for (i = 0; i < ppc_num_gprs; i++) - fetch_register (regcache, tid, tdep->ppc_gp0_regnum + i); + fetch_gp_regs (regcache, tid); if (tdep->ppc_fp0_regnum >= 0) +#ifdef HAVE_PTRACE_GETFPREGS + fetch_fp_regs (regcache, tid); +#else /* HAVE_PTRACE_GETFPREGS */ for (i = 0; i < ppc_num_fprs; i++) fetch_register (regcache, tid, tdep->ppc_fp0_regnum + i); +#endif /* HAVE_PTRACE_GETFPREGS */ fetch_register (regcache, tid, gdbarch_pc_regnum (gdbarch)); if (tdep->ppc_ps_regnum != -1) fetch_register (regcache, tid, tdep->ppc_ps_regnum); @@ -957,17 +1024,92 @@ store_altivec_registers (const struct regcache *regcache, int tid) } static void -store_ppc_registers (const struct regcache *regcache, int tid) +store_gp_regs (const struct regcache *regcache, int tid, int regno) { - int i; struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - + int i; + gdb_gregset_t gregset; + + gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8); + + if (tdep->wordsize == 4) + { +#if defined(HAVE_PTRACE_SETREGS) && defined(HAVE_PTRACE_GETREGS) + /* PPC 32-bit. */ + if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0) + perror_with_name (_("Couldn't get general-purpose registers.")); + + fill_gregset (regcache, &gregset, regno); + + if (ptrace (PTRACE_SETREGS, tid, 0, (void *) &gregset) < 0) + perror_with_name (_("Couldn't get general-purpose registers.")); + return; +#endif /* HAVE_PTRACE_SETREGS && HAVE_PTRACE_GETREGS */ + } + else if (tdep->wordsize == 8) + { +#if defined(HAVE_PTRACE_SETREGS64) && defined(HAVE_PTRACE_GETREGS64) + /* PPC 64-bit. */ + if (ptrace (PTRACE_GETREGS64, tid, 0, (void *) &gregset) < 0) + perror_with_name (_("Couldn't get general-purpose registers.")); + + fill_gregset (regcache, &gregset, regno); + + if (ptrace (PTRACE_SETREGS64, tid, 0, (void *) &gregset) < 0) + perror_with_name (_("Couldn't get general-purpose registers.")); + return; +#endif /* HAVE_PTRACE_SETREGS64 && HAVE_PTRACE_GETREGS64 */ + } + /* If we've hit this point, it doesn't really matter which + architecture we are using. We just need to store the + registers in the "old-fashioned way". */ for (i = 0; i < ppc_num_gprs; i++) store_register (regcache, tid, tdep->ppc_gp0_regnum + i); +} + +#if defined(HAVE_PTRACE_SETFPREGS) && defined(HAVE_PTRACE_GETFPREGS) + +static void +store_fp_regs (const struct regcache *regcache, int tid, int regno) +{ + gdb_fpregset_t fpregs; + + if (ptrace (PTRACE_GETFPREGS, tid, 0, (void *) &fpregs) < 0) + perror_with_name (_("Couldn't get floating point status")); + + fill_fpregset (regcache, &fpregs, regno); + + if (ptrace (PTRACE_SETFPREGS, tid, 0, (void *) &fpregs) < 0) + perror_with_name (_("Couldn't write floating point status")); +} + +#else /* HAVE_PTRACE_SETFPREGS && HAVE_PTRACE_GETFPREGS */ + +static void +store_fp_regs (const struct regcache *regcache, int tid) +{ + internal_error (__FILE__, __LINE__, + "The function should not be called."); +} + +#endif /* HAVE_PTRACE_SETFPREGS && HAVE_PTRACE_GETFPREGS */ + +static void +store_ppc_registers (const struct regcache *regcache, int tid) +{ + int i; + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + store_gp_regs (regcache, tid, -1); if (tdep->ppc_fp0_regnum >= 0) +#if defined(HAVE_PTRACE_SETFPREGS) && defined(HAVE_PTRACE_GETFPREGS) + store_fp_regs (regcache, tid, -1); +#else /* HAVE_PTRACE_SETFPREGS && HAVE_PTRACE_GETFPREGS */ for (i = 0; i < ppc_num_fprs; i++) store_register (regcache, tid, tdep->ppc_fp0_regnum + i); +#endif /* HAVE_PTRACE_SETFPREGS && HAVE_PTRACE_GETFPREGS */ store_register (regcache, tid, gdbarch_pc_regnum (gdbarch)); if (tdep->ppc_ps_regnum != -1) store_register (regcache, tid, tdep->ppc_ps_regnum);