aboutsummaryrefslogtreecommitdiff
path: root/gdb/rs6000-nat.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2007-04-27 13:22:18 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2007-04-27 13:22:18 +0000
commit037a727e3d7574f797adebad86e3eb8e37899be4 (patch)
tree126308446ff1b8301b8bf16387c2279a261e8bb7 /gdb/rs6000-nat.c
parentf7dd0ed7deb69614c40719a0c37985b3ec26503b (diff)
downloadgdb-037a727e3d7574f797adebad86e3eb8e37899be4.zip
gdb-037a727e3d7574f797adebad86e3eb8e37899be4.tar.gz
gdb-037a727e3d7574f797adebad86e3eb8e37899be4.tar.bz2
* 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-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" and "gdb_stdint.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. * Makefile.in (rs6000-nat.o): Update dependencies.
Diffstat (limited to 'gdb/rs6000-nat.c')
-rw-r--r--gdb/rs6000-nat.c203
1 files changed, 105 insertions, 98 deletions
diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c
index 46907ae..986f9a0 100644
--- a/gdb/rs6000-nat.c
+++ b/gdb/rs6000-nat.c
@@ -34,9 +34,11 @@
#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"
+#include "gdb_stdint.h"
#include <sys/ptrace.h>
#include <sys/reg.h>
@@ -343,8 +345,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 +386,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 +423,107 @@ 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)
-{
- /* Retrieved values may be -1, so infer errors from errno. */
- errno = 0;
+/* 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. */
- 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)
+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)
{
- /* 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;
-
- /* Copy supplied data into memory buffer. */
- memcpy ((char *)buf + (memaddr - addr), myaddr, 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;
- }
+ 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 *)(uintptr_t)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 *)(uintptr_t)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 *)(uintptr_t)rounded_offset,
+ 0, NULL);
+ if (errno)
+ return 0;
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (readbuf, buffer.byte + (offset - rounded_offset),
+ partial_len);
+ }
+
+ return partial_len;
+ }
+
+ 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 +1205,6 @@ xcoff_relocate_core (struct target_ops *target)
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 +1244,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;