/* Remote debugging interface for boot monitors, for GDB.
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2006, 2007 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
Resurrected from the ashes by Stu Grossman.
#include "gdb_regex.h"
#include "srec.h"
#include "regcache.h"
+#include "gdbthread.h"
static char *dev_name;
static struct target_ops *targ_ops;
static void monitor_interrupt_query (void);
static void monitor_interrupt_twice (int);
-static void monitor_stop (void);
+static void monitor_stop (ptid_t);
static void monitor_dump_regs (struct regcache *regcache);
#if 0
static int first_time = 0; /* is this the first time we're executing after
gaving created the child proccess? */
+
+/* This is the ptid we use while we're connected to a monitor. Its
+ value is arbitrary, as monitor targets don't have a notion of
+ processes or threads, but we need something non-null to place in
+ inferior_ptid. */
+static ptid_t monitor_ptid;
+
#define TARGET_BUF_SIZE 2048
/* Monitor specific debugging information. Typically only useful to
if (current_monitor->stop)
{
- monitor_stop ();
+ monitor_stop (inferior_ptid);
if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
{
monitor_debug ("EXP Open echo\n");
push_target (targ_ops);
- inferior_ptid = pid_to_ptid (42000); /* Make run command think we are busy... */
+ /* Start afresh. */
+ init_thread_list ();
+
+ /* Make run command think we are busy... */
+ inferior_ptid = monitor_ptid;
+ add_inferior_silent (ptid_get_pid (inferior_ptid));
+ add_thread_silent (inferior_ptid);
/* Give monitor_wait something to read */
}
monitor_desc = NULL;
+
+ delete_thread_silent (monitor_ptid);
+ delete_inferior_silent (ptid_get_pid (monitor_ptid));
}
/* Terminate the open connection to the remote debugger. Use this
when you want to detach and do something else with your gdb. */
static void
-monitor_detach (char *args, int from_tty)
+monitor_detach (struct target_ops *ops, char *args, int from_tty)
{
pop_target (); /* calls monitor_close to do the real work */
if (from_tty)
/* supply register stores in target byte order, so swap here */
- store_unsigned_integer (regbuf, register_size (current_gdbarch, regno), val);
+ store_unsigned_integer (regbuf,
+ register_size (get_regcache_arch (regcache), regno),
+ val);
regcache_raw_supply (regcache, regno, regbuf);
/* Tell the remote machine to resume. */
static void
-monitor_resume (ptid_t ptid, int step, enum target_signal sig)
+monitor_resume (struct target_ops *ops,
+ ptid_t ptid, int step, enum target_signal sig)
{
/* Some monitors require a different command when starting a program */
monitor_debug ("MON resume\n");
if (monitor_debug_p || remote_debug)
fprintf_unfiltered (gdb_stdlog, "monitor_interrupt called\n");
- target_stop ();
+ target_stop (inferior_ptid);
}
/* The user typed ^C twice. */
{
target_terminal_ours ();
- if (query ("Interrupted while waiting for the program.\n\
-Give up (and stop debugging it)? "))
+ if (query (_("Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? ")))
{
target_mourn_inferior ();
deprecated_throw_reason (RETURN_QUIT);
status just as `wait' would. */
static ptid_t
-monitor_wait (ptid_t ptid, struct target_waitstatus *status)
+monitor_wait (struct target_ops *ops,
+ ptid_t ptid, struct target_waitstatus *status)
{
int old_timeout = timeout;
char buf[TARGET_BUF_SIZE];
spaces, but stop reading if something else is seen. Some monitors
like to drop leading zeros. */
- for (i = 0; i < register_size (current_gdbarch, regno) * 2; i++)
+ for (i = 0; i < register_size (get_regcache_arch (regcache), regno) * 2; i++)
{
int c;
c = readchar (timeout);
}
static void
-monitor_fetch_registers (struct regcache *regcache, int regno)
+monitor_fetch_registers (struct target_ops *ops,
+ struct regcache *regcache, int regno)
{
monitor_debug ("MON fetchregs\n");
if (current_monitor->getreg.cmd)
return;
}
- for (regno = 0; regno < gdbarch_num_regs (current_gdbarch); regno++)
+ for (regno = 0; regno < gdbarch_num_regs (get_regcache_arch (regcache));
+ regno++)
monitor_fetch_register (regcache, regno);
}
else
regcache_cooked_read_unsigned (regcache, regno, &val);
monitor_debug ("MON storeg %d %s\n", regno,
- phex (val, register_size (current_gdbarch, regno)));
+ phex (val,
+ register_size (get_regcache_arch (regcache), regno)));
/* send the register deposit command */
/* Store the remote registers. */
static void
-monitor_store_registers (struct regcache *regcache, int regno)
+monitor_store_registers (struct target_ops *ops,
+ struct regcache *regcache, int regno)
{
if (regno >= 0)
{
return;
}
- for (regno = 0; regno < gdbarch_num_regs (current_gdbarch); regno++)
+ for (regno = 0; regno < gdbarch_num_regs (get_regcache_arch (regcache));
+ regno++)
monitor_store_register (regcache, regno);
}
/* All we actually do is set the PC to the start address of exec_bfd. */
static void
-monitor_create_inferior (char *exec_file, char *args, char **env,
- int from_tty)
+monitor_create_inferior (struct target_ops *ops, char *exec_file,
+ char *args, char **env, int from_tty)
{
if (args && (*args != '\000'))
error (_("Args are not supported by the monitor."));
instructions. */
static void
-monitor_mourn_inferior (void)
+monitor_mourn_inferior (struct target_ops *ops)
{
unpush_target (targ_ops);
generic_mourn_inferior (); /* Do all the proper things now */
+ delete_thread_silent (monitor_ptid);
}
/* Tell the monitor to add a breakpoint. */
{
CORE_ADDR addr = bp_tgt->placed_address;
int i;
- const unsigned char *bp;
int bplen;
monitor_debug ("MON inst bkpt %s\n", paddr (addr));
addr = gdbarch_addr_bits_remove (current_gdbarch, addr);
/* Determine appropriate breakpoint size for this address. */
- bp = gdbarch_breakpoint_from_pc (current_gdbarch, &addr, &bplen);
+ gdbarch_breakpoint_from_pc (current_gdbarch, &addr, &bplen);
bp_tgt->placed_address = addr;
bp_tgt->placed_size = bplen;
}
static void
-monitor_stop (void)
+monitor_stop (ptid_t ptid)
{
monitor_debug ("MON stop\n");
if ((current_monitor->flags & MO_SEND_BREAK_ON_STOP) != 0)
return dev_name;
}
+/* Check to see if a thread is still alive. */
+
+static int
+monitor_thread_alive (struct target_ops *ops, ptid_t ptid)
+{
+ if (ptid_equal (ptid, monitor_ptid))
+ /* The monitor's task is always alive. */
+ return 1;
+
+ return 0;
+}
+
+/* Convert a thread ID to a string. Returns the string in a static
+ buffer. */
+
+static char *
+monitor_pid_to_str (struct target_ops *ops, ptid_t ptid)
+{
+ static char buf[64];
+
+ if (ptid_equal (monitor_ptid, ptid))
+ {
+ xsnprintf (buf, sizeof buf, "Thread <main>");
+ return buf;
+ }
+
+ return normal_pid_to_str (ptid);
+}
+
static struct target_ops monitor_ops;
static void
monitor_ops.to_mourn_inferior = monitor_mourn_inferior;
monitor_ops.to_stop = monitor_stop;
monitor_ops.to_rcmd = monitor_rcmd;
+ monitor_ops.to_log_command = serial_log_command;
+ monitor_ops.to_thread_alive = monitor_thread_alive;
+ monitor_ops.to_pid_to_str = monitor_pid_to_str;
monitor_ops.to_stratum = process_stratum;
monitor_ops.to_has_all_memory = 1;
monitor_ops.to_has_memory = 1;
NULL,
NULL, /* FIXME: i18n: */
&setdebuglist, &showdebuglist);
+
+ /* Yes, 42000 is arbitrary. The only sense out of it, is that it
+ isn't 0. */
+ monitor_ptid = ptid_build (42000, 0, 42000);
}