select_event_lwp_callback: update comments
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-low.c
index 1682679f81012afa9b4476c8565d82dc9a5126e6..9558f46371664d5cd86a3ff8ed44b5229e70e867 100644 (file)
 
 #ifdef HAVE_LINUX_BTRACE
 # include "nat/linux-btrace.h"
 
 #ifdef HAVE_LINUX_BTRACE
 # include "nat/linux-btrace.h"
+# include "btrace-common.h"
 #endif
 
 #ifndef HAVE_ELF32_AUXV_T
 #endif
 
 #ifndef HAVE_ELF32_AUXV_T
@@ -356,13 +357,13 @@ linux_add_process (int pid, int attached)
   struct process_info *proc;
 
   proc = add_process (pid, attached);
   struct process_info *proc;
 
   proc = add_process (pid, attached);
-  proc->private = xcalloc (1, sizeof (*proc->private));
+  proc->priv = xcalloc (1, sizeof (*proc->priv));
 
   /* Set the arch when the first LWP stops.  */
 
   /* Set the arch when the first LWP stops.  */
-  proc->private->new_inferior = 1;
+  proc->priv->new_inferior = 1;
 
   if (the_low_target.new_process != NULL)
 
   if (the_low_target.new_process != NULL)
-    proc->private->arch_private = the_low_target.new_process ();
+    proc->priv->arch_private = the_low_target.new_process ();
 
   return proc;
 }
 
   return proc;
 }
@@ -492,6 +493,9 @@ check_stopped_by_breakpoint (struct lwp_info *lwp)
   CORE_ADDR pc;
   CORE_ADDR sw_breakpoint_pc;
   struct thread_info *saved_thread;
   CORE_ADDR pc;
   CORE_ADDR sw_breakpoint_pc;
   struct thread_info *saved_thread;
+#if USE_SIGTRAP_SIGINFO
+  siginfo_t siginfo;
+#endif
 
   if (the_low_target.get_pc == NULL)
     return 0;
 
   if (the_low_target.get_pc == NULL)
     return 0;
@@ -503,17 +507,59 @@ check_stopped_by_breakpoint (struct lwp_info *lwp)
   saved_thread = current_thread;
   current_thread = get_lwp_thread (lwp);
 
   saved_thread = current_thread;
   current_thread = get_lwp_thread (lwp);
 
+#if USE_SIGTRAP_SIGINFO
+  if (ptrace (PTRACE_GETSIGINFO, lwpid_of (current_thread),
+             (PTRACE_TYPE_ARG3) 0, &siginfo) == 0)
+    {
+      if (siginfo.si_signo == SIGTRAP)
+       {
+         if (siginfo.si_code == GDB_ARCH_TRAP_BRKPT)
+           {
+             if (debug_threads)
+               {
+                 struct thread_info *thr = get_lwp_thread (lwp);
+
+                 debug_printf ("CSBB: Push back software breakpoint for %s\n",
+                               target_pid_to_str (ptid_of (thr)));
+               }
+
+             /* Back up the PC if necessary.  */
+             if (pc != sw_breakpoint_pc)
+               {
+                 struct regcache *regcache
+                   = get_thread_regcache (current_thread, 1);
+                 (*the_low_target.set_pc) (regcache, sw_breakpoint_pc);
+               }
+
+             lwp->stop_pc = sw_breakpoint_pc;
+             lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
+             current_thread = saved_thread;
+             return 1;
+           }
+         else if (siginfo.si_code == TRAP_HWBKPT)
+           {
+             if (debug_threads)
+               {
+                 struct thread_info *thr = get_lwp_thread (lwp);
+
+                 debug_printf ("CSBB: Push back hardware "
+                               "breakpoint/watchpoint for %s\n",
+                               target_pid_to_str (ptid_of (thr)));
+               }
+
+             lwp->stop_pc = pc;
+             lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
+             current_thread = saved_thread;
+             return 1;
+           }
+       }
+    }
+#else
   /* We may have just stepped a breakpoint instruction.  E.g., in
      non-stop mode, GDB first tells the thread A to step a range, and
      then the user inserts a breakpoint inside the range.  In that
   /* We may have just stepped a breakpoint instruction.  E.g., in
      non-stop mode, GDB first tells the thread A to step a range, and
      then the user inserts a breakpoint inside the range.  In that
-     case, we need to report the breakpoint PC.  But, when we're
-     trying to step past one of our own breakpoints, that happens to
-     have been placed on top of a permanent breakpoint instruction, we
-     shouldn't adjust the PC, otherwise the program would keep
-     trapping the permanent breakpoint forever.  */
-  if ((!lwp->stepping
-       || (!ptid_equal (ptid_of (current_thread), step_over_bkpt)
-          && lwp->stop_pc == sw_breakpoint_pc))
+     case we need to report the breakpoint PC.  */
+  if ((!lwp->stepping || lwp->stop_pc == sw_breakpoint_pc)
       && (*the_low_target.breakpoint_at) (sw_breakpoint_pc))
     {
       if (debug_threads)
       && (*the_low_target.breakpoint_at) (sw_breakpoint_pc))
     {
       if (debug_threads)
@@ -533,7 +579,7 @@ check_stopped_by_breakpoint (struct lwp_info *lwp)
        }
 
       lwp->stop_pc = sw_breakpoint_pc;
        }
 
       lwp->stop_pc = sw_breakpoint_pc;
-      lwp->stop_reason = LWP_STOPPED_BY_SW_BREAKPOINT;
+      lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
       current_thread = saved_thread;
       return 1;
     }
       current_thread = saved_thread;
       return 1;
     }
@@ -549,10 +595,11 @@ check_stopped_by_breakpoint (struct lwp_info *lwp)
        }
 
       lwp->stop_pc = pc;
        }
 
       lwp->stop_pc = pc;
-      lwp->stop_reason = LWP_STOPPED_BY_HW_BREAKPOINT;
+      lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
       current_thread = saved_thread;
       return 1;
     }
       current_thread = saved_thread;
       return 1;
     }
+#endif
 
   current_thread = saved_thread;
   return 0;
 
   current_thread = saved_thread;
   return 0;
@@ -1172,10 +1219,10 @@ linux_mourn (struct process_info *process)
   find_inferior (&all_threads, delete_lwp_callback, process);
 
   /* Freeing all private data.  */
   find_inferior (&all_threads, delete_lwp_callback, process);
 
   /* Freeing all private data.  */
-  priv = process->private;
+  priv = process->priv;
   free (priv->arch_private);
   free (priv);
   free (priv->arch_private);
   free (priv);
-  process->private = NULL;
+  process->priv = NULL;
 
   remove_process (process);
 }
 
   remove_process (process);
 }
@@ -1226,8 +1273,8 @@ thread_still_has_status_pending_p (struct thread_info *thread)
     return 0;
 
   if (thread->last_resume_kind != resume_stop
     return 0;
 
   if (thread->last_resume_kind != resume_stop
-      && (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT
-         || lp->stop_reason == LWP_STOPPED_BY_HW_BREAKPOINT))
+      && (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+         || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT))
     {
       struct thread_info *saved_thread;
       CORE_ADDR pc;
     {
       struct thread_info *saved_thread;
       CORE_ADDR pc;
@@ -1247,7 +1294,9 @@ thread_still_has_status_pending_p (struct thread_info *thread)
                          lwpid_of (thread));
          discard = 1;
        }
                          lwpid_of (thread));
          discard = 1;
        }
-      else if (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT
+
+#if !USE_SIGTRAP_SIGINFO
+      else if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
               && !(*the_low_target.breakpoint_at) (pc))
        {
          if (debug_threads)
               && !(*the_low_target.breakpoint_at) (pc))
        {
          if (debug_threads)
@@ -1255,7 +1304,7 @@ thread_still_has_status_pending_p (struct thread_info *thread)
                          lwpid_of (thread));
          discard = 1;
        }
                          lwpid_of (thread));
          discard = 1;
        }
-      else if (lp->stop_reason == LWP_STOPPED_BY_HW_BREAKPOINT
+      else if (lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT
               && !hardware_breakpoint_inserted_here (pc))
        {
          if (debug_threads)
               && !hardware_breakpoint_inserted_here (pc))
        {
          if (debug_threads)
@@ -1263,6 +1312,7 @@ thread_still_has_status_pending_p (struct thread_info *thread)
                          lwpid_of (thread));
          discard = 1;
        }
                          lwpid_of (thread));
          discard = 1;
        }
+#endif
 
       current_thread = saved_thread;
 
 
       current_thread = saved_thread;
 
@@ -1287,9 +1337,8 @@ status_pending_p_callback (struct inferior_list_entry *entry, void *arg)
   ptid_t ptid = * (ptid_t *) arg;
 
   /* Check if we're only interested in events from a specific process
   ptid_t ptid = * (ptid_t *) arg;
 
   /* Check if we're only interested in events from a specific process
-     or its lwps.  */
-  if (!ptid_equal (minus_one_ptid, ptid)
-      && ptid_get_pid (ptid) != ptid_get_pid (thread->entry.id))
+     or a specific LWP.  */
+  if (!ptid_match (ptid_of (thread), ptid))
     return 0;
 
   if (lp->status_pending_p
     return 0;
 
   if (lp->status_pending_p
@@ -1737,19 +1786,6 @@ dequeue_one_deferred_signal (struct lwp_info *lwp, int *wstat)
   return 0;
 }
 
   return 0;
 }
 
-/* Return true if the event in LP may be caused by breakpoint.  */
-
-static int
-wstatus_maybe_breakpoint (int wstatus)
-{
-  return (WIFSTOPPED (wstatus)
-         && (WSTOPSIG (wstatus) == SIGTRAP
-             /* SIGILL and SIGSEGV are also treated as traps in case a
-                breakpoint is inserted at the current PC.  */
-             || WSTOPSIG (wstatus) == SIGILL
-             || WSTOPSIG (wstatus) == SIGSEGV));
-}
-
 /* Fetch the possibly triggered data watchpoint info and store it in
    CHILD.
 
 /* Fetch the possibly triggered data watchpoint info and store it in
    CHILD.
 
@@ -1777,7 +1813,7 @@ check_stopped_by_watchpoint (struct lwp_info *child)
 
       if (the_low_target.stopped_by_watchpoint ())
        {
 
       if (the_low_target.stopped_by_watchpoint ())
        {
-         child->stop_reason = LWP_STOPPED_BY_WATCHPOINT;
+         child->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
 
          if (the_low_target.stopped_data_address != NULL)
            child->stopped_data_address
 
          if (the_low_target.stopped_data_address != NULL)
            child->stopped_data_address
@@ -1789,7 +1825,7 @@ check_stopped_by_watchpoint (struct lwp_info *child)
       current_thread = saved_thread;
     }
 
       current_thread = saved_thread;
     }
 
-  return child->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
+  return child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
 }
 
 /* Do low-level handling of the event, and check if we should go on
 }
 
 /* Do low-level handling of the event, and check if we should go on
@@ -1861,7 +1897,7 @@ linux_low_filter_event (int lwpid, int wstat)
         is stopped for the first time, but before we access any
         inferior registers.  */
       proc = find_process_pid (pid_of (thread));
         is stopped for the first time, but before we access any
         inferior registers.  */
       proc = find_process_pid (pid_of (thread));
-      if (proc->private->new_inferior)
+      if (proc->priv->new_inferior)
        {
          struct thread_info *saved_thread;
 
        {
          struct thread_info *saved_thread;
 
@@ -1872,7 +1908,7 @@ linux_low_filter_event (int lwpid, int wstat)
 
          current_thread = saved_thread;
 
 
          current_thread = saved_thread;
 
-         proc->private->new_inferior = 0;
+         proc->priv->new_inferior = 0;
        }
     }
 
        }
     }
 
@@ -1894,15 +1930,24 @@ linux_low_filter_event (int lwpid, int wstat)
       return NULL;
     }
 
       return NULL;
     }
 
-  if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP
-      && check_stopped_by_watchpoint (child))
-    ;
-  else if (WIFSTOPPED (wstat) && wstatus_maybe_breakpoint (wstat))
+  /* Check first whether this was a SW/HW breakpoint before checking
+     watchpoints, because at least s390 can't tell the data address of
+     hardware watchpoint hits, and returns stopped-by-watchpoint as
+     long as there's a watchpoint set.  */
+  if (WIFSTOPPED (wstat) && linux_wstatus_maybe_breakpoint (wstat))
     {
       if (check_stopped_by_breakpoint (child))
        have_stop_pc = 1;
     }
 
     {
       if (check_stopped_by_breakpoint (child))
        have_stop_pc = 1;
     }
 
+  /* Note that TRAP_HWBKPT can indicate either a hardware breakpoint
+     or hardware watchpoint.  Check which is which if we got
+     TARGET_STOPPED_BY_HW_BREAKPOINT.  */
+  if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP
+      && (child->stop_reason == TARGET_STOPPED_BY_NO_REASON
+         || child->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT))
+    check_stopped_by_watchpoint (child);
+
   if (!have_stop_pc)
     child->stop_pc = get_pc (child);
 
   if (!have_stop_pc)
     child->stop_pc = get_pc (child);
 
@@ -2222,8 +2267,7 @@ select_singlestep_lwp_callback (struct inferior_list_entry *entry, void *data)
     return 0;
 }
 
     return 0;
 }
 
-/* Select the Nth LWP that has had a SIGTRAP event that should be
-   reported to GDB.  */
+/* Select the Nth LWP that has had an event.  */
 
 static int
 select_event_lwp_callback (struct inferior_list_entry *entry, void *data)
 
 static int
 select_event_lwp_callback (struct inferior_list_entry *entry, void *data)
@@ -2276,12 +2320,13 @@ select_event_lwp (struct lwp_info **orig_lp)
   if (event_thread == NULL)
     {
       /* No single-stepping LWP.  Select one at random, out of those
   if (event_thread == NULL)
     {
       /* No single-stepping LWP.  Select one at random, out of those
-         which have had SIGTRAP events.  */
+         which have had events.  */
 
 
-      /* First see how many SIGTRAP events we have.  */
+      /* First see how many events we have.  */
       find_inferior (&all_threads, count_events_callback, &num_events);
 
       find_inferior (&all_threads, count_events_callback, &num_events);
 
-      /* Now randomly pick a LWP out of those that have had a SIGTRAP.  */
+      /* Now randomly pick a LWP out of those that have had
+        events.  */
       random_selector = (int)
        ((num_events * (double) rand ()) / (RAND_MAX + 1.0));
 
       random_selector = (int)
        ((num_events * (double) rand ()) / (RAND_MAX + 1.0));
 
@@ -2565,6 +2610,36 @@ linux_wait_1 (ptid_t ptid,
       return ptid_of (current_thread);
     }
 
       return ptid_of (current_thread);
     }
 
+  /* If step-over executes a breakpoint instruction, it means a
+     gdb/gdbserver breakpoint had been planted on top of a permanent
+     breakpoint.  The PC has been adjusted by
+     check_stopped_by_breakpoint to point at the breakpoint address.
+     Advance the PC manually past the breakpoint, otherwise the
+     program would keep trapping the permanent breakpoint forever.  */
+  if (!ptid_equal (step_over_bkpt, null_ptid)
+      && event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT)
+    {
+      unsigned int increment_pc = the_low_target.breakpoint_len;
+
+      if (debug_threads)
+       {
+         debug_printf ("step-over for %s executed software breakpoint\n",
+                       target_pid_to_str (ptid_of (current_thread)));
+       }
+
+      if (increment_pc != 0)
+       {
+         struct regcache *regcache
+           = get_thread_regcache (current_thread, 1);
+
+         event_child->stop_pc += increment_pc;
+         (*the_low_target.set_pc) (regcache, event_child->stop_pc);
+
+         if (!(*the_low_target.breakpoint_at) (event_child->stop_pc))
+           event_child->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+       }
+    }
+
   /* If this event was not handled before, and is not a SIGTRAP, we
      report it.  SIGILL and SIGSEGV are also treated as traps in case
      a breakpoint is inserted at the current PC.  If this target does
   /* If this event was not handled before, and is not a SIGTRAP, we
      report it.  SIGILL and SIGSEGV are also treated as traps in case
      a breakpoint is inserted at the current PC.  If this target does
@@ -2738,21 +2813,23 @@ linux_wait_1 (ptid_t ptid,
      any that GDB specifically requested we ignore.  But never ignore
      SIGSTOP if we sent it ourselves, and do not ignore signals when
      stepping - they may require special handling to skip the signal
      any that GDB specifically requested we ignore.  But never ignore
      SIGSTOP if we sent it ourselves, and do not ignore signals when
      stepping - they may require special handling to skip the signal
-     handler.  */
+     handler. Also never ignore signals that could be caused by a
+     breakpoint.  */
   /* FIXME drow/2002-06-09: Get signal numbers from the inferior's
      thread library?  */
   if (WIFSTOPPED (w)
       && current_thread->last_resume_kind != resume_step
       && (
 #if defined (USE_THREAD_DB) && !defined (__ANDROID__)
   /* FIXME drow/2002-06-09: Get signal numbers from the inferior's
      thread library?  */
   if (WIFSTOPPED (w)
       && current_thread->last_resume_kind != resume_step
       && (
 #if defined (USE_THREAD_DB) && !defined (__ANDROID__)
-         (current_process ()->private->thread_db != NULL
+         (current_process ()->priv->thread_db != NULL
           && (WSTOPSIG (w) == __SIGRTMIN
               || WSTOPSIG (w) == __SIGRTMIN + 1))
          ||
 #endif
          (pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
           && !(WSTOPSIG (w) == SIGSTOP
           && (WSTOPSIG (w) == __SIGRTMIN
               || WSTOPSIG (w) == __SIGRTMIN + 1))
          ||
 #endif
          (pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
           && !(WSTOPSIG (w) == SIGSTOP
-               && current_thread->last_resume_kind == resume_stop))))
+               && current_thread->last_resume_kind == resume_stop)
+          && !linux_wstatus_maybe_breakpoint (w))))
     {
       siginfo_t info, *info_p;
 
     {
       siginfo_t info, *info_p;
 
@@ -2786,7 +2863,7 @@ linux_wait_1 (ptid_t ptid,
   report_to_gdb = (!maybe_internal_trap
                   || (current_thread->last_resume_kind == resume_step
                       && !in_step_range)
   report_to_gdb = (!maybe_internal_trap
                   || (current_thread->last_resume_kind == resume_step
                       && !in_step_range)
-                  || event_child->stop_reason == LWP_STOPPED_BY_WATCHPOINT
+                  || event_child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT
                   || (!step_over_finished && !in_step_range
                       && !bp_explains_trap && !trace_event)
                   || (gdb_breakpoint_here (event_child->stop_pc)
                   || (!step_over_finished && !in_step_range
                       && !bp_explains_trap && !trace_event)
                   || (gdb_breakpoint_here (event_child->stop_pc)
@@ -2850,7 +2927,7 @@ linux_wait_1 (ptid_t ptid,
          else if (!lwp_in_step_range (event_child))
            debug_printf ("Out of step range, reporting event.\n");
        }
          else if (!lwp_in_step_range (event_child))
            debug_printf ("Out of step range, reporting event.\n");
        }
-      if (event_child->stop_reason == LWP_STOPPED_BY_WATCHPOINT)
+      if (event_child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT)
        debug_printf ("Stopped by watchpoint.\n");
       else if (gdb_breakpoint_here (event_child->stop_pc))
        debug_printf ("Stopped by GDB breakpoint.\n");
        debug_printf ("Stopped by watchpoint.\n");
       else if (gdb_breakpoint_here (event_child->stop_pc))
        debug_printf ("Stopped by GDB breakpoint.\n");
@@ -2925,8 +3002,10 @@ linux_wait_1 (ptid_t ptid,
   ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
   /* Now that we've selected our final event LWP, un-adjust its PC if
   ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
   /* Now that we've selected our final event LWP, un-adjust its PC if
-     it was a software breakpoint.  */
-  if (event_child->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT)
+     it was a software breakpoint, and the client doesn't know we can
+     adjust the breakpoint ourselves.  */
+  if (event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+      && !swbreak_feature)
     {
       int decr_pc = the_low_target.decr_pc_after_break;
 
     {
       int decr_pc = the_low_target.decr_pc_after_break;
 
@@ -3203,7 +3282,7 @@ stuck_in_jump_pad_callback (struct inferior_list_entry *entry, void *data)
   return (supports_fast_tracepoints ()
          && agent_loaded_p ()
          && (gdb_breakpoint_here (lwp->stop_pc)
   return (supports_fast_tracepoints ()
          && agent_loaded_p ()
          && (gdb_breakpoint_here (lwp->stop_pc)
-             || lwp->stop_reason == LWP_STOPPED_BY_WATCHPOINT
+             || lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT
              || thread->last_resume_kind == resume_step)
          && linux_fast_tracepoint_collecting (lwp, NULL));
 }
              || thread->last_resume_kind == resume_step)
          && linux_fast_tracepoint_collecting (lwp, NULL));
 }
@@ -3222,7 +3301,7 @@ move_out_of_jump_pad_callback (struct inferior_list_entry *entry)
 
   /* Allow debugging the jump pad, gdb_collect, etc.  */
   if (!gdb_breakpoint_here (lwp->stop_pc)
 
   /* Allow debugging the jump pad, gdb_collect, etc.  */
   if (!gdb_breakpoint_here (lwp->stop_pc)
-      && lwp->stop_reason != LWP_STOPPED_BY_WATCHPOINT
+      && lwp->stop_reason != TARGET_STOPPED_BY_WATCHPOINT
       && thread->last_resume_kind != resume_step
       && maybe_move_out_of_jump_pad (lwp, wstat))
     {
       && thread->last_resume_kind != resume_step
       && maybe_move_out_of_jump_pad (lwp, wstat))
     {
@@ -3487,7 +3566,7 @@ linux_resume_one_lwp (struct lwp_info *lwp,
   regcache_invalidate_thread (thread);
   errno = 0;
   lwp->stopped = 0;
   regcache_invalidate_thread (thread);
   errno = 0;
   lwp->stopped = 0;
-  lwp->stop_reason = LWP_STOPPED_BY_NO_REASON;
+  lwp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
   lwp->stepping = step;
   ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (thread),
          (PTRACE_TYPE_ARG3) 0,
   lwp->stepping = step;
   ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (thread),
          (PTRACE_TYPE_ARG3) 0,
@@ -4808,7 +4887,7 @@ linux_look_up_symbols (void)
 #ifdef USE_THREAD_DB
   struct process_info *proc = current_process ();
 
 #ifdef USE_THREAD_DB
   struct process_info *proc = current_process ();
 
-  if (proc->private->thread_db != NULL)
+  if (proc->priv->thread_db != NULL)
     return;
 
   /* If the kernel supports tracing clones, then we don't need to
     return;
 
   /* If the kernel supports tracing clones, then we don't need to
@@ -4888,12 +4967,52 @@ linux_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
     return 1;
 }
 
     return 1;
 }
 
+/* Implement the to_stopped_by_sw_breakpoint target_ops
+   method.  */
+
+static int
+linux_stopped_by_sw_breakpoint (void)
+{
+  struct lwp_info *lwp = get_thread_lwp (current_thread);
+
+  return (lwp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT);
+}
+
+/* Implement the to_supports_stopped_by_sw_breakpoint target_ops
+   method.  */
+
+static int
+linux_supports_stopped_by_sw_breakpoint (void)
+{
+  return USE_SIGTRAP_SIGINFO;
+}
+
+/* Implement the to_stopped_by_hw_breakpoint target_ops
+   method.  */
+
+static int
+linux_stopped_by_hw_breakpoint (void)
+{
+  struct lwp_info *lwp = get_thread_lwp (current_thread);
+
+  return (lwp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT);
+}
+
+/* Implement the to_supports_stopped_by_hw_breakpoint target_ops
+   method.  */
+
+static int
+linux_supports_stopped_by_hw_breakpoint (void)
+{
+  return USE_SIGTRAP_SIGINFO;
+}
+
 static int
 linux_stopped_by_watchpoint (void)
 {
   struct lwp_info *lwp = get_thread_lwp (current_thread);
 
 static int
 linux_stopped_by_watchpoint (void)
 {
   struct lwp_info *lwp = get_thread_lwp (current_thread);
 
-  return lwp->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
+  return lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
 }
 
 static CORE_ADDR
 }
 
 static CORE_ADDR
@@ -5728,7 +5847,7 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
 {
   char *document;
   unsigned document_len;
 {
   char *document;
   unsigned document_len;
-  struct process_info_private *const priv = current_process ()->private;
+  struct process_info_private *const priv = current_process ()->priv;
   char filename[PATH_MAX];
   int pid, is_elf64;
 
   char filename[PATH_MAX];
   int pid, is_elf64;
 
@@ -5784,9 +5903,9 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
        break;
 
       len = sep - annex;
        break;
 
       len = sep - annex;
-      if (len == 5 && strncmp (annex, "start", 5) == 0)
+      if (len == 5 && startswith (annex, "start"))
        addrp = &lm_addr;
        addrp = &lm_addr;
-      else if (len == 4 && strncmp (annex, "prev", 4) == 0)
+      else if (len == 4 && startswith (annex, "prev"))
        addrp = &lm_prev;
       else
        {
        addrp = &lm_prev;
       else
        {
@@ -5937,13 +6056,13 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
 /* See to_enable_btrace target method.  */
 
 static struct btrace_target_info *
 /* See to_enable_btrace target method.  */
 
 static struct btrace_target_info *
-linux_low_enable_btrace (ptid_t ptid)
+linux_low_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 {
   struct btrace_target_info *tinfo;
 
 {
   struct btrace_target_info *tinfo;
 
-  tinfo = linux_enable_btrace (ptid);
+  tinfo = linux_enable_btrace (ptid, conf);
 
 
-  if (tinfo != NULL)
+  if (tinfo != NULL && tinfo->ptr_bits == 0)
     {
       struct thread_info *thread = find_thread_ptid (ptid);
       struct regcache *regcache = get_thread_regcache (thread, 0);
     {
       struct thread_info *thread = find_thread_ptid (ptid);
       struct regcache *regcache = get_thread_regcache (thread, 0);
@@ -5971,12 +6090,13 @@ static int
 linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
                       int type)
 {
 linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
                       int type)
 {
-  VEC (btrace_block_s) *btrace;
+  struct btrace_data btrace;
   struct btrace_block *block;
   enum btrace_error err;
   int i;
 
   struct btrace_block *block;
   enum btrace_error err;
   int i;
 
-  btrace = NULL;
+  btrace_data_init (&btrace);
+
   err = linux_read_btrace (&btrace, tinfo, type);
   if (err != BTRACE_ERR_NONE)
     {
   err = linux_read_btrace (&btrace, tinfo, type);
   if (err != BTRACE_ERR_NONE)
     {
@@ -5985,20 +6105,68 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
       else
        buffer_grow_str0 (buffer, "E.Generic Error.");
 
       else
        buffer_grow_str0 (buffer, "E.Generic Error.");
 
+      btrace_data_fini (&btrace);
+      return -1;
+    }
+
+  switch (btrace.format)
+    {
+    case BTRACE_FORMAT_NONE:
+      buffer_grow_str0 (buffer, "E.No Trace.");
+      break;
+
+    case BTRACE_FORMAT_BTS:
+      buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
+      buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+
+      for (i = 0;
+          VEC_iterate (btrace_block_s, btrace.variant.bts.blocks, i, block);
+          i++)
+       buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
+                          paddress (block->begin), paddress (block->end));
+
+      buffer_grow_str0 (buffer, "</btrace>\n");
+      break;
+
+    default:
+      buffer_grow_str0 (buffer, "E.Unknown Trace Format.");
+
+      btrace_data_fini (&btrace);
       return -1;
     }
 
       return -1;
     }
 
-  buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
-  buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+  btrace_data_fini (&btrace);
+  return 0;
+}
 
 
-  for (i = 0; VEC_iterate (btrace_block_s, btrace, i, block); i++)
-    buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
-                      paddress (block->begin), paddress (block->end));
+/* See to_btrace_conf target method.  */
 
 
-  buffer_grow_str0 (buffer, "</btrace>\n");
+static int
+linux_low_btrace_conf (const struct btrace_target_info *tinfo,
+                      struct buffer *buffer)
+{
+  const struct btrace_config *conf;
 
 
-  VEC_free (btrace_block_s, btrace);
+  buffer_grow_str (buffer, "<!DOCTYPE btrace-conf SYSTEM \"btrace-conf.dtd\">\n");
+  buffer_grow_str (buffer, "<btrace-conf version=\"1.0\">\n");
 
 
+  conf = linux_btrace_conf (tinfo);
+  if (conf != NULL)
+    {
+      switch (conf->format)
+       {
+       case BTRACE_FORMAT_NONE:
+         break;
+
+       case BTRACE_FORMAT_BTS:
+         buffer_xml_printf (buffer, "<bts");
+         buffer_xml_printf (buffer, " size=\"0x%x\"", conf->bts.size);
+         buffer_xml_printf (buffer, " />\n");
+         break;
+       }
+    }
+
+  buffer_grow_str0 (buffer, "</btrace-conf>\n");
   return 0;
 }
 #endif /* HAVE_LINUX_BTRACE */
   return 0;
 }
 #endif /* HAVE_LINUX_BTRACE */
@@ -6025,6 +6193,10 @@ static struct target_ops linux_target_ops = {
   linux_supports_z_point_type,
   linux_insert_point,
   linux_remove_point,
   linux_supports_z_point_type,
   linux_insert_point,
   linux_remove_point,
+  linux_stopped_by_sw_breakpoint,
+  linux_supports_stopped_by_sw_breakpoint,
+  linux_stopped_by_hw_breakpoint,
+  linux_supports_stopped_by_hw_breakpoint,
   linux_stopped_by_watchpoint,
   linux_stopped_data_address,
 #if defined(__UCLIBC__) && defined(HAS_NOMMU)        \
   linux_stopped_by_watchpoint,
   linux_stopped_data_address,
 #if defined(__UCLIBC__) && defined(HAS_NOMMU)        \
@@ -6074,11 +6246,13 @@ static struct target_ops linux_target_ops = {
   linux_low_enable_btrace,
   linux_low_disable_btrace,
   linux_low_read_btrace,
   linux_low_enable_btrace,
   linux_low_disable_btrace,
   linux_low_read_btrace,
+  linux_low_btrace_conf,
 #else
   NULL,
   NULL,
   NULL,
   NULL,
 #else
   NULL,
   NULL,
   NULL,
   NULL,
+  NULL,
 #endif
   linux_supports_range_stepping,
 };
 #endif
   linux_supports_range_stepping,
 };
This page took 0.040222 seconds and 4 git commands to generate.