/* Select target systems and architectures at runtime for GDB.
- Copyright 1990, 1992-1995, 1998-2000 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB.
#include "defs.h"
#include <errno.h>
-#include <ctype.h>
#include "gdb_string.h"
#include "target.h"
#include "gdbcmd.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdb_wait.h"
+#include "dcache.h"
#include <signal.h>
+#include "regcache.h"
extern int errno;
static void nosupport_runtime (void);
-static void normal_target_post_startup_inferior (int pid);
+static void normal_target_post_startup_inferior (ptid_t ptid);
/* Transfer LEN bytes between target address MEMADDR and GDB address
MYADDR. Returns 0 for success, errno code for failure (which
static void debug_to_detach (char *, int);
-static void debug_to_resume (int, int, enum target_signal);
+static void debug_to_resume (ptid_t, int, enum target_signal);
-static int debug_to_wait (int, struct target_waitstatus *);
+static ptid_t debug_to_wait (ptid_t, struct target_waitstatus *);
static void debug_to_fetch_registers (int);
static void debug_to_prepare_to_store (void);
static int
-debug_to_xfer_memory (CORE_ADDR, char *, int, int, struct target_ops *);
+debug_to_xfer_memory (CORE_ADDR, char *, int, int, struct mem_attrib *,
+ struct target_ops *);
static void debug_to_files_info (struct target_ops *);
static int debug_to_can_run (void);
-static void debug_to_notice_signals (int);
+static void debug_to_notice_signals (ptid_t);
-static int debug_to_thread_alive (int);
+static int debug_to_thread_alive (ptid_t);
static void debug_to_stop (void);
static void setup_target_debug (void);
+DCACHE *target_dcache;
+
/* The user just typed 'target' without the name of a target. */
/* ARGSUSED */
void
target_load (char *arg, int from_tty)
{
+ dcache_invalidate (target_dcache);
(*current_target.to_load) (arg, from_tty);
}
static void
nosupport_runtime (void)
{
- if (!inferior_pid)
+ if (ptid_equal (inferior_ptid, null_ptid))
noprocess ();
else
error ("No run-time support for this");
(void (*) (int, char *, int))
target_ignore);
de_fault (to_resume,
- (void (*) (int, int, enum target_signal))
+ (void (*) (ptid_t, int, enum target_signal))
noprocess);
de_fault (to_wait,
- (int (*) (int, struct target_waitstatus *))
+ (ptid_t (*) (ptid_t, struct target_waitstatus *))
noprocess);
de_fault (to_post_wait,
- (void (*) (int, int))
+ (void (*) (ptid_t, int))
target_ignore);
de_fault (to_fetch_registers,
(void (*) (int))
(void (*) (void))
noprocess);
de_fault (to_xfer_memory,
- (int (*) (CORE_ADDR, char *, int, int, struct target_ops *))
+ (int (*) (CORE_ADDR, char *, int, int, struct mem_attrib *, struct target_ops *))
nomemory);
de_fault (to_files_info,
(void (*) (struct target_ops *))
de_fault (to_create_inferior,
maybe_kill_then_create_inferior);
de_fault (to_post_startup_inferior,
- (void (*) (int))
+ (void (*) (ptid_t))
target_ignore);
de_fault (to_acknowledge_created_inferior,
(void (*) (int))
de_fault (to_can_run,
return_zero);
de_fault (to_notice_signals,
- (void (*) (int))
+ (void (*) (ptid_t))
target_ignore);
de_fault (to_thread_alive,
- (int (*) (int))
+ (int (*) (ptid_t))
return_zero);
de_fault (to_find_new_threads,
(void (*) (void))
de_fault (to_pid_to_exec_file,
(char *(*) (int))
return_zero);
- de_fault (to_core_file_to_sym_file,
- (char *(*) (char *))
- return_zero);
de_fault (to_can_async_p,
(int (*) (void))
return_zero);
INHERIT (to_enable_exception_callback, t);
INHERIT (to_get_current_exception_event, t);
INHERIT (to_pid_to_exec_file, t);
- INHERIT (to_core_file_to_sym_file, t);
INHERIT (to_stratum, t);
INHERIT (DONT_USE, t);
INHERIT (to_has_all_memory, t);
fprintf_unfiltered (gdb_stderr,
"Magic number of %s target struct wrong\n",
t->to_shortname);
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
}
/* Find the proper stratum to install this target in. */
else
target_stack = cur->next; /* Unchain first on list */
tmp = cur->next;
- free (cur);
+ xfree (cur);
cur = tmp;
}
else
prev->next = cur->next;
- free (cur); /* Release the target_stack_item */
+ xfree (cur); /* Release the target_stack_item */
update_current_target ();
cleanup_target (¤t_target);
fprintf_unfiltered (gdb_stderr,
"pop_target couldn't find target %s\n",
current_target.to_shortname);
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
}
#undef MIN
return target_xfer_memory (memaddr, myaddr, len, 1);
}
-/* Move memory to or from the targets. Iterate until all of it has
- been moved, if necessary. The top target gets priority; anything
- it doesn't want, is offered to the next one down, etc. Note the
- business with curlen: if an early target says "no, but I have a
- boundary overlapping this xfer" then we shorten what we offer to
- the subsequent targets so the early guy will get a chance at the
- tail before the subsequent ones do.
+/* Move memory to or from the targets. The top target gets priority;
+ if it cannot handle it, it is offered to the next one down, etc.
- Result is 0 or errno value. */
+ Result is -1 on error, or the number of bytes transfered. */
-static int
-target_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write)
+int
+do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+ struct mem_attrib *attrib)
{
- int curlen;
int res;
+ int done = 0;
struct target_ops *t;
struct target_stack_item *item;
0. */
errno = 0;
- /* The quick case is that the top target does it all. */
+ /* The quick case is that the top target can handle the transfer. */
res = current_target.to_xfer_memory
- (memaddr, myaddr, len, write, ¤t_target);
- if (res == len)
- return 0;
-
- if (res > 0)
- goto bump;
- /* If res <= 0 then we call it again in the loop. Ah well. */
+ (memaddr, myaddr, len, write, attrib, ¤t_target);
- for (; len > 0;)
+ /* If res <= 0 then we call it again in the loop. Ah well. */
+ if (res <= 0)
{
- curlen = len; /* Want to do it all */
for (item = target_stack; item; item = item->next)
{
t = item->target_ops;
if (!t->to_has_memory)
continue;
- res = t->to_xfer_memory (memaddr, myaddr, curlen, write, t);
+ res = t->to_xfer_memory (memaddr, myaddr, len, write, attrib, t);
if (res > 0)
break; /* Handled all or part of xfer */
if (t->to_has_all_memory)
}
if (res <= 0)
+ return -1;
+ }
+
+ return res;
+}
+
+
+/* Perform a memory transfer. Iterate until the entire region has
+ been transfered.
+
+ Result is 0 or errno value. */
+
+static int
+target_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write)
+{
+ int res;
+ int reg_len;
+ struct mem_region *region;
+
+ /* Zero length requests are ok and require no work. */
+ if (len == 0)
+ {
+ return 0;
+ }
+
+ while (len > 0)
+ {
+ region = lookup_mem_region(memaddr);
+ if (memaddr + len < region->hi)
+ reg_len = len;
+ else
+ reg_len = region->hi - memaddr;
+
+ switch (region->attrib.mode)
{
- /* If this address is for nonexistent memory,
- read zeros if reading, or do nothing if writing. Return error. */
+ case MEM_RO:
+ if (write)
+ return EIO;
+ break;
+
+ case MEM_WO:
if (!write)
- memset (myaddr, 0, len);
- if (errno == 0)
return EIO;
+ break;
+ }
+
+ while (reg_len > 0)
+ {
+ if (region->attrib.cache)
+ res = dcache_xfer_memory(target_dcache, memaddr, myaddr,
+ reg_len, write);
else
- return errno;
+ res = do_xfer_memory(memaddr, myaddr, reg_len, write,
+ ®ion->attrib);
+
+ if (res <= 0)
+ {
+ /* If this address is for nonexistent memory, read zeros
+ if reading, or do nothing if writing. Return
+ error. */
+ if (!write)
+ memset (myaddr, 0, len);
+ if (errno == 0)
+ return EIO;
+ else
+ return errno;
+ }
+
+ memaddr += res;
+ myaddr += res;
+ len -= res;
+ reg_len -= res;
}
- bump:
- memaddr += res;
- myaddr += res;
- len -= res;
}
+
return 0; /* We managed to cover it all somehow. */
}
-/* Perform a partial memory transfer. */
+/* Perform a partial memory transfer.
+
+ Result is -1 on error, or the number of bytes transfered. */
static int
-target_xfer_memory_partial (CORE_ADDR memaddr, char *buf, int len,
+target_xfer_memory_partial (CORE_ADDR memaddr, char *myaddr, int len,
int write_p, int *err)
{
int res;
- int err_res;
- int len_res;
- struct target_ops *t;
- struct target_stack_item *item;
+ int reg_len;
+ struct mem_region *region;
/* Zero length requests are ok and require no work. */
if (len == 0)
return 0;
}
- /* The quick case is that the top target does it all. */
- res = current_target.to_xfer_memory (memaddr, buf, len, write_p, ¤t_target);
- if (res > 0)
- {
- *err = 0;
- return res;
- }
-
- /* xfer memory doesn't always reliably set errno. */
- errno = 0;
+ region = lookup_mem_region(memaddr);
+ if (memaddr + len < region->hi)
+ reg_len = len;
+ else
+ reg_len = region->hi - memaddr;
- /* Try all levels of the target stack to see one can handle it. */
- for (item = target_stack; item; item = item->next)
+ switch (region->attrib.mode)
{
- t = item->target_ops;
- if (!t->to_has_memory)
- continue;
- res = t->to_xfer_memory (memaddr, buf, len, write_p, t);
- if (res > 0)
+ case MEM_RO:
+ if (write_p)
{
- /* Handled all or part of xfer */
- *err = 0;
- return res;
+ *err = EIO;
+ return -1;
}
- if (t->to_has_all_memory)
- break;
+ break;
+
+ case MEM_WO:
+ if (write_p)
+ {
+ *err = EIO;
+ return -1;
+ }
+ break;
}
- /* Total failure. Return error. */
- if (errno != 0)
+ if (region->attrib.cache)
+ res = dcache_xfer_memory (target_dcache, memaddr, myaddr,
+ reg_len, write_p);
+ else
+ res = do_xfer_memory (memaddr, myaddr, reg_len, write_p,
+ ®ion->attrib);
+
+ if (res <= 0)
{
- *err = errno;
- return -1;
+ if (errno != 0)
+ *err = errno;
+ else
+ *err = EIO;
+
+ return -1;
}
- *err = EIO;
- return -1;
+
+ *err = 0;
+ return res;
}
int
{
extern int show_breakpoint_hit_counts;
- inferior_pid = 0;
+ inferior_ptid = null_ptid;
attach_flag = 0;
breakpoint_init_inferior (inf_exited);
registers_changed ();
{"SIG63", "Real-time event 63"},
{"SIGCANCEL", "LWP internal signal"},
{"SIG32", "Real-time event 32"},
+ {"SIG64", "Real-time event 64"},
#if defined(MACH) || defined(__MACH__)
/* Mach exceptions */
if (33 <= hostsig && hostsig <= 63)
return (enum target_signal)
(hostsig - 33 + (int) TARGET_SIGNAL_REALTIME_33);
+ else if (hostsig == 64)
+ return TARGET_SIGNAL_REALTIME_64;
else
error ("GDB bug: target.c (target_signal_from_host): unrecognized real-time signal");
}
if (retsig >= SIGRTMIN && retsig <= SIGRTMAX)
return retsig;
}
+ else if (oursig == TARGET_SIGNAL_REALTIME_64)
+ return 64;
#endif
*oursig_ok = 0;
return 0;
buffer. */
char *
-normal_pid_to_str (int pid)
+normal_pid_to_str (ptid_t ptid)
{
static char buf[30];
- if (STREQ (current_target.to_shortname, "remote"))
- sprintf (buf, "thread %d", pid);
- else
- sprintf (buf, "process %d", pid);
-
+ sprintf (buf, "process %d", PIDGET (ptid));
return buf;
}
target_acknowledge_forked_child.
*/
static void
-normal_target_post_startup_inferior (int pid)
+normal_target_post_startup_inferior (ptid_t ptid)
{
/* This space intentionally left blank. */
}
}
static void
-debug_to_resume (int pid, int step, enum target_signal siggnal)
+debug_to_resume (ptid_t ptid, int step, enum target_signal siggnal)
{
- debug_target.to_resume (pid, step, siggnal);
+ debug_target.to_resume (ptid, step, siggnal);
- fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", pid,
+ fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", PIDGET (ptid),
step ? "step" : "continue",
target_signal_to_name (siggnal));
}
-static int
-debug_to_wait (int pid, struct target_waitstatus *status)
+static ptid_t
+debug_to_wait (ptid_t ptid, struct target_waitstatus *status)
{
- int retval;
+ ptid_t retval;
- retval = debug_target.to_wait (pid, status);
+ retval = debug_target.to_wait (ptid, status);
fprintf_unfiltered (gdb_stdlog,
- "target_wait (%d, status) = %d, ", pid, retval);
+ "target_wait (%d, status) = %d, ", PIDGET (ptid),
+ PIDGET (retval));
fprintf_unfiltered (gdb_stdlog, "status->kind = ");
switch (status->kind)
{
}
static void
-debug_to_post_wait (int pid, int status)
+debug_to_post_wait (ptid_t ptid, int status)
{
- debug_target.to_post_wait (pid, status);
+ debug_target.to_post_wait (ptid, status);
fprintf_unfiltered (gdb_stdlog, "target_post_wait (%d, %d)\n",
- pid, status);
+ PIDGET (ptid), status);
}
static void
static int
debug_to_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+ struct mem_attrib *attrib,
struct target_ops *target)
{
int retval;
- retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, target);
+ retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write,
+ attrib, target);
fprintf_unfiltered (gdb_stdlog,
"target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
}
static void
-debug_to_post_startup_inferior (int pid)
+debug_to_post_startup_inferior (ptid_t ptid)
{
- debug_target.to_post_startup_inferior (pid);
+ debug_target.to_post_startup_inferior (ptid);
fprintf_unfiltered (gdb_stdlog, "target_post_startup_inferior (%d)\n",
- pid);
+ PIDGET (ptid));
}
static void
}
static void
-debug_to_notice_signals (int pid)
+debug_to_notice_signals (ptid_t ptid)
{
- debug_target.to_notice_signals (pid);
+ debug_target.to_notice_signals (ptid);
- fprintf_unfiltered (gdb_stdlog, "target_notice_signals (%d)\n", pid);
+ fprintf_unfiltered (gdb_stdlog, "target_notice_signals (%d)\n",
+ PIDGET (ptid));
}
static int
-debug_to_thread_alive (int pid)
+debug_to_thread_alive (ptid_t ptid)
{
int retval;
- retval = debug_target.to_thread_alive (pid);
+ retval = debug_target.to_thread_alive (ptid);
fprintf_unfiltered (gdb_stdlog, "target_thread_alive (%d) = %d\n",
- pid, retval);
+ PIDGET (ptid), retval);
return retval;
}
return exec_file;
}
-static char *
-debug_to_core_file_to_sym_file (char *core)
-{
- char *sym_file;
-
- sym_file = debug_target.to_core_file_to_sym_file (core);
-
- fprintf_unfiltered (gdb_stdlog, "target_core_file_to_sym_file (%s) = %s\n",
- core, sym_file);
-
- return sym_file;
-}
-
static void
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;
- current_target.to_core_file_to_sym_file = debug_to_core_file_to_sym_file;
}
\f
add_com ("monitor", class_obscure, do_monitor_command,
"Send a command to the remote monitor (remote targets only).");
+ target_dcache = dcache_init();
+
if (!STREQ (signals[TARGET_SIGNAL_LAST].string, "TARGET_SIGNAL_MAGIC"))
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
}