Blob Blame History Raw
From feea5f36a9dd65a0ff279c71744423c419b77ada Mon Sep 17 00:00:00 2001
From: Andreas Arnez <arnez@linux.vnet.ibm.com>
Date: Fri, 12 Dec 2014 14:14:21 +0100
Subject: [PATCH 8/9] gdbserver: Support read-only regsets in linux-low.c

For GNU/Linux targets using the regsets interface, this change
supports regsets that can be read but not written.  The S390 "last
break" regset is an example.  So far it had been defined with
regset->set_request == PTRACE_GETREGSET, such that the respective
ptrace call does not cause any harm.  Now we just skip the whole
read/modify/write sequence for regsets that do not define a
fill_function.

gdb/gdbserver/ChangeLog:

	* linux-low.c (regsets_store_inferior_registers): Skip regsets
	without a fill_function.
	* linux-s390-low.c (s390_fill_last_break): Remove.
	(s390_regsets): Set fill_function to NULL for NT_S390_LAST_BREAK.
	(s390_arch_setup): Use regset's size instead of fill_function for
	loop end condition.
---
 gdb/gdbserver/ChangeLog        |  9 +++++++++
 gdb/gdbserver/linux-low.c      |  3 ++-
 gdb/gdbserver/linux-s390-low.c | 14 ++++----------
 3 files changed, 15 insertions(+), 11 deletions(-)

Index: gdb-7.6.1/gdb/gdbserver/linux-low.c
===================================================================
--- gdb-7.6.1.orig/gdb/gdbserver/linux-low.c
+++ gdb-7.6.1/gdb/gdbserver/linux-low.c
@@ -4120,7 +4120,8 @@ regsets_store_inferior_registers (struct
       void *buf, *data;
       int nt_type, res;
 
-      if (regset->size == 0 || disabled_regsets[regset - target_regsets])
+      if (regset->size == 0 || disabled_regsets[regset - target_regsets]
+	  || regset->fill_function == NULL)
 	{
 	  regset ++;
 	  continue;
Index: gdb-7.6.1/gdb/gdbserver/linux-s390-low.c
===================================================================
--- gdb-7.6.1.orig/gdb/gdbserver/linux-s390-low.c
+++ gdb-7.6.1/gdb/gdbserver/linux-s390-low.c
@@ -264,12 +264,6 @@ static void s390_fill_gregset (struct re
 /* Fill and store functions for extended register sets.  */
 
 static void
-s390_fill_last_break (struct regcache *regcache, void *buf)
-{
-  /* Last break address is read-only.  */
-}
-
-static void
 s390_store_last_break (struct regcache *regcache, const void *buf)
 {
   supply_register_by_name (regcache, "last_break",
@@ -290,9 +284,9 @@ s390_store_system_call (struct regcache
 
 struct regset_info target_regsets[] = {
   { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
-  /* Last break address is read-only; do not attempt PTRACE_SETREGSET.  */
-  { PTRACE_GETREGSET, PTRACE_GETREGSET, NT_S390_LAST_BREAK, 0,
-    EXTENDED_REGS, s390_fill_last_break, s390_store_last_break },
+  /* Last break address is read-only; no fill function.  */
+  { PTRACE_GETREGSET, -1, NT_S390_LAST_BREAK, 0, EXTENDED_REGS,
+    NULL, s390_store_last_break },
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_SYSTEM_CALL, 0,
     EXTENDED_REGS, s390_fill_system_call, s390_store_system_call },
   { 0, 0, 0, -1, -1, NULL, NULL }
@@ -454,7 +448,7 @@ s390_arch_setup (void)
   }
 #endif
   /* Update target_regsets according to available register sets.  */
-  for (regset = target_regsets; regset->fill_function != NULL; regset++)
+  for (regset = target_regsets; regset->size >= 0; regset++)
     if (regset->get_request == PTRACE_GETREGSET)
       switch (regset->nt_type)
 	{