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  <markus.t.metzger@intel.com>

	* 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  <markus.t.metzger@intel.com>

	* gdb.btrace/enable-new-thread.c: New test.
	* gdb.btrace/enable-new-thread.exp: New file.
This commit is contained in:
Markus Metzger 2020-03-18 10:53:41 +01:00
parent 4778a5f87d
commit 1a476b6d68
5 changed files with 112 additions and 4 deletions

View File

@ -1,3 +1,8 @@
2020-04-21 Markus Metzger <markus.t.metzger@intel.com>
* record-btrace.c (record_btrace_target::fetch_registers): Forward
request if we do not have a thread_info.
2020-04-21 Tom de Vries <tdevries@suse.de>
PR gdb/25471

View File

@ -1532,11 +1532,16 @@ record_btrace_target::remove_breakpoint (struct gdbarch *gdbarch,
void
record_btrace_target::fetch_registers (struct regcache *regcache, int regno)
{
thread_info *tp = find_thread_ptid (regcache->target (), regcache->ptid ());
gdb_assert (tp != NULL);
btrace_insn_iterator *replay = nullptr;
btrace_insn_iterator *replay = tp->btrace.replay;
if (replay != NULL && !record_btrace_generating_corefile)
/* 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 ());
if (tp != nullptr)
replay = tp->btrace.replay;
if (replay != nullptr && !record_btrace_generating_corefile)
{
const struct btrace_insn *insn;
struct gdbarch *gdbarch;

View File

@ -1,3 +1,8 @@
2020-04-21 Markus Metzger <markus.t.metzger@intel.com>
* gdb.btrace/enable-new-thread.c: New test.
* gdb.btrace/enable-new-thread.exp: New file.
2020-04-21 Tom de Vries <tdevries@suse.de>
PR gdb/25471

View File

@ -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 <http://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <unistd.h>
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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
# 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