* [PATCH v2 9/9] enable target-async
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
2013-07-31 20:20 ` Doug Evans
2013-08-01 8:34 ` Yao Qi
2013-07-31 18:28 ` [PATCH v2 3/9] add target method delegation Tom Tromey
` (7 subsequent siblings)
8 siblings, 2 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This enables target-async by default.
Unlike the CLI, MI chose to treat target-async specially -- setting it
changes the default behavior of commands. So, we can't get rid of the
option. Instead we have to make it MI-only.
The hardest part of this patch, to my surprise, was getting the MI
prompt to work properly. It was reasonably easy, and clean, to get
close to what the test suite expects; but to fix the last remaining
failure (mi-async.exp), I had to resort to a hack.
It seems to me that the MI grammar was never updated to account for
changes implied by async.
Perhaps some future MI can dispense with the prompt entirely.
Built and regtested on x86-64 Fedora 18.
PR gdb/15712:
* infrun.c (set_observer_mode): Don't set target_async_permitted.
* linux-nat.c (linux_nat_is_async_p): Always return 1.
(linux_nat_can_async_p): Likewise.
* mi/mi-interp.c (mi_interpreter_prompt_p): Maybe print the MI
prompt.
(mi_cmd_interpreter_exec): Set mi_last_was_cli.
(mi_execute_command_input_handler): Conditionally print prompt.
(mi_on_resume): Check sync_execution before printing prompt.
* mi/mi-main.h (mi_last_was_cli): Declare.
* mi/mi-main.c (mi_last_was_cli): New global.
(mi_target_can_async_p): New function.
(exec_continue): Maybe call async_disable_stdin.
(run_one_inferior, mi_cmd_exec_run, mi_cmd_list_target_features):
Use mi_target_can_async_p.
(captured_mi_execute_command): Clear mi_last_was_cli.
(mi_execute_async_cli_command): Use mi_target_can_async_p.
* remote.c (remote_open_1, remote_terminal_inferior)
(remote_terminal_ours, remote_can_async_p, remote_is_async_p):
Don't check target_async_permitted.
* gdb.texinfo (Non-Stop Mode): Remove "set target-async 1"
from example.
(Background Execution): Move target-async docs...
(Asynchronous and non-stop modes): ... here. Rewrite to
MI form.
* gdb.mi/mi-cli.exp: Don't check "$async".
---
gdb/cli/cli-interp.c | 1 +
gdb/doc/gdb.texinfo | 29 ++++++++++---------------
gdb/infrun.c | 1 -
gdb/linux-nat.c | 10 ++-------
gdb/mi/mi-interp.c | 28 +++++++++++++++++++-----
gdb/mi/mi-main.c | 29 +++++++++++++++++++------
gdb/mi/mi-main.h | 1 +
gdb/remote.c | 48 +++++++++++------------------------------
gdb/testsuite/gdb.mi/mi-cli.exp | 15 +------------
gdb/tui/tui-interp.c | 1 +
10 files changed, 76 insertions(+), 87 deletions(-)
diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 1003cc7..ef1e65b 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -25,6 +25,7 @@
#include "top.h" /* for "execute_command" */
#include "gdb_string.h"
#include "exceptions.h"
+#include "target.h"
struct ui_out *cli_uiout;
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index cb393e8..4ec4880 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -5672,9 +5672,6 @@ To enter non-stop mode, use this sequence of commands before you run
or attach to your program:
@smallexample
-# Enable the async interface.
-set target-async 1
-
# If using the CLI, pagination breaks non-stop.
set pagination off
@@ -5744,21 +5741,6 @@ the program to report that some thread has stopped before prompting for
another command. In background execution, @value{GDBN} immediately gives
a command prompt so that you can issue other commands while your program runs.
-You need to explicitly enable asynchronous mode before you can use
-background execution commands. You can use these commands to
-manipulate the asynchronous mode setting:
-
-@table @code
-@kindex set target-async
-@item set target-async on
-Enable asynchronous mode.
-@item set target-async off
-Disable asynchronous mode.
-@kindex show target-async
-@item show target-async
-Show the current target-async setting.
-@end table
-
If the target doesn't support async mode, @value{GDBN} issues an error
message if you attempt to use the background execution commands.
@@ -28505,6 +28487,17 @@ frontend has started the executable or attached to the target, it can
find if asynchronous execution is enabled using the
@code{-list-target-features} command.
+@table @code
+@kindex -gdb-set target-async
+@item -gdb-set target-async on
+Enable asynchronous mode. This mode only affects MI commands.
+@item -gdb-set target-async off
+Disable asynchronous mode.
+@kindex -gdb-show target-async
+@item -gdb-show target-async
+Show the current target-async setting.
+@end table
+
Even if @value{GDBN} can accept a command while target is running,
many commands that access the target do not work when the target is
running. Therefore, asynchronous command execution is most useful
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0052ef2..be12a02 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -242,7 +242,6 @@ set_observer_mode (char *args, int from_tty,
going out we leave it that way. */
if (observer_mode)
{
- target_async_permitted = 1;
pagination_enabled = 0;
non_stop = non_stop_1 = 1;
}
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index e9f3266..4a1ab16 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -4764,10 +4764,7 @@ linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
static int
linux_nat_is_async_p (struct target_ops *ops)
{
- /* NOTE: palves 2008-03-21: We're only async when the user requests
- it explicitly with the "set target-async" command.
- Someday, linux will always be async. */
- return target_async_permitted;
+ return 1;
}
/* target_can_async_p implementation. */
@@ -4775,10 +4772,7 @@ linux_nat_is_async_p (struct target_ops *ops)
static int
linux_nat_can_async_p (struct target_ops *ops)
{
- /* NOTE: palves 2008-03-21: We're only async when the user requests
- it explicitly with the "set target-async" command.
- Someday, linux will always be async. */
- return target_async_permitted;
+ return 1;
}
static int
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index b4515d9..886fde1 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -222,11 +222,25 @@ mi_interpreter_exec (void *data, const char *command)
return exception_none;
}
+int mi_last_was_cli;
+
/* Never display the default GDB prompt in MI case. */
static int
mi_interpreter_prompt_p (void *data)
{
+ if (!interp_quiet_p (NULL))
+ {
+ if (!target_is_async_p ()
+ || (!sync_execution && (!target_async_permitted || !mi_last_was_cli)))
+ /* && (!running_result_record_printed */
+ /* || !mi_proceeded )))) */
+ {
+ fputs_unfiltered ("(gdb) \n", raw_stdout);
+ gdb_flush (raw_stdout);
+ }
+ }
+
return 0;
}
@@ -252,6 +266,8 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
"does not support command execution"),
argv[0]);
+ mi_last_was_cli = strcmp (argv[0], "console") == 0;
+
/* Note that unlike the CLI version of this command, we don't
actually set INTERP_TO_USE as the current interpreter, as we
still want gdb_stdout, etc. to point at MI streams. */
@@ -323,8 +339,11 @@ mi_execute_command_input_handler (char *cmd)
{
mi_execute_command_wrapper (cmd);
- fputs_unfiltered ("(gdb) \n", raw_stdout);
- gdb_flush (raw_stdout);
+ if (!target_is_async_p () || !sync_execution)
+ {
+ fputs_unfiltered ("(gdb) \n", raw_stdout);
+ gdb_flush (raw_stdout);
+ }
}
static void
@@ -855,9 +874,8 @@ mi_on_resume (ptid_t ptid)
/* This is what gdb used to do historically -- printing prompt even if
it cannot actually accept any input. This will be surely removed
for MI3, and may be removed even earler. */
- /* FIXME: review the use of target_is_async_p here -- is that
- what we want? */
- if (!target_is_async_p ())
+ if (/* !target_async_permitted || */
+ !target_is_async_p () || sync_execution)
fputs_unfiltered ("(gdb) \n", raw_stdout);
}
gdb_flush (raw_stdout);
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index c2d8501..115308b 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -94,6 +94,10 @@ int running_result_record_printed = 1;
command was issued. */
int mi_proceeded;
+/* Flag indicating whether the most recent command was executed via
+ the CLI interpreter. */
+int mi_last_was_cli;
+
extern void _initialize_mi_main (void);
static void mi_cmd_execute (struct mi_parse *parse);
@@ -106,6 +110,15 @@ static int register_changed_p (int regnum, struct regcache *,
static void output_register (struct frame_info *, int regnum, int format,
int skip_unavailable);
+/* A wrapper for target_can_async_p that takes the MI setting into
+ account. */
+
+static int
+mi_target_can_async_p (void)
+{
+ return target_async_permitted && target_can_async_p ();
+}
+
/* Command implementations. FIXME: Is this libgdb? No. This is the MI
layer that calls libgdb. Any operation used in the below should be
formalized. */
@@ -262,6 +275,9 @@ exec_continue (char **argv, int argc)
{
struct cleanup *back_to = make_cleanup_restore_integer (&sched_multi);
+ if (!target_async_permitted && target_can_async_p ())
+ async_disable_stdin ();
+
if (current_context->all)
{
sched_multi = 1;
@@ -386,8 +402,8 @@ run_one_inferior (struct inferior *inf, void *arg)
switch_to_thread (null_ptid);
set_current_program_space (inf->pspace);
}
- mi_execute_cli_command ("run", target_can_async_p (),
- target_can_async_p () ? "&" : NULL);
+ mi_execute_cli_command ("run", mi_target_can_async_p (),
+ mi_target_can_async_p () ? "&" : NULL);
return 0;
}
@@ -403,8 +419,8 @@ mi_cmd_exec_run (char *command, char **argv, int argc)
}
else
{
- mi_execute_cli_command ("run", target_can_async_p (),
- target_can_async_p () ? "&" : NULL);
+ mi_execute_cli_command ("run", mi_target_can_async_p (),
+ mi_target_can_async_p () ? "&" : NULL);
}
}
@@ -1789,7 +1805,7 @@ mi_cmd_list_target_features (char *command, char **argv, int argc)
struct ui_out *uiout = current_uiout;
cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features");
- if (target_can_async_p ())
+ if (mi_target_can_async_p ())
ui_out_field_string (uiout, NULL, "async");
if (target_can_execute_reverse)
ui_out_field_string (uiout, NULL, "reverse");
@@ -1886,6 +1902,7 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
running_result_record_printed = 0;
mi_proceeded = 0;
+ mi_last_was_cli = 0;
switch (context->op)
{
case MI_COMMAND:
@@ -2204,7 +2221,7 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
struct cleanup *old_cleanups;
char *run;
- if (target_can_async_p ())
+ if (mi_target_can_async_p ())
run = xstrprintf ("%s %s&", cli_command, argc ? *argv : "");
else
run = xstrprintf ("%s %s", cli_command, argc ? *argv : "");
diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
index d75526a..22f8827 100644
--- a/gdb/mi/mi-main.h
+++ b/gdb/mi/mi-main.h
@@ -32,6 +32,7 @@ extern char *current_token;
extern int running_result_record_printed;
extern int mi_proceeded;
+extern int mi_last_was_cli;
struct mi_suppress_notification
{
diff --git a/gdb/remote.c b/gdb/remote.c
index 0892ae4..92ba239 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4252,8 +4252,7 @@ remote_open_1 (char *name, int from_tty,
"(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.)."));
/* See FIXME above. */
- if (!target_async_permitted)
- wait_forever_enabled_p = 1;
+ wait_forever_enabled_p = 1;
/* If we're connected to a running target, target_preopen will kill it.
Ask this question first, before target_preopen has a chance to kill
@@ -4339,20 +4338,17 @@ remote_open_1 (char *name, int from_tty,
use_threadinfo_query = 1;
use_threadextra_query = 1;
- if (target_async_permitted)
- {
- /* With this target we start out by owning the terminal. */
- remote_async_terminal_ours_p = 1;
+ /* With this target we start out by owning the terminal. */
+ remote_async_terminal_ours_p = 1;
- /* FIXME: cagney/1999-09-23: During the initial connection it is
- assumed that the target is already ready and able to respond to
- requests. Unfortunately remote_start_remote() eventually calls
- wait_for_inferior() with no timeout. wait_forever_enabled_p gets
- around this. Eventually a mechanism that allows
- wait_for_inferior() to expect/get timeouts will be
- implemented. */
- wait_forever_enabled_p = 0;
- }
+ /* FIXME: cagney/1999-09-23: During the initial connection it is
+ assumed that the target is already ready and able to respond to
+ requests. Unfortunately remote_start_remote() eventually calls
+ wait_for_inferior() with no timeout. wait_forever_enabled_p gets
+ around this. Eventually a mechanism that allows
+ wait_for_inferior() to expect/get timeouts will be
+ implemented. */
+ wait_forever_enabled_p = 0;
/* First delete any symbols previously loaded from shared libraries. */
no_shared_libraries (NULL, 0);
@@ -4388,14 +4384,12 @@ remote_open_1 (char *name, int from_tty,
already before throwing the exception. */
if (remote_desc != NULL)
remote_unpush_target ();
- if (target_async_permitted)
- wait_forever_enabled_p = 1;
+ wait_forever_enabled_p = 1;
throw_exception (ex);
}
}
- if (target_async_permitted)
- wait_forever_enabled_p = 1;
+ wait_forever_enabled_p = 1;
}
/* This takes a program previously attached to and detaches it. After
@@ -5190,10 +5184,6 @@ Give up (and stop debugging it)? ")))
static void
remote_terminal_inferior (void)
{
- if (!target_async_permitted)
- /* Nothing to do. */
- return;
-
/* FIXME: cagney/1999-09-27: Make calls to target_terminal_*()
idempotent. The event-loop GDB talking to an asynchronous target
with a synchronous command calls this function from both
@@ -5213,10 +5203,6 @@ remote_terminal_inferior (void)
static void
remote_terminal_ours (void)
{
- if (!target_async_permitted)
- /* Nothing to do. */
- return;
-
/* See FIXME in remote_terminal_inferior. */
if (remote_async_terminal_ours_p)
return;
@@ -11625,10 +11611,6 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
static int
remote_can_async_p (struct target_ops *ops)
{
- if (!target_async_permitted)
- /* We only enable async when the user specifically asks for it. */
- return 0;
-
/* We're async whenever the serial device is. */
return serial_can_async_p (remote_desc);
}
@@ -11636,10 +11618,6 @@ remote_can_async_p (struct target_ops *ops)
static int
remote_is_async_p (struct target_ops *ops)
{
- if (!target_async_permitted)
- /* We only enable async when the user specifically asks for it. */
- return 0;
-
/* We're async whenever the serial device is. */
return serial_is_async_p (remote_desc);
}
diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp
index bee296d..08e443e 100644
--- a/gdb/testsuite/gdb.mi/mi-cli.exp
+++ b/gdb/testsuite/gdb.mi/mi-cli.exp
@@ -134,20 +134,7 @@ mi_gdb_test "500-stack-select-frame 0" \
{500\^done} \
"-stack-select-frame 0"
-# When a CLI command is entered in MI session, the respose is different in
-# sync and async modes. In sync mode normal_stop is called when current
-# interpreter is CLI. So:
-# - print_stop_reason prints stop reason in CLI uiout, and we don't show it
-# in MI
-# - The stop position is printed, and appears in MI 'console' channel.
-#
-# In async mode the stop event is processed when we're back to MI interpreter,
-# so the stop reason is printed into MI uiout an.
-if {$async} {
- set reason "end-stepping-range"
-} else {
- set reason ""
-}
+set reason "end-stepping-range"
mi_execute_to "interpreter-exec console step" $reason "callee4" "" ".*basics.c" $line_callee4_next \
"" "check *stopped from CLI command"
diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c
index 42526e6..296519b 100644
--- a/gdb/tui/tui-interp.c
+++ b/gdb/tui/tui-interp.c
@@ -30,6 +30,7 @@
#include "tui/tui.h"
#include "tui/tui-io.h"
#include "exceptions.h"
+#include "target.h"
/* Set to 1 when the TUI mode must be activated when we first start
gdb. */
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 9/9] enable target-async
2013-07-31 18:28 ` [PATCH v2 9/9] enable target-async Tom Tromey
@ 2013-07-31 20:20 ` Doug Evans
2013-07-31 20:26 ` Tom Tromey
2013-08-01 8:34 ` Yao Qi
1 sibling, 1 reply; 16+ messages in thread
From: Doug Evans @ 2013-07-31 20:20 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Tom Tromey writes:
> This enables target-async by default.
>
> Unlike the CLI, MI chose to treat target-async specially -- setting it
> changes the default behavior of commands. So, we can't get rid of the
> option. Instead we have to make it MI-only.
>
> The hardest part of this patch, to my surprise, was getting the MI
> prompt to work properly. It was reasonably easy, and clean, to get
> close to what the test suite expects; but to fix the last remaining
> failure (mi-async.exp), I had to resort to a hack.
>
> It seems to me that the MI grammar was never updated to account for
> changes implied by async.
>
> Perhaps some future MI can dispense with the prompt entirely.
>
> Built and regtested on x86-64 Fedora 18.
>
> PR gdb/15712:
> * infrun.c (set_observer_mode): Don't set target_async_permitted.
> * linux-nat.c (linux_nat_is_async_p): Always return 1.
> (linux_nat_can_async_p): Likewise.
> * mi/mi-interp.c (mi_interpreter_prompt_p): Maybe print the MI
> prompt.
> (mi_cmd_interpreter_exec): Set mi_last_was_cli.
> (mi_execute_command_input_handler): Conditionally print prompt.
> (mi_on_resume): Check sync_execution before printing prompt.
> * mi/mi-main.h (mi_last_was_cli): Declare.
> * mi/mi-main.c (mi_last_was_cli): New global.
> (mi_target_can_async_p): New function.
> (exec_continue): Maybe call async_disable_stdin.
> (run_one_inferior, mi_cmd_exec_run, mi_cmd_list_target_features):
> Use mi_target_can_async_p.
> (captured_mi_execute_command): Clear mi_last_was_cli.
> (mi_execute_async_cli_command): Use mi_target_can_async_p.
> * remote.c (remote_open_1, remote_terminal_inferior)
> (remote_terminal_ours, remote_can_async_p, remote_is_async_p):
> Don't check target_async_permitted.
>
> * gdb.texinfo (Non-Stop Mode): Remove "set target-async 1"
> from example.
> (Background Execution): Move target-async docs...
> (Asynchronous and non-stop modes): ... here. Rewrite to
> MI form.
>
> * gdb.mi/mi-cli.exp: Don't check "$async".
> ---
> gdb/cli/cli-interp.c | 1 +
> gdb/doc/gdb.texinfo | 29 ++++++++++---------------
> gdb/infrun.c | 1 -
> gdb/linux-nat.c | 10 ++-------
> gdb/mi/mi-interp.c | 28 +++++++++++++++++++-----
> gdb/mi/mi-main.c | 29 +++++++++++++++++++------
> gdb/mi/mi-main.h | 1 +
> gdb/remote.c | 48 +++++++++++------------------------------
> gdb/testsuite/gdb.mi/mi-cli.exp | 15 +------------
> gdb/tui/tui-interp.c | 1 +
> 10 files changed, 76 insertions(+), 87 deletions(-)
>
> diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
> index 1003cc7..ef1e65b 100644
> --- a/gdb/cli/cli-interp.c
> +++ b/gdb/cli/cli-interp.c
> @@ -25,6 +25,7 @@
> #include "top.h" /* for "execute_command" */
> #include "gdb_string.h"
> #include "exceptions.h"
> +#include "target.h"
>
> struct ui_out *cli_uiout;
Needed?
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 0052ef2..be12a02 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -242,7 +242,6 @@ set_observer_mode (char *args, int from_tty,
> going out we leave it that way. */
> if (observer_mode)
> {
> - target_async_permitted = 1;
> pagination_enabled = 0;
> non_stop = non_stop_1 = 1;
> }
> diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
> index e9f3266..4a1ab16 100644
> --- a/gdb/linux-nat.c
> +++ b/gdb/linux-nat.c
> @@ -4764,10 +4764,7 @@ linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
> static int
> linux_nat_is_async_p (struct target_ops *ops)
> {
> - /* NOTE: palves 2008-03-21: We're only async when the user requests
> - it explicitly with the "set target-async" command.
> - Someday, linux will always be async. */
> - return target_async_permitted;
> + return 1;
> }
>
> /* target_can_async_p implementation. */
> @@ -4775,10 +4772,7 @@ linux_nat_is_async_p (struct target_ops *ops)
> static int
> linux_nat_can_async_p (struct target_ops *ops)
> {
> - /* NOTE: palves 2008-03-21: We're only async when the user requests
> - it explicitly with the "set target-async" command.
> - Someday, linux will always be async. */
> - return target_async_permitted;
> + return 1;
> }
>
> static int
> diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
> index b4515d9..886fde1 100644
> --- a/gdb/mi/mi-interp.c
> +++ b/gdb/mi/mi-interp.c
> @@ -222,11 +222,25 @@ mi_interpreter_exec (void *data, const char *command)
> return exception_none;
> }
>
> +int mi_last_was_cli;
> +
Delete? It's declared in mi-main.h.
> /* Never display the default GDB prompt in MI case. */
>
> static int
> mi_interpreter_prompt_p (void *data)
> {
> + if (!interp_quiet_p (NULL))
> + {
> + if (!target_is_async_p ()
> + || (!sync_execution && (!target_async_permitted || !mi_last_was_cli)))
> + /* && (!running_result_record_printed */
> + /* || !mi_proceeded )))) */
Add comment to indicate why the commented out code is present?
> + {
> + fputs_unfiltered ("(gdb) \n", raw_stdout);
> + gdb_flush (raw_stdout);
> + }
> + }
> +
> return 0;
> }
>
> @@ -252,6 +266,8 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
> "does not support command execution"),
> argv[0]);
>
> + mi_last_was_cli = strcmp (argv[0], "console") == 0;
> +
> /* Note that unlike the CLI version of this command, we don't
> actually set INTERP_TO_USE as the current interpreter, as we
> still want gdb_stdout, etc. to point at MI streams. */
> @@ -323,8 +339,11 @@ mi_execute_command_input_handler (char *cmd)
> {
> mi_execute_command_wrapper (cmd);
>
> - fputs_unfiltered ("(gdb) \n", raw_stdout);
> - gdb_flush (raw_stdout);
> + if (!target_is_async_p () || !sync_execution)
Please add a comment explaining the condition here.
It loosely reads as !async || async.
> + {
> + fputs_unfiltered ("(gdb) \n", raw_stdout);
> + gdb_flush (raw_stdout);
> + }
> }
>
> static void
> @@ -855,9 +874,8 @@ mi_on_resume (ptid_t ptid)
> /* This is what gdb used to do historically -- printing prompt even if
> it cannot actually accept any input. This will be surely removed
> for MI3, and may be removed even earler. */
> - /* FIXME: review the use of target_is_async_p here -- is that
> - what we want? */
> - if (!target_is_async_p ())
> + if (/* !target_async_permitted || */
> + !target_is_async_p () || sync_execution)
Why the addition of "/* !target_async_permitted || */" ?
Also a comment explaining why the sync_execution test is present
would be helpful.
> fputs_unfiltered ("(gdb) \n", raw_stdout);
> }
> gdb_flush (raw_stdout);
> diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
> index c2d8501..115308b 100644
> --- a/gdb/mi/mi-main.c
> +++ b/gdb/mi/mi-main.c
> @@ -94,6 +94,10 @@ int running_result_record_printed = 1;
> command was issued. */
> int mi_proceeded;
>
> +/* Flag indicating whether the most recent command was executed via
> + the CLI interpreter. */
> +int mi_last_was_cli;
> +
> extern void _initialize_mi_main (void);
> static void mi_cmd_execute (struct mi_parse *parse);
>
> @@ -106,6 +110,15 @@ static int register_changed_p (int regnum, struct regcache *,
> static void output_register (struct frame_info *, int regnum, int format,
> int skip_unavailable);
>
> +/* A wrapper for target_can_async_p that takes the MI setting into
> + account. */
> +
> +static int
> +mi_target_can_async_p (void)
> +{
> + return target_async_permitted && target_can_async_p ();
> +}
> +
> /* Command implementations. FIXME: Is this libgdb? No. This is the MI
> layer that calls libgdb. Any operation used in the below should be
> formalized. */
> @@ -262,6 +275,9 @@ exec_continue (char **argv, int argc)
> {
> struct cleanup *back_to = make_cleanup_restore_integer (&sched_multi);
>
> + if (!target_async_permitted && target_can_async_p ())
> + async_disable_stdin ();
> +
A comment explaining why this is here would be helpful.
I thought target_can_async_p was just a capability flag, not something
specifying the current state of anything.
> if (current_context->all)
> {
> sched_multi = 1;
> @@ -386,8 +402,8 @@ run_one_inferior (struct inferior *inf, void *arg)
> switch_to_thread (null_ptid);
> set_current_program_space (inf->pspace);
> }
> - mi_execute_cli_command ("run", target_can_async_p (),
> - target_can_async_p () ? "&" : NULL);
> + mi_execute_cli_command ("run", mi_target_can_async_p (),
> + mi_target_can_async_p () ? "&" : NULL);
> return 0;
> }
>
> @@ -403,8 +419,8 @@ mi_cmd_exec_run (char *command, char **argv, int argc)
> }
> else
> {
> - mi_execute_cli_command ("run", target_can_async_p (),
> - target_can_async_p () ? "&" : NULL);
> + mi_execute_cli_command ("run", mi_target_can_async_p (),
> + mi_target_can_async_p () ? "&" : NULL);
> }
> }
>
> @@ -1789,7 +1805,7 @@ mi_cmd_list_target_features (char *command, char **argv, int argc)
> struct ui_out *uiout = current_uiout;
>
> cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features");
> - if (target_can_async_p ())
> + if (mi_target_can_async_p ())
> ui_out_field_string (uiout, NULL, "async");
> if (target_can_execute_reverse)
> ui_out_field_string (uiout, NULL, "reverse");
> @@ -1886,6 +1902,7 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
>
> running_result_record_printed = 0;
> mi_proceeded = 0;
> + mi_last_was_cli = 0;
> switch (context->op)
> {
> case MI_COMMAND:
> @@ -2204,7 +2221,7 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
> struct cleanup *old_cleanups;
> char *run;
>
> - if (target_can_async_p ())
> + if (mi_target_can_async_p ())
> run = xstrprintf ("%s %s&", cli_command, argc ? *argv : "");
> else
> run = xstrprintf ("%s %s", cli_command, argc ? *argv : "");
> diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
> index d75526a..22f8827 100644
> --- a/gdb/mi/mi-main.h
> +++ b/gdb/mi/mi-main.h
> @@ -32,6 +32,7 @@ extern char *current_token;
>
> extern int running_result_record_printed;
> extern int mi_proceeded;
> +extern int mi_last_was_cli;
>
> struct mi_suppress_notification
> {
> diff --git a/gdb/remote.c b/gdb/remote.c
> index 0892ae4..92ba239 100644
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -4252,8 +4252,7 @@ remote_open_1 (char *name, int from_tty,
> "(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.)."));
>
> /* See FIXME above. */
> - if (!target_async_permitted)
> - wait_forever_enabled_p = 1;
> + wait_forever_enabled_p = 1;
>
> /* If we're connected to a running target, target_preopen will kill it.
> Ask this question first, before target_preopen has a chance to kill
> @@ -4339,20 +4338,17 @@ remote_open_1 (char *name, int from_tty,
> use_threadinfo_query = 1;
> use_threadextra_query = 1;
>
> - if (target_async_permitted)
> - {
> - /* With this target we start out by owning the terminal. */
> - remote_async_terminal_ours_p = 1;
> + /* With this target we start out by owning the terminal. */
> + remote_async_terminal_ours_p = 1;
>
> - /* FIXME: cagney/1999-09-23: During the initial connection it is
> - assumed that the target is already ready and able to respond to
> - requests. Unfortunately remote_start_remote() eventually calls
> - wait_for_inferior() with no timeout. wait_forever_enabled_p gets
> - around this. Eventually a mechanism that allows
> - wait_for_inferior() to expect/get timeouts will be
> - implemented. */
> - wait_forever_enabled_p = 0;
> - }
> + /* FIXME: cagney/1999-09-23: During the initial connection it is
> + assumed that the target is already ready and able to respond to
> + requests. Unfortunately remote_start_remote() eventually calls
> + wait_for_inferior() with no timeout. wait_forever_enabled_p gets
> + around this. Eventually a mechanism that allows
> + wait_for_inferior() to expect/get timeouts will be
> + implemented. */
> + wait_forever_enabled_p = 0;
>
> /* First delete any symbols previously loaded from shared libraries. */
> no_shared_libraries (NULL, 0);
> @@ -4388,14 +4384,12 @@ remote_open_1 (char *name, int from_tty,
> already before throwing the exception. */
> if (remote_desc != NULL)
> remote_unpush_target ();
> - if (target_async_permitted)
> - wait_forever_enabled_p = 1;
> + wait_forever_enabled_p = 1;
> throw_exception (ex);
> }
> }
>
> - if (target_async_permitted)
> - wait_forever_enabled_p = 1;
> + wait_forever_enabled_p = 1;
> }
>
> /* This takes a program previously attached to and detaches it. After
> @@ -5190,10 +5184,6 @@ Give up (and stop debugging it)? ")))
> static void
> remote_terminal_inferior (void)
> {
> - if (!target_async_permitted)
> - /* Nothing to do. */
> - return;
> -
> /* FIXME: cagney/1999-09-27: Make calls to target_terminal_*()
> idempotent. The event-loop GDB talking to an asynchronous target
> with a synchronous command calls this function from both
> @@ -5213,10 +5203,6 @@ remote_terminal_inferior (void)
> static void
> remote_terminal_ours (void)
> {
> - if (!target_async_permitted)
> - /* Nothing to do. */
> - return;
> -
> /* See FIXME in remote_terminal_inferior. */
> if (remote_async_terminal_ours_p)
> return;
> @@ -11625,10 +11611,6 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
> static int
> remote_can_async_p (struct target_ops *ops)
> {
> - if (!target_async_permitted)
> - /* We only enable async when the user specifically asks for it. */
> - return 0;
> -
> /* We're async whenever the serial device is. */
> return serial_can_async_p (remote_desc);
> }
> @@ -11636,10 +11618,6 @@ remote_can_async_p (struct target_ops *ops)
> static int
> remote_is_async_p (struct target_ops *ops)
> {
> - if (!target_async_permitted)
> - /* We only enable async when the user specifically asks for it. */
> - return 0;
> -
> /* We're async whenever the serial device is. */
> return serial_is_async_p (remote_desc);
> }
> diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp
> index bee296d..08e443e 100644
> --- a/gdb/testsuite/gdb.mi/mi-cli.exp
> +++ b/gdb/testsuite/gdb.mi/mi-cli.exp
> @@ -134,20 +134,7 @@ mi_gdb_test "500-stack-select-frame 0" \
> {500\^done} \
> "-stack-select-frame 0"
>
> -# When a CLI command is entered in MI session, the respose is different in
> -# sync and async modes. In sync mode normal_stop is called when current
> -# interpreter is CLI. So:
> -# - print_stop_reason prints stop reason in CLI uiout, and we don't show it
> -# in MI
> -# - The stop position is printed, and appears in MI 'console' channel.
> -#
> -# In async mode the stop event is processed when we're back to MI interpreter,
> -# so the stop reason is printed into MI uiout an.
> -if {$async} {
> - set reason "end-stepping-range"
> -} else {
> - set reason ""
> -}
> +set reason "end-stepping-range"
>
> mi_execute_to "interpreter-exec console step" $reason "callee4" "" ".*basics.c" $line_callee4_next \
> "" "check *stopped from CLI command"
> diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c
> index 42526e6..296519b 100644
> --- a/gdb/tui/tui-interp.c
> +++ b/gdb/tui/tui-interp.c
> @@ -30,6 +30,7 @@
> #include "tui/tui.h"
> #include "tui/tui-io.h"
> #include "exceptions.h"
> +#include "target.h"
Needed?
>
> /* Set to 1 when the TUI mode must be activated when we first start
> gdb. */
> --
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 9/9] enable target-async
2013-07-31 20:20 ` Doug Evans
@ 2013-07-31 20:26 ` Tom Tromey
0 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 20:26 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches
>>>>> "Doug" == Doug Evans <dje@google.com> writes:
>> +int mi_last_was_cli;
>> +
Doug> Delete? It's declared in mi-main.h.
Yeah. Sorry about this, I forgot to zap some old hacks I had been
trying out. Hence the commented-out code and other goo.
>> + if (!target_is_async_p () || !sync_execution)
Doug> Please add a comment explaining the condition here.
Doug> It loosely reads as !async || async.
Ok.
>> struct cleanup *back_to = make_cleanup_restore_integer (&sched_multi);
>>
>> + if (!target_async_permitted && target_can_async_p ())
>> + async_disable_stdin ();
>> +
Doug> A comment explaining why this is here would be helpful.
Doug> I thought target_can_async_p was just a capability flag, not something
Doug> specifying the current state of anything.
This mirrors a condition elsewhere.
I'll add a comment.
Tom
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 9/9] enable target-async
2013-07-31 18:28 ` [PATCH v2 9/9] enable target-async Tom Tromey
2013-07-31 20:20 ` Doug Evans
@ 2013-08-01 8:34 ` Yao Qi
2013-08-01 15:47 ` Tom Tromey
1 sibling, 1 reply; 16+ messages in thread
From: Yao Qi @ 2013-08-01 8:34 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 08/01/2013 02:28 AM, Tom Tromey wrote:
> +/* Flag indicating whether the most recent command was executed via
> + the CLI interpreter. */
> +int mi_last_was_cli;
> +
In patch 6/9, a new field 'command_interp' is added to 'struct
thread_control_state', as below,
> +
> + /* The interpreter that issued the execution command. NULL if the
> + thread was resumed as a result of a command applied to some other
> + thread (e.g., "next" with scheduler-locking off). */
> + struct interp *command_interp;
looks we can iterate over all threads, to check field command_interp to
know what interpreter is used by the previous command (assuming that
there should be only one thread whose command_interp is not NULL), so
that this flag 'mi_last_was_cli' can be removed?
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 9/9] enable target-async
2013-08-01 8:34 ` Yao Qi
@ 2013-08-01 15:47 ` Tom Tromey
2013-08-02 19:26 ` Tom Tromey
0 siblings, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2013-08-01 15:47 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
Yao> looks we can iterate over all threads, to check field command_interp
Yao> to know what interpreter is used by the previous command (assuming
Yao> that there should be only one thread whose command_interp is not
Yao> NULL), so that this flag 'mi_last_was_cli' can be removed?
Thanks, Yao. I will take a look.
Tom
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 9/9] enable target-async
2013-08-01 15:47 ` Tom Tromey
@ 2013-08-02 19:26 ` Tom Tromey
0 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-08-02 19:26 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
Yao> looks we can iterate over all threads, to check field command_interp
Yao> to know what interpreter is used by the previous command (assuming
Yao> that there should be only one thread whose command_interp is not
Yao> NULL), so that this flag 'mi_last_was_cli' can be removed?
Tom> Thanks, Yao. I will take a look.
This worked out nicely. Well, "nicely", in that the fundamental
hackiness still exists, but at least we didn't have to introduce another
new global. Thanks for catching this.
I'll send the new series shortly.
Tom
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 3/9] add target method delegation
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
2013-07-31 18:28 ` [PATCH v2 9/9] enable target-async Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
2013-07-31 18:28 ` [PATCH v2 8/9] fix py-finish-breakpoint.exp with always-async Tom Tromey
` (6 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This patch replaces some code in the record targets with target method
delegation.
Right now there are two latent problems in the record target.
First, record-full.c stores pointers to many target methods when the
record target is pushed. Then it later delegates some calls via
these. This is wrong because it violates the target stack contract.
In particular it is ok to unpush a target at any stratum, but
record-full does not keep track of this, so it could potentially call
into an unpushed target.
Second, RECORD_IS_USED and some other spots look at
current_target.to_stratum to determine whether a record target is in
use. This is bad because arch_stratum is greater than record_stratum.
To fix the first problem, this patch introduces a handful of
target_delegate_* functions, which forward calls further down the
target stack.
To fix the second problem, this patch adds find_target_at to determine
whether a target appears at a given stratum. This may seem like
overkill somehow, but I have a subsequent patch series (see archer.git
tromey/multi-target) that uses it more heavily.
* record-full.c (record_full_beneath_to_resume_ops)
(record_full_beneath_to_resume, record_full_beneath_to_wait_ops)
(record_full_beneath_to_wait)
(record_full_beneath_to_store_registers_ops)
(record_full_beneath_to_store_registers)
(record_full_beneath_to_xfer_partial_ops)
(record_full_beneath_to_xfer_partial)
(record_full_beneath_to_insert_breakpoint)
(record_full_beneath_to_remove_breakpoint)
(record_full_beneath_to_stopped_by_watchpoint)
(record_full_beneath_to_stopped_data_address)
(record_full_beneath_to_async, tmp_to_resume_ops, tmp_to_resume)
(tmp_to_wait_ops, tmp_to_wait, tmp_to_store_registers_ops)
(tmp_to_store_registers, tmp_to_xfer_partial_ops)
(tmp_to_xfer_partial, tmp_to_insert_breakpoint)
(tmp_to_remove_breakpoint, tmp_to_stopped_by_watchpoint)
(tmp_to_stopped_data_address, tmp_to_async): Remove.
(record_full_open_1, record_full_open): Update. Use RECORD_IS_USED.
(record_full_resume, record_full_wait_1)
(record_full_stopped_by_watchpoint, record_full_stopped_data_address)
(record_full_store_registers, record_full_xfer_partial)
(record_full_insert_breakpoint, record_full_remove_breakpoint)
(record_full_async, record_full_can_async_p, record_full_is_async_p)
(record_full_core_xfer_partial): Use target delegation.
* record.c (find_record_target): Use find_target_at.
* record.h (RECORD_IS_USED): Use find_target_at.
* target.c (update_current_target): Use target_delegate_xfer_partial.
(target_delegate_xfer_partial): Now public. Renamed from...
(current_xfer_partial): ...this. Remove.
(target_delegate_async, target_delegate_is_async_p)
(target_delegate_can_async_p, target_delegate_insert_breakpoint)
(target_delegate_remove_breakpoint, target_delegate_wait)
(target_delegate_resume, find_target_at)
(target_delegate_store_registers)
(target_delegate_stopped_by_watchpoint)
(target_delegate_stopped_data_address): New functions.
* target.h (target_delegate_async, target_delegate_is_async_p)
(target_delegate_can_async_p, target_delegate_insert_breakpoint)
(target_delegate_remove_breakpoint, target_delegate_wait)
(target_delegate_resume, find_target_at)
(target_delegate_store_registers)
(target_delegate_stopped_by_watchpoint)
(target_delegate_stopped_data_address)
(target_delegate_xfer_partial): Declare.
---
gdb/record-full.c | 209 ++++++------------------------------------------------
gdb/record.c | 8 +--
gdb/record.h | 2 +-
gdb/target.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++----
gdb/target.h | 76 ++++++++++++++++++--
5 files changed, 287 insertions(+), 214 deletions(-)
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 4904225..e8f46a6 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -215,43 +215,6 @@ static struct cmd_list_element *show_record_full_cmdlist;
/* Command list for "record full". */
static struct cmd_list_element *record_full_cmdlist;
-/* The beneath function pointers. */
-static struct target_ops *record_full_beneath_to_resume_ops;
-static void (*record_full_beneath_to_resume) (struct target_ops *, ptid_t, int,
- enum gdb_signal);
-static struct target_ops *record_full_beneath_to_wait_ops;
-static ptid_t (*record_full_beneath_to_wait) (struct target_ops *, ptid_t,
- struct target_waitstatus *,
- int);
-static struct target_ops *record_full_beneath_to_store_registers_ops;
-static void (*record_full_beneath_to_store_registers) (struct target_ops *,
- struct regcache *,
- int regno);
-static struct target_ops *record_full_beneath_to_xfer_partial_ops;
-static LONGEST
- (*record_full_beneath_to_xfer_partial) (struct target_ops *ops,
- enum target_object object,
- const char *annex,
- gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset,
- LONGEST len);
-static int
- (*record_full_beneath_to_insert_breakpoint) (struct target_ops *,
- struct gdbarch *,
- struct bp_target_info *);
-static int
- (*record_full_beneath_to_remove_breakpoint) (struct target_ops *,
- struct gdbarch *,
- struct bp_target_info *);
-static int (*record_full_beneath_to_stopped_by_watchpoint) (struct target_ops *);
-static int (*record_full_beneath_to_stopped_data_address) (struct target_ops *,
- CORE_ADDR *);
-static void
- (*record_full_beneath_to_async) (struct target_ops *,
- void (*) (enum inferior_event_type, void *),
- void *);
-
static void record_full_goto_insn (struct record_full_entry *entry,
enum exec_direction_kind dir);
static void record_full_save (const char *recfilename);
@@ -798,36 +761,6 @@ record_full_exec_insn (struct regcache *regcache,
}
}
-static struct target_ops *tmp_to_resume_ops;
-static void (*tmp_to_resume) (struct target_ops *, ptid_t, int,
- enum gdb_signal);
-static struct target_ops *tmp_to_wait_ops;
-static ptid_t (*tmp_to_wait) (struct target_ops *, ptid_t,
- struct target_waitstatus *,
- int);
-static struct target_ops *tmp_to_store_registers_ops;
-static void (*tmp_to_store_registers) (struct target_ops *,
- struct regcache *,
- int regno);
-static struct target_ops *tmp_to_xfer_partial_ops;
-static LONGEST (*tmp_to_xfer_partial) (struct target_ops *ops,
- enum target_object object,
- const char *annex,
- gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset,
- LONGEST len);
-static int (*tmp_to_insert_breakpoint) (struct target_ops *,
- struct gdbarch *,
- struct bp_target_info *);
-static int (*tmp_to_remove_breakpoint) (struct target_ops *ops,
- struct gdbarch *,
- struct bp_target_info *);
-static int (*tmp_to_stopped_by_watchpoint) (struct target_ops *);
-static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
-static void (*tmp_to_async) (struct target_ops *,
- void (*) (enum inferior_event_type, void *), void *);
-
static void record_full_restore (void);
/* Asynchronous signal handle registered as event loop source for when
@@ -890,26 +823,6 @@ record_full_open_1 (char *name, int from_tty)
error (_("Process record: the current architecture doesn't support "
"record function."));
- if (!tmp_to_resume)
- error (_("Could not find 'to_resume' method on the target stack."));
- if (!tmp_to_wait)
- error (_("Could not find 'to_wait' method on the target stack."));
- if (!tmp_to_store_registers)
- error (_("Could not find 'to_store_registers' "
- "method on the target stack."));
- if (!tmp_to_insert_breakpoint)
- error (_("Could not find 'to_insert_breakpoint' "
- "method on the target stack."));
- if (!tmp_to_remove_breakpoint)
- error (_("Could not find 'to_remove_breakpoint' "
- "method on the target stack."));
- if (!tmp_to_stopped_by_watchpoint)
- error (_("Could not find 'to_stopped_by_watchpoint' "
- "method on the target stack."));
- if (!tmp_to_stopped_data_address)
- error (_("Could not find 'to_stopped_data_address' "
- "method on the target stack."));
-
push_target (&record_full_ops);
}
@@ -926,83 +839,16 @@ record_full_open (char *name, int from_tty)
fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open\n");
/* Check if record target is already running. */
- if (current_target.to_stratum == record_stratum)
+ if (RECORD_IS_USED)
error (_("Process record target already running. Use \"record stop\" to "
"stop record target first."));
- /* Reset the tmp beneath pointers. */
- tmp_to_resume_ops = NULL;
- tmp_to_resume = NULL;
- tmp_to_wait_ops = NULL;
- tmp_to_wait = NULL;
- tmp_to_store_registers_ops = NULL;
- tmp_to_store_registers = NULL;
- tmp_to_xfer_partial_ops = NULL;
- tmp_to_xfer_partial = NULL;
- tmp_to_insert_breakpoint = NULL;
- tmp_to_remove_breakpoint = NULL;
- tmp_to_stopped_by_watchpoint = NULL;
- tmp_to_stopped_data_address = NULL;
- tmp_to_async = NULL;
-
- /* Set the beneath function pointers. */
- for (t = current_target.beneath; t != NULL; t = t->beneath)
- {
- if (!tmp_to_resume)
- {
- tmp_to_resume = t->to_resume;
- tmp_to_resume_ops = t;
- }
- if (!tmp_to_wait)
- {
- tmp_to_wait = t->to_wait;
- tmp_to_wait_ops = t;
- }
- if (!tmp_to_store_registers)
- {
- tmp_to_store_registers = t->to_store_registers;
- tmp_to_store_registers_ops = t;
- }
- if (!tmp_to_xfer_partial)
- {
- tmp_to_xfer_partial = t->to_xfer_partial;
- tmp_to_xfer_partial_ops = t;
- }
- if (!tmp_to_insert_breakpoint)
- tmp_to_insert_breakpoint = t->to_insert_breakpoint;
- if (!tmp_to_remove_breakpoint)
- tmp_to_remove_breakpoint = t->to_remove_breakpoint;
- if (!tmp_to_stopped_by_watchpoint)
- tmp_to_stopped_by_watchpoint = t->to_stopped_by_watchpoint;
- if (!tmp_to_stopped_data_address)
- tmp_to_stopped_data_address = t->to_stopped_data_address;
- if (!tmp_to_async)
- tmp_to_async = t->to_async;
- }
- if (!tmp_to_xfer_partial)
- error (_("Could not find 'to_xfer_partial' method on the target stack."));
-
/* Reset */
record_full_insn_num = 0;
record_full_insn_count = 0;
record_full_list = &record_full_first;
record_full_list->next = NULL;
- /* Set the tmp beneath pointers to beneath pointers. */
- record_full_beneath_to_resume_ops = tmp_to_resume_ops;
- record_full_beneath_to_resume = tmp_to_resume;
- record_full_beneath_to_wait_ops = tmp_to_wait_ops;
- record_full_beneath_to_wait = tmp_to_wait;
- record_full_beneath_to_store_registers_ops = tmp_to_store_registers_ops;
- record_full_beneath_to_store_registers = tmp_to_store_registers;
- record_full_beneath_to_xfer_partial_ops = tmp_to_xfer_partial_ops;
- record_full_beneath_to_xfer_partial = tmp_to_xfer_partial;
- record_full_beneath_to_insert_breakpoint = tmp_to_insert_breakpoint;
- record_full_beneath_to_remove_breakpoint = tmp_to_remove_breakpoint;
- record_full_beneath_to_stopped_by_watchpoint = tmp_to_stopped_by_watchpoint;
- record_full_beneath_to_stopped_data_address = tmp_to_stopped_data_address;
- record_full_beneath_to_async = tmp_to_async;
-
if (core_bfd)
record_full_core_open_1 (name, from_tty);
else
@@ -1126,8 +972,7 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
/* Make sure the target beneath reports all signals. */
target_pass_signals (0, NULL);
- record_full_beneath_to_resume (record_full_beneath_to_resume_ops,
- ptid, step, signal);
+ target_delegate_resume (ops, ptid, step, signal);
}
/* We are about to start executing the inferior (or simulate it),
@@ -1217,8 +1062,7 @@ record_full_wait_1 (struct target_ops *ops,
if (record_full_resume_step)
{
/* This is a single step. */
- return record_full_beneath_to_wait (record_full_beneath_to_wait_ops,
- ptid, status, options);
+ return target_delegate_wait (ops, ptid, status, options);
}
else
{
@@ -1229,8 +1073,7 @@ record_full_wait_1 (struct target_ops *ops,
while (1)
{
- ret = record_full_beneath_to_wait
- (record_full_beneath_to_wait_ops, ptid, status, options);
+ ret = target_delegate_wait (ops, ptid, status, options);
if (status->kind == TARGET_WAITKIND_IGNORE)
{
if (record_debug)
@@ -1314,9 +1157,7 @@ record_full_wait_1 (struct target_ops *ops,
"Process record: record_full_wait "
"issuing one more step in the "
"target beneath\n");
- record_full_beneath_to_resume
- (record_full_beneath_to_resume_ops, ptid, step,
- GDB_SIGNAL_0);
+ target_delegate_resume (ops, ptid, step, GDB_SIGNAL_0);
continue;
}
}
@@ -1520,7 +1361,7 @@ record_full_stopped_by_watchpoint (struct target_ops *ops)
if (RECORD_FULL_IS_REPLAY)
return record_full_hw_watchpoint;
else
- return record_full_beneath_to_stopped_by_watchpoint (find_target_beneath (ops));
+ return target_delegate_stopped_by_watchpoint (ops);
}
static int
@@ -1529,7 +1370,7 @@ record_full_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
if (RECORD_FULL_IS_REPLAY)
return 0;
else
- return record_full_beneath_to_stopped_data_address (ops, addr_p);
+ return target_delegate_stopped_data_address (ops, addr_p);
}
/* Record registers change (by user or by GDB) to list as an instruction. */
@@ -1632,8 +1473,7 @@ record_full_store_registers (struct target_ops *ops,
record_full_registers_change (regcache, regno);
}
- record_full_beneath_to_store_registers
- (record_full_beneath_to_store_registers_ops, regcache, regno);
+ target_delegate_store_registers (ops, regcache, regno);
}
/* "to_xfer_partial" method. Behavior is conditional on
@@ -1698,9 +1538,8 @@ record_full_xfer_partial (struct target_ops *ops, enum target_object object,
record_full_insn_num++;
}
- return record_full_beneath_to_xfer_partial
- (record_full_beneath_to_xfer_partial_ops, object, annex,
- readbuf, writebuf, offset, len);
+ return target_delegate_xfer_partial (ops, object, annex,
+ readbuf, writebuf, offset, len);
}
/* This structure represents a breakpoint inserted while the record
@@ -1781,8 +1620,7 @@ record_full_insert_breakpoint (struct target_ops *ops,
int ret;
old_cleanups = record_full_gdb_operation_disable_set ();
- ret = record_full_beneath_to_insert_breakpoint (find_target_beneath (ops),
- gdbarch, bp_tgt);
+ ret = target_delegate_insert_breakpoint (ops, gdbarch, bp_tgt);
do_cleanups (old_cleanups);
if (ret != 0)
@@ -1823,8 +1661,7 @@ record_full_remove_breakpoint (struct target_ops *ops,
int ret;
old_cleanups = record_full_gdb_operation_disable_set ();
- ret = record_full_beneath_to_remove_breakpoint (find_target_beneath (ops),
- gdbarch, bp_tgt);
+ ret = target_delegate_remove_breakpoint (ops, gdbarch, bp_tgt);
do_cleanups (old_cleanups);
if (ret != 0)
@@ -1906,22 +1743,19 @@ record_full_async (struct target_ops *ops,
/* If we're on top of a line target (e.g., linux-nat, remote), then
set it to async mode as well. Will be NULL if we're sitting on
top of the core target, for "record restore". */
- if (record_full_beneath_to_async != NULL)
- record_full_beneath_to_async (find_target_beneath (ops), callback, context);
+ target_delegate_async (ops, callback, context);
}
static int
record_full_can_async_p (struct target_ops *ops)
{
- /* We only enable async when the user specifically asks for it. */
- return target_async_permitted;
+ return target_delegate_can_async_p (ops);
}
static int
record_full_is_async_p (struct target_ops *ops)
{
- /* We only enable async when the user specifically asks for it. */
- return target_async_permitted;
+ return target_delegate_is_async_p (ops);
}
static enum exec_direction_kind
@@ -2247,10 +2081,10 @@ record_full_core_xfer_partial (struct target_ops *ops,
else
{
if (!entry)
- return record_full_beneath_to_xfer_partial
- (record_full_beneath_to_xfer_partial_ops,
- object, annex, readbuf, writebuf,
- offset, len);
+ return target_delegate_xfer_partial (ops,
+ object, annex,
+ readbuf, writebuf,
+ offset, len);
memcpy (readbuf, entry->buf + sec_offset,
(size_t) len);
@@ -2266,9 +2100,8 @@ record_full_core_xfer_partial (struct target_ops *ops,
error (_("You can't do that without a process to debug."));
}
- return record_full_beneath_to_xfer_partial
- (record_full_beneath_to_xfer_partial_ops, object, annex,
- readbuf, writebuf, offset, len);
+ return target_delegate_xfer_partial (ops, object, annex,
+ readbuf, writebuf, offset, len);
}
/* "to_insert_breakpoint" method for prec over corefile. */
diff --git a/gdb/record.c b/gdb/record.c
index cbbe365..8a199f9 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -62,13 +62,7 @@ struct cmd_list_element *info_record_cmdlist = NULL;
static struct target_ops *
find_record_target (void)
{
- struct target_ops *t;
-
- for (t = current_target.beneath; t != NULL; t = t->beneath)
- if (t->to_stratum == record_stratum)
- return t;
-
- return NULL;
+ return find_target_at (record_stratum);
}
/* Check that recording is active. Throw an error, if it isn't. */
diff --git a/gdb/record.h b/gdb/record.h
index 86e6bc6..00fbd3f 100644
--- a/gdb/record.h
+++ b/gdb/record.h
@@ -22,7 +22,7 @@
struct cmd_list_element;
-#define RECORD_IS_USED (current_target.to_stratum == record_stratum)
+#define RECORD_IS_USED (find_target_at (record_stratum) != NULL)
extern unsigned int record_debug;
diff --git a/gdb/target.c b/gdb/target.c
index b6b54cf..097e15f 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -75,12 +75,6 @@ static LONGEST default_xfer_partial (struct target_ops *ops,
const gdb_byte *writebuf,
ULONGEST offset, LONGEST len);
-static LONGEST current_xfer_partial (struct target_ops *ops,
- enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len);
-
static LONGEST target_xfer_partial (struct target_ops *ops,
enum target_object object,
const char *annex,
@@ -858,7 +852,7 @@ update_current_target (void)
de_fault (to_stop,
(void (*) (ptid_t))
target_ignore);
- current_target.to_xfer_partial = current_xfer_partial;
+ current_target.to_xfer_partial = target_delegate_xfer_partial;
de_fault (to_rcmd,
(void (*) (char *, struct ui_file *))
tcomplain);
@@ -1986,14 +1980,14 @@ default_xfer_partial (struct target_ops *ops, enum target_object object,
return -1;
}
-/* The xfer_partial handler for the topmost target. Unlike the default,
- it does not need to handle memory specially; it just passes all
- requests down the stack. */
+/* See target.h. */
-static LONGEST
-current_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+LONGEST
+target_delegate_xfer_partial (struct target_ops *ops,
+ enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len)
{
if (ops->beneath != NULL)
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
@@ -2002,6 +1996,53 @@ current_xfer_partial (struct target_ops *ops, enum target_object object,
return -1;
}
+/* See target.h. */
+
+void
+target_delegate_async (struct target_ops *self,
+ void (*callback) (enum inferior_event_type, void *),
+ void *datum)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_async)
+ {
+ t->to_async (t, callback, datum);
+ break;
+ }
+ }
+}
+
+/* See target.h. */
+
+int
+target_delegate_is_async_p (struct target_ops *self)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ if (t->to_is_async_p != NULL)
+ return t->to_is_async_p (t);
+
+ gdb_assert_not_reached (_("reached end of target stack during delegation"));
+}
+
+/* See target.h. */
+
+int
+target_delegate_can_async_p (struct target_ops *self)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ if (t->to_can_async_p != NULL)
+ return t->to_can_async_p (t);
+
+ gdb_assert_not_reached (_("reached end of target stack during delegation"));
+}
+
/* Target vector read/write partial wrapper functions. */
static LONGEST
@@ -2453,6 +2494,24 @@ target_insert_breakpoint (struct gdbarch *gdbarch,
gdbarch, bp_tgt);
}
+/* See target.h. */
+
+int
+target_delegate_insert_breakpoint (struct target_ops *self,
+ struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_insert_breakpoint)
+ return t->to_insert_breakpoint (t, gdbarch, bp_tgt);
+ }
+
+ gdb_assert_not_reached (_("reached end of target stack during delegation"));
+}
+
int
target_remove_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
@@ -2471,6 +2530,24 @@ target_remove_breakpoint (struct gdbarch *gdbarch,
gdbarch, bp_tgt);
}
+/* See target.h. */
+
+int
+target_delegate_remove_breakpoint (struct target_ops *self,
+ struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_remove_breakpoint)
+ return t->to_remove_breakpoint (t, gdbarch, bp_tgt);
+ }
+
+ gdb_assert_not_reached (_("reached end of target stack during delegation"));
+}
+
static void
target_info (char *args, int from_tty)
{
@@ -2677,6 +2754,24 @@ target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
noprocess ();
}
+/* See target.h. */
+
+ptid_t
+target_delegate_wait (struct target_ops *self,
+ ptid_t ptid, struct target_waitstatus *status,
+ int options)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_wait)
+ return t->to_wait (t, ptid, status, options);
+ }
+
+ gdb_assert_not_reached (_("reached end of target stack during delegation"));
+}
+
char *
target_pid_to_str (ptid_t ptid)
{
@@ -2734,6 +2829,24 @@ target_resume (ptid_t ptid, int step, enum gdb_signal signal)
noprocess ();
}
+/* See target.h. */
+
+void
+target_delegate_resume (struct target_ops *self,
+ ptid_t ptid, int step, enum gdb_signal signal)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_resume)
+ {
+ t->to_resume (t, ptid, step, signal);
+ break;
+ }
+ }
+}
+
void
target_pass_signals (int numsigs, unsigned char *pass_signals)
{
@@ -3629,6 +3742,20 @@ find_target_beneath (struct target_ops *t)
return t->beneath;
}
+/* See target.h. */
+
+struct target_ops *
+find_target_at (enum strata stratum)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_stratum == stratum)
+ return t;
+
+ return NULL;
+}
+
\f
/* The inferior process has died. Long live the inferior! */
@@ -3982,6 +4109,24 @@ target_store_registers (struct regcache *regcache, int regno)
noprocess ();
}
+/* See target.h. */
+
+void
+target_delegate_store_registers (struct target_ops *self,
+ struct regcache *regcache, int regno)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_store_registers)
+ {
+ t->to_store_registers (t, regcache, regno);
+ break;
+ }
+ }
+}
+
int
target_core_of_thread (ptid_t ptid)
{
@@ -4115,6 +4260,39 @@ target_ranged_break_num_registers (void)
/* See target.h. */
int
+target_delegate_stopped_by_watchpoint (struct target_ops *self)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_stopped_by_watchpoint)
+ return t->to_stopped_by_watchpoint (t);
+ }
+
+ gdb_assert_not_reached (_("reached end of target stack during delegation"));
+}
+
+/* See target.h. */
+
+int
+target_delegate_stopped_data_address (struct target_ops *self,
+ CORE_ADDR *addr_p)
+{
+ struct target_ops *t;
+
+ for (t = self->beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_stopped_data_address)
+ return t->to_stopped_data_address (t, addr_p);
+ }
+
+ gdb_assert_not_reached (_("reached end of target stack during delegation"));
+}
+
+/* See target.h. */
+
+int
target_supports_btrace (void)
{
struct target_ops *t;
diff --git a/gdb/target.h b/gdb/target.h
index b03d33d..dae31f2 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -940,6 +940,12 @@ extern void target_disconnect (char *, int);
extern void target_resume (ptid_t ptid, int step, enum gdb_signal signal);
+/* Delegate "target_resume" to a target beneath SELF. */
+
+extern void target_delegate_resume (struct target_ops *self,
+ ptid_t ptid, int step,
+ enum gdb_signal signal);
+
/* Wait for process pid to do something. PTID = -1 to wait for any
pid to do something. Return pid of child, or -1 in case of error;
store status through argument pointer STATUS. Note that it is
@@ -952,6 +958,13 @@ extern void target_resume (ptid_t ptid, int step, enum gdb_signal signal);
extern ptid_t target_wait (ptid_t ptid, struct target_waitstatus *status,
int options);
+/* Delegate "target_wait" to a target beneath SELF. */
+
+extern ptid_t target_delegate_wait (struct target_ops *self,
+ ptid_t ptid,
+ struct target_waitstatus *status,
+ int options);
+
/* Fetch at least register REGNO, or all regs if regno == -1. No result. */
extern void target_fetch_registers (struct regcache *regcache, int regno);
@@ -962,6 +975,12 @@ extern void target_fetch_registers (struct regcache *regcache, int regno);
extern void target_store_registers (struct regcache *regcache, int regs);
+/* Delegate "target_store_registers" to a target beneath SELF. */
+
+extern void target_delegate_store_registers (struct target_ops *self,
+ struct regcache *regcache,
+ int regno);
+
/* Get ready to modify the registers array. On machines which store
individual registers, this doesn't need to do anything. On machines
which store all the registers in one fell swoop, this makes sure
@@ -1094,12 +1113,24 @@ int target_write_memory_blocks (VEC(memory_write_request_s) *requests,
extern int target_insert_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt);
+/* Delegate "target_insert_breakpoint" to a target beneath SELF. */
+
+extern int target_delegate_insert_breakpoint (struct target_ops *self,
+ struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt);
+
/* Remove a breakpoint at address BP_TGT->placed_address in the target
machine. Result is 0 for success, or an errno value. */
extern int target_remove_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt);
+/* Delegate "target_remove_breakpoint" to a target beneath SELF. */
+
+extern int target_delegate_remove_breakpoint (struct target_ops *self,
+ struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt);
+
/* Initialize the terminal settings we record for the inferior,
before we actually run the inferior. */
@@ -1376,16 +1407,30 @@ extern int default_child_has_execution (struct target_ops *ops,
extern int target_async_permitted;
/* Can the target support asynchronous execution? */
-#define target_can_async_p() (current_target.to_can_async_p (¤t_target))
+#define target_can_async_p() (target_delegate_can_async_p (¤t_target))
+
+/* Delegate "target_can_async_p" to a target beneath SELF. */
+
+extern int target_delegate_can_async_p (struct target_ops *self);
/* Is the target in asynchronous execution mode? */
-#define target_is_async_p() (current_target.to_is_async_p (¤t_target))
+#define target_is_async_p() (target_delegate_is_async_p (¤t_target))
+
+/* Delegate "target_is_async_p" to a target beneath SELF. */
+
+extern int target_delegate_is_async_p (struct target_ops *self);
int target_supports_non_stop (void);
/* Put the target in async mode with the specified callback function. */
#define target_async(CALLBACK,CONTEXT) \
- (current_target.to_async (¤t_target, (CALLBACK), (CONTEXT)))
+ (target_delegate_async (¤t_target, (CALLBACK), (CONTEXT)))
+
+/* Delegate "target_async" to a target beneath SELF. */
+
+extern void target_delegate_async (struct target_ops *,
+ void (*) (enum inferior_event_type, void *),
+ void *);
#define target_execution_direction() \
(current_target.to_execution_direction ())
@@ -1460,7 +1505,11 @@ extern char *target_thread_name (struct thread_info *);
write). Only the INFERIOR_PTID task is being queried. */
#define target_stopped_by_watchpoint() \
- ((*current_target.to_stopped_by_watchpoint) (¤t_target))
+ (target_delegate_stopped_by_watchpoint (¤t_target))
+
+/* Delegate "target_stopped_by_watchpoint" to a target beneath SELF. */
+
+extern int target_delegate_stopped_by_watchpoint (struct target_ops *self);
/* Non-zero if we have steppable watchpoints */
@@ -1535,6 +1584,11 @@ extern int target_ranged_break_num_registers (void);
#define target_stopped_data_address(target, addr_p) \
(*target.to_stopped_data_address) (target, addr_p)
+/* Delegate "target_stopped_data_address" to a target beneath SELF. */
+
+extern int target_delegate_stopped_data_address (struct target_ops *self,
+ CORE_ADDR *addr_p);
+
/* Return non-zero if ADDR is within the range of a watchpoint spanning
LENGTH bytes beginning at START. */
#define target_watchpoint_addr_within_range(target, addr, start, length) \
@@ -1865,6 +1919,11 @@ extern void find_default_create_inferior (struct target_ops *,
extern struct target_ops *find_target_beneath (struct target_ops *);
+/* Find the target at STRATUM. If no target is at that stratum,
+ return NULL. */
+
+struct target_ops *find_target_at (enum strata stratum);
+
/* Read OS data object of type TYPE from the target, and return it in
XML format. The result is NUL-terminated and returned as a string,
allocated using xmalloc. If an error occurs or the transfer is
@@ -1967,4 +2026,13 @@ extern void target_call_history_from (ULONGEST begin, int size, int flags);
/* See to_call_history_range. */
extern void target_call_history_range (ULONGEST begin, ULONGEST end, int flags);
+/* Delegate "target_xfer_partial" to a target beneath SELF. */
+
+extern LONGEST target_delegate_xfer_partial (struct target_ops *ops,
+ enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len);
+
#endif /* !defined (TARGET_H) */
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v2 8/9] fix py-finish-breakpoint.exp with always-async
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
2013-07-31 18:28 ` [PATCH v2 9/9] enable target-async Tom Tromey
2013-07-31 18:28 ` [PATCH v2 3/9] add target method delegation Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
2013-07-31 19:41 ` Doug Evans
2013-07-31 18:28 ` [PATCH v2 2/9] add "this" pointers to more target APIs Tom Tromey
` (5 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
With target async enabled, py-finish-breakpoint.exp will trigger an
assertion failure.
The failure occurs because execute_command re-enters the event loop in
some circumstances, and in this case resets the sync_execution flag.
Then later gdb reaches this assertion in normal_stop:
gdb_assert (sync_execution || !target_can_async_p ());
execute_command has a comment explaining why it dispatches events:
/* If the interpreter is in sync mode (we're running a user
command's list, running command hooks or similars), and we
just ran a synchronous command that started the target, wait
for that command to end. */
However, the code did not follow this comment -- it didn't check to
see if the command started the target, just whether the target was
executing a sync command at this point.
This patch fixes the problem by noting whether the target was
executing in sync_execution mode before running the command, and then
augmenting the condition to test this as well.
Built and regtested on x86-64 Fedora 18.
PR gdb/14135:
* top.c (execute_command): Only dispatch events if command
started target.
---
gdb/top.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/gdb/top.c b/gdb/top.c
index 33a78da..03038b6 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -427,6 +427,8 @@ execute_command (char *p, int from_tty)
{
const char *cmd = p;
char *arg;
+ int was_sync = sync_execution;
+
line = p;
/* If trace-commands is set then this will print this command. */
@@ -482,7 +484,7 @@ execute_command (char *p, int from_tty)
command's list, running command hooks or similars), and we
just ran a synchronous command that started the target, wait
for that command to end. */
- if (!interpreter_async && sync_execution)
+ if (!interpreter_async && !was_sync && sync_execution)
{
while (gdb_do_one_event () >= 0)
if (!sync_execution)
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 8/9] fix py-finish-breakpoint.exp with always-async
2013-07-31 18:28 ` [PATCH v2 8/9] fix py-finish-breakpoint.exp with always-async Tom Tromey
@ 2013-07-31 19:41 ` Doug Evans
0 siblings, 0 replies; 16+ messages in thread
From: Doug Evans @ 2013-07-31 19:41 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Tom Tromey writes:
> With target async enabled, py-finish-breakpoint.exp will trigger an
> assertion failure.
>
> The failure occurs because execute_command re-enters the event loop in
> some circumstances, and in this case resets the sync_execution flag.
> Then later gdb reaches this assertion in normal_stop:
>
> gdb_assert (sync_execution || !target_can_async_p ());
>
> execute_command has a comment explaining why it dispatches events:
>
> /* If the interpreter is in sync mode (we're running a user
> command's list, running command hooks or similars), and we
> just ran a synchronous command that started the target, wait
> for that command to end. */
>
> However, the code did not follow this comment -- it didn't check to
> see if the command started the target, just whether the target was
> executing a sync command at this point.
>
> This patch fixes the problem by noting whether the target was
> executing in sync_execution mode before running the command, and then
> augmenting the condition to test this as well.
>
> Built and regtested on x86-64 Fedora 18.
>
> PR gdb/14135:
> * top.c (execute_command): Only dispatch events if command
> started target.
> ---
> gdb/top.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/top.c b/gdb/top.c
> index 33a78da..03038b6 100644
> --- a/gdb/top.c
> +++ b/gdb/top.c
> @@ -427,6 +427,8 @@ execute_command (char *p, int from_tty)
> {
> const char *cmd = p;
> char *arg;
> + int was_sync = sync_execution;
> +
> line = p;
>
> /* If trace-commands is set then this will print this command. */
> @@ -482,7 +484,7 @@ execute_command (char *p, int from_tty)
> command's list, running command hooks or similars), and we
> just ran a synchronous command that started the target, wait
> for that command to end. */
> - if (!interpreter_async && sync_execution)
> + if (!interpreter_async && !was_sync && sync_execution)
> {
> while (gdb_do_one_event () >= 0)
> if (!sync_execution)
> --
Looks ok to me.
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 2/9] add "this" pointers to more target APIs
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
` (2 preceding siblings ...)
2013-07-31 18:28 ` [PATCH v2 8/9] fix py-finish-breakpoint.exp with always-async Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
2013-07-31 18:28 ` [PATCH v2 7/9] make dprintf.exp pass in always-async mode Tom Tromey
` (4 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
A subsequent pass introduces delegation helper functions to the target
API. This delegation is much cleaner if the target_ops pointer is
directly available at delegation time.
This patch adds the "this" pointer to various to_* methods for this
purpose.
This updates a number of ports which I am unable to test. Please give
them a look-over. Any possible problem here is trivial, though, as
all that is required is adding an argument to a function.
* aarch64-linux-nat.c (aarch64_linux_stopped_by_watchpoint):
Add 'ops' argument.
* arm-linux-nat.c (arm_linux_stopped_by_watchpoint): Add
'ops' argument.
* corelow.c (ignore): Add 'ops' argument.
* exec.c (ignore): Add 'ops' argument.
* i386-nat.c (i386_stopped_by_watchpoint): Add 'ops' argument.
* ia64-linux-nat.c (ia64_linux_stopped_by_watchpoint): Add
'ops' argument.
* inf-ttrace.c (inf_ttrace_stopped_by_watchpoint): Add 'ops'
argument.
* linux-nat.c (save_sigtrap): Update.
(linux_nat_stopped_by_watchpoint, linux_nat_is_async_p)
(linux_nat_can_async_p, linux_nat_async): Add 'ops' argument.
(linux_nat_close): Update.
* mem-break.c (memory_insert_breakpoint, memory_remove_breakpoint):
Add 'ops' argument.
* mips-linux-nat.c (mips_linux_stopped_by_watchpoint): Add 'ops'
argument.
* monitor.c (monitor_insert_breakpoint, monitor_remove_breakpoint):
Add 'ops' argument.
* nto-procfs.c (procfs_insert_breakpoint, procfs_remove_breakpoint)
(procfs_stopped_by_watchpoint): Add 'ops' argument.
* ppc-linux-nat.c (ppc_linux_stopped_by_watchpoint): Add 'ops'
argument.
* procfs.c (procfs_stopped_by_watchpoint): Add 'ops' argument.
* record-full.c (record_full_beneath_to_insert_breakpoint)
(record_full_beneath_to_remove_breakpoint)
(record_full_beneath_to_stopped_by_watchpoint)
(record_full_beneath_to_async, tmp_to_insert_breakpoint)
(tmp_to_remove_breakpoint, tmp_to_stopped_by_watchpoint)
(tmp_to_async): Add 'ops' argument.
(record_full_stopped_by_watchpoint, record_full_insert_breakpoint)
(record_full_remove_breakpoint, record_full_async)
(record_full_can_async_p, record_full_is_async_p)
(record_full_core_insert_breakpoint)
(record_full_core_remove_breakpoint): Add 'ops' argument.
* remote-m32r-sdi.c (m32r_insert_breakpoint, m32r_remove_breakpoint)
(m32r_stopped_by_watchpoint): Add 'ops' argument.
* remote-mips.c (mips_insert_breakpoint, mips_remove_breakpoint)
(mips_stopped_by_watchpoint): Add 'ops' argument.
* remote.c (remote_insert_breakpoint, remote_remove_breakpoint)
(remote_stopped_by_watchpoint_p, remote_can_async_p)
(remote_is_async_p, remote_async): Add 'ops' argument.
* s390-nat.c (s390_stopped_by_watchpoint): Add 'ops' argument.
* target.c (update_current_target)
(target_insert_breakpoint, target_remove_breakpoint)
(find_default_can_async_p, find_default_is_async_p): Update.
(init_dummy_target): Update.
(debug_to_insert_breakpoint, debug_to_remove_breakpoint)
(debug_to_stopped_by_watchpoint): Add 'ops' argument.
* target.h (struct target_ops) <to_insert_breakpoint,
to_remove_breakpoint, to_stopped_by_watchpoint, to_can_async_p,
to_is_async_p, to_async>: Add 'ops' argument.
(target_can_async_p, target_is_async_p, target_async)
(target_stopped_by_watchpoint): Update.
(memory_remove_breakpoint, memory_insert_breakpoint): Add 'ops'
argument.
---
gdb/aarch64-linux-nat.c | 4 ++--
gdb/arm-linux-nat.c | 4 ++--
gdb/corelow.c | 3 ++-
gdb/exec.c | 3 ++-
gdb/i386-nat.c | 4 ++--
gdb/ia64-linux-nat.c | 4 ++--
gdb/inf-ttrace.c | 2 +-
gdb/linux-nat.c | 22 +++++++++-----------
gdb/mem-break.c | 6 ++++--
gdb/mips-linux-nat.c | 2 +-
gdb/monitor.c | 6 ++++--
gdb/nto-procfs.c | 10 +++++----
gdb/ppc-linux-nat.c | 4 ++--
gdb/procfs.c | 2 +-
gdb/record-full.c | 54 ++++++++++++++++++++++++++++++-------------------
gdb/remote-m32r-sdi.c | 8 +++++---
gdb/remote-mips.c | 12 ++++++-----
gdb/remote.c | 34 ++++++++++++++++++-------------
gdb/s390-nat.c | 2 +-
gdb/target.c | 45 ++++++++++++++++++++---------------------
gdb/target.h | 31 ++++++++++++++++------------
21 files changed, 147 insertions(+), 115 deletions(-)
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 846f156..a53a9b1 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -1472,11 +1472,11 @@ aarch64_linux_stopped_data_address (struct target_ops *target,
/* Implement the "to_stopped_by_watchpoint" target_ops method. */
static int
-aarch64_linux_stopped_by_watchpoint (void)
+aarch64_linux_stopped_by_watchpoint (struct target_ops *ops)
{
CORE_ADDR addr;
- return aarch64_linux_stopped_data_address (¤t_target, &addr);
+ return aarch64_linux_stopped_data_address (ops, &addr);
}
/* Implement the "to_watchpoint_addr_within_range" target_ops method. */
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
index 09359cd..1351a32 100644
--- a/gdb/arm-linux-nat.c
+++ b/gdb/arm-linux-nat.c
@@ -1171,10 +1171,10 @@ arm_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
/* Has the target been stopped by hitting a watchpoint? */
static int
-arm_linux_stopped_by_watchpoint (void)
+arm_linux_stopped_by_watchpoint (struct target_ops *ops)
{
CORE_ADDR addr;
- return arm_linux_stopped_data_address (¤t_target, &addr);
+ return arm_linux_stopped_data_address (ops, &addr);
}
static int
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 8371b58..9398bc1 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -836,7 +836,8 @@ core_xfer_partial (struct target_ops *ops, enum target_object object,
breakpoint_init_inferior). */
static int
-ignore (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
+ignore (struct target_ops *ops, struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
{
return 0;
}
diff --git a/gdb/exec.c b/gdb/exec.c
index 14ff6d7..892603a 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -745,7 +745,8 @@ exec_set_section_address (const char *filename, int index, CORE_ADDR address)
breakpoint_init_inferior). */
static int
-ignore (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
+ignore (struct target_ops *ops, struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
{
return 0;
}
diff --git a/gdb/i386-nat.c b/gdb/i386-nat.c
index 0a5deb0..8d54ae0 100644
--- a/gdb/i386-nat.c
+++ b/gdb/i386-nat.c
@@ -756,10 +756,10 @@ i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
}
static int
-i386_stopped_by_watchpoint (void)
+i386_stopped_by_watchpoint (struct target_ops *ops)
{
CORE_ADDR addr = 0;
- return i386_stopped_data_address (¤t_target, &addr);
+ return i386_stopped_data_address (ops, &addr);
}
/* Insert a hardware-assisted breakpoint at BP_TGT->placed_address.
diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c
index 3bd4237..7277f7b 100644
--- a/gdb/ia64-linux-nat.c
+++ b/gdb/ia64-linux-nat.c
@@ -669,10 +669,10 @@ ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
}
static int
-ia64_linux_stopped_by_watchpoint (void)
+ia64_linux_stopped_by_watchpoint (struct target_ops *ops)
{
CORE_ADDR addr;
- return ia64_linux_stopped_data_address (¤t_target, &addr);
+ return ia64_linux_stopped_data_address (ops, &addr);
}
static int
diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c
index 511a67c..54d3dd1 100644
--- a/gdb/inf-ttrace.c
+++ b/gdb/inf-ttrace.c
@@ -374,7 +374,7 @@ inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
by hitting a "hardware" watchpoint. */
static int
-inf_ttrace_stopped_by_watchpoint (void)
+inf_ttrace_stopped_by_watchpoint (struct target_ops *ops)
{
pid_t pid = ptid_get_pid (inferior_ptid);
lwpid_t lwpid = ptid_get_lwp (inferior_ptid);
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 45a6e5f..e9f3266 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -289,10 +289,6 @@ async_file_mark (void)
be awakened anyway. */
}
-static void linux_nat_async (void (*callback)
- (enum inferior_event_type event_type,
- void *context),
- void *context);
static int kill_lwp (int lwpid, int signo);
static int stop_callback (struct lwp_info *lp, void *data);
@@ -2754,7 +2750,7 @@ save_sigtrap (struct lwp_info *lp)
old_chain = save_inferior_ptid ();
inferior_ptid = lp->ptid;
- lp->stopped_by_watchpoint = linux_ops->to_stopped_by_watchpoint ();
+ lp->stopped_by_watchpoint = linux_ops->to_stopped_by_watchpoint (linux_ops);
if (lp->stopped_by_watchpoint)
{
@@ -2772,7 +2768,7 @@ save_sigtrap (struct lwp_info *lp)
/* See save_sigtrap. */
static int
-linux_nat_stopped_by_watchpoint (void)
+linux_nat_stopped_by_watchpoint (struct target_ops *ops)
{
struct lwp_info *lp = find_lwp_pid (inferior_ptid);
@@ -4766,7 +4762,7 @@ linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
/* target_is_async_p implementation. */
static int
-linux_nat_is_async_p (void)
+linux_nat_is_async_p (struct target_ops *ops)
{
/* NOTE: palves 2008-03-21: We're only async when the user requests
it explicitly with the "set target-async" command.
@@ -4777,7 +4773,7 @@ linux_nat_is_async_p (void)
/* target_can_async_p implementation. */
static int
-linux_nat_can_async_p (void)
+linux_nat_can_async_p (struct target_ops *ops)
{
/* NOTE: palves 2008-03-21: We're only async when the user requests
it explicitly with the "set target-async" command.
@@ -4935,8 +4931,10 @@ linux_async_pipe (int enable)
/* target_async implementation. */
static void
-linux_nat_async (void (*callback) (enum inferior_event_type event_type,
- void *context), void *context)
+linux_nat_async (struct target_ops *ops,
+ void (*callback) (enum inferior_event_type event_type,
+ void *context),
+ void *context)
{
if (callback != NULL)
{
@@ -5021,8 +5019,8 @@ static void
linux_nat_close (void)
{
/* Unregister from the event loop. */
- if (linux_nat_is_async_p ())
- linux_nat_async (NULL, 0);
+ if (linux_nat_is_async_p (linux_ops))
+ linux_nat_async (linux_ops, NULL, 0);
if (linux_ops->to_close)
linux_ops->to_close ();
diff --git a/gdb/mem-break.c b/gdb/mem-break.c
index 74fd8db..cb23e2a 100644
--- a/gdb/mem-break.c
+++ b/gdb/mem-break.c
@@ -77,14 +77,16 @@ default_memory_remove_breakpoint (struct gdbarch *gdbarch,
int
-memory_insert_breakpoint (struct gdbarch *gdbarch,
+memory_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return gdbarch_memory_insert_breakpoint (gdbarch, bp_tgt);
}
int
-memory_remove_breakpoint (struct gdbarch *gdbarch,
+memory_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return gdbarch_memory_remove_breakpoint (gdbarch, bp_tgt);
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index 9246741..2285b4b 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -553,7 +553,7 @@ mips_linux_can_use_hw_breakpoint (int type, int cnt, int ot)
register triggered. */
static int
-mips_linux_stopped_by_watchpoint (void)
+mips_linux_stopped_by_watchpoint (struct target_ops *ops)
{
int n;
int num_valid;
diff --git a/gdb/monitor.c b/gdb/monitor.c
index d0c9866..dde40f8 100644
--- a/gdb/monitor.c
+++ b/gdb/monitor.c
@@ -2077,7 +2077,8 @@ monitor_mourn_inferior (struct target_ops *ops)
/* Tell the monitor to add a breakpoint. */
static int
-monitor_insert_breakpoint (struct gdbarch *gdbarch,
+monitor_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
CORE_ADDR addr = bp_tgt->placed_address;
@@ -2114,7 +2115,8 @@ monitor_insert_breakpoint (struct gdbarch *gdbarch,
/* Tell the monitor to remove a breakpoint. */
static int
-monitor_remove_breakpoint (struct gdbarch *gdbarch,
+monitor_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
CORE_ADDR addr = bp_tgt->placed_address;
diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c
index 5109fac..c8d5fd1 100644
--- a/gdb/nto-procfs.c
+++ b/gdb/nto-procfs.c
@@ -75,7 +75,7 @@ static int procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type,
static int procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type,
struct expression *cond);
-static int procfs_stopped_by_watchpoint (void);
+static int procfs_stopped_by_watchpoint (struct target_ops *ops);
/* These two globals are only ever set in procfs_open(), but are
referenced elsewhere. 'nto_procfs_node' is a flag used to say
@@ -921,14 +921,16 @@ procfs_breakpoint (CORE_ADDR addr, int type, int size)
}
static int
-procfs_insert_breakpoint (struct gdbarch *gdbarch,
+procfs_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, 0);
}
static int
-procfs_remove_breakpoint (struct gdbarch *gdbarch,
+procfs_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, -1);
@@ -1507,7 +1509,7 @@ procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type,
}
static int
-procfs_stopped_by_watchpoint (void)
+procfs_stopped_by_watchpoint (struct target_ops *ops)
{
return 0;
}
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 1f3f080..e3a52cb 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -2283,10 +2283,10 @@ ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
}
static int
-ppc_linux_stopped_by_watchpoint (void)
+ppc_linux_stopped_by_watchpoint (struct target_ops *ops)
{
CORE_ADDR addr;
- return ppc_linux_stopped_data_address (¤t_target, &addr);
+ return ppc_linux_stopped_data_address (ops, &addr);
}
static int
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 20da81a..75cf216 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -4858,7 +4858,7 @@ procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
fault, else returns zero. */
static int
-procfs_stopped_by_watchpoint (void)
+procfs_stopped_by_watchpoint (struct target_ops *ops)
{
procinfo *pi;
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 1c4e68b..4904225 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -237,16 +237,19 @@ static LONGEST
ULONGEST offset,
LONGEST len);
static int
- (*record_full_beneath_to_insert_breakpoint) (struct gdbarch *,
+ (*record_full_beneath_to_insert_breakpoint) (struct target_ops *,
+ struct gdbarch *,
struct bp_target_info *);
static int
- (*record_full_beneath_to_remove_breakpoint) (struct gdbarch *,
+ (*record_full_beneath_to_remove_breakpoint) (struct target_ops *,
+ struct gdbarch *,
struct bp_target_info *);
-static int (*record_full_beneath_to_stopped_by_watchpoint) (void);
+static int (*record_full_beneath_to_stopped_by_watchpoint) (struct target_ops *);
static int (*record_full_beneath_to_stopped_data_address) (struct target_ops *,
CORE_ADDR *);
static void
- (*record_full_beneath_to_async) (void (*) (enum inferior_event_type, void *),
+ (*record_full_beneath_to_async) (struct target_ops *,
+ void (*) (enum inferior_event_type, void *),
void *);
static void record_full_goto_insn (struct record_full_entry *entry,
@@ -814,14 +817,16 @@ static LONGEST (*tmp_to_xfer_partial) (struct target_ops *ops,
const gdb_byte *writebuf,
ULONGEST offset,
LONGEST len);
-static int (*tmp_to_insert_breakpoint) (struct gdbarch *,
+static int (*tmp_to_insert_breakpoint) (struct target_ops *,
+ struct gdbarch *,
struct bp_target_info *);
-static int (*tmp_to_remove_breakpoint) (struct gdbarch *,
+static int (*tmp_to_remove_breakpoint) (struct target_ops *ops,
+ struct gdbarch *,
struct bp_target_info *);
-static int (*tmp_to_stopped_by_watchpoint) (void);
+static int (*tmp_to_stopped_by_watchpoint) (struct target_ops *);
static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
-static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
-static void (*tmp_to_async) (void (*) (enum inferior_event_type, void *), void *);
+static void (*tmp_to_async) (struct target_ops *,
+ void (*) (enum inferior_event_type, void *), void *);
static void record_full_restore (void);
@@ -1510,12 +1515,12 @@ record_full_wait (struct target_ops *ops,
}
static int
-record_full_stopped_by_watchpoint (void)
+record_full_stopped_by_watchpoint (struct target_ops *ops)
{
if (RECORD_FULL_IS_REPLAY)
return record_full_hw_watchpoint;
else
- return record_full_beneath_to_stopped_by_watchpoint ();
+ return record_full_beneath_to_stopped_by_watchpoint (find_target_beneath (ops));
}
static int
@@ -1758,7 +1763,8 @@ record_full_init_record_breakpoints (void)
when recording. */
static int
-record_full_insert_breakpoint (struct gdbarch *gdbarch,
+record_full_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
struct record_full_breakpoint *bp;
@@ -1775,7 +1781,8 @@ record_full_insert_breakpoint (struct gdbarch *gdbarch,
int ret;
old_cleanups = record_full_gdb_operation_disable_set ();
- ret = record_full_beneath_to_insert_breakpoint (gdbarch, bp_tgt);
+ ret = record_full_beneath_to_insert_breakpoint (find_target_beneath (ops),
+ gdbarch, bp_tgt);
do_cleanups (old_cleanups);
if (ret != 0)
@@ -1795,7 +1802,8 @@ record_full_insert_breakpoint (struct gdbarch *gdbarch,
/* "to_remove_breakpoint" method for process record target. */
static int
-record_full_remove_breakpoint (struct gdbarch *gdbarch,
+record_full_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
struct record_full_breakpoint *bp;
@@ -1815,7 +1823,8 @@ record_full_remove_breakpoint (struct gdbarch *gdbarch,
int ret;
old_cleanups = record_full_gdb_operation_disable_set ();
- ret = record_full_beneath_to_remove_breakpoint (gdbarch, bp_tgt);
+ ret = record_full_beneath_to_remove_breakpoint (find_target_beneath (ops),
+ gdbarch, bp_tgt);
do_cleanups (old_cleanups);
if (ret != 0)
@@ -1890,25 +1899,26 @@ record_full_goto_bookmark (gdb_byte *raw_bookmark, int from_tty)
}
static void
-record_full_async (void (*callback) (enum inferior_event_type event_type,
+record_full_async (struct target_ops *ops,
+ void (*callback) (enum inferior_event_type event_type,
void *context), void *context)
{
/* If we're on top of a line target (e.g., linux-nat, remote), then
set it to async mode as well. Will be NULL if we're sitting on
top of the core target, for "record restore". */
if (record_full_beneath_to_async != NULL)
- record_full_beneath_to_async (callback, context);
+ record_full_beneath_to_async (find_target_beneath (ops), callback, context);
}
static int
-record_full_can_async_p (void)
+record_full_can_async_p (struct target_ops *ops)
{
/* We only enable async when the user specifically asks for it. */
return target_async_permitted;
}
static int
-record_full_is_async_p (void)
+record_full_is_async_p (struct target_ops *ops)
{
/* We only enable async when the user specifically asks for it. */
return target_async_permitted;
@@ -2264,7 +2274,8 @@ record_full_core_xfer_partial (struct target_ops *ops,
/* "to_insert_breakpoint" method for prec over corefile. */
static int
-record_full_core_insert_breakpoint (struct gdbarch *gdbarch,
+record_full_core_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return 0;
@@ -2273,7 +2284,8 @@ record_full_core_insert_breakpoint (struct gdbarch *gdbarch,
/* "to_remove_breakpoint" method for prec over corefile. */
static int
-record_full_core_remove_breakpoint (struct gdbarch *gdbarch,
+record_full_core_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return 0;
diff --git a/gdb/remote-m32r-sdi.c b/gdb/remote-m32r-sdi.c
index 81fea53..21502d4 100644
--- a/gdb/remote-m32r-sdi.c
+++ b/gdb/remote-m32r-sdi.c
@@ -1145,7 +1145,8 @@ m32r_mourn_inferior (struct target_ops *ops)
}
static int
-m32r_insert_breakpoint (struct gdbarch *gdbarch,
+m32r_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
CORE_ADDR addr = bp_tgt->placed_address;
@@ -1189,7 +1190,8 @@ m32r_insert_breakpoint (struct gdbarch *gdbarch,
}
static int
-m32r_remove_breakpoint (struct gdbarch *gdbarch,
+m32r_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
CORE_ADDR addr = bp_tgt->placed_address;
@@ -1476,7 +1478,7 @@ m32r_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
}
static int
-m32r_stopped_by_watchpoint (void)
+m32r_stopped_by_watchpoint (struct target_ops *ops)
{
CORE_ADDR addr;
diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c
index 081fbd0..7a1658f 100644
--- a/gdb/remote-mips.c
+++ b/gdb/remote-mips.c
@@ -2364,27 +2364,29 @@ mips_mourn_inferior (struct target_ops *ops)
target contents. */
static int
-mips_insert_breakpoint (struct gdbarch *gdbarch,
+mips_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
if (monitor_supports_breakpoints)
return mips_set_breakpoint (bp_tgt->placed_address, MIPS_INSN32_SIZE,
BREAK_FETCH);
else
- return memory_insert_breakpoint (gdbarch, bp_tgt);
+ return memory_insert_breakpoint (ops, gdbarch, bp_tgt);
}
/* Remove a breakpoint. */
static int
-mips_remove_breakpoint (struct gdbarch *gdbarch,
+mips_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
if (monitor_supports_breakpoints)
return mips_clear_breakpoint (bp_tgt->placed_address, MIPS_INSN32_SIZE,
BREAK_FETCH);
else
- return memory_remove_breakpoint (gdbarch, bp_tgt);
+ return memory_remove_breakpoint (ops, gdbarch, bp_tgt);
}
/* Tell whether this target can support a hardware breakpoint. CNT
@@ -2451,7 +2453,7 @@ mips_remove_watchpoint (CORE_ADDR addr, int len, int type,
if not. */
static int
-mips_stopped_by_watchpoint (void)
+mips_stopped_by_watchpoint (struct target_ops *ops)
{
return hit_watchpoint;
}
diff --git a/gdb/remote.c b/gdb/remote.c
index 7830e67..0892ae4 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -129,12 +129,14 @@ static void remote_kill (struct target_ops *ops);
static int tohex (int nib);
-static int remote_can_async_p (void);
+static int remote_can_async_p (struct target_ops *);
-static int remote_is_async_p (void);
+static int remote_is_async_p (struct target_ops *);
-static void remote_async (void (*callback) (enum inferior_event_type event_type,
- void *context), void *context);
+static void remote_async (struct target_ops *ops,
+ void (*callback) (enum inferior_event_type event_type,
+ void *context),
+ void *context);
static void remote_detach (struct target_ops *ops, char *args, int from_tty);
@@ -8158,7 +8160,8 @@ remote_add_target_side_commands (struct gdbarch *gdbarch,
which don't, we insert a traditional memory breakpoint. */
static int
-remote_insert_breakpoint (struct gdbarch *gdbarch,
+remote_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
/* Try the "Z" s/w breakpoint packet if it is not already disabled.
@@ -8214,11 +8217,12 @@ remote_insert_breakpoint (struct gdbarch *gdbarch,
}
}
- return memory_insert_breakpoint (gdbarch, bp_tgt);
+ return memory_insert_breakpoint (ops, gdbarch, bp_tgt);
}
static int
-remote_remove_breakpoint (struct gdbarch *gdbarch,
+remote_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
CORE_ADDR addr = bp_tgt->placed_address;
@@ -8248,7 +8252,7 @@ remote_remove_breakpoint (struct gdbarch *gdbarch,
return (rs->buf[0] == 'E');
}
- return memory_remove_breakpoint (gdbarch, bp_tgt);
+ return memory_remove_breakpoint (ops, gdbarch, bp_tgt);
}
static int
@@ -8402,7 +8406,7 @@ remote_check_watch_resources (int type, int cnt, int ot)
}
static int
-remote_stopped_by_watchpoint (void)
+remote_stopped_by_watchpoint (struct target_ops *ops)
{
return remote_stopped_by_watchpoint_p;
}
@@ -8412,7 +8416,7 @@ remote_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
{
int rc = 0;
- if (remote_stopped_by_watchpoint ())
+ if (remote_stopped_by_watchpoint (target))
{
*addr_p = remote_watch_data_address;
rc = 1;
@@ -11619,7 +11623,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
}
static int
-remote_can_async_p (void)
+remote_can_async_p (struct target_ops *ops)
{
if (!target_async_permitted)
/* We only enable async when the user specifically asks for it. */
@@ -11630,7 +11634,7 @@ remote_can_async_p (void)
}
static int
-remote_is_async_p (void)
+remote_is_async_p (struct target_ops *ops)
{
if (!target_async_permitted)
/* We only enable async when the user specifically asks for it. */
@@ -11664,8 +11668,10 @@ remote_async_inferior_event_handler (gdb_client_data data)
}
static void
-remote_async (void (*callback) (enum inferior_event_type event_type,
- void *context), void *context)
+remote_async (struct target_ops *ops,
+ void (*callback) (enum inferior_event_type event_type,
+ void *context),
+ void *context)
{
if (callback != NULL)
{
diff --git a/gdb/s390-nat.c b/gdb/s390-nat.c
index de99348..cec7181 100644
--- a/gdb/s390-nat.c
+++ b/gdb/s390-nat.c
@@ -441,7 +441,7 @@ struct watch_area
static struct watch_area *watch_base = NULL;
static int
-s390_stopped_by_watchpoint (void)
+s390_stopped_by_watchpoint (struct target_ops *ops)
{
per_lowcore_bits per_lowcore;
ptrace_area parea;
diff --git a/gdb/target.c b/gdb/target.c
index 377724d..b6b54cf 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -100,12 +100,6 @@ static void debug_to_prepare_to_store (struct regcache *);
static void debug_to_files_info (struct target_ops *);
-static int debug_to_insert_breakpoint (struct gdbarch *,
- struct bp_target_info *);
-
-static int debug_to_remove_breakpoint (struct gdbarch *,
- struct bp_target_info *);
-
static int debug_to_can_use_hw_breakpoint (int, int, int);
static int debug_to_insert_hw_breakpoint (struct gdbarch *,
@@ -120,8 +114,6 @@ static int debug_to_insert_watchpoint (CORE_ADDR, int, int,
static int debug_to_remove_watchpoint (CORE_ADDR, int, int,
struct expression *);
-static int debug_to_stopped_by_watchpoint (void);
-
static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
static int debug_to_watchpoint_addr_within_range (struct target_ops *,
@@ -796,7 +788,7 @@ update_current_target (void)
(int (*) (CORE_ADDR, int, int, struct expression *))
return_minus_one);
de_fault (to_stopped_by_watchpoint,
- (int (*) (void))
+ (int (*) (struct target_ops *))
return_zero);
de_fault (to_stopped_data_address,
(int (*) (struct target_ops *, CORE_ADDR *))
@@ -874,7 +866,9 @@ update_current_target (void)
(char *(*) (int))
return_zero);
de_fault (to_async,
- (void (*) (void (*) (enum inferior_event_type, void*), void*))
+ (void (*) (struct target_ops *,
+ void (*) (enum inferior_event_type, void*),
+ void*))
tcomplain);
de_fault (to_thread_architecture,
default_thread_architecture);
@@ -2455,7 +2449,8 @@ target_insert_breakpoint (struct gdbarch *gdbarch,
return 1;
}
- return (*current_target.to_insert_breakpoint) (gdbarch, bp_tgt);
+ return (*current_target.to_insert_breakpoint) (¤t_target,
+ gdbarch, bp_tgt);
}
int
@@ -2472,7 +2467,8 @@ target_remove_breakpoint (struct gdbarch *gdbarch,
return 1;
}
- return (*current_target.to_remove_breakpoint) (gdbarch, bp_tgt);
+ return (*current_target.to_remove_breakpoint) (¤t_target,
+ gdbarch, bp_tgt);
}
static void
@@ -3122,7 +3118,7 @@ find_default_create_inferior (struct target_ops *ops,
}
static int
-find_default_can_async_p (void)
+find_default_can_async_p (struct target_ops *ignore)
{
struct target_ops *t;
@@ -3132,12 +3128,12 @@ find_default_can_async_p (void)
connected yet. */
t = find_default_run_target (NULL);
if (t && t->to_can_async_p)
- return (t->to_can_async_p) ();
+ return (t->to_can_async_p) (t);
return 0;
}
static int
-find_default_is_async_p (void)
+find_default_is_async_p (struct target_ops *ignore)
{
struct target_ops *t;
@@ -3147,7 +3143,7 @@ find_default_is_async_p (void)
connected yet. */
t = find_default_run_target (NULL);
if (t && t->to_is_async_p)
- return (t->to_is_async_p) ();
+ return (t->to_is_async_p) (t);
return 0;
}
@@ -3749,7 +3745,8 @@ init_dummy_target (void)
dummy_target.to_has_registers = (int (*) (struct target_ops *)) return_zero;
dummy_target.to_has_execution
= (int (*) (struct target_ops *, ptid_t)) return_zero;
- dummy_target.to_stopped_by_watchpoint = return_zero;
+ dummy_target.to_stopped_by_watchpoint
+ = (int (*) (struct target_ops *)) return_zero;
dummy_target.to_stopped_data_address =
(int (*) (struct target_ops *, CORE_ADDR *)) return_zero;
dummy_target.to_magic = OPS_MAGIC;
@@ -4495,12 +4492,13 @@ debug_to_files_info (struct target_ops *target)
}
static int
-debug_to_insert_breakpoint (struct gdbarch *gdbarch,
+debug_to_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_insert_breakpoint (gdbarch, bp_tgt);
+ retval = debug_target.to_insert_breakpoint (&debug_target, gdbarch, bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_insert_breakpoint (%s, xxx) = %ld\n",
@@ -4510,12 +4508,13 @@ debug_to_insert_breakpoint (struct gdbarch *gdbarch,
}
static int
-debug_to_remove_breakpoint (struct gdbarch *gdbarch,
+debug_to_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
int retval;
- retval = debug_target.to_remove_breakpoint (gdbarch, bp_tgt);
+ retval = debug_target.to_remove_breakpoint (&debug_target, gdbarch, bp_tgt);
fprintf_unfiltered (gdb_stdlog,
"target_remove_breakpoint (%s, xxx) = %ld\n",
@@ -4572,11 +4571,11 @@ debug_to_can_accel_watchpoint_condition (CORE_ADDR addr, int len, int rw,
}
static int
-debug_to_stopped_by_watchpoint (void)
+debug_to_stopped_by_watchpoint (struct target_ops *ops)
{
int retval;
- retval = debug_target.to_stopped_by_watchpoint ();
+ retval = debug_target.to_stopped_by_watchpoint (&debug_target);
fprintf_unfiltered (gdb_stdlog,
"target_stopped_by_watchpoint () = %ld\n",
diff --git a/gdb/target.h b/gdb/target.h
index 1d73bcd..b03d33d 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -364,8 +364,10 @@ struct target_ops
struct target_ops *target);
void (*to_files_info) (struct target_ops *);
- int (*to_insert_breakpoint) (struct gdbarch *, struct bp_target_info *);
- int (*to_remove_breakpoint) (struct gdbarch *, struct bp_target_info *);
+ int (*to_insert_breakpoint) (struct target_ops *, struct gdbarch *,
+ struct bp_target_info *);
+ int (*to_remove_breakpoint) (struct target_ops *, struct gdbarch *,
+ struct bp_target_info *);
int (*to_can_use_hw_breakpoint) (int, int, int);
int (*to_ranged_break_num_registers) (struct target_ops *);
int (*to_insert_hw_breakpoint) (struct gdbarch *, struct bp_target_info *);
@@ -380,7 +382,7 @@ struct target_ops
CORE_ADDR, CORE_ADDR, int);
int (*to_remove_mask_watchpoint) (struct target_ops *,
CORE_ADDR, CORE_ADDR, int);
- int (*to_stopped_by_watchpoint) (void);
+ int (*to_stopped_by_watchpoint) (struct target_ops *);
int to_have_steppable_watchpoint;
int to_have_continuable_watchpoint;
int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
@@ -445,9 +447,10 @@ struct target_ops
int to_has_thread_control; /* control thread execution */
int to_attach_no_wait;
/* ASYNC target controls */
- int (*to_can_async_p) (void);
- int (*to_is_async_p) (void);
- void (*to_async) (void (*) (enum inferior_event_type, void *), void *);
+ int (*to_can_async_p) (struct target_ops *);
+ int (*to_is_async_p) (struct target_ops *);
+ void (*to_async) (struct target_ops *,
+ void (*) (enum inferior_event_type, void *), void *);
int (*to_supports_non_stop) (void);
/* find_memory_regions support method for gcore */
int (*to_find_memory_regions) (find_memory_region_ftype func, void *data);
@@ -1373,16 +1376,16 @@ extern int default_child_has_execution (struct target_ops *ops,
extern int target_async_permitted;
/* Can the target support asynchronous execution? */
-#define target_can_async_p() (current_target.to_can_async_p ())
+#define target_can_async_p() (current_target.to_can_async_p (¤t_target))
/* Is the target in asynchronous execution mode? */
-#define target_is_async_p() (current_target.to_is_async_p ())
+#define target_is_async_p() (current_target.to_is_async_p (¤t_target))
int target_supports_non_stop (void);
/* Put the target in async mode with the specified callback function. */
#define target_async(CALLBACK,CONTEXT) \
- (current_target.to_async ((CALLBACK), (CONTEXT)))
+ (current_target.to_async (¤t_target, (CALLBACK), (CONTEXT)))
#define target_execution_direction() \
(current_target.to_execution_direction ())
@@ -1456,8 +1459,8 @@ extern char *target_thread_name (struct thread_info *);
/* Returns non-zero if we were stopped by a hardware watchpoint (memory read or
write). Only the INFERIOR_PTID task is being queried. */
-#define target_stopped_by_watchpoint \
- (*current_target.to_stopped_by_watchpoint)
+#define target_stopped_by_watchpoint() \
+ ((*current_target.to_stopped_by_watchpoint) (¤t_target))
/* Non-zero if we have steppable watchpoints */
@@ -1832,10 +1835,12 @@ extern struct target_section_table *target_get_section_table
/* From mem-break.c */
-extern int memory_remove_breakpoint (struct gdbarch *,
+extern int memory_remove_breakpoint (struct target_ops *,
+ struct gdbarch *,
struct bp_target_info *);
-extern int memory_insert_breakpoint (struct gdbarch *,
+extern int memory_insert_breakpoint (struct target_ops *,
+ struct gdbarch *,
struct bp_target_info *);
extern int default_memory_remove_breakpoint (struct gdbarch *,
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v2 7/9] make dprintf.exp pass in always-async mode
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
` (3 preceding siblings ...)
2013-07-31 18:28 ` [PATCH v2 2/9] add "this" pointers to more target APIs Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
2013-07-31 18:28 ` [PATCH v2 4/9] PR gdb/13860: make -interpreter-exec console "list" behave more like "list" Tom Tromey
` (3 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
When target-async is enabled, dprintf.exp fails.
This happens because run_inferior_call causes gdb to forget that it is
running in sync_execution mode, so something like a breakpoint
condition that makes an inferior call causes gdb to enter fully async
mode.
This patch fixes the problem by noticing when gdb was in
sync_execution mode in run_inferior_call, and taking care to restore
this state afterward.
Built and regtested on x86-64 Fedora 18.
PR cli/15718:
* infcall.c: Include event-top.h.
(run_inferior_call): Call async_disable_stdin if needed.
---
gdb/infcall.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 19af044..7398913 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -36,6 +36,7 @@
#include "ada-lang.h"
#include "gdbthread.h"
#include "exceptions.h"
+#include "event-top.h"
/* If we can't find a function's name from its address,
we print this instead. */
@@ -398,6 +399,8 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
TRY_CATCH (e, RETURN_MASK_ALL)
{
+ int was_sync = sync_execution;
+
proceed (real_pc, GDB_SIGNAL_0, 0);
/* Inferior function calls are always synchronous, even if the
@@ -407,6 +410,11 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
{
wait_for_inferior ();
normal_stop ();
+ /* If gdb was previously in sync execution mode, then ensure
+ that it remains so. normal_stop calls
+ async_enable_stdin, so reset it again here. */
+ if (was_sync)
+ async_disable_stdin ();
}
}
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v2 4/9] PR gdb/13860: make -interpreter-exec console "list" behave more like "list".
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
` (4 preceding siblings ...)
2013-07-31 18:28 ` [PATCH v2 7/9] make dprintf.exp pass in always-async mode Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
2013-07-31 18:28 ` [PATCH v2 6/9] PR gdb/13860: don't lose '-interpreter-exec console EXECUTION_COMMAND''s output in async mode Tom Tromey
` (2 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Pedro Alves
From: Pedro Alves <palves@redhat.com>
Patch 3 in this series made me notice that "list" behaves differently
in CLI vs MI. Particularly:
>./gdb -nx -q ./testsuite/gdb.mi/mi-cli
Reading symbols from /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/mi-cli...done.
(gdb) start
Temporary breakpoint 1 at 0x40054d: file ../../../src/gdb/testsuite/gdb.mi/basics.c, line 62.
Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/mi-cli
Temporary breakpoint 1, main () at ../../../src/gdb/testsuite/gdb.mi/basics.c:62
62 callee1 (2, "A string argument.", 3.5);
(gdb) list
57 {
58 }
59
60 main ()
61 {
62 callee1 (2, "A string argument.", 3.5);
63 callee1 (2, "A string argument.", 3.5);
64
65 do_nothing (); /* Hello, World! */
66
(gdb)
Note the list started at line 57. IOW, the program stopped at line
62, and GDB centered the list on that.
compare with:
>./gdb -nx -q ./testsuite/gdb.mi/mi-cli -i=mi
=thread-group-added,id="i1"
~"Reading symbols from /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/mi-cli..."
~"done.\n"
(gdb)
start
&"start\n"
~"Temporary breakpoint 1 at 0x40054d: file ../../../src/gdb/testsuite/gdb.mi/basics.c, line 62.\n"
=breakpoint-created,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x000000000040054d",func="main",file="../../../src/gdb/testsuite/gdb.mi/basics.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/basics.c",line="62",times="0",original-location="main"}
~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/mi-cli \n"
=thread-group-started,id="i1",pid="14221"
=thread-created,id="1",group-id="i1"
^running
*running,thread-id="all"
(gdb)
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
=library-loaded,id="/lib64/libm.so.6",target-name="/lib64/libm.so.6",host-name="/lib64/libm.so.6",symbols-loaded="0",thread-group="i1"
=library-loaded,id="/lib64/libc.so.6",target-name="/lib64/libc.so.6",host-name="/lib64/libc.so.6",symbols-loaded="0",thread-group="i1"
=breakpoint-modified,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x000000000040054d",func="main",file="../../../src/gdb/testsuite/gdb.mi/basics.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/basics.c",line="62",times="1",original-location="main"}
~"\nTemporary breakpoint "
~"1, main () at ../../../src/gdb/testsuite/gdb.mi/basics.c:62\n"
~"62\t callee1 (2, \"A string argument.\", 3.5);\n"
*stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x000000000040054d",func="main",args=[],file="../../../src/gdb/testsuite/gdb.mi/basics.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/basics.c",line="62"},thread-id="1",stopped-threads="all",core="0"
=breakpoint-deleted,id="1"
(gdb)
-interpreter-exec console list
~"62\t callee1 (2, \"A string argument.\", 3.5);\n"
~"63\t callee1 (2, \"A string argument.\", 3.5);\n"
~"64\t\n"
~"65\t do_nothing (); /* Hello, World! */\n"
~"66\t\n"
~"67\t callme (1);\n"
~"68\t callme (2);\n"
~"69\t\n"
~"70\t return 0;\n"
~"71\t}\n"
^done
(gdb)
Here the list starts at line 62, where the program was stopped.
This happens because print_stack_frame, called from both normal_stop
and mi_on_normal_stop, is the function responsible for setting the
current sal from the selected frame, overrides the PRINT_WHAT
argument, and only after that does it decide whether to center the
current sal line or not, based on the overriden value, and it will
always decide false.
(The print_stack_frame call in mi_on_normal_stop is a little different
from the call in normal_stop, in that it is an unconditional
SRC_AND_LOC call. The next patch will make those uniform.)
Tested on x86_64 Fedora 16, no regressions.
gdb/
2012-05-09 Pedro Alves <palves@redhat.com>
* stack.c (print_stack_frame): Compute CENTER before overriding
PRINT_WHAT.
gdb/testsuite/
2012-05-09 Pedro Alves <palves@redhat.com>
* gdb.mi/mi-cli.exp: Adjust expected output of "list".
---
gdb/stack.c | 4 ++--
gdb/testsuite/gdb.mi/mi-cli.exp | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/gdb/stack.c b/gdb/stack.c
index d89ff89..c64cfdc 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -159,14 +159,14 @@ print_stack_frame (struct frame_info *frame, int print_level,
{
volatile struct gdb_exception e;
+ int center = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
+
/* For mi, alway print location and address. */
if (ui_out_is_mi_like_p (current_uiout))
print_what = LOC_AND_ADDRESS;
TRY_CATCH (e, RETURN_MASK_ERROR)
{
- int center = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
-
print_frame_info (frame, print_level, print_what, 1 /* print_args */);
set_current_sal_from_frame (frame, center);
}
diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp
index 59af58b..5b809e2 100644
--- a/gdb/testsuite/gdb.mi/mi-cli.exp
+++ b/gdb/testsuite/gdb.mi/mi-cli.exp
@@ -91,7 +91,7 @@ mi_gdb_test "-interpreter-exec console \"set listsize 1\"" \
# {.*\~"32[ \t(\\t)]*callee1.*\\n".*\^done }
mi_gdb_test "-interpreter-exec console \"list\"" \
- ".*\~\"$line_main_body\[\\\\t \]*callee1.*;\\\\n\".*\\^done" \
+ ".*\~\"57\\\\t\{\\\\n\".*\\^done" \
"-interpreter-exec console \"list\""
mi_execute_to "exec-continue" "breakpoint-hit" "callee4" "" ".*basics.c" $line_callee4_body \
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v2 6/9] PR gdb/13860: don't lose '-interpreter-exec console EXECUTION_COMMAND''s output in async mode.
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
` (5 preceding siblings ...)
2013-07-31 18:28 ` [PATCH v2 4/9] PR gdb/13860: make -interpreter-exec console "list" behave more like "list" Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
2013-07-31 18:28 ` [PATCH v2 5/9] PR gdb/13860: make "-exec-foo"'s MI output equal to "foo"'s MI output Tom Tromey
2013-07-31 18:28 ` [PATCH v2 1/9] fix latent bugs in ui-out.c Tom Tromey
8 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Pedro Alves
From: Pedro Alves <palves@redhat.com>
The other part of PR gdb/13860 is about console execution commands
in MI getting their output half lost. E.g., take the finish command,
executed on a frontend's GDB console:
sync:
finish
&"finish\n"
~"Run till exit from #0 usleep (useconds=10) at ../sysdeps/unix/sysv/linux/usleep.c:27\n"
^running
*running,thread-id="1"
(gdb)
~"0x00000000004004d7 in foo () at stepinf.c:6\n"
~"6\t usleep (10);\n"
~"Value returned is $1 = 0\n"
*stopped,reason="function-finished",frame={addr="0x00000000004004d7",func="foo",args=[],file="stepinf.c",fullname="/home/pedro/gdb/tests/stepinf.c",line="6"},thread-id="1",stopped-threads="all",core="1"
async:
finish
&"finish\n"
~"Run till exit from #0 usleep (useconds=10) at ../sysdeps/unix/sysv/linux/usleep.c:27\n"
^running
*running,thread-id="1"
(gdb)
*stopped,reason="function-finished",frame={addr="0x00000000004004d7",func="foo",args=[],file="stepinf.c",fullname="/home/pedro/gdb/tests/stepinf.c",line="6"},gdb-result-var="$1",return-value="0",thread-id="1",stopped-threads="all",core="0"
Note how all the "Value returned" etc. output is missing in async mode.
The same happens with e.g., catchpoints:
=breakpoint-modified,bkpt={number="1",type="catchpoint",disp="keep",enabled="y",what="22016",times="1"}
~"\nCatchpoint "
~"1 (forked process 22016), 0x0000003791cbd8a6 in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:131\n"
~"131\t pid = ARCH_FORK ();\n"
*stopped,reason="fork",disp="keep",bkptno="1",newpid="22016",frame={addr="0x0000003791cbd8a6",func="__libc_fork",args=[],file="../nptl/sysdeps/unix/sysv/linux/fork.c",fullname="/usr/src/debug/glibc-2.14-394-g8f3b1ff/nptl/sysdeps/unix/sysv/linux/fork.c",line="131"},thread-id="1",stopped-threads="all",core="0"
where all those ~ lines are missing in async mode, or just the "step"
current line indication:
s
&"s\n"
^running
*running,thread-id="all"
(gdb)
~"13\t foo ();\n"
*stopped,frame={addr="0x00000000004004ef",func="main",args=[{name="argc",value="1"},{name="argv",value="0x7fffffffdd78"}],file="stepinf.c",fullname="/home/pedro/gdb/tests/stepinf.c",line="13"},thread-id="1",stopped-threads="all",core="3"
(gdb)
Or in the case of the PRs example, the "Stopped due to shared library
event" note:
start
&"start\n"
~"Temporary breakpoint 1 at 0x400608: file ../../../src/gdb/testsuite/gdb.mi/solib-main.c, line 21.\n"
=breakpoint-created,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x0000000000400608",func="main",file="../../../src/gdb/testsuite/gdb.mi/solib-main.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/solib-main.c",line="21",times="0",original-location="main"}
~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main \n"
=thread-group-started,id="i1",pid="21990"
=thread-created,id="1",group-id="i1"
^running
*running,thread-id="all"
(gdb)
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
~"Stopped due to shared library event (no libraries added or removed)\n"
*stopped,reason="solib-event",thread-id="1",stopped-threads="all",core="3"
(gdb)
IMO, if you're typing execution commands in a frontend's console, you
expect to see their output. Indeed it's what you get in sync mode. I
think async mode should do the same.
That's what this patch does.
Notes:
- mi->out is the same as gdb_stdout when MI is the current
interpreter. I think that referring to that directly is cleaner.
An earlier revision of this patch made the changes that are now
done in mi_on_normal_stop directly in infrun.c:normal_stop, and so
not having an obvious place to put the new uiout by then, and not
wanting to abuse CLI's uiout, I made a temporary uiout when
necessary.
- Hopefuly the rest of the patch is more or less obvious given the
comments I added.
Tested on x86_64 Fedora 16, no regressions.
2012-05-09 Pedro Alves <palves@redhat.com>
PR gdb/13860
* gdbthread.h (struct thread_control_state): New field
`command_interp'.
* infrun.c (follow_fork): Copy the new thread control field to the
child fork thread.
(clear_proceed_status_thread): Clear the new thread control field.
(proceed): Set the new thread control field.
* interps.h (command_interp): Declare.
* interps.c (command_interpreter): New global.
(command_interp): New function.
(interp_exec): Set `command_interpreter' while here.
* cli-out.c (cli_uiout_dtor): New function.
(cli_ui_out_impl): Install it.
* mi/mi-interp.c: Include cli-out.h.
(mi_cmd_interpreter_exec): Add comment.
(restore_current_uiout_cleanup): New function.
(ui_out_free_cleanup): New function.
(mi_on_normal_stop): In async mode, if finishing an execution
command started by a CLI command, or any kind of breakpoint-like
event triggered, print the stop event to the output (CLI) stream.
* mi/mi-out.c (mi_ui_out_impl): Install NULL `dtor' handler.
gdb/testsuite/
* gdb.mi/mi-cli.exp: Also expect the new source line to be output
after a "next", in async mode. Make it a pass/fail test.
* gdb.mi/mi-solib.exp: Test that the CLI solib event note is
output.
---
gdb/cli-out.c | 13 +++++++-
gdb/gdbthread.h | 5 +++
gdb/infrun.c | 14 +++++++++
gdb/interps.c | 36 ++++++++++++++++++++-
gdb/interps.h | 2 ++
gdb/mi/mi-interp.c | 66 +++++++++++++++++++++++++++++++++++++++
gdb/testsuite/gdb.mi/mi-cli.exp | 13 +++++---
gdb/testsuite/gdb.mi/mi-solib.exp | 11 +++++++
8 files changed, 154 insertions(+), 6 deletions(-)
diff --git a/gdb/cli-out.c b/gdb/cli-out.c
index 380352b..cedd3af 100644
--- a/gdb/cli-out.c
+++ b/gdb/cli-out.c
@@ -40,6 +40,17 @@ static void out_field_fmt (struct ui_out *uiout, int fldno,
const char *fldname,
const char *format,...) ATTRIBUTE_PRINTF (4, 5);
+/* The destructor. */
+
+static void
+cli_uiout_dtor (struct ui_out *ui_out)
+{
+ cli_out_data *data = ui_out_data (ui_out);
+
+ VEC_free (ui_filep, data->streams);
+ xfree (data);
+}
+
/* These are the CLI output functions */
/* Mark beginning of a table */
@@ -370,7 +381,7 @@ struct ui_out_impl cli_ui_out_impl =
cli_wrap_hint,
cli_flush,
cli_redirect,
- 0,
+ cli_uiout_dtor,
0, /* Does not need MI hacks (i.e. needs CLI hacks). */
};
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index c3b85dc..f3e8db1 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -122,6 +122,11 @@ struct thread_control_state
/* Chain containing status of breakpoint(s) the thread stopped
at. */
bpstat stop_bpstat;
+
+ /* The interpreter that issued the execution command. NULL if the
+ thread was resumed as a result of a command applied to some other
+ thread (e.g., "next" with scheduler-locking off). */
+ struct interp *command_interp;
};
/* Inferior thread specific part of `struct infcall_suspend_state'.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 53ecc1d..0052ef2 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -428,6 +428,7 @@ follow_fork (void)
CORE_ADDR step_range_start = 0;
CORE_ADDR step_range_end = 0;
struct frame_id step_frame_id = { 0 };
+ struct interp *command_interp = NULL;
if (!non_stop)
{
@@ -479,6 +480,7 @@ follow_fork (void)
step_frame_id = tp->control.step_frame_id;
exception_resume_breakpoint
= clone_momentary_breakpoint (tp->control.exception_resume_breakpoint);
+ command_interp = tp->control.command_interp;
/* For now, delete the parent's sr breakpoint, otherwise,
parent/child sr breakpoints are considered duplicates,
@@ -490,6 +492,7 @@ follow_fork (void)
tp->control.step_range_end = 0;
tp->control.step_frame_id = null_frame_id;
delete_exception_resume_breakpoint (tp);
+ tp->control.command_interp = NULL;
}
parent = inferior_ptid;
@@ -534,6 +537,7 @@ follow_fork (void)
tp->control.step_frame_id = step_frame_id;
tp->control.exception_resume_breakpoint
= exception_resume_breakpoint;
+ tp->control.command_interp = command_interp;
}
else
{
@@ -1993,6 +1997,8 @@ clear_proceed_status_thread (struct thread_info *tp)
tp->control.proceed_to_finish = 0;
+ tp->control.command_interp = NULL;
+
/* Discard any remaining commands or status from previous stop. */
bpstat_clear (&tp->control.stop_bpstat);
}
@@ -2194,6 +2200,14 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
regcache_write_pc (regcache, addr);
}
+ /* Record the interpreter that issued the execution command that
+ caused this thread to resume. If the top level interpreter is
+ MI/async, and the execution command was a CLI command
+ (next/step/etc.), we'll want to print stop event output to the MI
+ console channel (the stepped-to line, etc.), as if the user
+ entered the execution command on a real GDB console. */
+ inferior_thread ()->control.command_interp = command_interp ();
+
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: proceed (addr=%s, signal=%d, step=%d)\n",
diff --git a/gdb/interps.c b/gdb/interps.c
index 25500d6..ca3b9b5 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -315,6 +315,29 @@ current_interp_display_prompt_p (void)
data);
}
+/* The interpreter that is active while `interp_exec' is active, NULL
+ at all other times. */
+static struct interp *command_interpreter;
+
+/* The interpreter that was active when a command was executed.
+ Normally that'd always be CURRENT_INTERPRETER, except that MI's
+ -interpreter-exec command doesn't actually flip the current
+ interpreter when running its sub-command. The
+ `command_interpreter' global tracks when interp_exec is called
+ (IOW, when -interpreter-exec is called). If that is set, it is
+ INTERP in '-interpreter-exec INTERP "CMD"' or in 'interpreter-exec
+ INTERP "CMD". Otherwise, interp_exec isn't active, and so the
+ interpreter running the command is the current interpreter. */
+
+struct interp *
+command_interp (void)
+{
+ if (command_interpreter != NULL)
+ return command_interpreter;
+ else
+ return current_interpreter;
+}
+
/* Run the current command interpreter's main loop. */
void
current_interp_command_loop (void)
@@ -362,7 +385,18 @@ interp_exec (struct interp *interp, const char *command_str)
{
if (interp->procs->exec_proc != NULL)
{
- return interp->procs->exec_proc (interp->data, command_str);
+ struct gdb_exception ex;
+ struct interp *save_command_interp;
+
+ /* See `command_interp' for why we do this. */
+ save_command_interp = command_interpreter;
+ command_interpreter = interp;
+
+ ex = interp->procs->exec_proc (interp->data, command_str);
+
+ command_interpreter = save_command_interp;
+
+ return ex;
}
return exception_none;
}
diff --git a/gdb/interps.h b/gdb/interps.h
index 58ac6b2..6a45a7b 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -97,6 +97,8 @@ extern int current_interp_set_logging (int start_log, struct ui_file *out,
extern void *top_level_interpreter_data (void);
extern struct interp *top_level_interpreter (void);
+extern struct interp *command_interp (void);
+
/* True if the current interpreter is in async mode, false if in sync
mode. If in sync mode, running a synchronous execution command
(with execute_command, e.g, "next") will not return until the
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 0cd43f5..b4515d9 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -37,6 +37,7 @@
#include "gdb.h"
#include "objfiles.h"
#include "tracepoint.h"
+#include "cli-out.h"
/* These are the interpreter setup, etc. functions for the MI
interpreter. */
@@ -251,6 +252,10 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
"does not support command execution"),
argv[0]);
+ /* Note that unlike the CLI version of this command, we don't
+ actually set INTERP_TO_USE as the current interpreter, as we
+ still want gdb_stdout, etc. to point at MI streams. */
+
/* Insert the MI out hooks, making sure to also call the
interpreter's hooks if it has any. */
/* KRS: We shouldn't need this... Events should be installed and
@@ -453,6 +458,26 @@ mi_inferior_removed (struct inferior *inf)
gdb_flush (mi->event_channel);
}
+/* Cleanup that restores a previous current uiout. */
+
+static void
+restore_current_uiout_cleanup (void *arg)
+{
+ struct ui_out *saved_uiout = arg;
+
+ current_uiout = saved_uiout;
+}
+
+/* Cleanup that destroys the a ui_out object. */
+
+static void
+ui_out_free_cleanup (void *arg)
+{
+ struct ui_out *uiout = arg;
+
+ ui_out_destroy (uiout);
+}
+
static void
mi_on_normal_stop (struct bpstats *bs, int print_frame)
{
@@ -483,6 +508,47 @@ mi_on_normal_stop (struct bpstats *bs, int print_frame)
current_uiout = saved_uiout;
}
+ /* Otherwise, frame information has already been printed by
+ normal_stop. */
+ else if (target_can_async_p ())
+ {
+ /* However, CLI execution commands (-interpreter-exec
+ console "next", for example) in async mode have the
+ opposite issue. normal_stop has already printed frame
+ information to MI uiout, but nothing has printed the same
+ information to the CLI channel. We should print the
+ source line to the console when stepping or other similar
+ commands, iff the step was started by a console command
+ (but not if it was started with -exec-step or similar).
+ Breakpoint hits should always be mirrored to the
+ console. */
+ struct thread_info *tp = inferior_thread ();
+
+ if ((tp->control.command_interp != NULL
+ && tp->control.command_interp != top_level_interpreter ())
+ || (!tp->control.stop_step
+ && !tp->control.proceed_to_finish))
+ {
+ struct mi_interp *mi = top_level_interpreter_data ();
+ struct target_waitstatus last;
+ ptid_t last_ptid;
+ struct ui_out *cli_uiout;
+ struct cleanup *old_chain;
+
+ /* Sets the current uiout to a new temporary CLI uiout
+ assigned to STREAM. */
+ cli_uiout = cli_out_new (mi->out);
+ old_chain = make_cleanup (ui_out_free_cleanup, cli_uiout);
+
+ make_cleanup (restore_current_uiout_cleanup, current_uiout);
+ current_uiout = cli_uiout;
+
+ get_last_target_status (&last_ptid, &last);
+ print_stop_event (&last);
+
+ do_cleanups (old_chain);
+ }
+ }
ui_out_field_int (mi_uiout, "thread-id",
pid_to_thread_id (inferior_ptid));
diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp
index 5b809e2..bee296d 100644
--- a/gdb/testsuite/gdb.mi/mi-cli.exp
+++ b/gdb/testsuite/gdb.mi/mi-cli.exp
@@ -166,10 +166,15 @@ mi_gdb_test "34 next" \
".*34\\\^running.*\\*running,thread-id=\"all\"" \
"34 next: run"
-if {!$async} {
- gdb_expect {
- -re "~\[^\r\n\]+\r\n" {
- }
+# Test that the new current source line is output, given we executed
+# the console 'next' command, not -exec-next.
+set test "34 next: CLI output"
+gdb_expect {
+ -re "~\"67\[^\r\n\]+\r\n" {
+ pass $test
+ }
+ timeout {
+ fail "$test (timeout)"
}
}
diff --git a/gdb/testsuite/gdb.mi/mi-solib.exp b/gdb/testsuite/gdb.mi/mi-solib.exp
index cd400ea..0a8b43b 100644
--- a/gdb/testsuite/gdb.mi/mi-solib.exp
+++ b/gdb/testsuite/gdb.mi/mi-solib.exp
@@ -60,4 +60,15 @@ mi_gdb_test "777-gdb-set stop-on-solib-events 1" "777\\^done" \
# commands still cause the correct MI output to be generated.
mi_run_with_cli
+# Also test that the CLI solib event note is output.
+set test "CLI prints solib event"
+gdb_expect {
+ -re "~\"Stopped due to shared library event \\(no libraries added or removed\\)\\\\n" {
+ pass "$test"
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+}
+
mi_expect_stop solib-event .* .* .* .* .* "check for solib event"
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v2 5/9] PR gdb/13860: make "-exec-foo"'s MI output equal to "foo"'s MI output.
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
` (6 preceding siblings ...)
2013-07-31 18:28 ` [PATCH v2 6/9] PR gdb/13860: don't lose '-interpreter-exec console EXECUTION_COMMAND''s output in async mode Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
2013-07-31 18:28 ` [PATCH v2 1/9] fix latent bugs in ui-out.c Tom Tromey
8 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Pedro Alves
From: Pedro Alves <palves@redhat.com>
Part of PR gdb/13860 is about the mi-solib.exp test's output being
different in sync vs async modes.
sync:
>./gdb -nx -q ./testsuite/gdb.mi/solib-main -ex "set stop-on-solib-events 1" -ex "set target-async off" -i=mi
=thread-group-added,id="i1"
~"Reading symbols from /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main..."
~"done.\n"
(gdb)
&"start\n"
~"Temporary breakpoint 1 at 0x400608: file ../../../src/gdb/testsuite/gdb.mi/solib-main.c, line 21.\n"
=breakpoint-created,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x0000000000400608",func="main",file="../../../src/gdb/testsuite/gdb.mi/solib-main.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/solib-main.c",line="21",times="0",original-location="main"}
~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main \n"
=thread-group-started,id="i1",pid="17724"
=thread-created,id="1",group-id="i1"
^running
*running,thread-id="all"
(gdb)
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
~"Stopped due to shared library event (no libraries added or removed)\n"
*stopped,reason="solib-event",frame={addr="0x000000379180f990",func="_dl_debug_state",args=[],from="/lib64/ld-linux-x86-64.so.2"},thread-id="1",stopped-threads="all",core="3"
(gdb)
async:
>./gdb -nx -q ./testsuite/gdb.mi/solib-main -ex "set stop-on-solib-events 1" -ex "set target-async on" -i=mi
=thread-group-added,id="i1"
~"Reading symbols from /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main..."
~"done.\n"
(gdb)
start
&"start\n"
~"Temporary breakpoint 1 at 0x400608: file ../../../src/gdb/testsuite/gdb.mi/solib-main.c, line 21.\n"
=breakpoint-created,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x0000000000400608",func="main",file="../../../src/gdb/testsuite/gdb.mi/solib-main.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/solib-main.c",line="21",times="0",original-location="main"}
~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main \n"
=thread-group-started,id="i1",pid="17729"
=thread-created,id="1",group-id="i1"
^running
*running,thread-id="all"
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
(gdb)
*stopped,reason="solib-event",thread-id="1",stopped-threads="all",core="1"
For now, let's focus only on the *stopped event. We see that the
async output is missing frame info. And this causes a test failure in
async mode, as "mi_expect_stop solib-event" wants to see the frame
info.
However, if we compare the event output when a real MI execution
command is used, compared to a CLI command (e.g., run vs -exec-run,
next vs -exec-next, etc.), we see:
>./gdb -nx -q ./testsuite/gdb.mi/solib-main -ex "set stop-on-solib-events 1" -ex "set target-async off" -i=mi
=thread-group-added,id="i1"
~"Reading symbols from /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main..."
~"done.\n"
(gdb)
r
&"r\n"
~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main \n"
=thread-group-started,id="i1",pid="17751"
=thread-created,id="1",group-id="i1"
^running
*running,thread-id="all"
(gdb)
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
~"Stopped due to shared library event (no libraries added or removed)\n"
*stopped,reason="solib-event",frame={addr="0x000000379180f990",func="_dl_debug_state",args=[],from="/lib64/ld-linux-x86-64.so.2"},thread-id="1",stopped-threads="all",core="3"
(gdb)
-exec-run
=thread-exited,id="1",group-id="i1"
=thread-group-exited,id="i1"
=library-unloaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",thread-group="i1"
=thread-group-started,id="i1",pid="17754"
=thread-created,id="1",group-id="i1"
^running
*running,thread-id="all"
(gdb)
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
*stopped,reason="solib-event",thread-id="1",stopped-threads="all",core="1"
=thread-selected,id="1"
(gdb)
As seen above, with MI commands, the *stopped event _doesn't_ have
frame info. This is because normal_stop, as commanded by the result
of bpstat_print, skips printing frame info in this case (it's an
"event", not a "breakpoint"), and when the interpreter is MI,
mi_on_normal_stop skips calling print_stack_frame, as the normal_stop
call was already done with the MI uiout. This explains why the async
output is different even with a CLI command. Its because in async
mode, the mi_on_normal_stop path is always taken; it is always reached
with the MI uiout, because the stop is handled from the event loop,
instead of from within `proceed -> wait_for_inferior -> normal_stop'
with the interpreter overridden, as in sync mode.
This patch fixes the issue by making all cases output the same
*stopped event, by factoring out the print code from normal_stop, and
using it from mi_on_normal_stop as well. I chose the *stopped output
without a frame, mainly because that is what you already get if you
use MI execution commands, the commands frontends are supposed to use
(except when implementing a console). This patch makes it simpler to
tweak the MI output differently if desired, as we only have to change
the centralized print_stop_event (taking into account whether the
uiout is MI-like), and all different modes will change accordingly.
Tested on x86_64 Fedora 16, no regressions. The mi-solib.exp test no
longer fails in async mode with this patch, so the patch removes the
kfail.
2012-05-09 Pedro Alves <palves@redhat.com>
PR gdb/13860
gdb/
* inferior.h (print_stop_event): Declare.
* infrun.c (print_stop_event): New, factored out from ...
(normal_stop): ... this.
* mi/mi-interp.c (mi_on_normal_stop): Use print_stop_event instead
of bpstat_print/print_stack_frame.
gdb/testsuite/
* gdb.mi/mi-solib.exp: Remove gdb/13860 kfail.
* lib/mi-support.exp (mi_expect_stop): Add special handling for
solib-event.
---
gdb/inferior.h | 2 +
gdb/infrun.c | 118 ++++++++++++++++++++------------------
gdb/mi/mi-interp.c | 3 +-
gdb/testsuite/gdb.mi/mi-solib.exp | 4 --
gdb/testsuite/lib/mi-support.exp | 18 +++++-
5 files changed, 82 insertions(+), 63 deletions(-)
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 2a5770d..a748d8b 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -210,6 +210,8 @@ extern void start_remote (int from_tty);
extern void normal_stop (void);
+extern void print_stop_event (struct target_waitstatus *ws);
+
extern int signal_stop_state (int);
extern int signal_print_state (int);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index dc1036d..53ecc1d 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5922,6 +5922,68 @@ print_no_history_reason (void)
ui_out_text (current_uiout, "\nNo more reverse-execution history.\n");
}
+/* Print current location without a level number, if we have changed
+ functions or hit a breakpoint. Print source line if we have one.
+ bpstat_print contains the logic deciding in detail what to print,
+ based on the event(s) that just occurred. */
+
+void
+print_stop_event (struct target_waitstatus *ws)
+{
+ int bpstat_ret;
+ int source_flag;
+ int do_frame_printing = 1;
+ struct thread_info *tp = inferior_thread ();
+
+ bpstat_ret = bpstat_print (tp->control.stop_bpstat, ws->kind);
+ switch (bpstat_ret)
+ {
+ case PRINT_UNKNOWN:
+ /* FIXME: cagney/2002-12-01: Given that a frame ID does (or
+ should) carry around the function and does (or should) use
+ that when doing a frame comparison. */
+ if (tp->control.stop_step
+ && frame_id_eq (tp->control.step_frame_id,
+ get_frame_id (get_current_frame ()))
+ && step_start_function == find_pc_function (stop_pc))
+ {
+ /* Finished step, just print source line. */
+ source_flag = SRC_LINE;
+ }
+ else
+ {
+ /* Print location and source line. */
+ source_flag = SRC_AND_LOC;
+ }
+ break;
+ case PRINT_SRC_AND_LOC:
+ /* Print location and source line. */
+ source_flag = SRC_AND_LOC;
+ break;
+ case PRINT_SRC_ONLY:
+ source_flag = SRC_LINE;
+ break;
+ case PRINT_NOTHING:
+ /* Something bogus. */
+ source_flag = SRC_LINE;
+ do_frame_printing = 0;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, _("Unknown value."));
+ }
+
+ /* The behavior of this routine with respect to the source
+ flag is:
+ SRC_LINE: Print only source line
+ LOCATION: Print only location
+ SRC_AND_LOC: Print location and source line. */
+ if (do_frame_printing)
+ print_stack_frame (get_selected_frame (NULL), 0, source_flag);
+
+ /* Display the auto-display expressions. */
+ do_displays ();
+}
+
/* Here to return control to GDB when the inferior stops for real.
Print appropriate messages, remove breakpoints, give terminal our modes.
@@ -6044,65 +6106,11 @@ normal_stop (void)
{
select_frame (get_current_frame ());
- /* Print current location without a level number, if
- we have changed functions or hit a breakpoint.
- Print source line if we have one.
- bpstat_print() contains the logic deciding in detail
- what to print, based on the event(s) that just occurred. */
-
/* If --batch-silent is enabled then there's no need to print the current
source location, and to try risks causing an error message about
missing source files. */
if (stop_print_frame && !batch_silent)
- {
- int bpstat_ret;
- int source_flag;
- int do_frame_printing = 1;
- struct thread_info *tp = inferior_thread ();
-
- bpstat_ret = bpstat_print (tp->control.stop_bpstat, last.kind);
- switch (bpstat_ret)
- {
- case PRINT_UNKNOWN:
- /* FIXME: cagney/2002-12-01: Given that a frame ID does
- (or should) carry around the function and does (or
- should) use that when doing a frame comparison. */
- if (tp->control.stop_step
- && frame_id_eq (tp->control.step_frame_id,
- get_frame_id (get_current_frame ()))
- && step_start_function == find_pc_function (stop_pc))
- source_flag = SRC_LINE; /* Finished step, just
- print source line. */
- else
- source_flag = SRC_AND_LOC; /* Print location and
- source line. */
- break;
- case PRINT_SRC_AND_LOC:
- source_flag = SRC_AND_LOC; /* Print location and
- source line. */
- break;
- case PRINT_SRC_ONLY:
- source_flag = SRC_LINE;
- break;
- case PRINT_NOTHING:
- source_flag = SRC_LINE; /* something bogus */
- do_frame_printing = 0;
- break;
- default:
- internal_error (__FILE__, __LINE__, _("Unknown value."));
- }
-
- /* The behavior of this routine with respect to the source
- flag is:
- SRC_LINE: Print only source line
- LOCATION: Print only location
- SRC_AND_LOC: Print location and source line. */
- if (do_frame_printing)
- print_stack_frame (get_selected_frame (NULL), 0, source_flag);
-
- /* Display the auto-display expressions. */
- do_displays ();
- }
+ print_stop_event (&last);
}
/* Save the function value return registers, if we care.
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 2702f4f..0cd43f5 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -479,9 +479,8 @@ mi_on_normal_stop (struct bpstats *bs, int print_frame)
current_uiout = mi_uiout;
get_last_target_status (&last_ptid, &last);
- bpstat_print (bs, last.kind);
+ print_stop_event (&last);
- print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC);
current_uiout = saved_uiout;
}
diff --git a/gdb/testsuite/gdb.mi/mi-solib.exp b/gdb/testsuite/gdb.mi/mi-solib.exp
index a760f92..cd400ea 100644
--- a/gdb/testsuite/gdb.mi/mi-solib.exp
+++ b/gdb/testsuite/gdb.mi/mi-solib.exp
@@ -60,8 +60,4 @@ mi_gdb_test "777-gdb-set stop-on-solib-events 1" "777\\^done" \
# commands still cause the correct MI output to be generated.
mi_run_with_cli
-global async
-if { $async } {
- setup_kfail gdb/13860 *-*-*
-}
mi_expect_stop solib-event .* .* .* .* .* "check for solib event"
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 86a0fd6..6ad8f99 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -1013,6 +1013,8 @@ proc mi_expect_stop { reason func args file line extra test } {
global thread_selected_re
global breakpoint_re
+ set any "\[^\n\]*"
+
set after_stopped ""
set after_reason ""
if { [llength $extra] == 2 } {
@@ -1055,6 +1057,20 @@ proc mi_expect_stop { reason func args file line extra test } {
return
}
+ if { $reason == "solib-event" } {
+ set pattern "\\*stopped,reason=\"solib-event\",thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re"
+ verbose -log "mi_expect_stop: expecting: $pattern"
+ gdb_expect {
+ -re "$pattern" {
+ pass "$test"
+ }
+ timeout {
+ fail "$test (unknown output after running)"
+ }
+ }
+ return
+ }
+
set args "\\\[$args\\\]"
set bn ""
@@ -1072,8 +1088,6 @@ proc mi_expect_stop { reason func args file line extra test } {
set a $after_reason
- set any "\[^\n\]*"
-
verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,(?:file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"|from=\"$file\")\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re"
gdb_expect {
-re "\\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,(?:file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"|from=\"$file\")\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re" {
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v2 1/9] fix latent bugs in ui-out.c
2013-07-31 18:28 [PATCH v2 0/9] enable target-async by default Tom Tromey
` (7 preceding siblings ...)
2013-07-31 18:28 ` [PATCH v2 5/9] PR gdb/13860: make "-exec-foo"'s MI output equal to "foo"'s MI output Tom Tromey
@ 2013-07-31 18:28 ` Tom Tromey
8 siblings, 0 replies; 16+ messages in thread
From: Tom Tromey @ 2013-07-31 18:28 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
The destructor code in ui-out.c has a latent bug, which is hidden by
the fact that nothing uses this right now. This patch fixes the
problem. The bug is that we don't always clear a pointer in the
ui-out object, leading to bad a free.
* ui-out.c (clear_table, ui_out_new): Clear uiout->table.id.
---
gdb/ui-out.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index 03b1240..3c6c529 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -807,8 +807,8 @@ uo_table_header (struct ui_out *uiout, int width, enum ui_align align,
static void
clear_table (struct ui_out *uiout)
{
- if (uiout->table.id)
- xfree (uiout->table.id);
+ xfree (uiout->table.id);
+ uiout->table.id = NULL;
clear_header_list (uiout);
}
@@ -1114,6 +1114,7 @@ ui_out_new (struct ui_out_impl *impl, void *data,
current->field_count = 0;
VEC_safe_push (ui_out_level_p, uiout->levels, current);
+ uiout->table.id = NULL;
uiout->table.header_first = NULL;
uiout->table.header_last = NULL;
uiout->table.header_next = NULL;
--
1.8.1.4
^ permalink raw reply [flat|nested] 16+ messages in thread