* [PATCH] Prevent turning record on while threads are running (PR 20869)
@ 2016-11-29 15:08 Simon Marchi
2016-11-29 15:58 ` Luis Machado
2016-11-30 9:54 ` Metzger, Markus T
0 siblings, 2 replies; 9+ messages in thread
From: Simon Marchi @ 2016-11-29 15:08 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Simon Marchi
As stated in the bug description, trying to do "record" while threads
are running leads to a broken state. I tried to see in the code if
there was anything to try to support the use case of enabling record
while the program is running, but didn't find anything.
When full/software recording is active, we are single stepping each
instruction. Transitioning from the state where threads are running
freely (no recording) to recording enabled should therefore involve a
step where we stop them to initiate the single stepping. I can't find
anything that looks like this, so my conclusion is that this was never a
supported use case (please correct me if I'm wrong).
The easy solution is to prevent the user for enabling record if a thread
is running.
I also wanted to know whether it was supported to start btrace bts/pt
recording with threads running. When I try it with btrace bts, it works
halfway. "record btrace bts" gives me the error:
Couldn't get registers: No such process.
If I do the command again, gdb doesn't complain and then I'm able to
interrupt the target and use reverse-next. However, since the
initialization function was interrupted halfway, I am not sure that
everything is setup correctly. If we want to allow it, we would first
need to look into this issue.
I have therefore put a check for running threads in record_preopen,
which affects all recording methods. It can always be moved to
record_full_open if we only want to affect record full.
No regression on the buildbot.
gdb/ChangeLog:
* record.c: Include gdbthread.h.
(record_preopen): Check if any thread is running.
gdb/testsuite:
* gdb.reverse/record-while-running.c: New file.
* gdb.reverse/record-while-running.exp: New file.
---
gdb/record.c | 11 ++++++
gdb/testsuite/gdb.reverse/record-while-running.c | 29 ++++++++++++++++
gdb/testsuite/gdb.reverse/record-while-running.exp | 40 ++++++++++++++++++++++
3 files changed, 80 insertions(+)
create mode 100644 gdb/testsuite/gdb.reverse/record-while-running.c
create mode 100644 gdb/testsuite/gdb.reverse/record-while-running.exp
diff --git a/gdb/record.c b/gdb/record.c
index 34ebd1b..e0bc133 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -26,6 +26,7 @@
#include "common/common-utils.h"
#include "cli/cli-utils.h"
#include "disasm.h"
+#include "gdbthread.h"
#include <ctype.h>
@@ -89,6 +90,16 @@ record_preopen (void)
if (find_record_target () != NULL)
error (_("The process is already being recorded. Use \"record stop\" to "
"stop recording first."));
+
+ iterate_over_threads([] (struct thread_info *tp, void *) -> int {
+ if (tp->state == thread_state::THREAD_RUNNING)
+ error (_ ("Can't enable record while the program is running. Use "
+ "\"interrupt\" to stop it first."));
+
+ return 0;
+ }, NULL);
+
+
}
/* See record.h. */
diff --git a/gdb/testsuite/gdb.reverse/record-while-running.c b/gdb/testsuite/gdb.reverse/record-while-running.c
new file mode 100644
index 0000000..f00ceb6
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/record-while-running.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2016 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+
+int
+main ()
+{
+ int i;
+
+ for (i = 0; i < 30; i++)
+ sleep (1);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/record-while-running.exp b/gdb/testsuite/gdb.reverse/record-while-running.exp
new file mode 100644
index 0000000..57e1df3
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/record-while-running.exp
@@ -0,0 +1,40 @@
+# Copyright 2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+# Test that trying to turn on recording while the target is running is correctly
+# handled.
+
+if ![supports_reverse] {
+ return
+}
+
+standard_testfile
+
+if { [prepare_for_testing $testfile.exp $testfile $srcfile] } {
+ fail "failed to compile"
+ return
+}
+
+if { ![runto_main] } {
+ fail "couldn't run to main"
+ return
+}
+
+proc test_record_while_running { } {
+ gdb_test "continue &" "Continuing."
+ gdb_test "record" "Can't enable record while the program is running. Use \"interrupt\" to stop it first."
+}
+
+test_record_while_running
--
2.10.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Prevent turning record on while threads are running (PR 20869)
2016-11-29 15:08 [PATCH] Prevent turning record on while threads are running (PR 20869) Simon Marchi
@ 2016-11-29 15:58 ` Luis Machado
2016-11-29 16:42 ` Simon Marchi
2016-11-30 9:54 ` Metzger, Markus T
1 sibling, 1 reply; 9+ messages in thread
From: Luis Machado @ 2016-11-29 15:58 UTC (permalink / raw)
To: Simon Marchi, gdb-patches; +Cc: markus.t.metzger
On 11/29/2016 09:07 AM, Simon Marchi wrote:
> As stated in the bug description, trying to do "record" while threads
> are running leads to a broken state. I tried to see in the code if
> there was anything to try to support the use case of enabling record
> while the program is running, but didn't find anything.
>
> When full/software recording is active, we are single stepping each
> instruction. Transitioning from the state where threads are running
> freely (no recording) to recording enabled should therefore involve a
> step where we stop them to initiate the single stepping. I can't find
> anything that looks like this, so my conclusion is that this was never a
> supported use case (please correct me if I'm wrong).
>
> The easy solution is to prevent the user for enabling record if a thread
> is running.
>
> I also wanted to know whether it was supported to start btrace bts/pt
> recording with threads running. When I try it with btrace bts, it works
> halfway. "record btrace bts" gives me the error:
>
> Couldn't get registers: No such process.
>
> If I do the command again, gdb doesn't complain and then I'm able to
> interrupt the target and use reverse-next. However, since the
> initialization function was interrupted halfway, I am not sure that
> everything is setup correctly. If we want to allow it, we would first
> need to look into this issue.
>
> I have therefore put a check for running threads in record_preopen,
> which affects all recording methods. It can always be moved to
> record_full_open if we only want to affect record full.
>
> No regression on the buildbot.
>
> gdb/ChangeLog:
>
> * record.c: Include gdbthread.h.
> (record_preopen): Check if any thread is running.
>
> gdb/testsuite:
>
> * gdb.reverse/record-while-running.c: New file.
> * gdb.reverse/record-while-running.exp: New file.
> ---
> gdb/record.c | 11 ++++++
> gdb/testsuite/gdb.reverse/record-while-running.c | 29 ++++++++++++++++
> gdb/testsuite/gdb.reverse/record-while-running.exp | 40 ++++++++++++++++++++++
> 3 files changed, 80 insertions(+)
> create mode 100644 gdb/testsuite/gdb.reverse/record-while-running.c
> create mode 100644 gdb/testsuite/gdb.reverse/record-while-running.exp
>
> diff --git a/gdb/record.c b/gdb/record.c
> index 34ebd1b..e0bc133 100644
> --- a/gdb/record.c
> +++ b/gdb/record.c
> @@ -26,6 +26,7 @@
> #include "common/common-utils.h"
> #include "cli/cli-utils.h"
> #include "disasm.h"
> +#include "gdbthread.h"
>
> #include <ctype.h>
>
> @@ -89,6 +90,16 @@ record_preopen (void)
> if (find_record_target () != NULL)
> error (_("The process is already being recorded. Use \"record stop\" to "
> "stop recording first."));
> +
> + iterate_over_threads([] (struct thread_info *tp, void *) -> int {
> + if (tp->state == thread_state::THREAD_RUNNING)
> + error (_ ("Can't enable record while the program is running. Use "
> + "\"interrupt\" to stop it first."));
> +
> + return 0;
> + }, NULL);
> +
> +
> }
>
> /* See record.h. */
> diff --git a/gdb/testsuite/gdb.reverse/record-while-running.c b/gdb/testsuite/gdb.reverse/record-while-running.c
> new file mode 100644
> index 0000000..f00ceb6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/record-while-running.c
> @@ -0,0 +1,29 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> + Copyright 2016 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +#include <unistd.h>
> +
> +int
> +main ()
> +{
> + int i;
> +
> + for (i = 0; i < 30; i++)
> + sleep (1);
> +
> + return 0;
> +}
> diff --git a/gdb/testsuite/gdb.reverse/record-while-running.exp b/gdb/testsuite/gdb.reverse/record-while-running.exp
> new file mode 100644
> index 0000000..57e1df3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/record-while-running.exp
> @@ -0,0 +1,40 @@
> +# Copyright 2016 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +# Test that trying to turn on recording while the target is running is correctly
> +# handled.
> +
> +if ![supports_reverse] {
Add an explicit untested call here?
> + return
> +}
> +
> +standard_testfile
> +
> +if { [prepare_for_testing $testfile.exp $testfile $srcfile] } {
> + fail "failed to compile"
> + return
> +}
> +
> +if { ![runto_main] } {
> + fail "couldn't run to main"
> + return
> +}
> +
> +proc test_record_while_running { } {
> + gdb_test "continue &" "Continuing."
> + gdb_test "record" "Can't enable record while the program is running. Use \"interrupt\" to stop it first."
I have mixed feelings with the above test names. I'd know what to look
for in case of failure, but more explicit test names wouldn't hurt for a
quick inspection of the logs.
"move thread"
"switch record on when thread is moving"
Feel free to pick it up though. Not a hard requirement.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Prevent turning record on while threads are running (PR 20869)
2016-11-29 15:58 ` Luis Machado
@ 2016-11-29 16:42 ` Simon Marchi
2016-11-29 16:47 ` Luis Machado
0 siblings, 1 reply; 9+ messages in thread
From: Simon Marchi @ 2016-11-29 16:42 UTC (permalink / raw)
To: Luis Machado, gdb-patches; +Cc: markus.t.metzger
On 16-11-29 10:58 AM, Luis Machado wrote:
>> +if ![supports_reverse] {
>
> Add an explicit untested call here?
Right, adding:
untested "reverse debugging not supported"
>> +proc test_record_while_running { } {
>> + gdb_test "continue &" "Continuing."
>> + gdb_test "record" "Can't enable record while the program is running. Use \"interrupt\" to stop it first."
>
> I have mixed feelings with the above test names. I'd know what to look
> for in case of failure, but more explicit test names wouldn't hurt for a
> quick inspection of the logs.
>
> "move thread"
> "switch record on when thread is moving"
>
> Feel free to pick it up though. Not a hard requirement.
You are right, it helps when reading the test. The command by itself doesn't
convey why we are using doing that command. How about:
proc_with_prefix test_record_while_running { } {
gdb_test "continue &" "Continuing." "resume target"
gdb_test \
"record" \
"Can't enable record while the program is running. Use \"interrupt\" to stop it first." \
"switch record on while target is running"
}
PASS: gdb.reverse/record-while-running.exp: test_record_while_running: resume target
PASS: gdb.reverse/record-while-running.exp: test_record_while_running: switch record on while target is running
I added proc_with_prefix, I think it can help by giving some context to the messages.
Thanks for the feedback,
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Prevent turning record on while threads are running (PR 20869)
2016-11-29 16:42 ` Simon Marchi
@ 2016-11-29 16:47 ` Luis Machado
2016-11-30 15:36 ` Pedro Alves
0 siblings, 1 reply; 9+ messages in thread
From: Luis Machado @ 2016-11-29 16:47 UTC (permalink / raw)
To: Simon Marchi, gdb-patches; +Cc: markus.t.metzger
On 11/29/2016 10:42 AM, Simon Marchi wrote:
> On 16-11-29 10:58 AM, Luis Machado wrote:
>>> +if ![supports_reverse] {
>>
>> Add an explicit untested call here?
>
> Right, adding:
>
> untested "reverse debugging not supported"
>
>>> +proc test_record_while_running { } {
>>> + gdb_test "continue &" "Continuing."
>>> + gdb_test "record" "Can't enable record while the program is running. Use \"interrupt\" to stop it first."
>>
>> I have mixed feelings with the above test names. I'd know what to look
>> for in case of failure, but more explicit test names wouldn't hurt for a
>> quick inspection of the logs.
>>
>> "move thread"
>> "switch record on when thread is moving"
>>
>> Feel free to pick it up though. Not a hard requirement.
>
> You are right, it helps when reading the test. The command by itself doesn't
> convey why we are using doing that command. How about:
>
> proc_with_prefix test_record_while_running { } {
> gdb_test "continue &" "Continuing." "resume target"
> gdb_test \
> "record" \
> "Can't enable record while the program is running. Use \"interrupt\" to stop it first." \
> "switch record on while target is running"
> }
>
> PASS: gdb.reverse/record-while-running.exp: test_record_while_running: resume target
> PASS: gdb.reverse/record-while-running.exp: test_record_while_running: switch record on while target is running
>
> I added proc_with_prefix, I think it can help by giving some context to the messages.
>
> Thanks for the feedback,
>
> Simon
>
The above looks good to me.
Thanks,
Luis
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCH] Prevent turning record on while threads are running (PR 20869)
2016-11-29 15:08 [PATCH] Prevent turning record on while threads are running (PR 20869) Simon Marchi
2016-11-29 15:58 ` Luis Machado
@ 2016-11-30 9:54 ` Metzger, Markus T
2016-11-30 16:04 ` Simon Marchi
1 sibling, 1 reply; 9+ messages in thread
From: Metzger, Markus T @ 2016-11-30 9:54 UTC (permalink / raw)
To: Simon Marchi, gdb-patches
> -----Original Message-----
> From: Simon Marchi [mailto:simon.marchi@ericsson.com]
> Sent: Tuesday, November 29, 2016 4:08 PM
> To: gdb-patches@sourceware.org
> Cc: Metzger, Markus T <markus.t.metzger@intel.com>; Simon Marchi
> <simon.marchi@ericsson.com>
> Subject: [PATCH] Prevent turning record on while threads are running (PR 20869)
Hi Simon,
Thanks for looking into this.
> I also wanted to know whether it was supported to start btrace bts/pt
> recording with threads running. When I try it with btrace bts, it works
> halfway. "record btrace bts" gives me the error:
>
> Couldn't get registers: No such process.
>
> If I do the command again, gdb doesn't complain and then I'm able to
> interrupt the target and use reverse-next. However, since the
> initialization function was interrupted halfway, I am not sure that
> everything is setup correctly. If we want to allow it, we would first
> need to look into this issue.
The issue with record-btrace is that tracing can be enabled on the target also for
running threads. When we try to insert the first record for the current PC so the
trace starts at the location from where we disabled tracing, regcache_read_pc
throws the above error. Since record_btrace_open has not installed a cleanup
to disable tracing again for this thread, we leave it enabled.
(gdb) rec bts
[record-btrace] open
[btrace] enable thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
[btrace] compute ftrace
[btrace] enable thread 2 (Thread 0x7ffff77fd700 (LWP 110346))
[btrace] disable thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
[btrace] clear thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
Couldn't get registers: No such process.
The next time we try to enable tracing, that running thread is already traced so
we skip it. If we have more than two threads running, we disable tracing again
on this thread when we fail on the next running thread. But we always leave the
highest-number running thread traced.
(gdb)
[record-btrace] open
[btrace] enable thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
[btrace] compute ftrace
[btrace] enable thread 4 (Thread 0x7ffff67fb700 (LWP 110348))
[btrace] disable thread 3 (Thread 0x7ffff6ffc700 (LWP 110347))
[btrace] clear thread 3 (Thread 0x7ffff6ffc700 (LWP 110347))
[btrace] disable thread 2 (Thread 0x7ffff77fd700 (LWP 110346))
[btrace] clear thread 2 (Thread 0x7ffff77fd700 (LWP 110346))
[btrace] disable thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
[btrace] clear thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
Couldn't get registers: No such process.
Eventually, all running threads are already traced and we succeed to enable tracing.
The trace for running threads will start from their next branch target instead of from their
current position (for BTS). This shouldn't matter unless the thread was actually waiting
and not executing any code when we started tracing. We should be able to allow it like
this:
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 39d537c..b005627 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -1474,8 +1474,28 @@ btrace_enable (struct thread_info *tp, const struct btrace_config *conf)
/* Add an entry for the current PC so we start tracing from where we
enabled it. */
- if (tp->btrace.target != NULL)
- btrace_add_pc (tp);
+ TRY
+ {
+ if (tp->btrace.target != NULL)
+ btrace_add_pc (tp);
+ }
+ CATCH (error, RETURN_MASK_ERROR)
+ {
+ /* We may fail to add the initial entry, for example if TP is currently
+ running.
+
+ For BTRACE_FORMAT_PT this doesn't matter.
+
+ For BTRACE_FORMAT_BTS we won't be able to stitch the initial trace
+ chunk to this initial entry so tracing will start at the next branch
+ target instead of at the current PC. Since TP is currently running,
+ this shouldn't make a difference.
+
+ If TP were waiting most of the time and made only a little bit of
+ progress before it was stopped, we'd lose the instructions until the
+ first branch. */
+ }
+ END_CATCH
}
/* See btrace.h. */
Do you want to extend your patch to allow tracing to be enabled for btrace or
would you rather have me fix this on top of your patch?
Thanks,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Prevent turning record on while threads are running (PR 20869)
2016-11-29 16:47 ` Luis Machado
@ 2016-11-30 15:36 ` Pedro Alves
2016-11-30 16:11 ` Luis Machado
0 siblings, 1 reply; 9+ messages in thread
From: Pedro Alves @ 2016-11-30 15:36 UTC (permalink / raw)
To: Luis Machado, Simon Marchi, gdb-patches; +Cc: markus.t.metzger
On 11/29/2016 04:47 PM, Luis Machado wrote:
> On 11/29/2016 10:42 AM, Simon Marchi wrote:
>> On 16-11-29 10:58 AM, Luis Machado wrote:
>>>> +if ![supports_reverse] {
>>>
>>> Add an explicit untested call here?
>>
>> Right, adding:
>>
>> untested "reverse debugging not supported"
Shouldn't it be "unsupported" ?
> The above looks good to me.
Agreed.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Prevent turning record on while threads are running (PR 20869)
2016-11-30 9:54 ` Metzger, Markus T
@ 2016-11-30 16:04 ` Simon Marchi
0 siblings, 0 replies; 9+ messages in thread
From: Simon Marchi @ 2016-11-30 16:04 UTC (permalink / raw)
To: Metzger, Markus T, gdb-patches
On 16-11-30 04:54 AM, Metzger, Markus T wrote:
>> -----Original Message-----
>> From: Simon Marchi [mailto:simon.marchi@ericsson.com]
>> Sent: Tuesday, November 29, 2016 4:08 PM
>> To: gdb-patches@sourceware.org
>> Cc: Metzger, Markus T <markus.t.metzger@intel.com>; Simon Marchi
>> <simon.marchi@ericsson.com>
>> Subject: [PATCH] Prevent turning record on while threads are running (PR 20869)
>
> Hi Simon,
>
> Thanks for looking into this.
>
>> I also wanted to know whether it was supported to start btrace bts/pt
>> recording with threads running. When I try it with btrace bts, it works
>> halfway. "record btrace bts" gives me the error:
>>
>> Couldn't get registers: No such process.
>>
>> If I do the command again, gdb doesn't complain and then I'm able to
>> interrupt the target and use reverse-next. However, since the
>> initialization function was interrupted halfway, I am not sure that
>> everything is setup correctly. If we want to allow it, we would first
>> need to look into this issue.
>
> The issue with record-btrace is that tracing can be enabled on the target also for
> running threads. When we try to insert the first record for the current PC so the
> trace starts at the location from where we disabled tracing, regcache_read_pc
> throws the above error. Since record_btrace_open has not installed a cleanup
> to disable tracing again for this thread, we leave it enabled.
>
> (gdb) rec bts
> [record-btrace] open
> [btrace] enable thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
> [btrace] compute ftrace
> [btrace] enable thread 2 (Thread 0x7ffff77fd700 (LWP 110346))
> [btrace] disable thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
> [btrace] clear thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
> Couldn't get registers: No such process.
>
> The next time we try to enable tracing, that running thread is already traced so
> we skip it. If we have more than two threads running, we disable tracing again
> on this thread when we fail on the next running thread. But we always leave the
> highest-number running thread traced.
>
> (gdb)
> [record-btrace] open
> [btrace] enable thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
> [btrace] compute ftrace
> [btrace] enable thread 4 (Thread 0x7ffff67fb700 (LWP 110348))
> [btrace] disable thread 3 (Thread 0x7ffff6ffc700 (LWP 110347))
> [btrace] clear thread 3 (Thread 0x7ffff6ffc700 (LWP 110347))
> [btrace] disable thread 2 (Thread 0x7ffff77fd700 (LWP 110346))
> [btrace] clear thread 2 (Thread 0x7ffff77fd700 (LWP 110346))
> [btrace] disable thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
> [btrace] clear thread 1 (Thread 0x7ffff7fcd740 (LWP 110345))
> Couldn't get registers: No such process.
>
> Eventually, all running threads are already traced and we succeed to enable tracing.
>
> The trace for running threads will start from their next branch target instead of from their
> current position (for BTS). This shouldn't matter unless the thread was actually waiting
> and not executing any code when we started tracing. We should be able to allow it like
> this:
>
> diff --git a/gdb/btrace.c b/gdb/btrace.c
> index 39d537c..b005627 100644
> --- a/gdb/btrace.c
> +++ b/gdb/btrace.c
> @@ -1474,8 +1474,28 @@ btrace_enable (struct thread_info *tp, const struct btrace_config *conf)
>
> /* Add an entry for the current PC so we start tracing from where we
> enabled it. */
> - if (tp->btrace.target != NULL)
> - btrace_add_pc (tp);
> + TRY
> + {
> + if (tp->btrace.target != NULL)
> + btrace_add_pc (tp);
> + }
> + CATCH (error, RETURN_MASK_ERROR)
> + {
> + /* We may fail to add the initial entry, for example if TP is currently
> + running.
> +
> + For BTRACE_FORMAT_PT this doesn't matter.
> +
> + For BTRACE_FORMAT_BTS we won't be able to stitch the initial trace
> + chunk to this initial entry so tracing will start at the next branch
> + target instead of at the current PC. Since TP is currently running,
> + this shouldn't make a difference.
> +
> + If TP were waiting most of the time and made only a little bit of
> + progress before it was stopped, we'd lose the instructions until the
> + first branch. */
> + }
> + END_CATCH
> }
>
> /* See btrace.h. */
>
> Do you want to extend your patch to allow tracing to be enabled for btrace or
> would you rather have me fix this on top of your patch?
Hi Markus,
Thanks for the quick response, I can confirm that your patch works, so I've modified
mine to only affect record full. See the updated version below. I think it's better
if you do the btrace changes yourself, if possible. I also think it would be good to
add a test for "record btrace" while the target is running, at least a simple one.
I sketched one here, but I don't know if you'd prefer to have it with the other btrace
tests or not... Feel free to use it if you want, here it is:
https://github.com/simark/binutils-gdb/commit/b4c494125f11499ef6c4d912067348bbeb02b139
Note that the doc seems to confirm that it's not intended to be possible to use
"record full" while the target is running:
If the inferior is in the non-stop mode (see Non-Stop Mode) or in the asynchronous
execution mode (see Background Execution), not all recording methods are available.
The full recording method does not support these two modes.
Source: https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html
Perhaps it would also be good to mention in the doc that btrace allows you to start it
while the program is running, with the caveat you mentioned, that the recording will only
start at the next branch.
Here is the updated patch:
From 20bd7f6b38a69ae3d529427a11c281e2116272e7 Mon Sep 17 00:00:00 2001
From: Simon Marchi <simon.marchi@ericsson.com>
Date: Thu, 24 Nov 2016 13:45:10 -0500
Subject: [PATCH] Prevent turning record on while threads are running (PR
20869)
As stated in the bug description, trying to do "record" while threads
are running leads to a broken state. I tried to see in the code if
there was anything to try to support the use case of enabling record
while the program is running, but didn't find anything.
When full/software recording is active, we are single stepping each
instruction. Transitioning from the state where threads are running
freely (no recording) to recording enabled should therefore involve a
step where we stop them to initiate the single stepping. I can't find
anything that looks like this, so my conclusion is that this was never a
supported use case (please correct me if I'm wrong).
The doc seems to confirm this:
If the inferior is in the non-stop mode (see Non-Stop Mode) or in the
asynchronous execution mode (see Background Execution), not all
recording methods are available. The full recording method does not
support these two modes.
The easy solution is to prevent the user for enabling record if a thread
is running.
No regression on the buildbot.
gdb/ChangeLog:
* record-full.c (record_preopen): Error out if any thread is running.
gdb/testsuite:
* gdb.reverse/record-while-running.c: New file.
* gdb.reverse/record-while-running.exp: New file.
---
gdb/record-full.c | 10 ++++
gdb/testsuite/gdb.reverse/record-while-running.c | 29 ++++++++++
gdb/testsuite/gdb.reverse/record-while-running.exp | 67 ++++++++++++++++++++++
3 files changed, 106 insertions(+)
create mode 100644 gdb/testsuite/gdb.reverse/record-while-running.c
create mode 100644 gdb/testsuite/gdb.reverse/record-while-running.exp
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 5608e70..9c3660f 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -834,6 +834,16 @@ record_full_open_1 (const char *name, int from_tty)
error (_("Process record: the current architecture doesn't support "
"record function."));
+ /* We can't enable record while threads are running, so make sure it's not
+ the case. */
+ iterate_over_threads([] (struct thread_info *tp, void *) -> int {
+ if (tp->state == thread_state::THREAD_RUNNING)
+ error (_("Can't enable record while the program is running. Use "
+ "\"interrupt\" to stop it first."));
+
+ return 0;
+ }, NULL);
+
push_target (&record_full_ops);
}
diff --git a/gdb/testsuite/gdb.reverse/record-while-running.c b/gdb/testsuite/gdb.reverse/record-while-running.c
new file mode 100644
index 0000000..f00ceb6
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/record-while-running.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2016 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+
+int
+main ()
+{
+ int i;
+
+ for (i = 0; i < 30; i++)
+ sleep (1);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/record-while-running.exp b/gdb/testsuite/gdb.reverse/record-while-running.exp
new file mode 100644
index 0000000..18a85b5
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/record-while-running.exp
@@ -0,0 +1,67 @@
+# Copyright 2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+# Test that trying to turn on recording while the target is running is correctly
+# handled.
+
+if ![supports_reverse] {
+ untested "reverse debugging not supported"
+ return
+}
+
+standard_testfile
+
+if { [prepare_for_testing $testfile.exp $testfile $srcfile] } {
+ fail "failed to compile"
+ return
+}
+
+if { ![runto_main] } {
+ fail "couldn't run to main"
+ return
+}
+
+# Interrupt the target and consume the stop event.
+
+proc interrupt_target { } {
+ global gdb_prompt
+
+ # Interrupt the target.
+ set test "interrupt target"
+ gdb_test_multiple "interrupt" $test {
+ -re "interrupt\r\n$gdb_prompt" {
+ pass $test
+ }
+ }
+
+ # Consume the leftovers from the async stop caused by the interrupt.
+ gdb_test "print 123" ".*Program received signal SIGINT, Interrupt.* = 123" "consume stop event"
+}
+
+# Test that "record full" while the target is running fails gracefully.
+
+proc_with_prefix test_record_full_while_running { } {
+ gdb_test "continue &" "Continuing." "resume target"
+ gdb_test \
+ "record full" \
+ "Can't enable record while the program is running. Use \"interrupt\" to stop it first." \
+ "switch record on while target is running"
+
+ # Interrupt the target to make sure the test ends gracefully when testing
+ # remotely.
+ interrupt_target
+}
+
+test_record_full_while_running
--
2.10.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Prevent turning record on while threads are running (PR 20869)
2016-11-30 15:36 ` Pedro Alves
@ 2016-11-30 16:11 ` Luis Machado
2016-11-30 16:27 ` Simon Marchi
0 siblings, 1 reply; 9+ messages in thread
From: Luis Machado @ 2016-11-30 16:11 UTC (permalink / raw)
To: Pedro Alves, Simon Marchi, gdb-patches; +Cc: markus.t.metzger
On 11/30/2016 09:36 AM, Pedro Alves wrote:
> On 11/29/2016 04:47 PM, Luis Machado wrote:
>> On 11/29/2016 10:42 AM, Simon Marchi wrote:
>>> On 16-11-29 10:58 AM, Luis Machado wrote:
>>>>> +if ![supports_reverse] {
>>>>
>>>> Add an explicit untested call here?
>>>
>>> Right, adding:
>>>
>>> untested "reverse debugging not supported"
>
> Shouldn't it be "unsupported" ?
>
It does make more sense. But it is also untested, because it is unsupported.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Prevent turning record on while threads are running (PR 20869)
2016-11-30 16:11 ` Luis Machado
@ 2016-11-30 16:27 ` Simon Marchi
0 siblings, 0 replies; 9+ messages in thread
From: Simon Marchi @ 2016-11-30 16:27 UTC (permalink / raw)
To: Luis Machado, Pedro Alves, gdb-patches; +Cc: markus.t.metzger
On 16-11-30 11:11 AM, Luis Machado wrote:
> On 11/30/2016 09:36 AM, Pedro Alves wrote:
>> Shouldn't it be "unsupported" ?
>>
>
> It does make more sense. But it is also untested, because it is unsupported.
>
I also think it makes sense. Changing locally.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2016-11-30 16:27 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-29 15:08 [PATCH] Prevent turning record on while threads are running (PR 20869) Simon Marchi
2016-11-29 15:58 ` Luis Machado
2016-11-29 16:42 ` Simon Marchi
2016-11-29 16:47 ` Luis Machado
2016-11-30 15:36 ` Pedro Alves
2016-11-30 16:11 ` Luis Machado
2016-11-30 16:27 ` Simon Marchi
2016-11-30 9:54 ` Metzger, Markus T
2016-11-30 16:04 ` Simon Marchi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox