From: Andrew Burgess <andrew.burgess@embecosm.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 2/3] gdb: make thread_suspend_state::stop_pc optional
Date: Mon, 30 Aug 2021 21:03:10 +0100 [thread overview]
Message-ID: <d2f8d7496d6bfcff1ff61f0debb9bcefdccf7ca9.1630353626.git.andrew.burgess@embecosm.com> (raw)
In-Reply-To: <cover.1630353626.git.andrew.burgess@embecosm.com>
Currently the stop_pc field of thread_suspect_state is a CORE_ADDR and
when we want to indicate that there is no stop_pc available we set
this field back to a special value.
There are actually two special values used, in post_create_inferior
the stop_pc is set to 0. This is a little unfortunate, there are
plenty of embedded targets where 0 is a valid pc address. The more
common special value for stop_pc was set in
thread_info::set_executing, where the value (~(CORE_ADDR) 0) was used.
This commit changes things so that the stop_pc is instead a
gdb::optional. We can now explicitly reset the field to an
uninitialised state, we also have (when compiling with _GLIBCXX_DEBUG
defined) asserts that we don't read the stop_pc when its in an
uninitialised state (see gdbsupport/gdb_optional.h).
One situation where a thread will not have a stop_pc value is when the
thread is stopped as a consequence of GDB being in all stop mode, and
some other thread stopped at an interesting event. When GDB brings
all the other threads to a stop those other threads will not have a
stop_pc set (thus avoiding an unnecessary read of $pc).
Previously, when GDB passed through handle_one (in infrun.c) the
threads executing flag was set to false and the stop_pc field was left
unchanged, i.e. it would (previous) have been left as ~0.
Now, handle_one leaves the stop_pc with no value.
This caused a problem when we later try to set these threads running
again, in proceed() we compare the current pc with the cached
stop_pc. If the thread was stopped in via handle_one then the stop_pc
would have been left as ~0, and the compare (in proceed)
would (likely) fail. Now however, this compare tries to read the
stop_pc when it has no value, this would trigger an assert.
To resolve this I've added thread_info::stop_pc_p() which returns true
if the thread has a cached stop_pc. We should only ever call
thread_info::stop_pc() if we know that there is a cached stop_pc.
After running the testsuite I've seen no other situations where
stop_pc is read uninitialised.
---
gdb/gdbthread.h | 26 ++++++++++++++++++++++----
gdb/infcmd.c | 2 +-
gdb/infrun.c | 3 ++-
gdb/thread.c | 2 +-
4 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 734fe3bce64..245445a859b 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -197,9 +197,12 @@ struct thread_suspend_state
stop_reason: if the thread's PC has changed since the thread
last stopped, a pending breakpoint waitstatus is discarded.
- - If the thread is running, this is set to -1, to avoid leaving
- it with a stale value, to make it easier to catch bugs. */
- CORE_ADDR stop_pc = 0;
+ - If the thread is running, then this field has its value removed by
+ calling stop_pc.reset() (see thread_info::set_executing()).
+ Attempting to read a gdb::optional with no value is undefined
+ behaviour and will trigger an assertion error when _GLIBCXX_DEBUG is
+ defined, which should make error easier to track down. */
+ gdb::optional<CORE_ADDR> stop_pc;
};
/* Base class for target-specific thread data. */
@@ -326,7 +329,7 @@ class thread_info : public refcounted_object,
CORE_ADDR stop_pc () const
{
- return m_suspend.stop_pc;
+ return *m_suspend.stop_pc;
}
/* Set this thread's stop PC. */
@@ -336,6 +339,21 @@ class thread_info : public refcounted_object,
m_suspend.stop_pc = stop_pc;
}
+ /* Remove the stop_pc stored on this thread. */
+
+ void clear_stop_pc ()
+ {
+ m_suspend.stop_pc.reset ();
+ }
+
+ /* Return true if this thread has a cached stop pc value, otherwise
+ return false. */
+
+ bool stop_pc_p () const
+ {
+ return m_suspend.stop_pc.has_value ();
+ }
+
/* Return true if this thread has a pending wait status. */
bool has_pending_waitstatus () const
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index e6ee49bc43d..d948f4bafc5 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -249,7 +249,7 @@ post_create_inferior (int from_tty)
missing registers info), ignore it. */
thread_info *thr = inferior_thread ();
- thr->set_stop_pc (0);
+ thr->clear_stop_pc ();
try
{
regcache *rc = get_thread_regcache (thr);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 11440894b15..5554523a049 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3051,7 +3051,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
if (addr == (CORE_ADDR) -1)
{
- if (pc == cur_thr->stop_pc ()
+ if (cur_thr->stop_pc_p ()
+ && pc == cur_thr->stop_pc ()
&& breakpoint_here_p (aspace, pc) == ordinary_breakpoint_here
&& execution_direction != EXEC_REVERSE)
/* There is a breakpoint at the address we will resume at,
diff --git a/gdb/thread.c b/gdb/thread.c
index c95a9186681..10c3dcd6991 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -324,7 +324,7 @@ thread_info::set_executing (bool executing)
{
m_executing = executing;
if (executing)
- this->set_stop_pc (~(CORE_ADDR) 0);
+ this->clear_stop_pc ();
}
/* See gdbthread.h. */
--
2.25.4
next prev parent reply other threads:[~2021-08-30 20:03 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-30 20:03 [PATCH 0/3] Changes to thread state tracking Andrew Burgess
2021-08-30 20:03 ` [PATCH 1/3] gdb: make thread_info::executing private Andrew Burgess
2021-09-01 13:53 ` Simon Marchi via Gdb-patches
2021-09-07 11:46 ` Andrew Burgess
2021-08-30 20:03 ` Andrew Burgess [this message]
2021-09-01 14:23 ` [PATCH 2/3] gdb: make thread_suspend_state::stop_pc optional Simon Marchi via Gdb-patches
2021-09-07 13:21 ` Andrew Burgess
2021-09-07 14:10 ` Simon Marchi via Gdb-patches
2021-09-08 9:50 ` Andrew Burgess
2021-08-30 20:03 ` [PATCH 3/3] gdb: make thread_info executing and resumed state more consistent Andrew Burgess
2021-09-01 15:09 ` Simon Marchi via Gdb-patches
2021-09-22 11:21 ` Andrew Burgess
2021-09-23 17:14 ` Simon Marchi via Gdb-patches
2021-09-29 8:09 ` Andrew Burgess
2021-10-08 19:33 ` Simon Marchi via Gdb-patches
2022-01-13 18:34 ` [PATCHv3] " Andrew Burgess via Gdb-patches
2022-01-14 17:10 ` Simon Marchi via Gdb-patches
2022-02-24 15:52 ` Andrew Burgess via Gdb-patches
2022-03-03 19:42 ` Simon Marchi via Gdb-patches
2022-03-07 7:39 ` Aktemur, Tankut Baris via Gdb-patches
2022-03-30 9:19 ` Andrew Burgess via Gdb-patches
2022-04-21 16:45 ` [PATCHv4 0/2] Make " Andrew Burgess via Gdb-patches
2022-04-21 16:45 ` [PATCHv4 1/2] gdb: add some additional thread status debug output Andrew Burgess via Gdb-patches
2022-04-21 20:35 ` Lancelot SIX via Gdb-patches
2022-04-22 17:50 ` Andrew Burgess via Gdb-patches
2022-05-03 14:04 ` Andrew Burgess via Gdb-patches
2022-04-21 16:45 ` [PATCHv4 2/2] gdb: make thread_info executing and resumed state more consistent Andrew Burgess via Gdb-patches
2022-04-26 13:28 ` Nidal Faour via Gdb-patches
2022-08-08 11:04 ` [PATCHv4 0/2] Make " Craig Blackmore
2022-08-08 12:01 ` Andrew Burgess via Gdb-patches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d2f8d7496d6bfcff1ff61f0debb9bcefdccf7ca9.1630353626.git.andrew.burgess@embecosm.com \
--to=andrew.burgess@embecosm.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox