[v4,2/4] gdbserver: Prevent stale/random values in register cache

Message ID 1418379431-14407-3-git-send-email-arnez@linux.vnet.ibm.com
State New, archived
Headers

Commit Message

Andreas Arnez Dec. 12, 2014, 10:16 a.m. UTC
  When fetch_inferior_registers does not update all registers, this
patch assures that no stale register values remain in the register
cache.  On Linux platforms using the regsets interface, when one of
the ptrace calls used for fetching the register values returns an
error, this patch also avoids copying the random data returned from
ptrace into the register cache.  All unfetched registers are marked
"unavailable" instead.

gdb/gdbserver/ChangeLog:

	* linux-low.c (regsets_fetch_inferior_registers): Do not invoke
	the regset's store function when ptrace returned an error.
	* regcache.c (get_thread_regcache): Invalidate register cache
	before fetching inferior's registers.
---
 gdb/gdbserver/linux-low.c | 11 ++++++-----
 gdb/gdbserver/regcache.c  |  3 +++
 2 files changed, 9 insertions(+), 5 deletions(-)
  

Comments

Pedro Alves Dec. 12, 2014, 12:13 p.m. UTC | #1
On 12/12/2014 10:16 AM, Andreas Arnez wrote:
> When fetch_inferior_registers does not update all registers, this
> patch assures that no stale register values remain in the register
> cache.  On Linux platforms using the regsets interface, when one of
> the ptrace calls used for fetching the register values returns an
> error, this patch also avoids copying the random data returned from
> ptrace into the register cache.  All unfetched registers are marked
> "unavailable" instead.

Looks good to me.

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 164b0f6..c1b53ff 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -4255,8 +4255,6 @@  regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
 	      /* If we get EIO on a regset, do not try it again for
 		 this process mode.  */
 	      disable_regset (regsets_info, regset);
-	      free (buf);
-	      continue;
 	    }
 	  else
 	    {
@@ -4266,9 +4264,12 @@  regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
 	      perror (s);
 	    }
 	}
-      else if (regset->type == GENERAL_REGS)
-	saw_general_regs = 1;
-      regset->store_function (regcache, buf);
+      else
+	{
+	  if (regset->type == GENERAL_REGS)
+	    saw_general_regs = 1;
+	  regset->store_function (regcache, buf);
+	}
       free (buf);
     }
   if (saw_general_regs)
diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c
index 718ae8c..8c874f0 100644
--- a/gdb/gdbserver/regcache.c
+++ b/gdb/gdbserver/regcache.c
@@ -52,6 +52,9 @@  get_thread_regcache (struct thread_info *thread, int fetch)
       struct thread_info *saved_thread = current_thread;
 
       current_thread = thread;
+      /* Invalidate all registers, to prevent stale left-overs.  */
+      memset (regcache->register_status, REG_UNAVAILABLE,
+	      regcache->tdesc->num_registers);
       fetch_inferior_registers (regcache, -1);
       current_thread = saved_thread;
       regcache->registers_valid = 1;