From 75e51e1f8f2596ec1227502a79b67fcb3a21af2a Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Wed, 30 Mar 2005 14:59:31 +0000 Subject: * gdb/Makefile.in (arm-linux-nat.o): Update dependencies. * gdb/arm-linux-nat.c: Include "gdb_assert.h". (PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS): Define. (arm_linux_has_wmmx_registers): New flag. (GET_THREAD_ID): Remove stray punctuation. (IWMMXT_REGS_SIZE): Define. (fetch_wmmx_regs, store_wmmx_regs): New functions. (fetch_inferior_registers, store_inferior_registers): Call them. (arm_linux_available_registers): New function. * gdb/inftarg.c (child_xfer_partial): Handle TARGET_OBJECT_AVAILABLE_REGISTERS. * gdb/config/arm/nm-linux.h (arm_linux_available_registers): Add prototype. (NATIVE_XFER_AVAILABLE_REGISTERS): Define. * gdb/gdbserver/linux-arm-low.c (arm_fill_wmmxregset) (arm_store_wmmxregset): Remove stray text. (arm_available_registers): Remove debugging output. Use hex. * gdb/gdbserver/regcache.c (num_registers): Make global. * gdb/gdbserver/server.c (handle_p_packet, handle_P_packet): Check the value of regnum. --- ChangeLog.csl | 24 ++++++ gdb/Makefile.in | 2 +- gdb/arm-linux-nat.c | 173 ++++++++++++++++++++++++++++++++++++++++-- gdb/config/arm/nm-linux.h | 16 ++++ gdb/gdbserver/linux-arm-low.c | 12 +-- gdb/gdbserver/regcache.c | 2 +- gdb/gdbserver/server.c | 6 +- gdb/inftarg.c | 7 ++ 8 files changed, 219 insertions(+), 23 deletions(-) diff --git a/ChangeLog.csl b/ChangeLog.csl index 57842ed6e0e..2d493e7fa29 100644 --- a/ChangeLog.csl +++ b/ChangeLog.csl @@ -1,3 +1,27 @@ +2005-03-30 Daniel Jacobowitz + + * gdb/Makefile.in (arm-linux-nat.o): Update dependencies. + * gdb/arm-linux-nat.c: Include "gdb_assert.h". + (PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS): Define. + (arm_linux_has_wmmx_registers): New flag. + (GET_THREAD_ID): Remove stray punctuation. + (IWMMXT_REGS_SIZE): Define. + (fetch_wmmx_regs, store_wmmx_regs): New functions. + (fetch_inferior_registers, store_inferior_registers): Call them. + (arm_linux_available_registers): New function. + * gdb/inftarg.c (child_xfer_partial): Handle + TARGET_OBJECT_AVAILABLE_REGISTERS. + * gdb/config/arm/nm-linux.h (arm_linux_available_registers): Add + prototype. + (NATIVE_XFER_AVAILABLE_REGISTERS): Define. + + * gdb/gdbserver/linux-arm-low.c (arm_fill_wmmxregset) + (arm_store_wmmxregset): Remove stray text. + (arm_available_registers): Remove debugging output. Use hex. + * gdb/gdbserver/regcache.c (num_registers): Make global. + * gdb/gdbserver/server.c (handle_p_packet, handle_P_packet): Check + the value of regnum. + 2005-03-28 Paul Brook Daniel Jacobowitz diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 4a6e9715835..b126430bc1c 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1732,7 +1732,7 @@ arch-utils.o: arch-utils.c $(defs_h) $(arch_utils_h) $(buildsym_h) \ $(floatformat_h) arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \ $(gdb_string_h) $(regcache_h) $(arm_tdep_h) $(gregset_h)\ - $(gdb_proc_service_h) + $(gdb_proc_service_h) $(gdb_assert_h) arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \ $(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_h) \ $(doublest_h) $(solib_svr4_h) $(osabi_h) $(arm_tdep_h) \ diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c index cd9d5ff66ba..59377be6493 100644 --- a/gdb/arm-linux-nat.c +++ b/gdb/arm-linux-nat.c @@ -23,6 +23,7 @@ #include "gdbcore.h" #include "gdb_string.h" #include "regcache.h" +#include "gdb_assert.h" #include "arm-tdep.h" @@ -41,6 +42,13 @@ #define PTRACE_GET_THREAD_AREA 22 #endif +#ifndef PTRACE_GETWMMXREGS +#define PTRACE_GETWMMXREGS 18 +#define PTRACE_SETWMMXREGS 19 +#endif + +static int arm_linux_has_wmmx_registers = 1; + extern int arm_apcs_32; #define typeNone 0x00 @@ -99,7 +107,7 @@ get_thread_id (ptid_t ptid) tid = PIDGET (ptid); return tid; } -#define GET_THREAD_ID(PTID) get_thread_id ((PTID)); +#define GET_THREAD_ID(PTID) get_thread_id (PTID) static void fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11) @@ -550,6 +558,97 @@ store_regs (void) } } +/* Fetch all WMMX registers of the process and store into + regcache. */ + +#define IWMMXT_REGS_SIZE (16 * 8 + 6 * 4) + +static void +fetch_wmmx_regs (void) +{ + char regbuf[IWMMXT_REGS_SIZE]; + int ret, regno, tid, first; + + /* Get the thread id for the ptrace call. */ + tid = GET_THREAD_ID (inferior_ptid); + + ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf); + if (ret < 0) + { + warning (_("Unable to fetch WMMX registers.")); + return; + } + + first = gdbarch_tdep (current_gdbarch)->first_iwmmxt_regnum; + + for (regno = 0; regno < NUM_IWMMXT_COP0REGS; regno++) + regcache_raw_supply (current_regcache, first + regno, + ®buf[regno * 8]); + + first += NUM_IWMMXT_COP0REGS; + + for (regno = 0; regno < 2; regno++) + regcache_raw_supply (current_regcache, first + regno, NULL); + + for (regno = 2; regno < 4; regno++) + regcache_raw_supply (current_regcache, first + regno, + ®buf[16 * 8 + (regno - 2) * 4]); + + for (regno = 4; regno < 8; regno++) + regcache_raw_supply (current_regcache, first + regno, NULL); + + for (regno = 8; regno < 12; regno++) + regcache_raw_supply (current_regcache, first + regno, + ®buf[16 * 8 + 2 * 4 + (regno - 8) * 4]); + + for (regno = 12; regno < 16; regno++) + regcache_raw_supply (current_regcache, first + regno, NULL); +} + +static void +store_wmmx_regs (void) +{ + char regbuf[IWMMXT_REGS_SIZE]; + int ret, regno, tid, first; + + /* Get the thread id for the ptrace call. */ + tid = GET_THREAD_ID (inferior_ptid); + + ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf); + if (ret < 0) + { + warning (_("Unable to fetch WMMX registers.")); + return; + } + + first = gdbarch_tdep (current_gdbarch)->first_iwmmxt_regnum; + + for (regno = 0; regno < NUM_IWMMXT_COP0REGS; regno++) + if (register_cached (first + regno)) + regcache_raw_collect (current_regcache, first + regno, + ®buf[regno * 8]); + + first += 18; + for (regno = 0; regno < 2; regno++) + if (register_cached (first + regno)) + regcache_raw_collect (current_regcache, first + regno, + ®buf[16 * 8 + regno * 4]); + + first += 6; + for (regno = 0; regno < 4; regno++) + if (register_cached (first + regno)) + regcache_raw_collect (current_regcache, first + regno, + ®buf[16 * 8 + 2 * 4 + regno * 4]); + + ret = ptrace (PTRACE_SETWMMXREGS, tid, 0, regbuf); + + if (ret < 0) + { + warning (_("Unable to store WMMX registers.")); + return; + } +} + /* 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. */ @@ -561,14 +660,21 @@ fetch_inferior_registers (int regno) { fetch_regs (); fetch_fpa_regs (); + if (arm_linux_has_wmmx_registers) + fetch_wmmx_regs (); } else { - if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) + if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM) fetch_register (regno); - - if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM) + else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM) fetch_fpa_register (regno); + else if (arm_linux_has_wmmx_registers) + { + int first = gdbarch_tdep (current_gdbarch)->first_iwmmxt_regnum; + if (regno >= first && regno < first + NUM_IWMMXT_REGS) + fetch_wmmx_regs (); + } } } @@ -583,14 +689,21 @@ store_inferior_registers (int regno) { store_regs (); store_fpa_regs (); + if (arm_linux_has_wmmx_registers) + store_wmmx_regs (); } else { - if ((regno < ARM_F0_REGNUM) || (regno > ARM_FPS_REGNUM)) + if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM) store_register (regno); - - if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM)) - store_fpa_register (regno); + else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM)) + store_fpa_register (regno); + else if (arm_linux_has_wmmx_registers) + { + int first = gdbarch_tdep (current_gdbarch)->first_iwmmxt_regnum; + if (regno >= first && regno < first + NUM_IWMMXT_REGS) + store_wmmx_regs (); + } } } @@ -740,6 +853,50 @@ get_linux_version (unsigned int *vmajor, return ((*vmajor << 16) | (*vminor << 8) | *vrelease); } +LONGEST +arm_linux_available_registers (struct target_ops *ops, + int /* enum target_object */ object, + const char *annex, + void *readbuf, + const void *writebuf, + ULONGEST offset, + LONGEST len) +{ + char *result = NULL; + int total_len; + + gdb_assert (object == TARGET_OBJECT_AVAILABLE_REGISTERS); + gdb_assert (readbuf && !writebuf); + + if (arm_linux_has_wmmx_registers) + { + int ret; + char regbuf[IWMMXT_REGS_SIZE]; + + ret = ptrace (PTRACE_GETWMMXREGS, GET_THREAD_ID (inferior_ptid), 0, + regbuf); + if (ret < 0) + /* Should we be checking the error code? */ + arm_linux_has_wmmx_registers = 0; + } + + if (arm_linux_has_wmmx_registers) + result = "iwmmxt"; + + if (result == NULL) + return 0; + + total_len = strlen (result); + if (total_len > offset) + { + int bytes_read = min (total_len - offset, len); + memcpy (readbuf, result + offset, bytes_read); + return bytes_read; + } + + return 0; +} + void _initialize_arm_linux_nat (void) { diff --git a/gdb/config/arm/nm-linux.h b/gdb/config/arm/nm-linux.h index 1d7bbaa8650..2ad3968f636 100644 --- a/gdb/config/arm/nm-linux.h +++ b/gdb/config/arm/nm-linux.h @@ -38,4 +38,20 @@ extern int kernel_u_size (void); /* Override copies of {fetch,store}_inferior_registers in infptrace.c. */ #define FETCH_INFERIOR_REGISTERS +/* This function is called like a to_xfer_partial hook, + but must be called with TARGET_OBJECT_AVAILABLE_REGISTERS. */ + +struct target_ops; + +extern LONGEST arm_linux_available_registers + (struct target_ops *ops, + int /* enum target_object */ object, + const char *annex, + void *readbuf, + const void *writebuf, + ULONGEST offset, + LONGEST len); + +#define NATIVE_XFER_AVAILABLE_REGISTERS arm_linux_available_registers + #endif /* NM_ARMLINUX_H */ diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index e49c86e16e1..606a6669ede 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -155,11 +155,6 @@ arm_fill_wmmxregset (void *buf) for (i = 0; i < 4; i++) collect_register (arm_num_regs + i + 16 + 8, ((char *) buf) + 16 * 8 + 8 + i * 4); - - ((int*)buf)[0], - ((int*)buf)[1], - ((int*)buf)[2], - ((int*)buf)[3]); } static void @@ -167,10 +162,6 @@ arm_store_wmmxregset (const void *buf) { int i; - ((int*)buf)[0], - ((int*)buf)[1], - ((int*)buf)[2], - ((int*)buf)[3]); for (i = 0; i < 16; i++) supply_register (arm_num_regs + i, ((char *) buf) + i * 8); @@ -186,11 +177,10 @@ arm_available_registers (void) { char buf[64]; - printf ("use_regsets %d target_regsets %d\n", use_regsets_p, target_regsets[1].size); if (use_regsets_p && target_regsets[1].size > 0) { int wr0 = find_regno ("wr0"); - sprintf (buf, "iwmmxt:%d", wr0); + sprintf (buf, "iwmmxt:%x", wr0); return strdup (buf); } diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c index 011fac1c5d9..8bfb3ec7833 100644 --- a/gdb/gdbserver/regcache.c +++ b/gdb/gdbserver/regcache.c @@ -38,7 +38,7 @@ struct inferior_regcache_data static int register_bytes, g_register_bytes; static struct reg *reg_defs; -static int num_registers; +int num_registers; const char **gdbserver_expedite_regs; diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 1389231770f..1c5f767c295 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -295,6 +295,8 @@ handle_v_requests (char *own_buf, char *status, unsigned char *signal) return; } +extern int num_registers; + /* Handle a register fetch ('p') request. */ void handle_p_packet (char *own_buf) @@ -302,7 +304,7 @@ handle_p_packet (char *own_buf) char *end = own_buf + 1; int regnum = strtol (own_buf + 1, &end, 16); - if (*end) + if (*end || regnum < 0 || regnum >= num_registers) { write_enn (own_buf); return; @@ -318,7 +320,7 @@ handle_P_packet (char *own_buf) char *end = own_buf + 1; int regnum = strtol (own_buf + 1, &end, 16); - if (*end != '=') + if (*end != '=' || regnum < 0 || regnum >= num_registers) { write_enn (own_buf); return; diff --git a/gdb/inftarg.c b/gdb/inftarg.c index cd8674dc758..15dd8ebc087 100644 --- a/gdb/inftarg.c +++ b/gdb/inftarg.c @@ -559,6 +559,13 @@ child_xfer_partial (struct target_ops *ops, enum target_object object, return NATIVE_XFER_AUXV (ops, object, annex, readbuf, writebuf, offset, len); + case TARGET_OBJECT_AVAILABLE_REGISTERS: +#ifndef NATIVE_XFER_AVAILABLE_REGISTERS +#define NATIVE_XFER_AVAILABLE_REGISTERS(OPS,OBJECT,ANNEX,WRITEBUF,READBUF,OFFSET,LEN) (-1) +#endif + return NATIVE_XFER_AVAILABLE_REGISTERS (ops, object, annex, readbuf, + writebuf, offset, len); + default: return -1; } -- cgit v1.2.1