/* Select target systems and architectures at runtime for GDB.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by Cygnus Support.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include <errno.h>
static void default_terminal_info (char *, int);
-static int default_region_size_ok_for_hw_watchpoint (int);
+static int default_region_ok_for_hw_watchpoint (CORE_ADDR, int);
static int nosymbol (char *, CORE_ADDR *);
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);
static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
-static int debug_to_region_size_ok_for_hw_watchpoint (int);
+static int debug_to_region_ok_for_hw_watchpoint (CORE_ADDR, int);
static void debug_to_terminal_init (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);
INHERIT (to_stopped_data_address, t);
INHERIT (to_stopped_by_watchpoint, t);
INHERIT (to_have_continuable_watchpoint, t);
- INHERIT (to_region_size_ok_for_hw_watchpoint, t);
+ INHERIT (to_region_ok_for_hw_watchpoint, t);
INHERIT (to_terminal_init, t);
INHERIT (to_terminal_inferior, t);
INHERIT (to_terminal_ours_for_output, t);
INHERIT (to_remove_fork_catchpoint, t);
INHERIT (to_insert_vfork_catchpoint, t);
INHERIT (to_remove_vfork_catchpoint, t);
- INHERIT (to_follow_fork, t);
+ /* Do not inherit to_follow_fork. */
INHERIT (to_insert_exec_catchpoint, t);
INHERIT (to_remove_exec_catchpoint, t);
INHERIT (to_reported_exec_events_per_exec_call, 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))
de_fault (to_stopped_data_address,
(int (*) (struct target_ops *, CORE_ADDR *))
return_zero);
- de_fault (to_region_size_ok_for_hw_watchpoint,
- default_region_size_ok_for_hw_watchpoint);
+ de_fault (to_region_ok_for_hw_watchpoint,
+ default_region_ok_for_hw_watchpoint);
de_fault (to_terminal_init,
(void (*) (void))
target_ignore);
de_fault (to_remove_vfork_catchpoint,
(int (*) (int))
tcomplain);
- de_fault (to_follow_fork,
- (int (*) (int))
- target_ignore);
de_fault (to_insert_exec_catchpoint,
(void (*) (int))
tcomplain);
}
/* 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)
{
/* Perform a partial memory transfer.
- Result is -1 on error, or the number of bytes transfered. */
+ If we succeed, set *ERR to zero and return the number of bytes transferred.
+ If we fail, set *ERR to a non-zero errno value, and return -1. */
static int
-target_xfer_memory_partial (CORE_ADDR memaddr, char *myaddr, int len,
+target_xfer_memory_partial (CORE_ADDR memaddr, gdb_byte *myaddr, int len,
int write_p, int *err)
{
int res;
}
int
-target_read_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err)
+target_read_memory_partial (CORE_ADDR memaddr, gdb_byte *buf,
+ int len, int *err)
{
if (target_xfer_partial_p ())
{
}
int
-target_write_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err)
+target_write_memory_partial (CORE_ADDR memaddr, gdb_byte *buf,
+ int len, int *err)
{
if (target_xfer_partial_p ())
{
(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
get_target_memory_unsigned (struct target_ops *ops,
CORE_ADDR addr, int len)
{
- char buf[sizeof (ULONGEST)];
+ gdb_byte buf[sizeof (ULONGEST)];
gdb_assert (len <= sizeof (buf));
get_target_memory (ops, addr, buf, len);
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
return saved_async_masked_status;
}
+/* Look through the list of possible targets for a target that can
+ follow forks. */
+
+int
+target_follow_fork (int follow_child)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_follow_fork != NULL)
+ {
+ int retval = t->to_follow_fork (t, follow_child);
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_follow_fork (%d) = %d\n",
+ follow_child, retval);
+ return retval;
+ }
+ }
+
+ /* Some target returned a fork event, but did not know how to follow it. */
+ internal_error (__FILE__, __LINE__,
+ "could not find a target to follow fork");
+}
+
/* Look through the list of possible targets for a target that can
execute a run or attach command without any other data. This is
used to locate the default process stratum.
}
static int
-default_region_size_ok_for_hw_watchpoint (int byte_count)
+default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
- return (byte_count <= TYPE_LENGTH (builtin_type_void_data_ptr));
+ return (len <= TYPE_LENGTH (builtin_type_void_data_ptr));
}
static 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_region_size_ok_for_hw_watchpoint (int byte_count)
+debug_to_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
CORE_ADDR retval;
- retval = debug_target.to_region_size_ok_for_hw_watchpoint (byte_count);
+ retval = debug_target.to_region_ok_for_hw_watchpoint (addr, len);
fprintf_unfiltered (gdb_stdlog,
- "TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT (%ld) = 0x%lx\n",
- (unsigned long) byte_count,
+ "TARGET_REGION_OK_FOR_HW_WATCHPOINT (%ld, %ld) = 0x%lx\n",
+ (unsigned long) addr,
+ (unsigned long) len,
(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;
}
return retval;
}
-static int
-debug_to_follow_fork (int follow_child)
-{
- int retval = debug_target.to_follow_fork (follow_child);
-
- fprintf_unfiltered (gdb_stdlog, "target_follow_fork (%d) = %d\n",
- follow_child, retval);
-
- return retval;
-}
-
static void
debug_to_insert_exec_catchpoint (int pid)
{
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_remove_watchpoint = debug_to_remove_watchpoint;
current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
current_target.to_stopped_data_address = debug_to_stopped_data_address;
- current_target.to_region_size_ok_for_hw_watchpoint = debug_to_region_size_ok_for_hw_watchpoint;
+ current_target.to_region_ok_for_hw_watchpoint = debug_to_region_ok_for_hw_watchpoint;
current_target.to_terminal_init = debug_to_terminal_init;
current_target.to_terminal_inferior = debug_to_terminal_inferior;
current_target.to_terminal_ours_for_output = debug_to_terminal_ours_for_output;
current_target.to_remove_fork_catchpoint = debug_to_remove_fork_catchpoint;
current_target.to_insert_vfork_catchpoint = debug_to_insert_vfork_catchpoint;
current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint;
- current_target.to_follow_fork = debug_to_follow_fork;
current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint;
current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint;
current_target.to_reported_exec_events_per_exec_call = debug_to_reported_exec_events_per_exec_call;
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