[PATCH v5 1/5] gdb: protect some 'regcache_read_pc' calls
Tankut Baris Aktemur
tankut.baris.aktemur@intel.com
Mon Apr 6 15:45:47 GMT 2020
It possible that a thread whose PC we attempt to read is already dead.
In this case, 'regcache_read_pc' errors out. This impacts the
"proceed" execution flow, where GDB quits early before having a chance
to check if there exists a pending event. To remedy, keep going with
a 0 value for the PC if 'regcache_read_pc' fails. Because the value
of PC before resuming a thread is mostly used for storing and checking
the next time the thread stops, this tolerance is expected to be
harmless for a dead thread/process.
gdb/ChangeLog:
2020-04-03 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* regcache.c (regcache_read_pc_protected): New function
implementation that returns 0 if the PC cannot read via
'regcache_read_pc'.
* infrun.c (proceed): Call 'regcache_read_pc_protected'
instead of 'regcache_read_pc'.
(keep_going_pass_signal): Ditto.
gdbsupport/ChangeLog:
2020-04-03 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* common-regcache.h (regcache_read_pc_protected): New function
declaration.
---
gdb/infrun.c | 7 ++++---
gdb/regcache.c | 18 ++++++++++++++++++
gdbsupport/common-regcache.h | 5 +++++
3 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 8ff34c382d6..d6265c6df51 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2987,7 +2987,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
gdbarch = regcache->arch ();
const address_space *aspace = regcache->aspace ();
- pc = regcache_read_pc (regcache);
+ pc = regcache_read_pc_protected (regcache);
+
thread_info *cur_thr = inferior_thread ();
/* Fill in with reasonable starting values. */
@@ -3114,7 +3115,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
advanced. Must do this before resuming any thread, as in
all-stop/remote, once we resume we can't send any other packet
until the target stops again. */
- cur_thr->prev_pc = regcache_read_pc (regcache);
+ cur_thr->prev_pc = regcache_read_pc_protected (regcache);
{
scoped_restore save_defer_tc = make_scoped_defer_target_commit_resume ();
@@ -7921,7 +7922,7 @@ keep_going_pass_signal (struct execution_control_state *ecs)
/* Save the pc before execution, to compare with pc after stop. */
ecs->event_thread->prev_pc
- = regcache_read_pc (get_thread_regcache (ecs->event_thread));
+ = regcache_read_pc_protected (get_thread_regcache (ecs->event_thread));
if (ecs->event_thread->control.trap_expected)
{
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 4f079c91a7f..4a1cf552505 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1220,6 +1220,24 @@ regcache_read_pc (struct regcache *regcache)
return pc_val;
}
+/* See gdbsupport/common-regcache.h. */
+
+CORE_ADDR
+regcache_read_pc_protected (regcache *regcache)
+{
+ CORE_ADDR pc;
+ try
+ {
+ pc = regcache_read_pc (regcache);
+ }
+ catch (const gdb_exception &ex)
+ {
+ pc = 0;
+ }
+
+ return pc;
+}
+
void
regcache_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
diff --git a/gdbsupport/common-regcache.h b/gdbsupport/common-regcache.h
index 18446ff8416..650536e8a88 100644
--- a/gdbsupport/common-regcache.h
+++ b/gdbsupport/common-regcache.h
@@ -56,6 +56,11 @@ extern int regcache_register_size (const struct regcache *regcache, int n);
extern CORE_ADDR regcache_read_pc (struct regcache *regcache);
+/* Read the PC register. If PC cannot be read, return 0.
+ This is a wrapper around 'regcache_read_pc'. */
+
+extern CORE_ADDR regcache_read_pc_protected (regcache *regcache);
+
/* Read a raw register into a unsigned integer. */
extern enum register_status regcache_raw_read_unsigned
(struct regcache *regcache, int regnum, ULONGEST *val);
--
2.17.1
More information about the Gdb-patches
mailing list