This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[rfc] [5/7] Modernize AIX target: switch to inf-ptrace
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: gdb-patches at sourceware dot org
- Date: Tue, 24 Apr 2007 23:37:56 +0200 (CEST)
- Subject: [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