diff options
-rw-r--r-- | gdb/ChangeLog | 20 | ||||
-rw-r--r-- | gdb/config/powerpc/linux.mh | 2 | ||||
-rw-r--r-- | gdb/config/powerpc/nm-linux.h | 6 | ||||
-rw-r--r-- | gdb/ppc-linux-nat.c | 158 |
4 files changed, 168 insertions, 18 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c796c70..2470ddd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,25 @@ 2001-12-20 Elena Zannoni <ezannoni@redhat.com> + * ppc-linux-nat.c (ppc_ptrace_cannot_fetch_store_register): + New function. + (fetch_register): New function. + (fetch_ppc_registers): New function. + (fetch_inferior_registers): New function. + (store_register): New function. + (store_ppc_registers): New function. + (store_inferior_registers): New function. + (ppc_register_u_addr): Eliminate ustart parameter and its + uses. Make static. + (PT_READ_U, PT_WRITE_U, PTRACE_XFER_TYPE): Define if needed. + Include sys/ptrace.h. + + * config/powerpc/nm-linux.h (FETCH_INFERIOR_REGISTERS): Define. + (U_REGS_OFFSET, REGISTER_U_ADDR): Delete. + + * config/powerpc/linux.mh (NATDEPFILES): Delete core-aout.o. + +2001-12-20 Elena Zannoni <ezannoni@redhat.com> + * rs6000-nat.c (fetch_register): Don't error out unless the register number is really bogus. diff --git a/gdb/config/powerpc/linux.mh b/gdb/config/powerpc/linux.mh index 6890357..07f83bd 100644 --- a/gdb/config/powerpc/linux.mh +++ b/gdb/config/powerpc/linux.mh @@ -6,7 +6,7 @@ XM_CLIBS= NAT_FILE= nm-linux.h NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \ -core-aout.o core-regset.o ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o +core-regset.o ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o LOADLIBES = -ldl -rdynamic diff --git a/gdb/config/powerpc/nm-linux.h b/gdb/config/powerpc/nm-linux.h index e9e6abd..dee39b4 100644 --- a/gdb/config/powerpc/nm-linux.h +++ b/gdb/config/powerpc/nm-linux.h @@ -28,10 +28,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define KERNEL_U_SIZE kernel_u_size() extern int kernel_u_size (void); -#define U_REGS_OFFSET 0 - -extern int ppc_register_u_addr (int, int); -#define REGISTER_U_ADDR(addr, blockend, regno) \ - (addr) = ppc_register_u_addr ((blockend),(regno)); +#define FETCH_INFERIOR_REGISTERS #endif /* #ifndef NM_LINUX_H */ diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 1d57a9a..a967f48 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -32,11 +32,24 @@ #include <sys/wait.h> #include <fcntl.h> #include <sys/procfs.h> +#include <sys/ptrace.h> /* Prototypes for supply_gregset etc. */ #include "gregset.h" #include "ppc-tdep.h" +#ifndef PT_READ_U +#define PT_READ_U PTRACE_PEEKUSR +#endif +#ifndef PT_WRITE_U +#define PT_WRITE_U PTRACE_POKEUSR +#endif + +/* Default the type of the ptrace transfer to int. */ +#ifndef PTRACE_XFER_TYPE +#define PTRACE_XFER_TYPE int +#endif + int kernel_u_size (void) { @@ -56,39 +69,161 @@ PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */ /* *INDENT_ON * */ -int -ppc_register_u_addr (int ustart, int regno) +static int +ppc_register_u_addr (int regno) { int u_addr = -1; /* General purpose registers occupy 1 slot each in the buffer */ if (regno >= gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum && regno <= gdbarch_tdep (current_gdbarch)->ppc_gplast_regnum ) - u_addr = (ustart + (PT_R0 + regno) * 4); + u_addr = ((PT_R0 + regno) * 4); /* Floating point regs: 2 slots each */ if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM) - u_addr = (ustart + (PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4); + u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4); /* UISA special purpose registers: 1 slot each */ if (regno == PC_REGNUM) - u_addr = ustart + PT_NIP * 4; + u_addr = PT_NIP * 4; if (regno == gdbarch_tdep (current_gdbarch)->ppc_lr_regnum) - u_addr = ustart + PT_LNK * 4; + u_addr = PT_LNK * 4; if (regno == gdbarch_tdep (current_gdbarch)->ppc_cr_regnum) - u_addr = ustart + PT_CCR * 4; + u_addr = PT_CCR * 4; if (regno == gdbarch_tdep (current_gdbarch)->ppc_xer_regnum) - u_addr = ustart + PT_XER * 4; + u_addr = PT_XER * 4; if (regno == gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum) - u_addr = ustart + PT_CTR * 4; + u_addr = PT_CTR * 4; if (regno == gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) - u_addr = ustart + PT_MQ * 4; + u_addr = PT_MQ * 4; if (regno == gdbarch_tdep (current_gdbarch)->ppc_ps_regnum) - u_addr = ustart + PT_MSR * 4; + u_addr = PT_MSR * 4; return u_addr; } +static int +ppc_ptrace_cannot_fetch_store_register (int regno) +{ + return (ppc_register_u_addr (regno) == -1); +} + +static void +fetch_register (int regno) +{ + /* This isn't really an address. But ptrace thinks of it as one. */ + char mess[128]; /* For messages */ + register int i; + unsigned int offset; /* Offset of registers within the u area. */ + char *buf = alloca (MAX_REGISTER_RAW_SIZE); + int tid; + CORE_ADDR regaddr = ppc_register_u_addr (regno); + + if (regaddr == -1) + { + memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */ + supply_register (regno, buf); + return; + } + + /* Overload thread id onto process id */ + if ((tid = TIDGET (inferior_ptid)) == 0) + tid = PIDGET (inferior_ptid); /* no thread id, just use process id */ + + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) + { + errno = 0; + *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid, + (PTRACE_ARG3_TYPE) regaddr, 0); + regaddr += sizeof (PTRACE_XFER_TYPE); + if (errno != 0) + { + sprintf (mess, "reading register %s (#%d)", + REGISTER_NAME (regno), regno); + perror_with_name (mess); + } + } + supply_register (regno, buf); +} + +static void +fetch_ppc_registers (void) +{ + int i; + int last_register = gdbarch_tdep (current_gdbarch)->ppc_mq_regnum; + + for (i = 0; i <= last_register; i++) + fetch_register (i); +} + +/* Fetch registers from the child process. Fetch all registers if + regno == -1, otherwise fetch all general registers or all floating + point registers depending upon the value of regno. */ +void +fetch_inferior_registers (int regno) +{ + if (regno == -1) + fetch_ppc_registers (); + else + fetch_register (regno); +} + +/* Store one register. */ +static void +store_register (int regno) +{ + /* This isn't really an address. But ptrace thinks of it as one. */ + CORE_ADDR regaddr = ppc_register_u_addr (regno); + char mess[128]; /* For messages */ + register int i; + unsigned int offset; /* Offset of registers within the u area. */ + int tid; + char *buf = alloca (MAX_REGISTER_RAW_SIZE); + + if (regaddr == -1) + { + return; + } + + /* Overload thread id onto process id */ + if ((tid = TIDGET (inferior_ptid)) == 0) + tid = PIDGET (inferior_ptid); /* no thread id, just use process id */ + + regcache_collect (regno, buf); + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) + { + errno = 0; + ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr, + *(PTRACE_XFER_TYPE *) & buf[i]); + regaddr += sizeof (PTRACE_XFER_TYPE); + if (errno != 0) + { + sprintf (mess, "writing register %s (#%d)", + REGISTER_NAME (regno), regno); + perror_with_name (mess); + } + } +} + +static void +store_ppc_registers (void) +{ + int i; + int last_register = gdbarch_tdep (current_gdbarch)->ppc_mq_regnum; + + for (i = 0; i <= last_register; i++) + store_register (i); +} + +void +store_inferior_registers (int regno) +{ + if (regno >= 0) + store_register (regno); + else + store_ppc_registers (); +} + void supply_gregset (gdb_gregset_t *gregsetp) { @@ -111,7 +246,6 @@ supply_gregset (gdb_gregset_t *gregsetp) (char *) (regp + PT_MQ)); supply_register (gdbarch_tdep (current_gdbarch)->ppc_ps_regnum, (char *) (regp + PT_MSR)); - } void |