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 *);
static void debug_to_files_info (struct target_ops *);
-static int debug_to_insert_breakpoint (CORE_ADDR, gdb_byte *);
+static int debug_to_insert_breakpoint (struct bp_target_info *);
-static int debug_to_remove_breakpoint (CORE_ADDR, gdb_byte *);
+static int debug_to_remove_breakpoint (struct bp_target_info *);
static int debug_to_can_use_hw_breakpoint (int, int, int);
-static int debug_to_insert_hw_breakpoint (CORE_ADDR, gdb_byte *);
+static int debug_to_insert_hw_breakpoint (struct bp_target_info *);
-static int debug_to_remove_hw_breakpoint (CORE_ADDR, gdb_byte *);
+static int debug_to_remove_hw_breakpoint (struct bp_target_info *);
static int debug_to_insert_watchpoint (CORE_ADDR, int, int);
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);
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);
(int (*) (int, int, int))
return_zero);
de_fault (to_insert_hw_breakpoint,
- (int (*) (CORE_ADDR, gdb_byte *))
+ (int (*) (struct bp_target_info *))
return_minus_one);
de_fault (to_remove_hw_breakpoint,
- (int (*) (CORE_ADDR, gdb_byte *))
+ (int (*) (struct bp_target_info *))
return_minus_one);
de_fault (to_insert_watchpoint,
(int (*) (CORE_ADDR, int, int))
}
/* If there's already targets at this stratum, remove them. */
- /* FIXME: cagney/2003-10-15: I think this should be poping all
+ /* FIXME: cagney/2003-10-15: I think this should be popping all
targets to CUR, and not just those at this stratum level. */
while ((*cur) != NULL && t->to_stratum == (*cur)->to_stratum)
{
(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,
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,
(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;
(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;
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
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
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)
{
}
static int
-debug_to_insert_breakpoint (CORE_ADDR addr, gdb_byte *save)
+debug_to_insert_breakpoint (struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_insert_breakpoint (addr, save);
+ retval = debug_target.to_insert_breakpoint (bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_insert_breakpoint (0x%lx, xxx) = %ld\n",
- (unsigned long) addr,
+ (unsigned long) bp_tgt->placed_address,
(unsigned long) retval);
return retval;
}
static int
-debug_to_remove_breakpoint (CORE_ADDR addr, gdb_byte *save)
+debug_to_remove_breakpoint (struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_remove_breakpoint (addr, save);
+ retval = debug_target.to_remove_breakpoint (bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_remove_breakpoint (0x%lx, xxx) = %ld\n",
- (unsigned long) addr,
+ (unsigned long) bp_tgt->placed_address,
(unsigned long) retval);
return retval;
}
}
static int
-debug_to_insert_hw_breakpoint (CORE_ADDR addr, gdb_byte *save)
+debug_to_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_insert_hw_breakpoint (addr, save);
+ retval = debug_target.to_insert_hw_breakpoint (bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_insert_hw_breakpoint (0x%lx, xxx) = %ld\n",
- (unsigned long) addr,
+ (unsigned long) bp_tgt->placed_address,
(unsigned long) retval);
return retval;
}
static int
-debug_to_remove_hw_breakpoint (CORE_ADDR addr, gdb_byte *save)
+debug_to_remove_hw_breakpoint (struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_remove_hw_breakpoint (addr, save);
+ retval = debug_target.to_remove_hw_breakpoint (bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_remove_hw_breakpoint (0x%lx, xxx) = %ld\n",
- (unsigned long) addr,
+ (unsigned long) bp_tgt->placed_address,
(unsigned long) retval);
return retval;
}
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;
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