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]

[rfc] [5/7] Modernize AIX target: switch to inf-ptrace


Hello,

this patch switches AIX to use inf-ptrace.  It's pretty straight-forward,
the most interesting part is replacement of an xfer_memory with an 
xfer_partial method -- this has to be done in aix-thread.c as well.

Tested on powerpc-aix-ibm5.3.0.0, actually fixes a couple of FAILs.

Bye,
Ulrich

ChangeLog:

	* aix-thread.c (aix_thread_xfer_memory): Replace by ...
	(aix_thread_xfer_partial): ... this.
	(init_aix_thread_ops): Install to_xfer_partial instead
	of deprecated_xfer_memory target method.

	* config/powerpc/aix.mh (NATDEPFILES): Remove infptrace.o
	and inftarg.o, add inf-child.o and inf-ptrace.o.
	* config/rs6000/nm-rs6000.h (FETCH_INFERIOR_REGISTERS,
	CHILD_XFER_MEMORY, KERNEL_U_SIZE, kernel_u_size): Remove.
	* rs6000-nat.c: Include "inf-ptrace.h".
	(fetch_inferior_registers): Rename to ...
	(rs6000_fetch_inferior_registers): ... this.  Make static.
	(store_inferior_registers): Rename to ...
	(rs6000_store_inferior_registers): ... this.  Make static.
	(read_word, child_xfer_memory): Remove.
	(rs6000_xfer_partial): New function.
	(kernel_u_size): Remove.
	(_initialize_core_rs6000): Add inf_ptrace-based target.


diff -urNp gdb-orig/gdb/Makefile.in gdb-head/gdb/Makefile.in
--- gdb-orig/gdb/Makefile.in	Wed Apr 18 16:17:17 2007
+++ gdb-head/gdb/Makefile.in	Mon Apr 23 21:16:16 2007
@@ -2509,7 +2509,7 @@ remote-sim.o: remote-sim.c $(defs_h) $(i
 rs6000-nat.o: rs6000-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \
 	$(xcoffsolib_h) $(symfile_h) $(objfiles_h) $(libbfd_h) $(bfd_h) \
 	$(exceptions_h) $(gdb_stabs_h) $(regcache_h) $(arch_utils_h) \
-	$(ppc_tdep_h) $(rs6000_tdep_h) $(exec_h) $(gdb_stat_h)
+	$(inf_ptrace_h) $(ppc_tdep_h) $(rs6000_tdep_h) $(exec_h) $(gdb_stat_h)
 rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \
 	$(target_h) $(gdbcore_h) $(gdbcmd_h) $(objfiles_h) $(arch_utils_h) \
 	$(regcache_h) $(regset_h) $(doublest_h) $(value_h) $(parser_defs_h) \
diff -urNp gdb-orig/gdb/aix-thread.c gdb-head/gdb/aix-thread.c
--- gdb-orig/gdb/aix-thread.c	Tue Apr 24 13:54:37 2007
+++ gdb-head/gdb/aix-thread.c	Tue Apr 24 12:43:24 2007
@@ -1615,23 +1615,24 @@ aix_thread_store_registers (int regno)
     }
 }
 
-/* Transfer LEN bytes of memory from GDB address MYADDR to target
-   address MEMADDR if WRITE and vice versa otherwise.  */
-
-static int
-aix_thread_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
-		      struct mem_attrib *attrib,
-		      struct target_ops *target)
+/* Attempt a transfer all LEN bytes starting at OFFSET between the
+   inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer.
+   Return the number of bytes actually transferred.  */
+
+static LONGEST
+aix_thread_xfer_partial (struct target_ops *ops, enum target_object object,
+			 const char *annex, gdb_byte *readbuf,
+			 const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
 {
-  int n;
-  struct cleanup *cleanup = save_inferior_ptid ();
+  struct cleanup *old_chain = save_inferior_ptid ();
+  LONGEST xfer;
 
   inferior_ptid = pid_to_ptid (PIDGET (inferior_ptid));
-  n = base_target.deprecated_xfer_memory (memaddr, myaddr, len, 
-					  write, attrib, &base_target);
-  do_cleanups (cleanup);
+  xfer = base_target.to_xfer_partial (ops, object, annex,
+				      readbuf, writebuf, offset, len);
 
-  return n;
+  do_cleanups (old_chain);
+  return xfer;
 }
 
 /* Kill and forget about the inferior process.  */
@@ -1763,7 +1764,7 @@ init_aix_thread_ops (void)
   aix_thread_ops.to_wait               = aix_thread_wait;
   aix_thread_ops.to_fetch_registers    = aix_thread_fetch_registers;
   aix_thread_ops.to_store_registers    = aix_thread_store_registers;
-  aix_thread_ops.deprecated_xfer_memory = aix_thread_xfer_memory;
+  aix_thread_ops.to_xfer_partial       = aix_thread_xfer_partial;
   /* No need for aix_thread_ops.to_create_inferior, because we activate thread
      debugging when the inferior reaches pd_brk_addr.  */
   aix_thread_ops.to_kill               = aix_thread_kill;
diff -urNp gdb-orig/gdb/config/powerpc/aix.mh gdb-head/gdb/config/powerpc/aix.mh
--- gdb-orig/gdb/config/powerpc/aix.mh	Mon Apr 23 20:39:45 2007
+++ gdb-head/gdb/config/powerpc/aix.mh	Mon Apr 23 20:40:33 2007
@@ -3,7 +3,7 @@
 NAT_FILE= config/rs6000/nm-rs6000.h
 
 # aix-thread.o is not listed in NATDEPFILES as it is pulled in by configure.
-NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o rs6000-nat.o \
+NATDEPFILES= fork-child.o inf-child.o inf-ptrace.o corelow.o rs6000-nat.o \
 	     xcoffread.o xcoffsolib.o
 
 # When compiled with cc, for debugging, this argument should be passed.
diff -urNp gdb-orig/gdb/config/rs6000/nm-rs6000.h gdb-head/gdb/config/rs6000/nm-rs6000.h
--- gdb-orig/gdb/config/rs6000/nm-rs6000.h	Wed Apr 18 16:17:30 2007
+++ gdb-head/gdb/config/rs6000/nm-rs6000.h	Mon Apr 23 20:41:15 2007
@@ -19,14 +19,6 @@
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
-
-#define FETCH_INFERIOR_REGISTERS
-
-/* Override child_xfer_memory in infptrace.c. */
-
-#define CHILD_XFER_MEMORY
-
 /* When a child process is just starting, we sneak in and relocate
    the symbol table (and other stuff) after the dynamic linker has
    figured out where they go.  */
@@ -55,11 +47,6 @@ extern void xcoff_relocate_core (struct 
 
 #define	PC_SOLIB(PC)	xcoff_solib_address(PC)
 extern char *xcoff_solib_address (CORE_ADDR);
-
-/* Return sizeof user struct to callers in less machine dependent routines */
-
-#define KERNEL_U_SIZE kernel_u_size()
-extern int kernel_u_size (void);
 
 /* Flag for machine-specific stuff in shared files.  FIXME */
 #define DEPRECATED_IBM6000_TARGET
diff -urNp gdb-orig/gdb/rs6000-nat.c gdb-head/gdb/rs6000-nat.c
--- gdb-orig/gdb/rs6000-nat.c	Tue Apr 24 13:54:37 2007
+++ gdb-head/gdb/rs6000-nat.c	Tue Apr 24 13:13:46 2007
@@ -34,6 +34,7 @@
 #include "gdb-stabs.h"
 #include "regcache.h"
 #include "arch-utils.h"
+#include "inf-ptrace.h"
 #include "ppc-tdep.h"
 #include "rs6000-tdep.h"
 #include "exec.h"
@@ -343,8 +344,8 @@ store_register (int regno)
 /* Read from the inferior all registers if REGNO == -1 and just register
    REGNO otherwise. */
 
-void
-fetch_inferior_registers (int regno)
+static void
+rs6000_fetch_inferior_registers (int regno)
 {
   if (regno != -1)
     fetch_register (regno);
@@ -384,8 +385,8 @@ fetch_inferior_registers (int regno)
    If REGNO is -1, do this for all registers.
    Otherwise, REGNO specifies which register (so we can save time).  */
 
-void
-store_inferior_registers (int regno)
+static void
+rs6000_store_inferior_registers (int regno)
 {
   if (regno != -1)
     store_register (regno);
@@ -421,104 +422,105 @@ store_inferior_registers (int regno)
     }
 }
 
-/* Store in *TO the 32-bit word at 32-bit-aligned ADDR in the child
-   process, which is 64-bit if ARCH64 and 32-bit otherwise.  Return
-   success. */
 
-static int
-read_word (CORE_ADDR from, int *to, int arch64)
+/* Attempt a transfer all LEN bytes starting at OFFSET between the
+   inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer.
+   Return the number of bytes actually transferred.  */
+
+static LONGEST
+rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
+		     const char *annex, gdb_byte *readbuf,
+		     const gdb_byte *writebuf,
+		     ULONGEST offset, LONGEST len)
 {
-  /* Retrieved values may be -1, so infer errors from errno. */
-  errno = 0;
-
-  if (arch64)
-    *to = rs6000_ptrace64 (PT_READ_I, PIDGET (inferior_ptid), from, 0, NULL);
-  else
-    *to = rs6000_ptrace32 (PT_READ_I, PIDGET (inferior_ptid), (int *)(long) from,
-                    0, NULL);
-
-  return !errno;
-}
-
-/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
-   to debugger memory starting at MYADDR.  Copy to inferior if
-   WRITE is nonzero.
-
-   Returns the length copied, which is either the LEN argument or
-   zero.  This xfer function does not do partial moves, since
-   deprecated_child_ops doesn't allow memory operations to cross below
-   us in the target stack anyway.  */
-
-int
-child_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len,
-		   int write, struct mem_attrib *attrib,
-		   struct target_ops *target)
-{
-  /* Round starting address down to 32-bit word boundary. */
-  int mask = sizeof (int) - 1;
-  CORE_ADDR addr = memaddr & ~(CORE_ADDR)mask;
-
-  /* Round ending address up to 32-bit word boundary. */
-  int count = ((memaddr + len - addr + mask) & ~(CORE_ADDR)mask)
-    / sizeof (int);
-
-  /* Allocate word transfer buffer. */
-  /* FIXME (alloca): This code, cloned from infptrace.c, is unsafe
-     because it uses alloca to allocate a buffer of arbitrary size.
-     For very large xfers, this could crash GDB's stack.  */
-  int *buf = (int *) alloca (count * sizeof (int));
-
+  pid_t pid = ptid_get_pid (inferior_ptid);
   int arch64 = ARCH64 ();
-  int i;
 
-  if (!write)
+  switch (object)
     {
-      /* Retrieve memory a word at a time. */
-      for (i = 0; i < count; i++, addr += sizeof (int))
+    case TARGET_OBJECT_MEMORY:
+      {
+	union
 	{
-	  if (!read_word (addr, buf + i, arch64))
-	    return 0;
-	  QUIT;
-	}
-
-      /* Copy memory to supplied buffer. */
-      addr -= count * sizeof (int);
-      memcpy (myaddr, (char *)buf + (memaddr - addr), len);
-    }
-  else
-    {
-      /* Fetch leading memory needed for alignment. */
-      if (addr < memaddr)
-	if (!read_word (addr, buf, arch64))
-	  return 0;
-
-      /* Fetch trailing memory needed for alignment. */
-      if (addr + count * sizeof (int) > memaddr + len)
-	if (!read_word (addr + (count - 1) * sizeof (int),
-                        buf + count - 1, arch64))
-	  return 0;
+	  PTRACE_TYPE_RET word;
+	  gdb_byte byte[sizeof (PTRACE_TYPE_RET)];
+	} buffer;
+	ULONGEST rounded_offset;
+	LONGEST partial_len;
+
+	/* Round the start offset down to the next long word
+	   boundary.  */
+	rounded_offset = offset & -(ULONGEST) sizeof (PTRACE_TYPE_RET);
+
+	/* Since ptrace will transfer a single word starting at that
+	   rounded_offset the partial_len needs to be adjusted down to
+	   that (remember this function only does a single transfer).
+	   Should the required length be even less, adjust it down
+	   again.  */
+	partial_len = (rounded_offset + sizeof (PTRACE_TYPE_RET)) - offset;
+	if (partial_len > len)
+	  partial_len = len;
+
+	if (writebuf)
+	  {
+	    /* If OFFSET:PARTIAL_LEN is smaller than
+	       ROUNDED_OFFSET:WORDSIZE then a read/modify write will
+	       be needed.  Read in the entire word.  */
+	    if (rounded_offset < offset
+		|| (offset + partial_len
+		    < rounded_offset + sizeof (PTRACE_TYPE_RET)))
+	      {
+		/* Need part of initial word -- fetch it.  */
+		if (arch64)
+		  buffer.word = rs6000_ptrace64 (PT_READ_I, pid,
+						 rounded_offset, 0, NULL);
+		else
+		  buffer.word = rs6000_ptrace32 (PT_READ_I, pid,
+						 (int *)(long)rounded_offset, 0, NULL);
+	      }
+
+	    /* Copy data to be written over corresponding part of
+	       buffer.  */
+	    memcpy (buffer.byte + (offset - rounded_offset),
+		    writebuf, partial_len);
+
+	    errno = 0;
+	    if (arch64)
+	      rs6000_ptrace64 (PT_WRITE_D, pid,
+			       rounded_offset, buffer.word, NULL);
+	    else
+	      rs6000_ptrace32 (PT_WRITE_D, pid,
+			       (int *)(long)rounded_offset, buffer.word, NULL);
+	    if (errno)
+	      return 0;
+	  }
+
+	if (readbuf)
+	  {
+	    errno = 0;
+	    if (arch64)
+	      buffer.word = rs6000_ptrace64 (PT_READ_I, pid,
+					     rounded_offset, 0, NULL);
+	    else
+	      buffer.word = rs6000_ptrace32 (PT_READ_I, pid,
+					     (int *)(long) rounded_offset, 0, NULL);
+	    if (errno)
+	      return 0;
+
+	    /* Copy appropriate bytes out of the buffer.  */
+	    memcpy (readbuf, buffer.byte + (offset - rounded_offset),
+		    partial_len);
+	  }
 
-      /* Copy supplied data into memory buffer. */
-      memcpy ((char *)buf + (memaddr - addr), myaddr, len);
+	return partial_len;
+      }
 
-      /* Store memory one word at a time. */
-      for (i = 0, errno = 0; i < count; i++, addr += sizeof (int))
-	{
-	  if (arch64)
-	    rs6000_ptrace64 (PT_WRITE_D, PIDGET (inferior_ptid), addr, buf[i], NULL);
-	  else
-	    rs6000_ptrace32 (PT_WRITE_D, PIDGET (inferior_ptid), (int *)(long) addr,
-		      buf[i], NULL);
-
-	  if (errno)
-	    return 0;
-	  QUIT;
-	}
+    default:
+      return -1;
     }
-
-  return len;
 }
 
+
 /* Execute one dummy breakpoint instruction.  This way we give the kernel
    a chance to do some housekeeping and update inferior's internal data,
    including u_area. */
@@ -1200,12 +1202,6 @@ xcoff_relocate_core (struct target_ops *
   breakpoint_re_set ();
   do_cleanups (old);
 }
-
-int
-kernel_u_size (void)
-{
-  return (sizeof (struct user));
-}
 
 /* Under AIX, we have to pass the correct TOC pointer to a function
    when calling functions in the inferior.
@@ -1245,6 +1241,14 @@ static struct core_fns rs6000_core_fns =
 void
 _initialize_core_rs6000 (void)
 {
+  struct target_ops *t;
+
+  t = inf_ptrace_target ();
+  t->to_fetch_registers = rs6000_fetch_inferior_registers;
+  t->to_store_registers = rs6000_store_inferior_registers;
+  t->to_xfer_partial = rs6000_xfer_partial;
+  add_target (t);
+
   /* Initialize hook in rs6000-tdep.c for determining the TOC address
      when calling functions in the inferior.  */
   rs6000_find_toc_address_hook = find_toc_address;
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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