diff options
Diffstat (limited to 'gdb/remote.c')
-rw-r--r-- | gdb/remote.c | 210 |
1 files changed, 192 insertions, 18 deletions
diff --git a/gdb/remote.c b/gdb/remote.c index 8e59d4c..103bf15 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -135,6 +135,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ running and the debugger should continue to wait for 'W', 'T', etc. + thread alive TXX Find out if the thread XX is alive. + reply OK thread is still alive + ENN thread is dead + + remote restart RXX Restart the remote server + + extended ops ! Use the extended remote protocol. + Sticky -- only needs to be set once. + kill request k toggle debug d toggle debug flag (see 386 & 68k stubs) @@ -165,7 +174,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ "0* " means the same as "0000". */ #include "defs.h" -#include <string.h> +#include "gdb_string.h" #include <fcntl.h> #include "frame.h" #include "inferior.h" @@ -213,10 +222,24 @@ static int remote_start_remote PARAMS ((char *dummy)); static void remote_open PARAMS ((char *name, int from_tty)); +static void extended_remote_open PARAMS ((char *name, int from_tty)); + +static void remote_open_1 PARAMS ((char *, int, struct target_ops *)); + static void remote_close PARAMS ((int quitting)); static void remote_store_registers PARAMS ((int regno)); +static void remote_mourn PARAMS ((void)); + +static void extended_remote_restart PARAMS ((void)); + +static void extended_remote_mourn PARAMS ((void)); + +static void extended_remote_create_inferior PARAMS ((char *, char *, char **)); + +static void remote_mourn_1 PARAMS ((struct target_ops *)); + static void getpkt PARAMS ((char *buf, int forever)); static int putpkt PARAMS ((char *buf)); @@ -242,6 +265,7 @@ static void remote_interrupt_twice PARAMS ((int signo)); static void interrupt_query PARAMS ((void)); extern struct target_ops remote_ops; /* Forward decl */ +extern struct target_ops extended_remote_ops; /* Forward decl */ /* This was 5 seconds, which is a long time to sit and wait. Unless this is going though some terminal server or multiplexer or @@ -313,7 +337,7 @@ set_thread (th, gen) cont_thread = th; } -/* Return nonzero if the thread TH is still alive on the remote system. */ +/* Return nonzero if the thread TH is still alive on the remote system. */ static int remote_thread_alive (th) @@ -330,6 +354,25 @@ remote_thread_alive (th) getpkt (buf, 0); return (buf[0] == 'O' && buf[1] == 'K'); } + +/* Restart the remote side; this is an extended protocol operation. */ + +static void +extended_remote_restart () +{ + char buf[PBUFSIZ]; + + /* Send the restart command; for reasons I don't understand the + remote side really expects a number after the "R". */ + buf[0] = 'R'; + sprintf (&buf[1], "%x", 0); + putpkt (buf); + + /* Now query for status so this looks just like we restarted + gdbserver from scratch. */ + putpkt ("?"); + getpkt (buf, 0); +} /* Clean up connection to a remote debugger. */ @@ -420,12 +463,41 @@ remote_start_remote (dummy) /* Open a connection to a remote debugger. NAME is the filename used for communication. */ +static void +remote_open (name, from_tty) + char *name; + int from_tty; +{ + remote_open_1 (name, from_tty, &remote_ops); +} + +/* Open a connection to a remote debugger using the extended + remote gdb protocol. NAME is hte filename used for communication. */ + +static void +extended_remote_open (name, from_tty) + char *name; + int from_tty; +{ + char buf[PBUFSIZ]; + + /* Do the basic remote open stuff. */ + remote_open_1 (name, from_tty, &extended_remote_ops); + + /* Now tell the remote that we're using the extended protocol. */ + putpkt ("!"); + getpkt (buf, 0); + +} + +/* Generic code for opening a connection to a remote target. */ static DCACHE *remote_dcache; static void -remote_open (name, from_tty) +remote_open_1 (name, from_tty, target) char *name; int from_tty; + struct target_ops *target; { if (name == 0) error ("To open a remote debug connection, you need to specify what serial\n\ @@ -433,7 +505,7 @@ device is attached to the remote system (e.g. /dev/ttya)."); target_preopen (from_tty); - unpush_target (&remote_ops); + unpush_target (target); remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes); @@ -463,7 +535,7 @@ device is attached to the remote system (e.g. /dev/ttya)."); puts_filtered (name); puts_filtered ("\n"); } - push_target (&remote_ops); /* Switch to using remote target now */ + push_target (target); /* Switch to using remote target now */ /* Start out by trying the 'P' request to set registers. We set this each time that we open a new target so that if the user switches from one @@ -669,20 +741,21 @@ remote_wait (pid, status) { unsigned char *p1; char *p_temp; + unsigned LONGEST val; - regno = strtol (p, &p_temp, 16); /* Read the register number */ + regno = strtol ((const char *) p, &p_temp, 16); /* Read the register number */ p1 = (unsigned char *)p_temp; if (p1 == p) { - p1 = (unsigned char *) strchr (p, ':'); + p1 = (unsigned char *) strchr ((const char *) p, ':'); if (p1 == NULL) warning ("Malformed packet (missing colon): %s\n\ Packet: '%s'\n", p, buf); - if (strncmp (p, "thread", p1 - p) == 0) + if (strncmp ((const char *) p, "thread", p1 - p) == 0) { - thread_num = strtol (++p1, &p_temp, 16); + thread_num = strtol ((const char *) ++p1, &p_temp, 16); p = (unsigned char *)p_temp; } } @@ -696,17 +769,20 @@ Packet: '%s'\n", p, buf); if (regno >= NUM_REGS) - warning ("Remote sent bad register number %d: %s\n\ + warning ("Remote sent bad register number %ld: %s\n\ Packet: '%s'\n", regno, p, buf); + val = 0L; for (i = 0; i < REGISTER_RAW_SIZE (regno); i++) { if (p[0] == 0 || p[1] == 0) warning ("Remote reply is too short: %s", buf); - regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); + val = val * 256 + fromhex (p[0]) * 16 + fromhex (p[1]); p += 2; + } + store_unsigned_integer (regs, REGISTER_RAW_SIZE (regno), val); supply_register (regno, regs); } @@ -750,8 +826,8 @@ Packet: '%s'\n", last_sent_signal = TARGET_SIGNAL_0; target_terminal_inferior (); - strcpy (buf, last_sent_step ? "s" : "c"); - putpkt (buf); + strcpy ((char *) buf, last_sent_step ? "s" : "c"); + putpkt ((char *) buf); continue; } /* else fallthrough */ @@ -928,6 +1004,7 @@ remote_store_registers (regno) /* Read a word from remote address ADDR and return it. This goes through the data cache. */ +#if 0 /* unused? */ static int remote_fetch_word (addr) CORE_ADDR addr; @@ -945,6 +1022,7 @@ remote_store_word (addr, word) { dcache_poke (remote_dcache, addr, word); } +#endif /* 0 (unused?) */ /* Write memory data directly to the remote machine. @@ -1403,7 +1481,6 @@ getpkt (buf, forever) char *buf; int forever; { - char *bp; int c; int tries; int timeout; @@ -1502,9 +1579,62 @@ remote_kill () static void remote_mourn () { - unpush_target (&remote_ops); + remote_mourn_1 (&remote_ops); +} + +static void +extended_remote_mourn () +{ + /* We do _not_ want to mourn the target like this; this will + remove the extended remote target from the target stack, + and the next time the user says "run" it'll fail. + + FIXME: What is the right thing to do here? */ +#if 0 + remote_mourn_1 (&extended_remote_ops); +#endif +} + +/* Worker function for remote_mourn. */ +static void +remote_mourn_1 (target) + struct target_ops *target; +{ + unpush_target (target); generic_mourn_inferior (); } + +/* In the extended protocol we want to be able to do things like + "run" and have them basically work as expected. So we need + a special create_inferior function. + + FIXME: One day add support for changing the exec file + we're debugging, arguments and an environment. */ + +static void +extended_remote_create_inferior (exec_file, args, env) + char *exec_file; + char *args; + char **env; +{ + /* Rip out the breakpoints; we'll reinsert them after restarting + the remote server. */ + remove_breakpoints (); + + /* Now restart the remote server. */ + extended_remote_restart (); + + /* Now put the breakpoints back in. This way we're safe if the + restart function works via a unix fork on the remote side. */ + insert_breakpoints (); + + /* Clean up from the last time we were running. */ + clear_proceed_status (); + + /* Let the remote process run. */ + proceed (-1, TARGET_SIGNAL_0, 0); +} + #ifdef REMOTE_BREAKPOINT @@ -1512,9 +1642,6 @@ remote_mourn () than other targets. */ static unsigned char break_insn[] = REMOTE_BREAKPOINT; -/* Check that it fits in BREAKPOINT_MAX bytes. */ -static unsigned char check_break_insn_size[BREAKPOINT_MAX] = REMOTE_BREAKPOINT; - #else /* No REMOTE_BREAKPOINT. */ /* Same old breakpoint instruction. This code does nothing different @@ -1602,8 +1729,55 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */ OPS_MAGIC /* to_magic */ }; +struct target_ops extended_remote_ops = { + "extended-remote", /* to_shortname */ + "Extended remote serial target in gdb-specific protocol",/* to_longname */ + "Use a remote computer via a serial line, using a gdb-specific protocol.\n\ +Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */ + extended_remote_open, /* to_open */ + remote_close, /* to_close */ + NULL, /* to_attach */ + remote_detach, /* to_detach */ + remote_resume, /* to_resume */ + remote_wait, /* to_wait */ + remote_fetch_registers, /* to_fetch_registers */ + remote_store_registers, /* to_store_registers */ + remote_prepare_to_store, /* to_prepare_to_store */ + remote_xfer_memory, /* to_xfer_memory */ + remote_files_info, /* to_files_info */ + + remote_insert_breakpoint, /* to_insert_breakpoint */ + remote_remove_breakpoint, /* to_remove_breakpoint */ + + NULL, /* to_terminal_init */ + NULL, /* to_terminal_inferior */ + NULL, /* to_terminal_ours_for_output */ + NULL, /* to_terminal_ours */ + NULL, /* to_terminal_info */ + remote_kill, /* to_kill */ + generic_load, /* to_load */ + NULL, /* to_lookup_symbol */ + extended_remote_create_inferior,/* to_create_inferior */ + extended_remote_mourn, /* to_mourn_inferior */ + 0, /* to_can_run */ + 0, /* to_notice_signals */ + remote_thread_alive, /* to_thread_alive */ + 0, /* to_stop */ + process_stratum, /* to_stratum */ + NULL, /* to_next */ + 1, /* to_has_all_memory */ + 1, /* to_has_memory */ + 1, /* to_has_stack */ + 1, /* to_has_registers */ + 1, /* to_has_execution */ + NULL, /* sections */ + NULL, /* sections_end */ + OPS_MAGIC /* to_magic */ +}; + void _initialize_remote () { add_target (&remote_ops); + add_target (&extended_remote_ops); } |