From 67b5c0c1a4336318f23f65b8fa98a08b569c5c39 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Wed, 5 Mar 2014 15:38:11 +0100 Subject: [PATCH] btrace: control memory access during replay The btrace record target does not trace data. We therefore do not allow accessing read-write memory during replay. In some cases, this might be useful to advanced users, though, who we assume to know what they are doing. Add a set|show command pair to turn this memory access restriction off. * record-btrace.c (record_btrace_allow_memory_access): Remove. (replay_memory_access_read_only, replay_memory_access_read_write) (replay_memory_access_types, replay_memory_access) (set_record_btrace_cmdlist, show_record_btrace_cmdlist) (cmd_set_record_btrace, cmd_show_record_btrace) (cmd_show_replay_memory_access): New. (record_btrace_xfer_partial, record_btrace_insert_breakpoint) (record_btrace_remove_breakpoint): Replace record_btrace_allow_memory_access with replay_memory_access. (_initialize_record_btrace): Add commands. * NEWS: Announce it. testsuite/ * gdb.btrace/data.exp: Test it. doc/ * gdb.texinfo (Process Record and Replay): Document it. --- gdb/ChangeLog | 14 +++++ gdb/NEWS | 4 ++ gdb/doc/ChangeLog | 5 ++ gdb/doc/gdb.texinfo | 22 ++++++++ gdb/record-btrace.c | 88 +++++++++++++++++++++++++++---- gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.btrace/data.exp | 10 +++- 7 files changed, 135 insertions(+), 12 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2418b45e786..a6050859243 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2014-05-23 Markus Metzger + + * record-btrace.c (record_btrace_allow_memory_access): Remove. + (replay_memory_access_read_only, replay_memory_access_read_write) + (replay_memory_access_types, replay_memory_access) + (set_record_btrace_cmdlist, show_record_btrace_cmdlist) + (cmd_set_record_btrace, cmd_show_record_btrace) + (cmd_show_replay_memory_access): New. + (record_btrace_xfer_partial, record_btrace_insert_breakpoint) + (record_btrace_remove_breakpoint): Replace + record_btrace_allow_memory_access with replay_memory_access. + (_initialize_record_btrace): Add commands. + * NEWS: Announce it. + 2014-05-22 Ramana Radhakrishnan * aarch64-linux-nat.c (asm/ptrace.h): Include. diff --git a/gdb/NEWS b/gdb/NEWS index 4663650253e..5a0a76e2ffe 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -67,6 +67,10 @@ set auto-connect-native-target native target for the run, attach, etc. commands when not connected to any target yet. See also "target native" below. +set record btrace replay-memory-access (read-only|read-write) +show record btrace replay-memory-access + Control what memory accesses are allowed during replay. + * New features in the GDB remote stub, GDBserver ** New option --debug-format=option1[,option2,...] allows one to add diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 18588f6c7be..25bdc32b03b 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2014-05-23 Markus Metzger + + * gdb.texinfo (Process Record and Replay): Document "set/show btrace + replay-memory-access". + 2014-05-21 Pedro Alves * gdb.texinfo (Starting): Document "set/show diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 47d4bb71f6b..cc188aec478 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6451,6 +6451,28 @@ results. @item show record full memory-query Show the current setting of @code{memory-query}. +@kindex set record btrace +The @code{btrace} record target does not trace data. As a +convenience, when replaying, @value{GDBN} reads read-only memory off +the live program directly, assuming that the addresses of the +read-only areas don't change. This for example makes it possible to +disassemble code while replaying, but not to print variables. +In some cases, being able to inspect variables might be useful. +You can use the following command for that: + +@item set record btrace replay-memory-access +Control the behavior of the @code{btrace} recording method when +accessing memory during replay. If @code{read-only} (the default), +@value{GDBN} will only allow accesses to read-only memory. +If @code{read-write}, @value{GDBN} will allow accesses to read-only +and to read-write memory. Beware that the accessed memory corresponds +to the live target and not necessarily to the current replay +position. + +@kindex show record btrace +@item show record btrace replay-memory-access +Show the current setting of @code{replay-memory-access}. + @kindex info record @item info record Show various statistics about the recording depending on the recording diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 2304020f80c..166e78edace 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -43,8 +43,22 @@ static struct target_ops record_btrace_ops; /* A new thread observer enabling branch tracing for the new thread. */ static struct observer *record_btrace_thread_observer; -/* Temporarily allow memory accesses. */ -static int record_btrace_allow_memory_access; +/* Memory access types used in set/show record btrace replay-memory-access. */ +static const char replay_memory_access_read_only[] = "read-only"; +static const char replay_memory_access_read_write[] = "read-write"; +static const char *const replay_memory_access_types[] = +{ + replay_memory_access_read_only, + replay_memory_access_read_write, + NULL +}; + +/* The currently allowed replay memory access type. */ +static const char *replay_memory_access = replay_memory_access_read_only; + +/* Command lists for "set/show record btrace". */ +static struct cmd_list_element *set_record_btrace_cmdlist; +static struct cmd_list_element *show_record_btrace_cmdlist; /* Print a record-btrace debug message. Use do ... while (0) to avoid ambiguities when used in if statements. */ @@ -816,7 +830,8 @@ record_btrace_xfer_partial (struct target_ops *ops, enum target_object object, struct target_ops *t; /* Filter out requests that don't make sense during replay. */ - if (!record_btrace_allow_memory_access && record_btrace_is_replaying (ops)) + if (replay_memory_access == replay_memory_access_read_only + && record_btrace_is_replaying (ops)) { switch (object) { @@ -870,18 +885,19 @@ record_btrace_insert_breakpoint (struct target_ops *ops, struct bp_target_info *bp_tgt) { volatile struct gdb_exception except; - int old, ret; + const char *old; + int ret; /* Inserting breakpoints requires accessing memory. Allow it for the duration of this function. */ - old = record_btrace_allow_memory_access; - record_btrace_allow_memory_access = 1; + old = replay_memory_access; + replay_memory_access = replay_memory_access_read_write; ret = 0; TRY_CATCH (except, RETURN_MASK_ALL) ret = ops->beneath->to_insert_breakpoint (ops->beneath, gdbarch, bp_tgt); - record_btrace_allow_memory_access = old; + replay_memory_access = old; if (except.reason < 0) throw_exception (except); @@ -897,18 +913,19 @@ record_btrace_remove_breakpoint (struct target_ops *ops, struct bp_target_info *bp_tgt) { volatile struct gdb_exception except; - int old, ret; + const char *old; + int ret; /* Removing breakpoints requires accessing memory. Allow it for the duration of this function. */ - old = record_btrace_allow_memory_access; - record_btrace_allow_memory_access = 1; + old = replay_memory_access; + replay_memory_access = replay_memory_access_read_write; ret = 0; TRY_CATCH (except, RETURN_MASK_ALL) ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch, bp_tgt); - record_btrace_allow_memory_access = old; + replay_memory_access = old; if (except.reason < 0) throw_exception (except); @@ -1939,6 +1956,32 @@ cmd_record_btrace_start (char *args, int from_tty) execute_command ("target record-btrace", from_tty); } +/* The "set record btrace" command. */ + +static void +cmd_set_record_btrace (char *args, int from_tty) +{ + cmd_show_list (set_record_btrace_cmdlist, from_tty, ""); +} + +/* The "show record btrace" command. */ + +static void +cmd_show_record_btrace (char *args, int from_tty) +{ + cmd_show_list (show_record_btrace_cmdlist, from_tty, ""); +} + +/* The "show record btrace replay-memory-access" command. */ + +static void +cmd_show_replay_memory_access (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (gdb_stdout, _("Replay memory access is %s.\n"), + replay_memory_access); +} + void _initialize_record_btrace (void); /* Initialize btrace commands. */ @@ -1951,6 +1994,29 @@ _initialize_record_btrace (void) &record_cmdlist); add_alias_cmd ("b", "btrace", class_obscure, 1, &record_cmdlist); + add_prefix_cmd ("btrace", class_support, cmd_set_record_btrace, + _("Set record options"), &set_record_btrace_cmdlist, + "set record btrace ", 0, &set_record_cmdlist); + + add_prefix_cmd ("btrace", class_support, cmd_show_record_btrace, + _("Show record options"), &show_record_btrace_cmdlist, + "show record btrace ", 0, &show_record_cmdlist); + + add_setshow_enum_cmd ("replay-memory-access", no_class, + replay_memory_access_types, &replay_memory_access, _("\ +Set what memory accesses are allowed during replay."), _("\ +Show what memory accesses are allowed during replay."), + _("Default is READ-ONLY.\n\n\ +The btrace record target does not trace data.\n\ +The memory therefore corresponds to the live target and not \ +to the current replay position.\n\n\ +When READ-ONLY, allow accesses to read-only memory during replay.\n\ +When READ-WRITE, allow accesses to read-only and read-write memory during \ +replay."), + NULL, cmd_show_replay_memory_access, + &set_record_btrace_cmdlist, + &show_record_btrace_cmdlist); + init_record_btrace_ops (); add_target (&record_btrace_ops); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 1473d9681b1..fdbae2573e9 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-05-23 Markus Metzger + + * gdb.btrace/data.exp: Test memory access during btrace replay. + 2014-05-22 Simon Marchi * lib/mi-support.exp (mi_run_cmd_full): Add comments. diff --git a/gdb/testsuite/gdb.btrace/data.exp b/gdb/testsuite/gdb.btrace/data.exp index 64c5443ae45..91d8d8bd7d7 100644 --- a/gdb/testsuite/gdb.btrace/data.exp +++ b/gdb/testsuite/gdb.btrace/data.exp @@ -40,6 +40,14 @@ gdb_test "reverse-step" ".*test\.4.*" gdb_test "print glob" "unavailable\[^\\\r\\\n\]*" gdb_test "print loc" "unavailable\[^\\\r\\\n\]*" +# we can read memory if we explicitly allow it. +gdb_test_no_output "set record btrace replay-memory-access read-write" +gdb_test "print glob" "1" + +# we can't if we don't explicitly allow it. +gdb_test_no_output "set record btrace replay-memory-access read-only" +gdb_test "print glob" "unavailable\[^\\\r\\\n\]*" + # stop replaying and try again -gdb_test "record goto end" +gdb_test "record goto end" ".*main\.3.*" gdb_test "print glob" "1" -- 2.30.2