This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfa] ARM native GDB iWMMXt support


This patch adds support to a native ARM GDB for reading the iWMMXt
registers using ptrace.  gdbserver already has this.  It works exactly
the same way, except that it also autodetects instead of choosing at
compile time.  If the iWMMXt registers are available, then we supply
the same XML description that gdbserver would use.  (Or, a warning
message appears, if you don't have expat.)

My last iWMMXt patch, at least for now.  One thing missing is core
file support - but the kernel doesn't dump the registers into core
files yet :-(

Tested on arm-linux-gnueabi with iwmmxt.  OK?

-- 
Daniel Jacobowitz
CodeSourcery

2007-02-13  Daniel Jacobowitz  <dan@codesourcery.com>

	* Makefile.in (XMLFILES): Include $(TDEP_XML).
	(filenames_h): New variable.
	(clean): Clean up xml-builtin.c and stamp-xml.
	(arm-linux-nat.o): Update.
	* config/arm/linux.mh (TDEP_XML): Define.
	* arm-linux-nat.c (PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS): Define.
	(arm_linux_has_wmmx_registers): New.
	(GET_THREAD_ID): Fix typo.
	(IWMMXT_REGS_SIZE): Define.
	(fetch_wmmx_regs, store_wmmx_regs): New.
	(arm_linux_fetch_inferior_registers): Use fetch_wmmx_regs.
	(arm_linux_store_inferior_registers): Use store_wmmx_regs.
	(super_xfer_partial, arm_linux_xfer_partial): New.
	(_initialize_arm_linux_nat): Use them.
	* xml-support.c (fetch_xml_builtin): Move outside HAVE_LIBEXPAT.
	(xml_builtin_xfer_partial): New function.
	* xml-support.h (xml_builtin_xfer_partial): New prototype.
	* NEWS: Update mention of iWMMXt support.

---
 gdb/Makefile.in         |    8 +-
 gdb/NEWS                |    4 -
 gdb/arm-linux-nat.c     |  148 +++++++++++++++++++++++++++++++++++++++++++++---
 gdb/config/arm/linux.mh |    3 
 gdb/xml-support.c       |   42 +++++++++++--
 gdb/xml-support.h       |    9 ++
 6 files changed, 197 insertions(+), 17 deletions(-)

Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in	2007-02-13 09:34:00.000000000 -0500
+++ src/gdb/Makefile.in	2007-02-13 09:34:15.000000000 -0500
@@ -401,7 +401,8 @@ RUNTEST = runtest
 RUNTESTFLAGS=
 
 # XML files to build in to GDB.
-XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd
+XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
+	$(TDEP_XML)
 
 # This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
 # interface to the serial port.  Hopefully if get ported to OS/2, VMS,
@@ -614,6 +615,7 @@ gdb_sim_sh_h =	$(INCLUDE_DIR)/gdb/sim-sh
 splay_tree_h =  $(INCLUDE_DIR)/splay-tree.h
 safe_ctype_h =  $(INCLUDE_DIR)/safe-ctype.h
 hashtab_h =	$(INCLUDE_DIR)/hashtab.h
+filenames_h =	$(INCLUDE_DIR)/filenames.h
 
 #
 # $BUILD/ headers
@@ -1285,6 +1287,7 @@ clean mostlyclean: $(CONFIG_CLEAN)
 	rm -f gdb$(EXEEXT) core make.log
 	rm -f gdb[0-9]$(EXEEXT)
 	rm -f test-cp-name-parser$(EXEEXT)
+	rm -f xml-builtin.c stamp-xml
 
 .PHONY: clean-tui
 clean-tui:
@@ -1802,7 +1805,8 @@ arch-utils.o: arch-utils.c $(defs_h) $(a
 	$(floatformat_h) $(target_descriptions_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) \
-	$(target_h) $(linux_nat_h) $(gdb_proc_service_h) $(arm_linux_tdep_h)
+	$(target_h) $(linux_nat_h) $(gdb_proc_service_h) $(arm_linux_tdep_h) \
+	$(target_descriptions_h) $(xml_support_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) \
Index: src/gdb/config/arm/linux.mh
===================================================================
--- src.orig/gdb/config/arm/linux.mh	2007-02-13 09:34:00.000000000 -0500
+++ src/gdb/config/arm/linux.mh	2007-02-13 09:34:15.000000000 -0500
@@ -6,3 +6,6 @@ NATDEPFILES= inf-ptrace.o fork-child.o a
 
 LOADLIBES= -ldl -rdynamic
 
+TDEP_XML = $(srcdir)/features/arm-with-iwmmxt.xml \
+	$(srcdir)/features/xscale-iwmmxt.xml \
+	$(srcdir)/features/arm-core.xml
Index: src/gdb/arm-linux-nat.c
===================================================================
--- src.orig/gdb/arm-linux-nat.c	2007-02-13 09:34:01.000000000 -0500
+++ src/gdb/arm-linux-nat.c	2007-02-13 09:34:15.000000000 -0500
@@ -26,6 +26,8 @@
 #include "regcache.h"
 #include "target.h"
 #include "linux-nat.h"
+#include "target-descriptions.h"
+#include "xml-support.h"
 
 #include "arm-tdep.h"
 #include "arm-linux-tdep.h"
@@ -45,6 +47,14 @@
 #define PTRACE_GET_THREAD_AREA 22
 #endif
 
+#ifndef PTRACE_GETWMMXREGS
+#define PTRACE_GETWMMXREGS 18
+#define PTRACE_SETWMMXREGS 19
+#endif
+
+/* A flag for whether the WMMX registers are available.  */
+static int arm_linux_has_wmmx_registers;
+
 extern int arm_apcs_32;
 
 /* The following variables are used to determine the version of the
@@ -77,7 +87,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)
 
 /* Get the value of a particular register from the floating point
    state of the process and store it into regcache.  */
@@ -363,6 +373,80 @@ 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;
+
+  /* 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;
+    }
+
+  for (regno = 0; regno < 16; regno++)
+    regcache_raw_supply (current_regcache, regno + ARM_WR0_REGNUM,
+			 &regbuf[regno * 8]);
+
+  for (regno = 0; regno < 2; regno++)
+    regcache_raw_supply (current_regcache, regno + ARM_WCSSF_REGNUM,
+			 &regbuf[16 * 8 + regno * 4]);
+
+  for (regno = 0; regno < 4; regno++)
+    regcache_raw_supply (current_regcache, regno + ARM_WCGR0_REGNUM,
+			 &regbuf[16 * 8 + 2 * 4 + regno * 4]);
+}
+
+static void
+store_wmmx_regs (void)
+{
+  char regbuf[IWMMXT_REGS_SIZE];
+  int ret, regno, tid;
+
+  /* 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;
+    }
+
+  for (regno = 0; regno < 16; regno++)
+    if (register_cached (regno + ARM_WR0_REGNUM))
+      regcache_raw_collect (current_regcache, regno + ARM_WR0_REGNUM,
+			    &regbuf[regno * 8]);
+
+  for (regno = 0; regno < 2; regno++)
+    if (register_cached (regno + ARM_WCSSF_REGNUM))
+      regcache_raw_collect (current_regcache, regno + ARM_WCSSF_REGNUM,
+			    &regbuf[16 * 8 + regno * 4]);
+
+  for (regno = 0; regno < 4; regno++)
+    if (register_cached (regno + ARM_WCGR0_REGNUM))
+      regcache_raw_collect (current_regcache, regno + ARM_WCGR0_REGNUM,
+			    &regbuf[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.  */
@@ -374,14 +458,18 @@ arm_linux_fetch_inferior_registers (int 
     {
       fetch_regs ();
       fetch_fpregs ();
+      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_fpregister (regno);
+      else if (arm_linux_has_wmmx_registers
+	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
+	fetch_wmmx_regs ();
     }
 }
 
@@ -396,14 +484,18 @@ arm_linux_store_inferior_registers (int 
     {
       store_regs ();
       store_fpregs ();
+      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))
+      else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
         store_fpregister (regno);
+      else if (arm_linux_has_wmmx_registers
+	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
+	store_wmmx_regs ();
     }
 }
 
@@ -485,6 +577,44 @@ get_linux_version (unsigned int *vmajor,
   return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
 }
 
+static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object,
+				      const char *, gdb_byte *, const gdb_byte *,
+				      ULONGEST, LONGEST);
+
+static LONGEST
+arm_linux_xfer_partial (struct target_ops *ops,
+			 enum target_object object,
+			 const char *annex,
+			 gdb_byte *readbuf, const gdb_byte *writebuf,
+			 ULONGEST offset, LONGEST len)
+{
+  if (object == TARGET_OBJECT_AVAILABLE_FEATURES)
+    {
+      if (annex != NULL && strcmp (annex, "target.xml") == 0)
+	{
+	  int ret;
+	  char regbuf[IWMMXT_REGS_SIZE];
+
+	  ret = ptrace (PTRACE_GETWMMXREGS, GET_THREAD_ID (inferior_ptid),
+			0, regbuf);
+	  if (ret < 0)
+	    arm_linux_has_wmmx_registers = 0;
+	  else
+	    arm_linux_has_wmmx_registers = 1;
+
+	  if (arm_linux_has_wmmx_registers)
+	    annex = "arm-with-iwmmxt.xml";
+	  else
+	    return -1;
+	}
+
+      return xml_builtin_xfer_partial (annex, readbuf, writebuf, offset, len);
+    }
+
+  return super_xfer_partial (ops, object, annex, readbuf, writebuf,
+			     offset, len);
+}
+
 void _initialize_arm_linux_nat (void);
 
 void
@@ -501,6 +631,10 @@ _initialize_arm_linux_nat (void)
   t->to_fetch_registers = arm_linux_fetch_inferior_registers;
   t->to_store_registers = arm_linux_store_inferior_registers;
 
+  /* Override the default to_xfer_partial.  */
+  super_xfer_partial = t->to_xfer_partial;
+  t->to_xfer_partial = arm_linux_xfer_partial;
+
   /* Register the target.  */
   linux_nat_add_target (t);
 }
Index: src/gdb/xml-support.c
===================================================================
--- src.orig/gdb/xml-support.c	2007-02-13 09:34:01.000000000 -0500
+++ src/gdb/xml-support.c	2007-02-13 09:35:10.000000000 -0500
@@ -21,6 +21,11 @@
 
 #include "defs.h"
 #include "gdbcmd.h"
+#include "exceptions.h"
+#include "xml-support.h"
+
+#include "gdb_string.h"
+#include "safe-ctype.h"
 
 /* Debugging flag.  */
 static int debug_xml;
@@ -29,12 +34,7 @@ static int debug_xml;
    available.  */
 #ifdef HAVE_LIBEXPAT
 
-#include "exceptions.h"
-#include "xml-support.h"
-
 #include "gdb_expat.h"
-#include "gdb_string.h"
-#include "safe-ctype.h"
 
 /* The maximum depth of <xi:include> nesting.  No need to be miserly,
    we just want to avoid running out of stack on loops.  */
@@ -880,6 +880,7 @@ xml_process_xincludes (const char *name,
   do_cleanups (back_to);
   return result;
 }
+#endif /* HAVE_LIBEXPAT */
 
 
 /* Return an XML document which was compiled into GDB, from
@@ -897,7 +898,36 @@ fetch_xml_builtin (const char *filename)
   return NULL;
 }
 
-#endif /* HAVE_LIBEXPAT */
+/* A to_xfer_partial helper function which reads XML files which were
+   compiled into GDB.  The target may call this function from its own
+   to_xfer_partial handler, after converting object and annex to the
+   appropriate filename.  */
+
+LONGEST
+xml_builtin_xfer_partial (const char *filename,
+			  gdb_byte *readbuf, const gdb_byte *writebuf,
+			  ULONGEST offset, LONGEST len)
+{
+  const char *buf;
+  LONGEST len_avail;
+
+  gdb_assert (readbuf != NULL && writebuf == NULL);
+  gdb_assert (filename != NULL);
+
+  buf = fetch_xml_builtin (filename);
+  if (buf == NULL)
+    return -1;
+
+  len_avail = strlen (buf);
+  if (offset >= len_avail)
+    return 0;
+
+  if (len > len_avail - offset)
+    len = len_avail - offset;
+  memcpy (readbuf, buf + offset, len);
+  return len;
+}
+
 
 static void
 show_debug_xml (struct ui_file *file, int from_tty,
Index: src/gdb/xml-support.h
===================================================================
--- src.orig/gdb/xml-support.h	2007-02-13 09:34:01.000000000 -0500
+++ src/gdb/xml-support.h	2007-02-13 09:34:15.000000000 -0500
@@ -53,6 +53,15 @@ char *xml_process_xincludes (const char 
 
 const char *fetch_xml_builtin (const char *filename);
 
+/* A to_xfer_partial helper function which reads XML files which were
+   compiled into GDB.  The target may call this function from its own
+   to_xfer_partial handler, after converting object and annex to the
+   appropriate filename.  */
+
+LONGEST xml_builtin_xfer_partial (const char *filename,
+				  gdb_byte *readbuf, const gdb_byte *writebuf,
+				  ULONGEST offset, LONGEST len);
+
 /* The text of compiled-in XML documents, from xml-builtin.c
    (generated).  */
 extern const char *xml_builtin[][2];
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS	2007-02-13 11:31:39.000000000 -0500
+++ src/gdb/NEWS	2007-02-13 11:33:42.000000000 -0500
@@ -22,8 +22,8 @@ a local file or over the remote serial p
 for architectures which have implemented the support (currently
 only ARM).
 
-* The GDB remote stub, gdbserver, now supports the XScale iWMMXt
-coprocessor.
+* GDB and the GDB remote stub, gdbserver, now support the XScale
+iWMMXt coprocessor.
 
 * New commands
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]