* target.c (target_read): Stop if target_read_partial returns 0
[deliverable/binutils-gdb.git] / gdb / target.c
index 52e45270afbfd9d58ed6119991224344f6df3b09..c378ce56f74e2ea4906b884d8b7beae0c1b2c54f 100644 (file)
@@ -97,8 +97,6 @@ static void debug_to_attach (char *, int);
 
 static void debug_to_detach (char *, int);
 
-static void debug_to_disconnect (char *, int);
-
 static void debug_to_resume (ptid_t, int, enum target_signal);
 
 static ptid_t debug_to_wait (ptid_t, struct target_waitstatus *);
@@ -388,7 +386,7 @@ update_current_target (void)
       INHERIT (to_attach, t);
       INHERIT (to_post_attach, t);
       INHERIT (to_detach, t);
-      INHERIT (to_disconnect, t);
+      /* Do not inherit to_disconnect.  */
       INHERIT (to_resume, t);
       INHERIT (to_wait, t);
       INHERIT (to_fetch_registers, t);
@@ -483,9 +481,6 @@ update_current_target (void)
   de_fault (to_detach, 
            (void (*) (char *, int)) 
            target_ignore);
-  de_fault (to_disconnect, 
-           (void (*) (char *, int)) 
-           tcomplain);
   de_fault (to_resume, 
            (void (*) (ptid_t, int, enum target_signal)) 
            noprocess);
@@ -1346,7 +1341,7 @@ default_xfer_partial (struct target_ops *ops, enum target_object object,
    (inbuf, outbuf)", instead of separate read/write methods, make life
    easier.  */
 
-LONGEST
+static LONGEST
 target_read_partial (struct target_ops *ops,
                     enum target_object object,
                     const char *annex, gdb_byte *buf,
@@ -1355,7 +1350,7 @@ target_read_partial (struct target_ops *ops,
   return target_xfer_partial (ops, object, annex, buf, NULL, offset, len);
 }
 
-LONGEST
+static LONGEST
 target_write_partial (struct target_ops *ops,
                      enum target_object object,
                      const char *annex, const gdb_byte *buf,
@@ -1378,8 +1373,9 @@ target_read (struct target_ops *ops,
                                          (gdb_byte *) buf + xfered,
                                          offset + xfered, len - xfered);
       /* Call an observer, notifying them of the xfer progress?  */
-      if (xfer <= 0)
-       /* Call memory_error?  */
+      if (xfer == 0)
+       return xfered;
+      if (xfer < 0)
        return -1;
       xfered += xfer;
       QUIT;
@@ -1400,8 +1396,9 @@ target_write (struct target_ops *ops,
                                           (gdb_byte *) buf + xfered,
                                           offset + xfered, len - xfered);
       /* Call an observer, notifying them of the xfer progress?  */
-      if (xfer <= 0)
-       /* Call memory_error?  */
+      if (xfer == 0)
+       return xfered;
+      if (xfer < 0)
        return -1;
       xfered += xfer;
       QUIT;
@@ -1409,6 +1406,72 @@ target_write (struct target_ops *ops,
   return len;
 }
 
+/* Wrapper to perform a full read of unknown size.  OBJECT/ANNEX will
+   be read using OPS.  The return value will be -1 if the transfer
+   fails or is not supported; 0 if the object is empty; or the length
+   of the object otherwise.  If a positive value is returned, a
+   sufficiently large buffer will be allocated using xmalloc and
+   returned in *BUF_P containing the contents of the object.
+
+   This method should be used for objects sufficiently small to store
+   in a single xmalloc'd buffer, when no fixed bound on the object's
+   size is known in advance.  Don't try to read TARGET_OBJECT_MEMORY
+   through this function.  */
+
+LONGEST
+target_read_alloc (struct target_ops *ops,
+                  enum target_object object,
+                  const char *annex, gdb_byte **buf_p)
+{
+  size_t buf_alloc, buf_pos;
+  gdb_byte *buf;
+  LONGEST n;
+
+  /* This function does not have a length parameter; it reads the
+     entire OBJECT).  Also, it doesn't support objects fetched partly
+     from one target and partly from another (in a different stratum,
+     e.g. a core file and an executable).  Both reasons make it
+     unsuitable for reading memory.  */
+  gdb_assert (object != TARGET_OBJECT_MEMORY);
+
+  /* Start by reading up to 4K at a time.  The target will throttle
+     this number down if necessary.  */
+  buf_alloc = 4096;
+  buf = xmalloc (buf_alloc);
+  buf_pos = 0;
+  while (1)
+    {
+      n = target_read_partial (ops, object, annex, &buf[buf_pos],
+                              buf_pos, buf_alloc - buf_pos);
+      if (n < 0)
+       {
+         /* An error occurred.  */
+         xfree (buf);
+         return -1;
+       }
+      else if (n == 0)
+       {
+         /* Read all there was.  */
+         if (buf_pos == 0)
+           xfree (buf);
+         else
+           *buf_p = buf;
+         return buf_pos;
+       }
+
+      buf_pos += n;
+
+      /* If the buffer is filling up, expand it.  */
+      if (buf_alloc < buf_pos * 2)
+       {
+         buf_alloc *= 2;
+         buf = xrealloc (buf, buf_alloc);
+       }
+
+      QUIT;
+    }
+}
+
 /* Memory transfer methods.  */
 
 void
@@ -1490,7 +1553,19 @@ target_detach (char *args, int from_tty)
 void
 target_disconnect (char *args, int from_tty)
 {
-  (current_target.to_disconnect) (args, from_tty);
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    if (t->to_disconnect != NULL)
+       {
+         if (targetdebug)
+           fprintf_unfiltered (gdb_stdlog, "target_disconnect (%s, %d)\n",
+                               args, from_tty);
+         t->to_disconnect (t, args, from_tty);
+         return;
+       }
+
+  tcomplain ();
 }
 
 int
@@ -1906,15 +1981,6 @@ debug_to_detach (char *args, int from_tty)
   fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", args, from_tty);
 }
 
-static void
-debug_to_disconnect (char *args, int from_tty)
-{
-  debug_target.to_disconnect (args, from_tty);
-
-  fprintf_unfiltered (gdb_stdlog, "target_disconnect (%s, %d)\n",
-                     args, from_tty);
-}
-
 static void
 debug_to_resume (ptid_t ptid, int step, enum target_signal siggnal)
 {
@@ -2521,7 +2587,6 @@ setup_target_debug (void)
   current_target.to_attach = debug_to_attach;
   current_target.to_post_attach = debug_to_post_attach;
   current_target.to_detach = debug_to_detach;
-  current_target.to_disconnect = debug_to_disconnect;
   current_target.to_resume = debug_to_resume;
   current_target.to_wait = debug_to_wait;
   current_target.to_fetch_registers = debug_to_fetch_registers;
@@ -2569,7 +2634,6 @@ setup_target_debug (void)
   current_target.to_enable_exception_callback = debug_to_enable_exception_callback;
   current_target.to_get_current_exception_event = debug_to_get_current_exception_event;
   current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
-
 }
 \f
 
This page took 0.058227 seconds and 4 git commands to generate.