[PATCH v10 20/28] record-btrace: provide xfer_partial target method

Markus Metzger markus.t.metzger@intel.com
Tue Jan 14 08:04:00 GMT 2014


Provide the xfer_partial target method for the btrace record target.

Only allow memory read accesses to readonly memory while we're replaying,
except for inserting and removing breakpoints.

2014-01-14  Markus Metzger  <markus.t.metzger@intel.com>

	* record-btrace.c (record_btrace_xfer_partial)
	(record_btrace_insert_breakpoint, record_btrace_remove_breakpoint)
	(record_btrace_allow_memory_access): New.
	(init_record_btrace_ops): Initialize new methods.
	* target.c (raw_memory_xfer_partial): Bail out if target reports
	that this memory is not available.


---
 gdb/record-btrace.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/target.c        |   4 ++
 2 files changed, 116 insertions(+)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 870ad7d..24e697f 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -41,6 +41,9 @@ static struct target_ops record_btrace_ops;
 /* A new thread observer enabling branch tracing for the new thread.  */
 static struct observer *record_btrace_thread_observer;
 
+/* Temporarily allow memory accesses.  */
+static int record_btrace_allow_memory_access;
+
 /* Print a record-btrace debug message.  Use do ... while (0) to avoid
    ambiguities when used in if statements.  */
 
@@ -753,6 +756,112 @@ record_btrace_is_replaying (void)
   return 0;
 }
 
+/* The to_xfer_partial method of target record-btrace.  */
+
+static LONGEST
+record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
+			    const char *annex, gdb_byte *readbuf,
+			    const gdb_byte *writebuf, ULONGEST offset,
+			    LONGEST len)
+{
+  struct target_ops *t;
+
+  /* Filter out requests that don't make sense during replay.  */
+  if (!record_btrace_allow_memory_access && record_btrace_is_replaying ())
+    {
+      switch (object)
+	{
+	case TARGET_OBJECT_MEMORY:
+	  {
+	    struct target_section *section;
+
+	    /* We do not allow writing memory in general.  */
+	    if (writebuf != NULL)
+	      return TARGET_XFER_E_UNAVAILABLE;
+
+	    /* We allow reading readonly memory.  */
+	    section = target_section_by_addr (ops, offset);
+	    if (section != NULL)
+	      {
+		/* Check if the section we found is readonly.  */
+		if ((bfd_get_section_flags (section->the_bfd_section->owner,
+					    section->the_bfd_section)
+		     & SEC_READONLY) != 0)
+		  {
+		    /* Truncate the request to fit into this section.  */
+		    len = min (len, section->endaddr - offset);
+		    break;
+		  }
+	      }
+
+	    return TARGET_XFER_E_UNAVAILABLE;
+	  }
+	}
+    }
+
+  /* Forward the request.  */
+  for (ops = ops->beneath; ops != NULL; ops = ops->beneath)
+    if (ops->to_xfer_partial != NULL)
+      return ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
+				   offset, len);
+
+  return TARGET_XFER_E_UNAVAILABLE;
+}
+
+/* The to_insert_breakpoint method of target record-btrace.  */
+
+static int
+record_btrace_insert_breakpoint (struct target_ops *ops,
+				 struct gdbarch *gdbarch,
+				 struct bp_target_info *bp_tgt)
+{
+  volatile struct gdb_exception except;
+  int old, ret;
+
+  /* Inserting breakpoints requires accessing memory.  Allow it for the
+     duration of this function.  */
+  old = record_btrace_allow_memory_access;
+  record_btrace_allow_memory_access = 1;
+
+  ret = 0;
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    ret = forward_target_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
+
+  record_btrace_allow_memory_access = old;
+
+  if (except.reason < 0)
+    throw_exception (except);
+
+  return ret;
+}
+
+/* The to_remove_breakpoint method of target record-btrace.  */
+
+static int
+record_btrace_remove_breakpoint (struct target_ops *ops,
+				 struct gdbarch *gdbarch,
+				 struct bp_target_info *bp_tgt)
+{
+  volatile struct gdb_exception except;
+  int old, ret;
+
+  /* Removing breakpoints requires accessing memory.  Allow it for the
+     duration of this function.  */
+  old = record_btrace_allow_memory_access;
+  record_btrace_allow_memory_access = 1;
+
+  ret = 0;
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    ret = forward_target_remove_breakpoint (ops->beneath, gdbarch, bp_tgt);
+
+  record_btrace_allow_memory_access = old;
+
+  if (except.reason < 0)
+    throw_exception (except);
+
+  return ret;
+}
+
 /* The to_fetch_registers method of target record-btrace.  */
 
 static void
@@ -930,6 +1039,9 @@ init_record_btrace_ops (void)
   ops->to_call_history_from = record_btrace_call_history_from;
   ops->to_call_history_range = record_btrace_call_history_range;
   ops->to_record_is_replaying = record_btrace_is_replaying;
+  ops->to_xfer_partial = record_btrace_xfer_partial;
+  ops->to_remove_breakpoint = record_btrace_remove_breakpoint;
+  ops->to_insert_breakpoint = record_btrace_insert_breakpoint;
   ops->to_fetch_registers = record_btrace_fetch_registers;
   ops->to_store_registers = record_btrace_store_registers;
   ops->to_prepare_to_store = record_btrace_prepare_to_store;
diff --git a/gdb/target.c b/gdb/target.c
index 36e23aa..c3e42f2 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -1406,6 +1406,10 @@ raw_memory_xfer_partial (struct target_ops *ops, void *readbuf,
       if (res > 0)
 	break;
 
+      /* Stop if the target reports that the memory is not available. */
+      if (res == TARGET_XFER_E_UNAVAILABLE)
+	break;
+
       /* We want to continue past core files to executables, but not
 	 past a running target's memory.  */
       if (ops->to_has_all_memory (ops))
-- 
1.8.3.1



More information about the Gdb-patches mailing list