2008-08-19 Pedro Alves * remote-mips.c (ofunc): New. (mips_wait_cleanup): New. (mips_wait): Set SIGINT so mips_interrupt. (mips_kill): Do nothing. (mips_stop): New, based on old mips_kill. (mips_interrupt, mips_interrupt_twice, mips_interrupt_query): New. (mips_load): Use regcache_invalidate instead of regcache_set_valid_p. (_initialize_remote_mips): Register mips_stop. --- gdb/remote-mips.c | 118 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 87 insertions(+), 31 deletions(-) Index: src/gdb/remote-mips.c =================================================================== --- src.orig/gdb/remote-mips.c 2008-08-19 19:58:54.000000000 +0100 +++ src/gdb/remote-mips.c 2008-08-19 20:04:11.000000000 +0100 @@ -35,6 +35,7 @@ #include "regcache.h" #include #include "mips-tdep.h" +#include /* Breakpoint types. Values 0, 1, and 2 must agree with the watch @@ -148,6 +149,10 @@ static int mips_clear_breakpoint (CORE_A static int mips_common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type); +static void mips_interrupt (int signo); +static void mips_interrupt_twice (int signo); +static void mips_interrupt_query (void); + /* Forward declarations. */ extern struct target_ops mips_ops; extern struct target_ops pmon_ops; @@ -385,6 +390,8 @@ static int mips_wait_flag = 0; /* If non-zero, monitor supports breakpoint commands. */ static int monitor_supports_breakpoints = 0; +static void (*ofunc) (); /* Old SIGINT signal handler */ + /* Data cache header. */ #if 0 /* not used (yet?) */ @@ -1701,6 +1708,13 @@ mips_signal_from_protocol (int sig) return (enum target_signal) sig; } +static void +mips_wait_cleanup (void *arg) +{ + signal (SIGINT, ofunc); + mips_wait_flag = 0; +} + /* Wait until the remote stops, and return a wait status. */ static ptid_t @@ -1713,6 +1727,7 @@ mips_wait (ptid_t ptid, struct target_wa char flags[20]; int nfields; int i; + struct cleanup *old_chain; interrupt_count = 0; hit_watchpoint = 0; @@ -1727,10 +1742,17 @@ mips_wait (ptid_t ptid, struct target_wa return inferior_ptid; } + old_chain = make_cleanup (mips_wait_cleanup, NULL); + /* No timeout; we sit here as long as the program continues to execute. */ mips_wait_flag = 1; + ofunc = (void (*)()) signal (SIGINT, mips_interrupt); rstatus = mips_request ('\000', 0, 0, &err, -1, buff); + signal (SIGINT, ofunc); mips_wait_flag = 0; + + discard_cleanups (old_chain); + if (err) mips_error ("Remote failure: %s", safe_strerror (errno)); @@ -2130,43 +2152,24 @@ mips_files_info (struct target_ops *igno printf_unfiltered ("Debugging a MIPS board over a serial line.\n"); } -/* Kill the process running on the board. This will actually only +static void +mips_kill (void) +{ + /* ignore attempts to kill target system */ + return; +} + +/* Interrupt the process running on the board. This will actually only work if we are doing remote debugging over the console input. I think that if IDT/sim had the remote debug interrupt enabled on the right port, we could interrupt the process with a break signal. */ static void -mips_kill (void) +mips_stop (ptid_t ptid) { if (!mips_wait_flag) return; - interrupt_count++; - - if (interrupt_count >= 2) - { - interrupt_count = 0; - - target_terminal_ours (); - - if (query ("Interrupted while waiting for the program.\n\ -Give up (and stop debugging it)? ")) - { - /* Clean up in such a way that mips_close won't try to talk to the - board (it almost surely won't work since we weren't able to talk to - it). */ - mips_wait_flag = 0; - close_ports (); - - printf_unfiltered ("Ending remote MIPS debugging.\n"); - target_mourn_inferior (); - - deprecated_throw_reason (RETURN_QUIT); - } - - target_terminal_inferior (); - } - if (remote_debug > 0) printf_unfiltered ("Sending break\n"); @@ -2186,6 +2189,59 @@ Give up (and stop debugging it)? ")) #endif } +/* Send ^C to target to halt it. Target will respond, and send us a + packet. */ + +static void +mips_interrupt (int signo) +{ + /* If this doesn't work, try more severe steps. */ + signal (signo, mips_interrupt_twice); + + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "mips_interrupt called\n"); + + target_stop (inferior_ptid); +} + +/* The user typed ^C twice. */ + +static void +mips_interrupt_twice (int signo) +{ + signal (signo, ofunc); + + mips_interrupt_query (); + + signal (signo, mips_interrupt); +} + +/* Ask the user what to do when an interrupt is received. */ + +static void +mips_interrupt_query (void) +{ + target_terminal_ours (); + + if (query ("Interrupted while waiting for the program.\n\ +Give up (and stop debugging it)? ")) + { + /* Clean up in such a way that mips_close won't try to talk to the + board (it almost surely won't work since we weren't able to talk to + it). */ + mips_wait_flag = 0; + close_ports (); + + printf_unfiltered ("Ending remote MIPS debugging.\n"); + target_mourn_inferior (); + + deprecated_throw_reason (RETURN_QUIT); + } + + target_terminal_inferior (); +} + + /* Start running on the target board. */ static void @@ -3282,9 +3338,8 @@ mips_load (char *file, int from_tty) to a different value than GDB thinks it has. The following ensures that the write_pc() WILL update the PC value: */ struct regcache *regcache = get_current_regcache (); - regcache_set_valid_p (regcache, - gdbarch_pc_regnum (get_regcache_arch (regcache)), - 0); + regcache_invalidate (regcache, + gdbarch_pc_regnum (get_regcache_arch (regcache))); } if (exec_bfd) write_pc (bfd_get_start_address (exec_bfd)); @@ -3340,6 +3395,7 @@ _initialize_remote_mips (void) mips_ops.to_stopped_by_watchpoint = mips_stopped_by_watchpoint; mips_ops.to_can_use_hw_breakpoint = mips_can_use_watchpoint; mips_ops.to_kill = mips_kill; + mips_ops.to_stop = mips_stop; mips_ops.to_load = mips_load; mips_ops.to_create_inferior = mips_create_inferior; mips_ops.to_mourn_inferior = mips_mourn_inferior;