From 1a476b6d68f338e6daa0345501c0cf0fe97dd8f3 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Wed, 18 Mar 2020 10:53:41 +0100 Subject: [PATCH] gdb, btrace: forward fetch_registers for unknown threads In the record-btrace target, while replaying, we can only provide the PC register. The btrace state is stored in the thread_info. So, when trying to determine whether we are currently replaying, GDB calls find_thread_ptid() to obtain the thread_info. It also asserts that we do have a thread_info. For new threads, libthread-db may fetch registers before the thread is known to GDB. In this case, find_thread_ptid() returns nullptr and the assertion fails. Forward the fetch_registers request to the target beneath in that case. gdb/ChangeLog: 2020-03-19 Markus Metzger * record-btrace.c (record_btrace_target::fetch_registers): Forward request if we do not have a thread_info. gdb/testsuite/ChangeLog: 2020-03-19 Markus Metzger * gdb.btrace/enable-new-thread.c: New test. * gdb.btrace/enable-new-thread.exp: New file. --- gdb/ChangeLog | 5 ++ gdb/record-btrace.c | 11 +++- gdb/testsuite/ChangeLog | 5 ++ gdb/testsuite/gdb.btrace/enable-new-thread.c | 36 ++++++++++++ .../gdb.btrace/enable-new-thread.exp | 57 +++++++++++++++++++ 5 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 gdb/testsuite/gdb.btrace/enable-new-thread.c create mode 100644 gdb/testsuite/gdb.btrace/enable-new-thread.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0e80cdb2d16..c761d498b7f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2020-04-21 Markus Metzger + + * record-btrace.c (record_btrace_target::fetch_registers): Forward + request if we do not have a thread_info. + 2020-04-21 Tom de Vries PR gdb/25471 diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index fe2ab8ad9a9..9b04d060149 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -1532,11 +1532,16 @@ record_btrace_target::remove_breakpoint (struct gdbarch *gdbarch, void record_btrace_target::fetch_registers (struct regcache *regcache, int regno) { + btrace_insn_iterator *replay = nullptr; + + /* Thread-db may ask for a thread's registers before GDB knows about the + thread. We forward the request to the target beneath in this + case. */ thread_info *tp = find_thread_ptid (regcache->target (), regcache->ptid ()); - gdb_assert (tp != NULL); + if (tp != nullptr) + replay = tp->btrace.replay; - btrace_insn_iterator *replay = tp->btrace.replay; - if (replay != NULL && !record_btrace_generating_corefile) + if (replay != nullptr && !record_btrace_generating_corefile) { const struct btrace_insn *insn; struct gdbarch *gdbarch; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index f72256730f3..09ad4cd3d23 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-21 Markus Metzger + + * gdb.btrace/enable-new-thread.c: New test. + * gdb.btrace/enable-new-thread.exp: New file. + 2020-04-21 Tom de Vries PR gdb/25471 diff --git a/gdb/testsuite/gdb.btrace/enable-new-thread.c b/gdb/testsuite/gdb.btrace/enable-new-thread.c new file mode 100644 index 00000000000..d4dc240e314 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/enable-new-thread.c @@ -0,0 +1,36 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2020 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 . */ + +#include +#include + +static void * +test (void *arg) +{ + return arg; /* bp.1 */ +} + +int +main (void) +{ + pthread_t th; + + pthread_create (&th, NULL, test, NULL); + pthread_join (th, NULL); + + return 0; +} diff --git a/gdb/testsuite/gdb.btrace/enable-new-thread.exp b/gdb/testsuite/gdb.btrace/enable-new-thread.exp new file mode 100644 index 00000000000..e8b17ad0ba2 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/enable-new-thread.exp @@ -0,0 +1,57 @@ +# This testcase is part of GDB, the GNU debugger. +# +# Copyright 2020 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 . + +# Test that new threads of recorded inferiors also get recorded. + +if { [skip_btrace_tests] } { + unsupported "target does not support record-btrace" + return -1 +} + +standard_testfile +if [prepare_for_testing "failed to prepare" $testfile $srcfile {debug pthreads}] { + return -1 +} + +if ![runto_main] { + untested "failed to run to main" + return -1 +} + +# Record the main thread. Recording will automatically be enabled for the +# other thread. +gdb_test "record btrace" + +gdb_breakpoint [gdb_get_line_number "bp.1" $srcfile] +gdb_continue_to_breakpoint "cont to bp.1" ".*/\\* bp\.1 \\*/.*" + +proc check_thread_recorded { num } { + global decimal + + with_test_prefix "thread $num" { + gdb_test "thread $num" "Switching to thread $num.*" + + gdb_test "info record" [multi_line \ + "Active record target: record-btrace" \ + ".*" \ + "Recorded $decimal instructions in $decimal functions \[^\\\r\\\n\]*" \ + ] + } +} + +check_thread_recorded 1 +check_thread_recorded 2 -- 2.30.2