daily update
[deliverable/binutils-gdb.git] / gdb / infptrace.c
index d0df64291fae0a2c1edba56a654273b2671e59bb..777a5b491ed7c0e013eb5ab54f77cf6f24ddd150 100644 (file)
@@ -1,6 +1,6 @@
 /* Low level Unix child interface to ptrace, for GDB when running under Unix.
-   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
-   1999, 2000, 2001
+   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+   1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -359,7 +359,7 @@ fetch_register (int regno)
   char mess[128];              /* For messages */
   register int i;
   unsigned int offset;         /* Offset of registers within the u area.  */
-  char buf[MAX_REGISTER_RAW_SIZE];
+  char *buf = alloca (MAX_REGISTER_RAW_SIZE);
   int tid;
 
   if (CANNOT_FETCH_REGISTER (regno))
@@ -424,6 +424,7 @@ store_register (int regno)
   register int i;
   unsigned int offset;         /* Offset of registers within the u area.  */
   int tid;
+  char *buf = alloca (MAX_REGISTER_RAW_SIZE);
 
   if (CANNOT_STORE_REGISTER (regno))
     {
@@ -437,11 +438,16 @@ store_register (int regno)
   offset = U_REGS_OFFSET;
 
   regaddr = register_addr (regno, offset);
+
+  /* Put the contents of regno into a local buffer */
+  regcache_collect (regno, buf);
+
+  /* Store the local buffer into the inferior a chunk at the time. */
   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
       ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
-             *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]);
+             *(PTRACE_XFER_TYPE *) (buf + i));
       regaddr += sizeof (PTRACE_XFER_TYPE);
       if (errno != 0)
        {
@@ -474,6 +480,11 @@ store_inferior_registers (int regno)
 #endif /* !defined (FETCH_INFERIOR_REGISTERS).  */
 \f
 
+/* Set an upper limit on alloca.  */
+#ifndef GDB_MAX_ALLOCA
+#define GDB_MAX_ALLOCA 0x1000
+#endif
+
 #if !defined (CHILD_XFER_MEMORY)
 /* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
    in the NEW_SUN_PTRACE case.  It ought to be straightforward.  But
@@ -491,8 +502,7 @@ store_inferior_registers (int regno)
 
 int
 child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
-                  struct mem_attrib *attrib ATTRIBUTE_UNUSED,
-                  struct target_ops *target)
+                  struct mem_attrib *attrib, struct target_ops *target)
 {
   int i;
   /* Round starting address down to longword boundary.  */
@@ -500,9 +510,20 @@ child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
   /* Round ending address up; get number of longwords that makes.  */
   int count = ((((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
               / sizeof (PTRACE_XFER_TYPE));
+  int alloc = count * sizeof (PTRACE_XFER_TYPE);
+  PTRACE_XFER_TYPE *buffer;
+  struct cleanup *old_chain = NULL;
+
   /* Allocate buffer of that many longwords.  */
-  PTRACE_XFER_TYPE *buffer =
-    (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+  if (len < GDB_MAX_ALLOCA)
+    {
+      buffer = (PTRACE_XFER_TYPE *) alloca (alloc);
+    }
+  else
+    {
+      buffer = (PTRACE_XFER_TYPE *) xmalloc (alloc);
+      old_chain = make_cleanup (xfree, buffer);
+    }
 
   if (write)
     {
@@ -567,6 +588,8 @@ child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
              len);
     }
 
+  if (old_chain != NULL)
+    do_cleanups (old_chain);
   return len;
 }
 \f
This page took 0.024253 seconds and 4 git commands to generate.