This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC v2 04/38] add target method delegation


This patch replaces some code in the record targets with target method
delegation.

record-full.c stores pointers to many target methods when the record
target is pushed.  Then it later delegates some calls via these.  This
is wrong because it violates the target stack contract.  In particular
it is ok to unpush a target at any stratum, but record-full does not
keep track of this, so it could potentially call into an unpushed
target.

This patch fixes the problem by using the newly-introduced generic
approach to target delegation for the methods in question.

2014-02-06  Tom Tromey  <tromey@redhat.com>

	* record-full.c (record_full_beneath_to_resume_ops)
	(record_full_beneath_to_resume, record_full_beneath_to_wait_ops)
	(record_full_beneath_to_wait)
	(record_full_beneath_to_store_registers_ops)
	(record_full_beneath_to_store_registers)
	(record_full_beneath_to_xfer_partial_ops)
	(record_full_beneath_to_xfer_partial)
	(record_full_beneath_to_insert_breakpoint_ops)
	(record_full_beneath_to_insert_breakpoint)
	(record_full_beneath_to_remove_breakpoint_ops)
	(record_full_beneath_to_remove_breakpoint)
	(record_full_beneath_to_stopped_by_watchpoint)
	(record_full_beneath_to_stopped_data_address)
	(record_full_beneath_to_async, tmp_to_resume_ops, tmp_to_resume)
	(tmp_to_wait_ops, tmp_to_wait, tmp_to_store_registers_ops)
	(tmp_to_store_registers, tmp_to_xfer_partial_ops)
	(tmp_to_xfer_partial, tmp_to_instmp_to_insert_breakpoint_ops)
	(tmp_to_insert_breakpoint, tmp_to_remove_breakpoint_ops)
	(tmp_to_remove_breakpoint, tmp_to_stopped_by_watchpoint)
	(tmp_to_stopped_data_address, tmp_to_async): Remove.
	(record_full_open_1, record_full_open): Update.  Use RECORD_IS_USED.
	(record_full_resume, record_full_wait_1)
	(record_full_stopped_by_watchpoint, record_full_stopped_data_address)
	(record_full_store_registers, record_full_xfer_partial)
	(record_full_insert_breakpoint, record_full_remove_breakpoint)
	(record_full_async, record_full_core_xfer_partial): Use target
	delegation.
	* target-delegates.c: Rebuild.
	* target.c (current_xfer_partial): Remove.
	(update_current_target): Do not INHERIT or de_fault
	to_insert_breakpoint, to_remove_breakpoint,
	to_stopped_data_address, to_stopped_by_watchpoint, to_can_async_p,
	to_is_async_p, to_async.  Do not set to_xfer_partial field.
	(default_xfer_partial): Simplify.
	(current_xfer_partial): Remove.
	(target_wait, target_resume): Simplify.
	(find_default_can_async_p, find_default_is_async_p): Update.
	(init_dummy_target): Don't set to_can_async_p, to_is_async_p,
	to_xfer_partial, to_stopped_by_watchpoint,
	to_stopped_data_address.
	(target_store_registers): Simplify.
	(forward_target_remove_breakpoint)
	(forward_target_insert_breakpoint): Remove.
	(target_remove_breakpoint, target_insert_breakpoint)
	(debug_to_insert_breakpoint, debug_to_remove_breakpoint): Update.
	* target.h (struct target_ops) <to_resume, to_wait,
	to_store_registers, to_insert_breakpoint, to_remove_breakpoint,
	to_stopped_by_watchpoint, to_stopped_data_address, to_can_async_p,
	to_is_async_p, to_async, to_xfer_partial>: Add TARGET_DEFAULT
	markup.
	(forward_target_remove_breakpoint)
	(forward_target_insert_breakpoint): Remove.
	* record-btrace.c (record_btrace_remove_breakpoint): Delegate
	directly.
	(record_btrace_insert_breakpoint): Delegate directly.
---
 gdb/ChangeLog          |  58 +++++++++++++
 gdb/record-btrace.c    |   4 +-
 gdb/record-full.c      | 222 +++++--------------------------------------------
 gdb/target-delegates.c | 152 +++++++++++++++++++++++++++++++++
 gdb/target.c           | 188 ++++++++++++-----------------------------
 gdb/target.h           |  51 +++++-------
 6 files changed, 306 insertions(+), 369 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 365b6be..e1125b5 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -869,7 +869,7 @@ record_btrace_insert_breakpoint (struct target_ops *ops,
 
   ret = 0;
   TRY_CATCH (except, RETURN_MASK_ALL)
-    ret = forward_target_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
+    ret = ops->beneath->to_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
 
   record_btrace_allow_memory_access = old;
 
@@ -896,7 +896,7 @@ record_btrace_remove_breakpoint (struct target_ops *ops,
 
   ret = 0;
   TRY_CATCH (except, RETURN_MASK_ALL)
-    ret = forward_target_remove_breakpoint (ops->beneath, gdbarch, bp_tgt);
+    ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch, bp_tgt);
 
   record_btrace_allow_memory_access = old;
 
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 41a93eb..d330892 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -228,38 +228,6 @@ static struct cmd_list_element *show_record_full_cmdlist;
 /* Command list for "record full".  */
 static struct cmd_list_element *record_full_cmdlist;
 
-/* The beneath function pointers.  */
-static struct target_ops *record_full_beneath_to_resume_ops;
-static void (*record_full_beneath_to_resume) (struct target_ops *, ptid_t, int,
-					      enum gdb_signal);
-static struct target_ops *record_full_beneath_to_wait_ops;
-static ptid_t (*record_full_beneath_to_wait) (struct target_ops *, ptid_t,
-					      struct target_waitstatus *,
-					      int);
-static struct target_ops *record_full_beneath_to_store_registers_ops;
-static void (*record_full_beneath_to_store_registers) (struct target_ops *,
-						       struct regcache *,
-						       int regno);
-static struct target_ops *record_full_beneath_to_xfer_partial_ops;
-static target_xfer_partial_ftype *record_full_beneath_to_xfer_partial;
-static int
-  (*record_full_beneath_to_insert_breakpoint) (struct target_ops *,
-					       struct gdbarch *,
-					       struct bp_target_info *);
-static struct target_ops *record_full_beneath_to_insert_breakpoint_ops;
-static int
-  (*record_full_beneath_to_remove_breakpoint) (struct target_ops *,
-					       struct gdbarch *,
-					       struct bp_target_info *);
-static struct target_ops *record_full_beneath_to_remove_breakpoint_ops;
-static int (*record_full_beneath_to_stopped_by_watchpoint) (struct target_ops *);
-static int (*record_full_beneath_to_stopped_data_address) (struct target_ops *,
-							   CORE_ADDR *);
-static void
-  (*record_full_beneath_to_async) (struct target_ops *,
-				   void (*) (enum inferior_event_type, void *),
-				   void *);
-
 static void record_full_goto_insn (struct record_full_entry *entry,
 				   enum exec_direction_kind dir);
 static void record_full_save (const char *recfilename);
@@ -806,30 +774,6 @@ record_full_exec_insn (struct regcache *regcache,
     }
 }
 
-static struct target_ops *tmp_to_resume_ops;
-static void (*tmp_to_resume) (struct target_ops *, ptid_t, int,
-			      enum gdb_signal);
-static struct target_ops *tmp_to_wait_ops;
-static ptid_t (*tmp_to_wait) (struct target_ops *, ptid_t,
-			      struct target_waitstatus *,
-			      int);
-static struct target_ops *tmp_to_store_registers_ops;
-static void (*tmp_to_store_registers) (struct target_ops *,
-				       struct regcache *,
-				       int regno);
-static struct target_ops *tmp_to_xfer_partial_ops;
-static target_xfer_partial_ftype *tmp_to_xfer_partial;
-static int (*tmp_to_insert_breakpoint) (struct target_ops *, struct gdbarch *,
-					struct bp_target_info *);
-static struct target_ops *tmp_to_insert_breakpoint_ops;
-static int (*tmp_to_remove_breakpoint) (struct target_ops *, struct gdbarch *,
-					struct bp_target_info *);
-static struct target_ops *tmp_to_remove_breakpoint_ops;
-static int (*tmp_to_stopped_by_watchpoint) (struct target_ops *);
-static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
-static void (*tmp_to_async) (struct target_ops *,
-			     void (*) (enum inferior_event_type, void *), void *);
-
 static void record_full_restore (void);
 
 /* Asynchronous signal handle registered as event loop source for when
@@ -892,26 +836,6 @@ record_full_open_1 (char *name, int from_tty)
     error (_("Process record: the current architecture doesn't support "
 	     "record function."));
 
-  if (!tmp_to_resume)
-    error (_("Could not find 'to_resume' method on the target stack."));
-  if (!tmp_to_wait)
-    error (_("Could not find 'to_wait' method on the target stack."));
-  if (!tmp_to_store_registers)
-    error (_("Could not find 'to_store_registers' "
-	     "method on the target stack."));
-  if (!tmp_to_insert_breakpoint)
-    error (_("Could not find 'to_insert_breakpoint' "
-	     "method on the target stack."));
-  if (!tmp_to_remove_breakpoint)
-    error (_("Could not find 'to_remove_breakpoint' "
-	     "method on the target stack."));
-  if (!tmp_to_stopped_by_watchpoint)
-    error (_("Could not find 'to_stopped_by_watchpoint' "
-	     "method on the target stack."));
-  if (!tmp_to_stopped_data_address)
-    error (_("Could not find 'to_stopped_data_address' "
-	     "method on the target stack."));
-
   push_target (&record_full_ops);
 }
 
@@ -929,89 +853,12 @@ record_full_open (char *name, int from_tty)
 
   record_preopen ();
 
-  /* Reset the tmp beneath pointers.  */
-  tmp_to_resume_ops = NULL;
-  tmp_to_resume = NULL;
-  tmp_to_wait_ops = NULL;
-  tmp_to_wait = NULL;
-  tmp_to_store_registers_ops = NULL;
-  tmp_to_store_registers = NULL;
-  tmp_to_xfer_partial_ops = NULL;
-  tmp_to_xfer_partial = NULL;
-  tmp_to_insert_breakpoint = NULL;
-  tmp_to_remove_breakpoint = NULL;
-  tmp_to_stopped_by_watchpoint = NULL;
-  tmp_to_stopped_data_address = NULL;
-  tmp_to_async = NULL;
-  tmp_to_insert_breakpoint_ops = NULL;
-  tmp_to_remove_breakpoint_ops = NULL;
-
-  /* Set the beneath function pointers.  */
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    {
-      if (!tmp_to_resume)
-        {
-	  tmp_to_resume = t->to_resume;
-	  tmp_to_resume_ops = t;
-        }
-      if (!tmp_to_wait)
-        {
-	  tmp_to_wait = t->to_wait;
-	  tmp_to_wait_ops = t;
-        }
-      if (!tmp_to_store_registers)
-        {
-	  tmp_to_store_registers = t->to_store_registers;
-	  tmp_to_store_registers_ops = t;
-        }
-      if (!tmp_to_xfer_partial)
-        {
-	  tmp_to_xfer_partial = t->to_xfer_partial;
-	  tmp_to_xfer_partial_ops = t;
-        }
-      if (!tmp_to_insert_breakpoint)
-	{
-	  tmp_to_insert_breakpoint = t->to_insert_breakpoint;
-	  tmp_to_insert_breakpoint_ops = t;
-	}
-      if (!tmp_to_remove_breakpoint)
-	{
-	  tmp_to_remove_breakpoint = t->to_remove_breakpoint;
-	  tmp_to_remove_breakpoint_ops = t;
-	}
-      if (!tmp_to_stopped_by_watchpoint)
-	tmp_to_stopped_by_watchpoint = t->to_stopped_by_watchpoint;
-      if (!tmp_to_stopped_data_address)
-	tmp_to_stopped_data_address = t->to_stopped_data_address;
-      if (!tmp_to_async)
-	tmp_to_async = t->to_async;
-    }
-  if (!tmp_to_xfer_partial)
-    error (_("Could not find 'to_xfer_partial' method on the target stack."));
-
   /* Reset */
   record_full_insn_num = 0;
   record_full_insn_count = 0;
   record_full_list = &record_full_first;
   record_full_list->next = NULL;
 
-  /* Set the tmp beneath pointers to beneath pointers.  */
-  record_full_beneath_to_resume_ops = tmp_to_resume_ops;
-  record_full_beneath_to_resume = tmp_to_resume;
-  record_full_beneath_to_wait_ops = tmp_to_wait_ops;
-  record_full_beneath_to_wait = tmp_to_wait;
-  record_full_beneath_to_store_registers_ops = tmp_to_store_registers_ops;
-  record_full_beneath_to_store_registers = tmp_to_store_registers;
-  record_full_beneath_to_xfer_partial_ops = tmp_to_xfer_partial_ops;
-  record_full_beneath_to_xfer_partial = tmp_to_xfer_partial;
-  record_full_beneath_to_insert_breakpoint = tmp_to_insert_breakpoint;
-  record_full_beneath_to_insert_breakpoint_ops = tmp_to_insert_breakpoint_ops;
-  record_full_beneath_to_remove_breakpoint = tmp_to_remove_breakpoint;
-  record_full_beneath_to_remove_breakpoint_ops = tmp_to_remove_breakpoint_ops;
-  record_full_beneath_to_stopped_by_watchpoint = tmp_to_stopped_by_watchpoint;
-  record_full_beneath_to_stopped_data_address = tmp_to_stopped_data_address;
-  record_full_beneath_to_async = tmp_to_async;
-
   if (core_bfd)
     record_full_core_open_1 (name, from_tty);
   else
@@ -1135,8 +982,7 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
       /* Make sure the target beneath reports all signals.  */
       target_pass_signals (0, NULL);
 
-      record_full_beneath_to_resume (record_full_beneath_to_resume_ops,
-				     ptid, step, signal);
+      ops->beneath->to_resume (ops->beneath, ptid, step, signal);
     }
 
   /* We are about to start executing the inferior (or simulate it),
@@ -1226,8 +1072,7 @@ record_full_wait_1 (struct target_ops *ops,
       if (record_full_resume_step)
 	{
 	  /* This is a single step.  */
-	  return record_full_beneath_to_wait (record_full_beneath_to_wait_ops,
-					      ptid, status, options);
+	  return ops->beneath->to_wait (ops->beneath, ptid, status, options);
 	}
       else
 	{
@@ -1238,8 +1083,7 @@ record_full_wait_1 (struct target_ops *ops,
 
 	  while (1)
 	    {
-	      ret = record_full_beneath_to_wait
-		(record_full_beneath_to_wait_ops, ptid, status, options);
+	      ret = ops->beneath->to_wait (ops->beneath, ptid, status, options);
 	      if (status->kind == TARGET_WAITKIND_IGNORE)
 		{
 		  if (record_debug)
@@ -1323,9 +1167,8 @@ record_full_wait_1 (struct target_ops *ops,
 					    "Process record: record_full_wait "
 					    "issuing one more step in the "
 					    "target beneath\n");
-		      record_full_beneath_to_resume
-			(record_full_beneath_to_resume_ops, ptid, step,
-			 GDB_SIGNAL_0);
+		      ops->beneath->to_resume (ops->beneath, ptid, step,
+					       GDB_SIGNAL_0);
 		      continue;
 		    }
 		}
@@ -1529,11 +1372,7 @@ record_full_stopped_by_watchpoint (struct target_ops *ops)
   if (RECORD_FULL_IS_REPLAY)
     return record_full_hw_watchpoint;
   else
-    {
-      struct target_ops *beneath = find_target_beneath (ops);
-
-      return record_full_beneath_to_stopped_by_watchpoint (beneath);
-    }
+    return ops->beneath->to_stopped_by_watchpoint (ops->beneath);
 }
 
 static int
@@ -1542,7 +1381,7 @@ record_full_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
   if (RECORD_FULL_IS_REPLAY)
     return 0;
   else
-    return record_full_beneath_to_stopped_data_address (ops, addr_p);
+    return ops->beneath->to_stopped_data_address (ops->beneath, addr_p);
 }
 
 /* Record registers change (by user or by GDB) to list as an instruction.  */
@@ -1645,8 +1484,7 @@ record_full_store_registers (struct target_ops *ops,
 
       record_full_registers_change (regcache, regno);
     }
-  record_full_beneath_to_store_registers
-    (record_full_beneath_to_store_registers_ops, regcache, regno);
+  ops->beneath->to_store_registers (ops->beneath, regcache, regno);
 }
 
 /* "to_xfer_partial" method.  Behavior is conditional on
@@ -1711,9 +1549,9 @@ record_full_xfer_partial (struct target_ops *ops, enum target_object object,
 	record_full_insn_num++;
     }
 
-  return record_full_beneath_to_xfer_partial
-    (record_full_beneath_to_xfer_partial_ops, object, annex,
-     readbuf, writebuf, offset, len);
+  return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+					readbuf, writebuf, offset,
+					len);
 }
 
 /* This structure represents a breakpoint inserted while the record
@@ -1794,9 +1632,7 @@ record_full_insert_breakpoint (struct target_ops *ops,
       int ret;
 
       old_cleanups = record_full_gdb_operation_disable_set ();
-      ops = record_full_beneath_to_insert_breakpoint_ops;
-      ret = record_full_beneath_to_insert_breakpoint (ops, gdbarch,
-						      bp_tgt);
+      ret = ops->beneath->to_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
       do_cleanups (old_cleanups);
 
       if (ret != 0)
@@ -1837,9 +1673,8 @@ record_full_remove_breakpoint (struct target_ops *ops,
 	      int ret;
 
 	      old_cleanups = record_full_gdb_operation_disable_set ();
-	      ops = record_full_beneath_to_remove_breakpoint_ops;
-	      ret = record_full_beneath_to_remove_breakpoint (ops, gdbarch,
-							      bp_tgt);
+	      ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch,
+							bp_tgt);
 	      do_cleanups (old_cleanups);
 
 	      if (ret != 0)
@@ -1913,18 +1748,6 @@ record_full_goto_bookmark (gdb_byte *raw_bookmark, int from_tty)
   return;
 }
 
-static void
-record_full_async (struct target_ops *ops,
-		   void (*callback) (enum inferior_event_type event_type,
-				     void *context), void *context)
-{
-  /* If we're on top of a line target (e.g., linux-nat, remote), then
-     set it to async mode as well.  Will be NULL if we're sitting on
-     top of the core target, for "record restore".  */
-  if (record_full_beneath_to_async != NULL)
-    record_full_beneath_to_async (find_target_beneath (ops), callback, context);
-}
-
 static int
 record_full_can_async_p (struct target_ops *ops)
 {
@@ -2103,7 +1926,6 @@ init_record_full_ops (void)
   /* Add bookmark target methods.  */
   record_full_ops.to_get_bookmark = record_full_get_bookmark;
   record_full_ops.to_goto_bookmark = record_full_goto_bookmark;
-  record_full_ops.to_async = record_full_async;
   record_full_ops.to_can_async_p = record_full_can_async_p;
   record_full_ops.to_is_async_p = record_full_is_async_p;
   record_full_ops.to_execution_direction = record_full_execution_direction;
@@ -2263,10 +2085,10 @@ record_full_core_xfer_partial (struct target_ops *ops,
 		  else
 		    {
 		      if (!entry)
-			return record_full_beneath_to_xfer_partial
-			  (record_full_beneath_to_xfer_partial_ops,
-			   object, annex, readbuf, writebuf,
-			   offset, len);
+			return ops->beneath->to_xfer_partial (ops->beneath,
+							      object, annex,
+							      readbuf, writebuf,
+							      offset, len);
 
 		      memcpy (readbuf, entry->buf + sec_offset,
 			      (size_t) len);
@@ -2282,9 +2104,8 @@ record_full_core_xfer_partial (struct target_ops *ops,
 	error (_("You can't do that without a process to debug."));
     }
 
-  return record_full_beneath_to_xfer_partial
-    (record_full_beneath_to_xfer_partial_ops, object, annex,
-     readbuf, writebuf, offset, len);
+  return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+					readbuf, writebuf, offset, len);
 }
 
 /* "to_insert_breakpoint" method for prec over corefile.  */
@@ -2346,9 +2167,6 @@ init_record_full_core_ops (void)
   /* Add bookmark target methods.  */
   record_full_core_ops.to_get_bookmark = record_full_get_bookmark;
   record_full_core_ops.to_goto_bookmark = record_full_goto_bookmark;
-  record_full_core_ops.to_async = record_full_async;
-  record_full_core_ops.to_can_async_p = record_full_can_async_p;
-  record_full_core_ops.to_is_async_p = record_full_is_async_p;
   record_full_core_ops.to_execution_direction
     = record_full_execution_direction;
   record_full_core_ops.to_info_record = record_full_info;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index cf6364d..8f28321 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -4,11 +4,163 @@
 /* To regenerate this file, run:*/
 /*      make-target-delegates target.h > target-delegates.c */
 static void
+delegate_resume (struct target_ops *self, ptid_t arg1, int arg2, enum gdb_signal arg3)
+{
+  self = self->beneath;
+  self->to_resume (self, arg1, arg2, arg3);
+}
+
+static void
+tdefault_resume (struct target_ops *self, ptid_t arg1, int arg2, enum gdb_signal arg3)
+{
+  noprocess ();
+}
+
+static ptid_t
+delegate_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3)
+{
+  self = self->beneath;
+  return self->to_wait (self, arg1, arg2, arg3);
+}
+
+static ptid_t
+tdefault_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3)
+{
+  noprocess ();
+}
+
+static void
+delegate_store_registers (struct target_ops *self, struct regcache *arg1, int arg2)
+{
+  self = self->beneath;
+  self->to_store_registers (self, arg1, arg2);
+}
+
+static void
+tdefault_store_registers (struct target_ops *self, struct regcache *arg1, int arg2)
+{
+  noprocess ();
+}
+
+static int
+delegate_insert_breakpoint (struct target_ops *self, struct gdbarch *arg1, struct bp_target_info *arg2)
+{
+  self = self->beneath;
+  return self->to_insert_breakpoint (self, arg1, arg2);
+}
+
+static int
+delegate_remove_breakpoint (struct target_ops *self, struct gdbarch *arg1, struct bp_target_info *arg2)
+{
+  self = self->beneath;
+  return self->to_remove_breakpoint (self, arg1, arg2);
+}
+
+static int
+delegate_stopped_by_watchpoint (struct target_ops *self)
+{
+  self = self->beneath;
+  return self->to_stopped_by_watchpoint (self);
+}
+
+static int
+tdefault_stopped_by_watchpoint (struct target_ops *self)
+{
+  return 0;
+}
+
+static int
+delegate_stopped_data_address (struct target_ops *self, CORE_ADDR *arg1)
+{
+  self = self->beneath;
+  return self->to_stopped_data_address (self, arg1);
+}
+
+static int
+tdefault_stopped_data_address (struct target_ops *self, CORE_ADDR *arg1)
+{
+  return 0;
+}
+
+static int
+delegate_can_async_p (struct target_ops *self)
+{
+  self = self->beneath;
+  return self->to_can_async_p (self);
+}
+
+static int
+delegate_is_async_p (struct target_ops *self)
+{
+  self = self->beneath;
+  return self->to_is_async_p (self);
+}
+
+static void
+delegate_async (struct target_ops *self, async_callback_ftype *arg1, void *arg2)
+{
+  self = self->beneath;
+  self->to_async (self, arg1, arg2);
+}
+
+static void
+tdefault_async (struct target_ops *self, async_callback_ftype *arg1, void *arg2)
+{
+  tcomplain ();
+}
+
+static LONGEST
+delegate_xfer_partial (struct target_ops *self, enum target_object  arg1, const char *arg2, gdb_byte *arg3, const gdb_byte *arg4, ULONGEST arg5, ULONGEST arg6)
+{
+  self = self->beneath;
+  return self->to_xfer_partial (self, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+
+static LONGEST
+tdefault_xfer_partial (struct target_ops *self, enum target_object  arg1, const char *arg2, gdb_byte *arg3, const gdb_byte *arg4, ULONGEST arg5, ULONGEST arg6)
+{
+  return -1;
+}
+
+static void
 install_delegators (struct target_ops *ops)
 {
+  if (ops->to_resume == NULL)
+    ops->to_resume = delegate_resume;
+  if (ops->to_wait == NULL)
+    ops->to_wait = delegate_wait;
+  if (ops->to_store_registers == NULL)
+    ops->to_store_registers = delegate_store_registers;
+  if (ops->to_insert_breakpoint == NULL)
+    ops->to_insert_breakpoint = delegate_insert_breakpoint;
+  if (ops->to_remove_breakpoint == NULL)
+    ops->to_remove_breakpoint = delegate_remove_breakpoint;
+  if (ops->to_stopped_by_watchpoint == NULL)
+    ops->to_stopped_by_watchpoint = delegate_stopped_by_watchpoint;
+  if (ops->to_stopped_data_address == NULL)
+    ops->to_stopped_data_address = delegate_stopped_data_address;
+  if (ops->to_can_async_p == NULL)
+    ops->to_can_async_p = delegate_can_async_p;
+  if (ops->to_is_async_p == NULL)
+    ops->to_is_async_p = delegate_is_async_p;
+  if (ops->to_async == NULL)
+    ops->to_async = delegate_async;
+  if (ops->to_xfer_partial == NULL)
+    ops->to_xfer_partial = delegate_xfer_partial;
 }
 
 static void
 install_dummy_methods (struct target_ops *ops)
 {
+  ops->to_resume = tdefault_resume;
+  ops->to_wait = tdefault_wait;
+  ops->to_store_registers = tdefault_store_registers;
+  ops->to_insert_breakpoint = memory_insert_breakpoint;
+  ops->to_remove_breakpoint = memory_remove_breakpoint;
+  ops->to_stopped_by_watchpoint = tdefault_stopped_by_watchpoint;
+  ops->to_stopped_data_address = tdefault_stopped_data_address;
+  ops->to_can_async_p = find_default_can_async_p;
+  ops->to_is_async_p = find_default_is_async_p;
+  ops->to_async = tdefault_async;
+  ops->to_xfer_partial = tdefault_xfer_partial;
 }
diff --git a/gdb/target.c b/gdb/target.c
index 3109559..bde91ab 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -74,11 +74,13 @@ static struct target_ops *find_default_run_target (char *);
 
 static target_xfer_partial_ftype default_xfer_partial;
 
-static target_xfer_partial_ftype current_xfer_partial;
-
 static struct gdbarch *default_thread_architecture (struct target_ops *ops,
 						    ptid_t ptid);
 
+static int find_default_can_async_p (struct target_ops *ignore);
+
+static int find_default_is_async_p (struct target_ops *ignore);
+
 #include "target-delegates.c"
 
 static void init_dummy_target (void);
@@ -600,10 +602,10 @@ update_current_target (void)
       INHERIT (to_remove_watchpoint, t);
       /* Do not inherit to_insert_mask_watchpoint.  */
       /* Do not inherit to_remove_mask_watchpoint.  */
-      INHERIT (to_stopped_data_address, t);
+      /* Do not inherit to_stopped_data_address.  */
       INHERIT (to_have_steppable_watchpoint, t);
       INHERIT (to_have_continuable_watchpoint, t);
-      INHERIT (to_stopped_by_watchpoint, t);
+      /* Do not inherit to_stopped_by_watchpoint.  */
       INHERIT (to_watchpoint_addr_within_range, t);
       INHERIT (to_region_ok_for_hw_watchpoint, t);
       INHERIT (to_can_accel_watchpoint_condition, t);
@@ -648,9 +650,9 @@ update_current_target (void)
       /* Do not inherit to_has_registers.  */
       /* Do not inherit to_has_execution.  */
       INHERIT (to_has_thread_control, t);
-      INHERIT (to_can_async_p, t);
-      INHERIT (to_is_async_p, t);
-      INHERIT (to_async, t);
+      /* Do not inherit to_can_async_p.  */
+      /* Do not inherit to_is_async_p.  */
+      /* Do not inherit to_async.  */
       INHERIT (to_find_memory_regions, t);
       INHERIT (to_make_corefile_notes, t);
       INHERIT (to_get_bookmark, t);
@@ -746,12 +748,6 @@ update_current_target (void)
   de_fault (to_remove_watchpoint,
 	    (int (*) (CORE_ADDR, int, int, struct expression *))
 	    return_minus_one);
-  de_fault (to_stopped_by_watchpoint,
-	    (int (*) (struct target_ops *))
-	    return_zero);
-  de_fault (to_stopped_data_address,
-	    (int (*) (struct target_ops *, CORE_ADDR *))
-	    return_zero);
   de_fault (to_watchpoint_addr_within_range,
 	    default_watchpoint_addr_within_range);
   de_fault (to_region_ok_for_hw_watchpoint,
@@ -817,18 +813,12 @@ update_current_target (void)
   de_fault (to_stop,
 	    (void (*) (ptid_t))
 	    target_ignore);
-  current_target.to_xfer_partial = current_xfer_partial;
   de_fault (to_rcmd,
 	    (void (*) (char *, struct ui_file *))
 	    tcomplain);
   de_fault (to_pid_to_exec_file,
 	    (char *(*) (int))
 	    return_null);
-  de_fault (to_async,
-	    (void (*) (struct target_ops *,
-		       void (*) (enum inferior_event_type, void*),
-		       void*))
-	    tcomplain);
   de_fault (to_thread_architecture,
 	    default_thread_architecture);
   current_target.to_read_description = NULL;
@@ -2004,27 +1994,12 @@ default_xfer_partial (struct target_ops *ops, enum target_object object,
       else
 	return -1;
     }
-  else if (ops->beneath != NULL)
-    return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
-					  readbuf, writebuf, offset, len);
-  else
-    return -1;
-}
-
-/* The xfer_partial handler for the topmost target.  Unlike the default,
-   it does not need to handle memory specially; it just passes all
-   requests down the stack.  */
-
-static LONGEST
-current_xfer_partial (struct target_ops *ops, enum target_object object,
-		      const char *annex, gdb_byte *readbuf,
-		      const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
-{
-  if (ops->beneath != NULL)
-    return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
-					  readbuf, writebuf, offset, len);
   else
-    return -1;
+    {
+      gdb_assert (ops->beneath != NULL);
+      return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+					    readbuf, writebuf, offset, len);
+    }
 }
 
 /* Target vector read/write partial wrapper functions.  */
@@ -2467,20 +2442,6 @@ get_target_memory_unsigned (struct target_ops *ops, CORE_ADDR addr,
 /* See target.h.  */
 
 int
-forward_target_insert_breakpoint (struct target_ops *ops,
-				  struct gdbarch *gdbarch,
-				  struct bp_target_info *bp_tgt)
-{
-  for (; ops != NULL; ops = ops->beneath)
-    if (ops->to_insert_breakpoint != NULL)
-      return ops->to_insert_breakpoint (ops, gdbarch, bp_tgt);
-
-  return memory_insert_breakpoint (ops, gdbarch, bp_tgt);
-}
-
-/* See target.h.  */
-
-int
 target_insert_breakpoint (struct gdbarch *gdbarch,
 			  struct bp_target_info *bp_tgt)
 {
@@ -2490,15 +2451,15 @@ target_insert_breakpoint (struct gdbarch *gdbarch,
       return 1;
     }
 
-  return forward_target_insert_breakpoint (&current_target, gdbarch, bp_tgt);
+  return current_target.to_insert_breakpoint (&current_target,
+					      gdbarch, bp_tgt);
 }
 
 /* See target.h.  */
 
 int
-forward_target_remove_breakpoint (struct target_ops *ops,
-				  struct gdbarch *gdbarch,
-				  struct bp_target_info *bp_tgt)
+target_remove_breakpoint (struct gdbarch *gdbarch,
+			  struct bp_target_info *bp_tgt)
 {
   /* This is kind of a weird case to handle, but the permission might
      have been changed after breakpoints were inserted - in which case
@@ -2510,20 +2471,8 @@ forward_target_remove_breakpoint (struct target_ops *ops,
       return 1;
     }
 
-  for (; ops != NULL; ops = ops->beneath)
-    if (ops->to_remove_breakpoint != NULL)
-      return ops->to_remove_breakpoint (ops, gdbarch, bp_tgt);
-
-  return memory_remove_breakpoint (ops, gdbarch, bp_tgt);
-}
-
-/* See target.h.  */
-
-int
-target_remove_breakpoint (struct gdbarch *gdbarch,
-			  struct bp_target_info *bp_tgt)
-{
-  return forward_target_remove_breakpoint (&current_target, gdbarch, bp_tgt);
+  return current_target.to_remove_breakpoint (&current_target,
+					      gdbarch, bp_tgt);
 }
 
 static void
@@ -2703,34 +2652,26 @@ ptid_t
 target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
 {
   struct target_ops *t;
+  ptid_t retval = (current_target.to_wait) (&current_target, ptid,
+					    status, options);
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
+  if (targetdebug)
     {
-      if (t->to_wait != NULL)
-	{
-	  ptid_t retval = (*t->to_wait) (t, ptid, status, options);
+      char *status_string;
+      char *options_string;
 
-	  if (targetdebug)
-	    {
-	      char *status_string;
-	      char *options_string;
-
-	      status_string = target_waitstatus_to_string (status);
-	      options_string = target_options_to_string (options);
-	      fprintf_unfiltered (gdb_stdlog,
-				  "target_wait (%d, status, options={%s})"
-				  " = %d,   %s\n",
-				  ptid_get_pid (ptid), options_string,
-				  ptid_get_pid (retval), status_string);
-	      xfree (status_string);
-	      xfree (options_string);
-	    }
-
-	  return retval;
-	}
+      status_string = target_waitstatus_to_string (status);
+      options_string = target_options_to_string (options);
+      fprintf_unfiltered (gdb_stdlog,
+			  "target_wait (%d, status, options={%s})"
+			  " = %d,   %s\n",
+			  ptid_get_pid (ptid), options_string,
+			  ptid_get_pid (retval), status_string);
+      xfree (status_string);
+      xfree (options_string);
     }
 
-  noprocess ();
+  return retval;
 }
 
 char *
@@ -2768,26 +2709,17 @@ target_resume (ptid_t ptid, int step, enum gdb_signal signal)
 
   target_dcache_invalidate ();
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    {
-      if (t->to_resume != NULL)
-	{
-	  t->to_resume (t, ptid, step, signal);
-	  if (targetdebug)
-	    fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n",
-				ptid_get_pid (ptid),
-				step ? "step" : "continue",
-				gdb_signal_to_name (signal));
-
-	  registers_changed_ptid (ptid);
-	  set_executing (ptid, 1);
-	  set_running (ptid, 1);
-	  clear_inline_frame_state (ptid);
-	  return;
-	}
-    }
+  current_target.to_resume (&current_target, ptid, step, signal);
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n",
+			ptid_get_pid (ptid),
+			step ? "step" : "continue",
+			gdb_signal_to_name (signal));
 
-  noprocess ();
+  registers_changed_ptid (ptid);
+  set_executing (ptid, 1);
+  set_running (ptid, 1);
+  clear_inline_frame_state (ptid);
 }
 
 void
@@ -3184,7 +3116,7 @@ find_default_can_async_p (struct target_ops *ignore)
      configured with a native debugger, and target remote isn't
      connected yet.  */
   t = find_default_run_target (NULL);
-  if (t && t->to_can_async_p)
+  if (t && t->to_can_async_p != delegate_can_async_p)
     return (t->to_can_async_p) (t);
   return 0;
 }
@@ -3199,7 +3131,7 @@ find_default_is_async_p (struct target_ops *ignore)
      configured with a native debugger, and target remote isn't
      connected yet.  */
   t = find_default_run_target (NULL);
-  if (t && t->to_is_async_p)
+  if (t && t->to_is_async_p != delegate_is_async_p)
     return (t->to_is_async_p) (t);
   return 0;
 }
@@ -3804,8 +3736,6 @@ init_dummy_target (void)
   dummy_target.to_detach = 
     (void (*)(struct target_ops *, const char *, int))target_ignore;
   dummy_target.to_create_inferior = find_default_create_inferior;
-  dummy_target.to_can_async_p = find_default_can_async_p;
-  dummy_target.to_is_async_p = find_default_is_async_p;
   dummy_target.to_supports_non_stop = find_default_supports_non_stop;
   dummy_target.to_supports_disable_randomization
     = find_default_supports_disable_randomization;
@@ -3815,17 +3745,12 @@ init_dummy_target (void)
   dummy_target.to_make_corefile_notes = dummy_make_corefile_notes;
   dummy_target.to_get_bookmark = dummy_get_bookmark;
   dummy_target.to_goto_bookmark = dummy_goto_bookmark;
-  dummy_target.to_xfer_partial = default_xfer_partial;
   dummy_target.to_has_all_memory = (int (*) (struct target_ops *)) return_zero;
   dummy_target.to_has_memory = (int (*) (struct target_ops *)) return_zero;
   dummy_target.to_has_stack = (int (*) (struct target_ops *)) return_zero;
   dummy_target.to_has_registers = (int (*) (struct target_ops *)) return_zero;
   dummy_target.to_has_execution
     = (int (*) (struct target_ops *, ptid_t)) return_zero;
-  dummy_target.to_stopped_by_watchpoint
-    = (int (*) (struct target_ops *)) return_zero;
-  dummy_target.to_stopped_data_address =
-    (int (*) (struct target_ops *, CORE_ADDR *)) return_zero;
   dummy_target.to_magic = OPS_MAGIC;
 
   install_dummy_methods (&dummy_target);
@@ -4045,20 +3970,11 @@ target_store_registers (struct regcache *regcache, int regno)
   if (!may_write_registers)
     error (_("Writing to registers is not allowed (regno %d)"), regno);
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
+  current_target.to_store_registers (&current_target, regcache, regno);
+  if (targetdebug)
     {
-      if (t->to_store_registers != NULL)
-	{
-	  t->to_store_registers (t, regcache, regno);
-	  if (targetdebug)
-	    {
-	      debug_print_register ("target_store_registers", regcache, regno);
-	    }
-	  return;
-	}
+      debug_print_register ("target_store_registers", regcache, regno);
     }
-
-  noprocess ();
 }
 
 int
@@ -4632,7 +4548,7 @@ debug_to_insert_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
 {
   int retval;
 
-  retval = forward_target_insert_breakpoint (&debug_target, gdbarch, bp_tgt);
+  retval = debug_target.to_insert_breakpoint (&debug_target, gdbarch, bp_tgt);
 
   fprintf_unfiltered (gdb_stdlog,
 		      "target_insert_breakpoint (%s, xxx) = %ld\n",
@@ -4647,7 +4563,7 @@ debug_to_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
 {
   int retval;
 
-  retval = forward_target_remove_breakpoint (&debug_target, gdbarch, bp_tgt);
+  retval = debug_target.to_remove_breakpoint (&debug_target, gdbarch, bp_tgt);
 
   fprintf_unfiltered (gdb_stdlog,
 		      "target_remove_breakpoint (%s, xxx) = %ld\n",
diff --git a/gdb/target.h b/gdb/target.h
index 19db907..8d00d3a 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -398,11 +398,14 @@ struct target_ops
     void (*to_post_attach) (int);
     void (*to_detach) (struct target_ops *ops, const char *, int);
     void (*to_disconnect) (struct target_ops *, char *, int);
-    void (*to_resume) (struct target_ops *, ptid_t, int, enum gdb_signal);
+    void (*to_resume) (struct target_ops *, ptid_t, int, enum gdb_signal)
+      TARGET_DEFAULT_NORETURN (noprocess ());
     ptid_t (*to_wait) (struct target_ops *,
-		       ptid_t, struct target_waitstatus *, int);
+		       ptid_t, struct target_waitstatus *, int)
+      TARGET_DEFAULT_NORETURN (noprocess ());
     void (*to_fetch_registers) (struct target_ops *, struct regcache *, int);
-    void (*to_store_registers) (struct target_ops *, struct regcache *, int);
+    void (*to_store_registers) (struct target_ops *, struct regcache *, int)
+      TARGET_DEFAULT_NORETURN (noprocess ());
     void (*to_prepare_to_store) (struct target_ops *, struct regcache *);
 
     /* Transfer LEN bytes of memory between GDB address MYADDR and
@@ -433,9 +436,11 @@ struct target_ops
 
     void (*to_files_info) (struct target_ops *);
     int (*to_insert_breakpoint) (struct target_ops *, struct gdbarch *,
-				 struct bp_target_info *);
+				 struct bp_target_info *)
+      TARGET_DEFAULT_FUNC (memory_insert_breakpoint);
     int (*to_remove_breakpoint) (struct target_ops *, struct gdbarch *,
-				 struct bp_target_info *);
+				 struct bp_target_info *)
+      TARGET_DEFAULT_FUNC (memory_remove_breakpoint);
     int (*to_can_use_hw_breakpoint) (int, int, int);
     int (*to_ranged_break_num_registers) (struct target_ops *);
     int (*to_insert_hw_breakpoint) (struct gdbarch *, struct bp_target_info *);
@@ -450,10 +455,12 @@ struct target_ops
 				      CORE_ADDR, CORE_ADDR, int);
     int (*to_remove_mask_watchpoint) (struct target_ops *,
 				      CORE_ADDR, CORE_ADDR, int);
-    int (*to_stopped_by_watchpoint) (struct target_ops *);
+    int (*to_stopped_by_watchpoint) (struct target_ops *)
+      TARGET_DEFAULT_RETURN (0);
     int to_have_steppable_watchpoint;
     int to_have_continuable_watchpoint;
-    int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
+    int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *)
+      TARGET_DEFAULT_RETURN (0);
     int (*to_watchpoint_addr_within_range) (struct target_ops *,
 					    CORE_ADDR, CORE_ADDR, int);
 
@@ -515,10 +522,12 @@ struct target_ops
     int to_has_thread_control;	/* control thread execution */
     int to_attach_no_wait;
     /* ASYNC target controls */
-    int (*to_can_async_p) (struct target_ops *);
-    int (*to_is_async_p) (struct target_ops *);
-    void (*to_async) (struct target_ops *,
-		      async_callback_ftype *, void *);
+    int (*to_can_async_p) (struct target_ops *)
+      TARGET_DEFAULT_FUNC (find_default_can_async_p);
+    int (*to_is_async_p) (struct target_ops *)
+      TARGET_DEFAULT_FUNC (find_default_is_async_p);
+    void (*to_async) (struct target_ops *, async_callback_ftype *, void *)
+      TARGET_DEFAULT_NORETURN (tcomplain ());
     int (*to_supports_non_stop) (void);
     /* find_memory_regions support method for gcore */
     int (*to_find_memory_regions) (find_memory_region_ftype func, void *data);
@@ -569,7 +578,8 @@ struct target_ops
     LONGEST (*to_xfer_partial) (struct target_ops *ops,
 				enum target_object object, const char *annex,
 				gdb_byte *readbuf, const gdb_byte *writebuf,
-				ULONGEST offset, ULONGEST len);
+				ULONGEST offset, ULONGEST len)
+      TARGET_DEFAULT_RETURN (-1);
 
     /* Returns the memory map for the target.  A return value of NULL
        means that no memory map is available.  If a memory address
@@ -1177,29 +1187,12 @@ int target_write_memory_blocks (VEC(memory_write_request_s) *requests,
 /* Insert a hardware breakpoint at address BP_TGT->placed_address in
    the target machine.  Returns 0 for success, and returns non-zero or
    throws an error (with a detailed failure reason error code and
-   message) otherwise.
-   Start the target search at OPS.  */
-
-extern int forward_target_insert_breakpoint (struct target_ops *ops,
-					     struct gdbarch *gdbarch,
-					     struct bp_target_info *bp_tgt);
-
-/* Insert a hardware breakpoint at address BP_TGT->placed_address in
-   the target machine.  Returns 0 for success, and returns non-zero or
-   throws an error (with a detailed failure reason error code and
    message) otherwise.  */
 
 extern int target_insert_breakpoint (struct gdbarch *gdbarch,
 				     struct bp_target_info *bp_tgt);
 
 /* Remove a breakpoint at address BP_TGT->placed_address in the target
-   machine.  Result is 0 for success, non-zero for error.
-   Start the target search at OPS.  */
-
-extern int forward_target_remove_breakpoint (struct target_ops *ops,
-					     struct gdbarch *gdbarch,
-					     struct bp_target_info *bp_tgt);
-/* Remove a breakpoint at address BP_TGT->placed_address in the target
    machine.  Result is 0 for success, non-zero for error.  */
 
 extern int target_remove_breakpoint (struct gdbarch *gdbarch,
-- 
1.8.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]