aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Metzger <markus.t.metzger@intel.com>2013-04-24 13:24:11 +0200
committerMarkus Metzger <markus.t.metzger@intel.com>2014-01-16 13:06:14 +0100
commit633785ff2876e5bf03070a235d3e8cfe94cbf6bd (patch)
tree651cf8d1b64b09f804b5e47208d07574c05bd763
parent3db08215d47b576303a8cbaf6195b5f4a3bb9a13 (diff)
downloadgdb-633785ff2876e5bf03070a235d3e8cfe94cbf6bd.zip
gdb-633785ff2876e5bf03070a235d3e8cfe94cbf6bd.tar.gz
gdb-633785ff2876e5bf03070a235d3e8cfe94cbf6bd.tar.bz2
record-btrace: provide xfer_partial target method
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-16 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.
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/record-btrace.c112
-rw-r--r--gdb/target.c4
3 files changed, 125 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b4dd9c6..29f00d8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2014-01-16 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.
+
+2014-01-16 Markus Metzger <markus.t.metzger@intel.com>
+
* target.h (target_ops) <to_insert_breakpoint>
<to_remove_breakpoint>: Add target_ops parameter.
(forward_target_insert_breakpoint): New.
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 146d273..a12dba1 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. */
@@ -752,6 +755,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,
+ ULONGEST 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
@@ -929,6 +1038,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 612d909..d9c27b8 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))