gdbserver/linux-low: turn watchpoint ops into methods
[deliverable/binutils-gdb.git] / gdbserver / linux-low.h
index 7ac9086fb9991d51dacab3133a1e19d8dee39e45..ee2fdb8e865b93e4658e6001cdfeccd226a8b000 100644 (file)
@@ -131,32 +131,6 @@ struct lwp_info;
 
 struct linux_target_ops
 {
-  CORE_ADDR (*get_pc) (struct regcache *regcache);
-  void (*set_pc) (struct regcache *regcache, CORE_ADDR newpc);
-
-  /* See target.h for details.  */
-  int (*breakpoint_kind_from_pc) (CORE_ADDR *pcptr);
-
-  /* See target.h for details.  */
-  const gdb_byte *(*sw_breakpoint_from_kind) (int kind, int *size);
-
-  /* Find the next possible PCs after the current instruction executes.  */
-  std::vector<CORE_ADDR> (*get_next_pcs) (struct regcache *regcache);
-
-  int decr_pc_after_break;
-  int (*breakpoint_at) (CORE_ADDR pc);
-
-  /* Breakpoint and watchpoint related functions.  See target.h for
-     comments.  */
-  int (*supports_z_point_type) (char z_type);
-  int (*insert_point) (enum raw_bkpt_type type, CORE_ADDR addr,
-                      int size, struct raw_breakpoint *bp);
-  int (*remove_point) (enum raw_bkpt_type type, CORE_ADDR addr,
-                      int size, struct raw_breakpoint *bp);
-
-  int (*stopped_by_watchpoint) (void);
-  CORE_ADDR (*stopped_data_address) (void);
-
   /* Hooks to reformat register data for PEEKUSR/POKEUSR (in particular
      for registers smaller than an xfer unit).  */
   void (*collect_ptrace_register) (struct regcache *regcache,
@@ -230,9 +204,6 @@ struct linux_target_ops
   /* Returns true if the low target supports range stepping.  */
   int (*supports_range_stepping) (void);
 
-  /* See target.h.  */
-  int (*breakpoint_kind_from_current_state) (CORE_ADDR *pcptr);
-
   /* See target.h.  */
   int (*supports_hardware_single_step) (void);
 
@@ -297,8 +268,6 @@ public:
   int read_auxv (CORE_ADDR offset, unsigned char *myaddr,
                 unsigned int len) override;
 
-  bool supports_z_point_type (char z_type) override;
-
   int insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
                    int size, raw_breakpoint *bp) override;
 
@@ -445,12 +414,6 @@ public:
   ssize_t multifs_readlink (int pid, const char *filename, char *buf,
                            size_t bufsiz) override;
 
-  int breakpoint_kind_from_pc (CORE_ADDR *pcptr) override;
-
-  const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
-
-  int breakpoint_kind_from_current_state (CORE_ADDR *pcptr) override;
-
   const char *thread_name (ptid_t thread) override;
 
 #if USE_THREAD_DB
@@ -458,8 +421,6 @@ public:
                      int *handle_len) override;
 #endif
 
-  bool supports_software_single_step () override;
-
   bool supports_catch_syscall () override;
 
   int get_ipa_tdesc_idx () override;
@@ -580,6 +541,100 @@ private:
   void usr_store_inferior_registers (const regs_info *regs_info,
                                     regcache *regcache, int regno, int all);
 
+  /* Return the PC as read from the regcache of LWP, without any
+     adjustment.  */
+  CORE_ADDR get_pc (lwp_info *lwp);
+
+  /* Called when the LWP stopped for a signal/trap.  If it stopped for a
+     trap check what caused it (breakpoint, watchpoint, trace, etc.),
+     and save the result in the LWP's stop_reason field.  If it stopped
+     for a breakpoint, decrement the PC if necessary on the lwp's
+     architecture.  Returns true if we now have the LWP's stop PC.  */
+  bool save_stop_reason (lwp_info *lwp);
+
+  /* Resume execution of LWP.  If STEP is nonzero, single-step it.  If
+     SIGNAL is nonzero, give it that signal.  */
+  void resume_one_lwp_throw (lwp_info *lwp, int step, int signal,
+                            siginfo_t *info);
+
+  /* Like resume_one_lwp_throw, but no error is thrown if the LWP
+     disappears while we try to resume it.  */
+  void resume_one_lwp (lwp_info *lwp, int step, int signal, siginfo_t *info);
+
+  /* This function is called once per thread.  We check the thread's
+     last resume request, which will tell us whether to resume, step, or
+     leave the thread stopped.  Any signal the client requested to be
+     delivered has already been enqueued at this point.
+
+     If any thread that GDB wants running is stopped at an internal
+     breakpoint that needs stepping over, we start a step-over operation
+     on that particular thread, and leave all others stopped.  */
+  void proceed_one_lwp (thread_info *thread, lwp_info *except);
+
+  /* This function is called once per thread.  We check the thread's
+     resume request, which will tell us whether to resume, step, or
+     leave the thread stopped; and what signal, if any, it should be
+     sent.
+
+     For threads which we aren't explicitly told otherwise, we preserve
+     the stepping flag; this is used for stepping over gdbserver-placed
+     breakpoints.
+
+     If pending_flags was set in any thread, we queue any needed
+     signals, since we won't actually resume.  We already have a pending
+     event to report, so we don't need to preserve any step requests;
+     they should be re-issued if necessary.  */
+  void resume_one_thread (thread_info *thread, bool leave_all_stopped);
+
+  /* Return true if this lwp has an interesting status pending.  */
+  bool status_pending_p_callback (thread_info *thread, ptid_t ptid);
+
+  /* Resume LWPs that are currently stopped without any pending status
+     to report, but are resumed from the core's perspective.  */
+  void resume_stopped_resumed_lwps (thread_info *thread);
+
+  /* Unsuspend THREAD, except EXCEPT, and proceed.  */
+  void unsuspend_and_proceed_one_lwp (thread_info *thread, lwp_info *except);
+
+  /* Return true if this lwp still has an interesting status pending.
+     If not (e.g., it had stopped for a breakpoint that is gone), return
+     false.  */
+  bool thread_still_has_status_pending (thread_info *thread);
+
+  /* Return true if this lwp is to-be-resumed and has an interesting
+     status pending.  */
+  bool resume_status_pending (thread_info *thread);
+
+  /* Return true if this lwp that GDB wants running is stopped at an
+     internal breakpoint that we need to step over.  It assumes that
+     any required STOP_PC adjustment has already been propagated to
+     the inferior's regcache.  */
+  bool thread_needs_step_over (thread_info *thread);
+
+  /* Single step via hardware or software single step.
+     Return 1 if hardware single stepping, 0 if software single stepping
+     or can't single step.  */
+  int single_step (lwp_info* lwp);
+
+  /* Install breakpoints for software single stepping.  */
+  void install_software_single_step_breakpoints (lwp_info *lwp);
+
+  /* Fetch the possibly triggered data watchpoint info and store it in
+     CHILD.
+
+     On some archs, like x86, that use debug registers to set
+     watchpoints, it's possible that the way to know which watched
+     address trapped, is to check the register that is used to select
+     which address to watch.  Problem is, between setting the watchpoint
+     and reading back which data address trapped, the user may change
+     the set of watchpoints, and, as a consequence, GDB changes the
+     debug registers in the inferior.  To avoid reading back a stale
+     stopped-data-address when that happens, we cache in LP the fact
+     that a watchpoint trapped, and the corresponding data address, as
+     soon as we see CHILD stop with a SIGTRAP.  If GDB changes the debug
+     registers meanwhile, we have the cached data we can rely on.  */
+  bool check_stopped_by_watchpoint (lwp_info *child);
+
 protected:
   /* The architecture-specific "low" methods are listed below.  */
 
@@ -598,6 +653,37 @@ protected:
      REGNO was supplied, false if not, and we should fallback to the
      standard ptrace methods.  */
   virtual bool low_fetch_register (regcache *regcache, int regno);
+
+  /* Return true if breakpoints are supported.  Such targets must
+     implement the GET_PC and SET_PC methods.  */
+  virtual bool low_supports_breakpoints ();
+
+  virtual CORE_ADDR low_get_pc (regcache *regcache);
+
+  virtual void low_set_pc (regcache *regcache, CORE_ADDR newpc);
+
+  /* Find the next possible PCs after the current instruction executes.
+     Targets that override this method should also override
+     'supports_software_single_step' to return true.  */
+  virtual std::vector<CORE_ADDR> low_get_next_pcs (regcache *regcache);
+
+  /* Return true if there is a breakpoint at PC.  */
+  virtual bool low_breakpoint_at (CORE_ADDR pc) = 0;
+
+  /* Breakpoint and watchpoint related functions.  See target.h for
+     comments.  */
+  virtual int low_insert_point (raw_bkpt_type type, CORE_ADDR addr,
+                               int size, raw_breakpoint *bp);
+
+  virtual int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
+                               int size, raw_breakpoint *bp);
+
+  virtual bool low_stopped_by_watchpoint ();
+
+  virtual CORE_ADDR low_stopped_data_address ();
+
+  /* How many bytes the PC should be decremented after a break.  */
+  virtual int low_decr_pc_after_break ();
 };
 
 extern linux_process_target *the_linux_target;
This page took 0.037899 seconds and 4 git commands to generate.