/* 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, 2010
+ Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
Resurrected from the ashes by Stu Grossman.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* This file was derived from various remote-* modules. It is a collection
of generic support functions so GDB can talk directly to a ROM based
#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
the developer of a new monitor interface. */
-static void monitor_debug (const char *fmt, ...) ATTR_FORMAT(printf, 1, 2);
+static void monitor_debug (const char *fmt, ...) ATTRIBUTE_PRINTF (1, 2);
static int monitor_debug_p = 0;
if (monitor_debug_p)
{
va_list args;
+
va_start (args, fmt);
vfprintf_filtered (gdb_stdlog, fmt, args);
va_end (args);
{
int real_len = (len == 0 && string != (char *) 0) ? strlen (string) : len;
char *safe_string = alloca ((real_len * 4) + 1);
+
monitor_printable_string (safe_string, string, real_len);
if (final_char)
- error (_("%s (0x%s): %s: %s%c"), function, paddr_nz (memaddr), message, safe_string, final_char);
+ error (_("%s (%s): %s: %s%c"),
+ function, paddress (target_gdbarch, memaddr),
+ message, safe_string, final_char);
else
- error (_("%s (0x%s): %s: %s"), function, paddr_nz (memaddr), message, safe_string);
+ error (_("%s (%s): %s: %s"),
+ function, paddress (target_gdbarch, memaddr),
+ message, safe_string);
}
/* Convert hex digit A to a number. */
static void
monitor_vsprintf (char *sndbuf, char *pattern, va_list args)
{
+ int addr_bit = gdbarch_addr_bit (target_gdbarch);
char format[10];
char fmt;
char *p;
break;
case 'A':
arg_addr = va_arg (args, CORE_ADDR);
- strcpy (sndbuf, paddr_nz (arg_addr));
+ strcpy (sndbuf, phex_nz (arg_addr, addr_bit / 8));
break;
case 's':
arg_string = va_arg (args, char *);
if (monitor_debug_p)
{
char *safe_string = (char *) alloca ((strlen (sndbuf) * 4) + 1);
+
monitor_printable_string (safe_string, sndbuf, 0);
fprintf_unfiltered (gdb_stdlog, "sent[%s]\n", safe_string);
}
if (monitor_debug_p)
{
char *safe_string = (char *) alloca ((len * 4) + 1);
+
monitor_printable_string (safe_string, sndbuf, 0);
fprintf_unfiltered (gdb_stdlog, "sent[%s]\n", safe_string);
}
if (monitor_debug_p || remote_debug)
{
char buf[2];
+
buf[0] = c;
buf[1] = '\0';
puts_debug ("read -->", buf, "<--");
{
char *mybuf;
char *p;
+
monitor_debug ("MON Expecting regexp\n");
if (buf)
mybuf = buf;
{
char *name;
char **p;
+ struct inferior *inf;
if (mon_ops->magic != MONITOR_OPS_MAGIC)
error (_("Magic number of monitor_ops struct wrong."));
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;
+ inf = current_inferior ();
+ inferior_appeared (inf, 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)
char *
monitor_supply_register (struct regcache *regcache, int regno, char *valstr)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST val;
unsigned char regbuf[MAX_REGISTER_SIZE];
char *p;
/* 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 (gdbarch, regno), byte_order,
+ 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");
{
int regnamelen, vallen;
char *regname, *val;
+
/* Element 0 points to start of register name, and element 1
points to the start of the register value. */
struct re_registers register_strings;
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);
struct target_waitstatus *status)
{
int resp_len;
+
do
{
resp_len = monitor_expect_prompt (buf, bufmax);
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 options)
{
int old_timeout = timeout;
char buf[TARGET_BUF_SIZE];
}
if (current_monitor->register_pattern)
- parse_register_dump (current_regcache, buf, resp_len);
+ parse_register_dump (get_current_regcache (), buf, resp_len);
#else
monitor_debug ("Wait fetching registers after stop\n");
- monitor_dump_regs (current_regcache);
+ monitor_dump_regs (get_current_regcache ());
#endif
status->kind = TARGET_WAITKIND_STOPPED;
if (current_monitor->flags & MO_HEX_PREFIX)
{
int c;
+
c = readchar (timeout);
while (c == ' ')
c = readchar (timeout);
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);
while (c == ' ')
c = readchar (timeout);
{
char buf[TARGET_BUF_SIZE];
int resp_len;
+
monitor_printf (block_cmd);
resp_len = monitor_expect_prompt (buf, sizeof (buf));
parse_register_dump (regcache, buf, resp_len);
{
char buf[TARGET_BUF_SIZE];
int resp_len;
+
if (current_monitor->dumpregs)
(*(current_monitor->dumpregs)) (regcache); /* call supplied function */
else if (current_monitor->dump_registers) /* default version */
}
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
static void
monitor_store_register (struct regcache *regcache, int regno)
{
+ int reg_size = register_size (get_regcache_arch (regcache), regno);
const char *name;
ULONGEST val;
}
regcache_cooked_read_unsigned (regcache, regno, &val);
- monitor_debug ("MON storeg %d %s\n", regno,
- phex (val, register_size (current_gdbarch, regno)));
+ monitor_debug ("MON storeg %d %s\n", regno, phex (val, reg_size));
/* send the register deposit command */
monitor_debug ("EXP setreg.resp_delim\n");
monitor_expect_regexp (&setreg_resp_delim_pattern, NULL, 0);
if (current_monitor->flags & MO_SETREG_INTERACTIVE)
- monitor_printf ("%s\r", paddr_nz (val));
+ monitor_printf ("%s\r", phex_nz (val, reg_size));
}
if (current_monitor->setreg.term)
{
monitor_debug ("EXP setreg.term\n");
monitor_expect (current_monitor->setreg.term, NULL, 0);
if (current_monitor->flags & MO_SETREG_INTERACTIVE)
- monitor_printf ("%s\r", paddr_nz (val));
+ monitor_printf ("%s\r", phex_nz (val, reg_size));
monitor_expect_prompt (NULL, 0);
}
else
/* 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);
}
static int
monitor_write_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
unsigned int val, hostval;
char *cmd;
int i;
- monitor_debug ("MON write %d %s\n", len, paddr (memaddr));
+ monitor_debug ("MON write %d %s\n", len, paddress (target_gdbarch, memaddr));
if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
- memaddr = ADDR_BITS_REMOVE (memaddr);
+ memaddr = gdbarch_addr_bits_remove (target_gdbarch, memaddr);
/* Use memory fill command for leading 0 bytes. */
cmd = current_monitor->setmem.cmdb;
}
- val = extract_unsigned_integer (myaddr, len);
+ val = extract_unsigned_integer (myaddr, len, byte_order);
if (len == 4)
{
monitor_printf_noecho (cmd, memaddr, val);
else if (current_monitor->flags & MO_SETMEM_INTERACTIVE)
{
-
monitor_printf_noecho (cmd, memaddr);
if (current_monitor->setmem.resp_delim)
monitor_printf ("%x\r", val);
}
if (current_monitor->setmem.term_cmd)
- { /* Emit this to get out of the memory editing state */
+ { /* Emit this to get out of the memory editing state */
monitor_printf ("%s", current_monitor->setmem.term_cmd);
/* Drop through to expecting a prompt */
}
{
unsigned char val;
int written = 0;
+
if (len == 0)
return 0;
/* Enter the sub mode */
{
int i, j;
unsigned char x;
+
i = 0;
j = 7;
while (i < 4)
unsigned char *scan, *limit; /* loop controls */
unsigned char c, nib;
int leadzero = 1;
+
scan = disbuf;
limit = scan + 8;
{
unsigned long long *dp;
+
dp = (unsigned long long *) scan;
*dp = value;
}
long long *llptr;
long long value;
int written = 0;
+
llptr = (unsigned long long *) myaddr;
if (len == 0)
return 0;
monitor_write_memory_block (CORE_ADDR memaddr, char *myaddr, int len)
{
int written;
+
written = 0;
/* FIXME: This would be a good place to put the zero test */
#if 1
static int
monitor_read_memory_single (CORE_ADDR memaddr, char *myaddr, int len)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
unsigned int val;
char membuf[sizeof (int) * 2 + 1];
char *p;
{
int i;
+
for (i = 0; i < len * 2; i++)
{
int c;
/* supply register stores in target byte order, so swap here */
- store_unsigned_integer (myaddr, len, val);
+ store_unsigned_integer (myaddr, len, byte_order, val);
return len;
}
}
monitor_debug ("MON read block ta(%s) ha(%lx) %d\n",
- paddr_nz (memaddr), (long) myaddr, len);
+ paddress (target_gdbarch, memaddr), (long) myaddr, len);
if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
- memaddr = ADDR_BITS_REMOVE (memaddr);
+ memaddr = gdbarch_addr_bits_remove (target_gdbarch, memaddr);
if (current_monitor->flags & MO_GETMEM_READ_SINGLE)
return monitor_read_memory_single (memaddr, myaddr, len);
{
int retval, tmp;
struct re_registers resp_strings;
+
monitor_debug ("MON getmem.resp_delim %s\n", current_monitor->getmem.resp_delim);
memset (&resp_strings, 0, sizeof (struct re_registers));
}
static void
-monitor_kill (void)
+monitor_kill (struct target_ops *ops)
{
return; /* ignore attempts to kill target system */
}
/* 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."));
first_time = 1;
clear_proceed_status ();
- write_pc (bfd_get_start_address (exec_bfd));
+ regcache_write_pc (get_current_regcache (),
+ bfd_get_start_address (exec_bfd));
}
/* Clean up when a program exits.
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. */
static int
-monitor_insert_breakpoint (struct bp_target_info *bp_tgt)
+monitor_insert_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
{
CORE_ADDR addr = bp_tgt->placed_address;
int i;
- const unsigned char *bp;
int bplen;
- monitor_debug ("MON inst bkpt %s\n", paddr (addr));
+ monitor_debug ("MON inst bkpt %s\n", paddress (gdbarch, addr));
if (current_monitor->set_break == NULL)
error (_("No set_break defined for this monitor"));
if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
- addr = ADDR_BITS_REMOVE (addr);
+ addr = gdbarch_addr_bits_remove (gdbarch, addr);
/* Determine appropriate breakpoint size for this address. */
- bp = gdbarch_breakpoint_from_pc (current_gdbarch, &addr, &bplen);
+ gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);
bp_tgt->placed_address = addr;
bp_tgt->placed_size = bplen;
/* Tell the monitor to remove a breakpoint. */
static int
-monitor_remove_breakpoint (struct bp_target_info *bp_tgt)
+monitor_remove_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
{
CORE_ADDR addr = bp_tgt->placed_address;
int i;
- monitor_debug ("MON rmbkpt %s\n", paddr (addr));
+ monitor_debug ("MON rmbkpt %s\n", paddress (gdbarch, addr));
if (current_monitor->clr_break == NULL)
error (_("No clr_break defined for this monitor"));
}
}
fprintf_unfiltered (gdb_stderr,
- "Can't find breakpoint associated with 0x%s\n",
- paddr_nz (addr));
+ "Can't find breakpoint associated with %s\n",
+ paddress (gdbarch, addr));
return 1;
}
/* Finally, make the PC point at the start address */
if (exec_bfd)
- write_pc (bfd_get_start_address (exec_bfd));
+ regcache_write_pc (get_current_regcache (),
+ bfd_get_start_address (exec_bfd));
/* There used to be code here which would clear inferior_ptid and
call clear_symtab_users. None of that should be necessary:
}
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;
- monitor_ops.to_has_stack = 1;
- monitor_ops.to_has_registers = 1;
- monitor_ops.to_has_execution = 1;
+ monitor_ops.to_has_all_memory = default_child_has_all_memory;
+ monitor_ops.to_has_memory = default_child_has_memory;
+ monitor_ops.to_has_stack = default_child_has_stack;
+ monitor_ops.to_has_registers = default_child_has_registers;
+ monitor_ops.to_has_execution = default_child_has_execution;
monitor_ops.to_magic = OPS_MAGIC;
} /* init_base_monitor_ops */
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);
}