This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[01/02] remote-mips.c, always a thread (take 2)
On Monday 18 August 2008 14:07:34, Pedro Alves wrote:
> On Monday 18 August 2008 13:29:28, Pedro Alves wrote:
> > - mips_load was clearing inferior_ptid, and calling clear_symtab_users.
> > I notice that inferior_ptid is being cleared after a load command, but
> > that is wrong, I believe. See this change of Jim's to monitor.c, that
> > removed this clearing from the monitor target:
> > http://sourceware.org/ml/gdb/2001-09/msg00125.html
> >
> > I'm applying the exact same reasoning and change here.
>
> Hmmm, I just noticed that mips_kill is being used to interrupting
> the target ( '\03' / ^C / SIGINT ), instead of installing a SIGINT
> handler like at least monitor.c, remote.c and remote-sim.c do.
> This looks broken to me -- target_kill is definitelly not the
> right target method for this (and neither is the "kill" command).
This patch makes the remote-mips target register a SIGINT handler
instead, like monitor.c does.
Of course, only after doing this, I noticed that that there's
no configuration currently that builds this file...
I've checked that this at least builds after tweaking configure.tgt
to include it in a --target=mips-elf build. CS has a similar tweak
in its internal trees, but AFAIK we don't have customers
using this target either.
To make this build, I also needed to change regcache_set_valid_p to
regcache_invalidate. regcache_set_valid_p isn't defined anywhere.
It seems it would supposed to go in with this:
http://sourceware.org/ml/gdb-patches/2007-12/msg00150.html
But only the remote-mips.c bits went in.
Anyway, as long as I've written it the patch here it is.
--
Pedro Alves
2008-08-19 Pedro Alves <pedro@codesourcery.com>
* 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 <ctype.h>
#include "mips-tdep.h"
+#include <signal.h>
/* 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;