Make print_command_trace varargs
[deliverable/binutils-gdb.git] / gdb / fbsd-nat.c
index b3524188137f9bb2264e829693aca1ab026a356a..069e1e44bee7694f4f614fd5857fc8304aad3a49 100644 (file)
@@ -26,6 +26,7 @@
 #include "gdbcmd.h"
 #include "gdbthread.h"
 #include "gdb_wait.h"
+#include "inf-ptrace.h"
 #include <sys/types.h>
 #include <sys/procfs.h>
 #include <sys/ptrace.h>
@@ -48,8 +49,8 @@
 /* Return the name of a file that can be opened to get the symbols for
    the child process identified by PID.  */
 
-static char *
-fbsd_pid_to_exec_file (struct target_ops *self, int pid)
+char *
+fbsd_nat_target::pid_to_exec_file (int pid)
 {
   ssize_t len;
   static char buf[PATH_MAX];
@@ -87,9 +88,9 @@ fbsd_pid_to_exec_file (struct target_ops *self, int pid)
    calling FUNC for each memory region.  OBFD is passed as the last
    argument to FUNC.  */
 
-static int
-fbsd_find_memory_regions (struct target_ops *self,
-                         find_memory_region_ftype func, void *obfd)
+int
+fbsd_nat_target::find_memory_regions (find_memory_region_ftype func,
+                                     void *obfd)
 {
   pid_t pid = ptid_get_pid (inferior_ptid);
   struct kinfo_vmentry *kve;
@@ -161,9 +162,9 @@ fbsd_read_mapping (FILE *mapfile, unsigned long *start, unsigned long *end,
    calling FUNC for each memory region.  OBFD is passed as the last
    argument to FUNC.  */
 
-static int
-fbsd_find_memory_regions (struct target_ops *self,
-                         find_memory_region_ftype func, void *obfd)
+int
+fbsd_nat_target::find_memory_regions (find_memory_region_ftype func,
+                                     void *obfd)
 {
   pid_t pid = ptid_get_pid (inferior_ptid);
   unsigned long start, end, size;
@@ -250,11 +251,10 @@ fbsd_fetch_kinfo_proc (pid_t pid, struct kinfo_proc *kp)
   return (sysctl (mib, 4, kp, &len, NULL, 0) == 0);
 }
 
-/* Implement the "to_info_proc target_ops" method.  */
+/* Implement the "info_proc" target_ops method.  */
 
-static void
-fbsd_info_proc (struct target_ops *ops, const char *args,
-               enum info_proc_what what)
+bool
+fbsd_nat_target::info_proc (const char *args, enum info_proc_what what)
 {
 #ifdef HAVE_KINFO_GETFILE
   gdb::unique_xmalloc_ptr<struct kinfo_file> fdtbl;
@@ -369,7 +369,7 @@ fbsd_info_proc (struct target_ops *ops, const char *args,
        }
 #endif
       if (exe == NULL)
-       exe = fbsd_pid_to_exec_file (ops, pid);
+       exe = pid_to_exec_file (pid);
       if (exe != NULL)
        printf_filtered ("exe = '%s'\n", exe);
       else
@@ -530,17 +530,11 @@ fbsd_info_proc (struct target_ops *ops, const char *args,
          printf_filtered ("\n");
        }
     }
+
+  return true;
 }
 
 #ifdef KERN_PROC_AUXV
-static enum target_xfer_status (*super_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 *xfered_len);
 
 #ifdef PT_LWPINFO
 /* Return the size of siginfo for the current inferior.  */
@@ -671,13 +665,14 @@ fbsd_convert_siginfo (siginfo_t *si)
 }
 #endif
 
-/* Implement the "to_xfer_partial target_ops" method.  */
+/* Implement the "xfer_partial" target_ops method.  */
 
-static enum target_xfer_status
-fbsd_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 *xfered_len)
+enum target_xfer_status
+fbsd_nat_target::xfer_partial (enum target_object object,
+                              const char *annex, gdb_byte *readbuf,
+                              const gdb_byte *writebuf,
+                              ULONGEST offset, ULONGEST len,
+                              ULONGEST *xfered_len)
 {
   pid_t pid = ptid_get_pid (inferior_ptid);
 
@@ -757,23 +752,16 @@ fbsd_xfer_partial (struct target_ops *ops, enum target_object object,
        return TARGET_XFER_E_IO;
       }
     default:
-      return super_xfer_partial (ops, object, annex, readbuf, writebuf, offset,
-                                len, xfered_len);
+      return inf_ptrace_target::xfer_partial (object, annex,
+                                             readbuf, writebuf, offset,
+                                             len, xfered_len);
     }
 }
 #endif
 
 #ifdef PT_LWPINFO
 static int debug_fbsd_lwp;
-
-static void (*super_resume) (struct target_ops *,
-                            ptid_t,
-                            int,
-                            enum gdb_signal);
-static ptid_t (*super_wait) (struct target_ops *,
-                            ptid_t,
-                            struct target_waitstatus *,
-                            int);
+static int debug_fbsd_nat;
 
 static void
 show_fbsd_lwp_debug (struct ui_file *file, int from_tty,
@@ -782,6 +770,14 @@ show_fbsd_lwp_debug (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Debugging of FreeBSD lwp module is %s.\n"), value);
 }
 
+static void
+show_fbsd_nat_debug (struct ui_file *file, int from_tty,
+                    struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Debugging of FreeBSD native target is %s.\n"),
+                   value);
+}
+
 /*
   FreeBSD's first thread support was via a "reentrant" version of libc
   (libc_r) that first shipped in 2.2.7.  This library multiplexed all
@@ -811,8 +807,8 @@ show_fbsd_lwp_debug (struct ui_file *file, int from_tty,
 
 /* Return true if PTID is still active in the inferior.  */
 
-static int
-fbsd_thread_alive (struct target_ops *ops, ptid_t ptid)
+bool
+fbsd_nat_target::thread_alive (ptid_t ptid)
 {
   if (ptid_lwp_p (ptid))
     {
@@ -820,21 +816,21 @@ fbsd_thread_alive (struct target_ops *ops, ptid_t ptid)
 
       if (ptrace (PT_LWPINFO, ptid_get_lwp (ptid), (caddr_t) &pl, sizeof pl)
          == -1)
-       return 0;
+       return false;
 #ifdef PL_FLAG_EXITED
       if (pl.pl_flags & PL_FLAG_EXITED)
-       return 0;
+       return false;
 #endif
     }
 
-  return 1;
+  return true;
 }
 
 /* Convert PTID to a string.  Returns the string in a static
    buffer.  */
 
-static const char *
-fbsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
+const char *
+fbsd_nat_target::pid_to_str (ptid_t ptid)
 {
   lwpid_t lwp;
 
@@ -855,8 +851,8 @@ fbsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
 /* Return the name assigned to a thread by an application.  Returns
    the string in a static buffer.  */
 
-static const char *
-fbsd_thread_name (struct target_ops *self, struct thread_info *thr)
+const char *
+fbsd_nat_target::thread_name (struct thread_info *thr)
 {
   struct ptrace_lwpinfo pl;
   struct kinfo_proc kp;
@@ -966,10 +962,10 @@ fbsd_add_threads (pid_t pid)
     }
 }
 
-/* Implement the "to_update_thread_list" target_ops method.  */
+/* Implement the "update_thread_list" target_ops method.  */
 
-static void
-fbsd_update_thread_list (struct target_ops *ops)
+void
+fbsd_nat_target::update_thread_list ()
 {
 #ifdef PT_LWP_EVENTS
   /* With support for thread events, threads are added/deleted from the
@@ -1084,11 +1080,10 @@ fbsd_next_vfork_done (void)
 #endif
 #endif
 
-/* Implement the "to_resume" target_ops method.  */
+/* Implement the "resume" target_ops method.  */
 
-static void
-fbsd_resume (struct target_ops *ops,
-            ptid_t ptid, int step, enum gdb_signal signo)
+void
+fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
 {
 #if defined(TDP_RFPPWAIT) && !defined(PTRACE_VFORK)
   pid_t pid;
@@ -1143,17 +1138,97 @@ fbsd_resume (struct target_ops *ops,
        }
       ptid = inferior_ptid;
     }
-  super_resume (ops, ptid, step, signo);
+
+#if __FreeBSD_version < 1200052
+  /* When multiple threads within a process wish to report STOPPED
+     events from wait(), the kernel picks one thread event as the
+     thread event to report.  The chosen thread event is retrieved via
+     PT_LWPINFO by passing the process ID as the request pid.  If
+     multiple events are pending, then the subsequent wait() after
+     resuming a process will report another STOPPED event after
+     resuming the process to handle the next thread event and so on.
+
+     A single thread event is cleared as a side effect of resuming the
+     process with PT_CONTINUE, PT_STEP, etc.  In older kernels,
+     however, the request pid was used to select which thread's event
+     was cleared rather than always clearing the event that was just
+     reported.  To avoid clearing the event of the wrong LWP, always
+     pass the process ID instead of an LWP ID to PT_CONTINUE or
+     PT_SYSCALL.
+
+     In the case of stepping, the process ID cannot be used with
+     PT_STEP since it would step the thread that reported an event
+     which may not be the thread indicated by PTID.  For stepping, use
+     PT_SETSTEP to enable stepping on the desired thread before
+     resuming the process via PT_CONTINUE instead of using
+     PT_STEP.  */
+  if (step)
+    {
+      if (ptrace (PT_SETSTEP, get_ptrace_pid (ptid), NULL, 0) == -1)
+       perror_with_name (("ptrace"));
+      step = 0;
+    }
+  ptid = ptid_t (ptid.pid ());
+#endif
+  inf_ptrace_target::resume (ptid, step, signo);
+}
+
+#ifdef USE_SIGTRAP_SIGINFO
+/* Handle breakpoint and trace traps reported via SIGTRAP.  If the
+   trap was a breakpoint or trace trap that should be reported to the
+   core, return true.  */
+
+static bool
+fbsd_handle_debug_trap (ptid_t ptid, const struct ptrace_lwpinfo &pl)
+{
+
+  /* Ignore traps without valid siginfo or for signals other than
+     SIGTRAP.  */
+  if (! (pl.pl_flags & PL_FLAG_SI) || pl.pl_siginfo.si_signo != SIGTRAP)
+    return false;
+
+  /* Trace traps are either a single step or a hardware watchpoint or
+     breakpoint.  */
+  if (pl.pl_siginfo.si_code == TRAP_TRACE)
+    {
+      if (debug_fbsd_nat)
+       fprintf_unfiltered (gdb_stdlog,
+                           "FNAT: trace trap for LWP %ld\n", ptid.lwp ());
+      return true;
+    }
+
+  if (pl.pl_siginfo.si_code == TRAP_BRKPT)
+    {
+      /* Fixup PC for the software breakpoint.  */
+      struct regcache *regcache = get_thread_regcache (ptid);
+      struct gdbarch *gdbarch = regcache->arch ();
+      int decr_pc = gdbarch_decr_pc_after_break (gdbarch);
+
+      if (debug_fbsd_nat)
+       fprintf_unfiltered (gdb_stdlog,
+                           "FNAT: sw breakpoint trap for LWP %ld\n",
+                           ptid.lwp ());
+      if (decr_pc != 0)
+       {
+         CORE_ADDR pc;
+
+         pc = regcache_read_pc (regcache);
+         regcache_write_pc (regcache, pc - decr_pc);
+       }
+      return true;
+    }
+
+  return false;
 }
+#endif
 
 /* Wait for the child specified by PTID to do something.  Return the
    process ID of the child, or MINUS_ONE_PTID in case of error; store
    the status in *OURSTATUS.  */
 
-static ptid_t
-fbsd_wait (struct target_ops *ops,
-          ptid_t ptid, struct target_waitstatus *ourstatus,
-          int target_options)
+ptid_t
+fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
+                      int target_options)
 {
   ptid_t wptid;
 
@@ -1167,7 +1242,7 @@ fbsd_wait (struct target_ops *ops,
          return wptid;
        }
 #endif
-      wptid = super_wait (ops, ptid, ourstatus, target_options);
+      wptid = inf_ptrace_target::wait (ptid, ourstatus, target_options);
       if (ourstatus->kind == TARGET_WAITKIND_STOPPED)
        {
          struct ptrace_lwpinfo pl;
@@ -1180,11 +1255,23 @@ fbsd_wait (struct target_ops *ops,
 
          wptid = ptid_build (pid, pl.pl_lwpid, 0);
 
+         if (debug_fbsd_nat)
+           {
+             fprintf_unfiltered (gdb_stdlog,
+                                 "FNAT: stop for LWP %u event %d flags %#x\n",
+                                 pl.pl_lwpid, pl.pl_event, pl.pl_flags);
+             if (pl.pl_flags & PL_FLAG_SI)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "FNAT: si_signo %u si_code %u\n",
+                                   pl.pl_siginfo.si_signo,
+                                   pl.pl_siginfo.si_code);
+           }
+
 #ifdef PT_LWP_EVENTS
          if (pl.pl_flags & PL_FLAG_EXITED)
            {
              /* If GDB attaches to a multi-threaded process, exiting
-                threads might be skipped during fbsd_post_attach that
+                threads might be skipped during post_attach that
                 have not yet reported their PL_FLAG_EXITED event.
                 Ignore EXITED events for an unknown LWP.  */
              if (in_thread_list (wptid))
@@ -1314,11 +1401,16 @@ fbsd_wait (struct target_ops *ops,
            {
              ourstatus->kind = TARGET_WAITKIND_EXECD;
              ourstatus->value.execd_pathname
-               = xstrdup (fbsd_pid_to_exec_file (NULL, pid));
+               = xstrdup (pid_to_exec_file (pid));
              return wptid;
            }
 #endif
 
+#ifdef USE_SIGTRAP_SIGINFO
+         if (fbsd_handle_debug_trap (wptid, pl))
+           return wptid;
+#endif
+
          /* Note that PL_FLAG_SCE is set for any event reported while
             a thread is executing a system call in the kernel.  In
             particular, signals that interrupt a sleep in a system
@@ -1357,13 +1449,39 @@ fbsd_wait (struct target_ops *ops,
     }
 }
 
+#ifdef USE_SIGTRAP_SIGINFO
+/* Implement the "stopped_by_sw_breakpoint" target_ops method.  */
+
+bool
+fbsd_nat_target::stopped_by_sw_breakpoint ()
+{
+  struct ptrace_lwpinfo pl;
+
+  if (ptrace (PT_LWPINFO, get_ptrace_pid (inferior_ptid), (caddr_t) &pl,
+             sizeof pl) == -1)
+    return false;
+
+  return ((pl.pl_flags & PL_FLAG_SI)
+         && pl.pl_siginfo.si_signo == SIGTRAP
+         && pl.pl_siginfo.si_code == TRAP_BRKPT);
+}
+
+/* Implement the "supports_stopped_by_sw_breakpoint" target_ops
+   method.  */
+
+bool
+fbsd_nat_target::supports_stopped_by_sw_breakpoint ()
+{
+  return true;
+}
+#endif
+
 #ifdef TDP_RFPPWAIT
 /* Target hook for follow_fork.  On entry and at return inferior_ptid is
    the ptid of the followed inferior.  */
 
-static int
-fbsd_follow_fork (struct target_ops *ops, int follow_child,
-                       int detach_fork)
+int
+fbsd_nat_target::follow_fork (int follow_child, int detach_fork)
 {
   if (!follow_child && detach_fork)
     {
@@ -1409,43 +1527,43 @@ fbsd_follow_fork (struct target_ops *ops, int follow_child,
   return 0;
 }
 
-static int
-fbsd_insert_fork_catchpoint (struct target_ops *self, int pid)
+int
+fbsd_nat_target::insert_fork_catchpoint (int pid)
 {
   return 0;
 }
 
-static int
-fbsd_remove_fork_catchpoint (struct target_ops *self, int pid)
+int
+fbsd_nat_target::remove_fork_catchpoint (int pid)
 {
   return 0;
 }
 
-static int
-fbsd_insert_vfork_catchpoint (struct target_ops *self, int pid)
+int
+fbsd_nat_target::insert_vfork_catchpoint (int pid)
 {
   return 0;
 }
 
-static int
-fbsd_remove_vfork_catchpoint (struct target_ops *self, int pid)
+int
+fbsd_nat_target::remove_vfork_catchpoint (int pid)
 {
   return 0;
 }
 #endif
 
-/* Implement the "to_post_startup_inferior" target_ops method.  */
+/* Implement the "post_startup_inferior" target_ops method.  */
 
-static void
-fbsd_post_startup_inferior (struct target_ops *self, ptid_t pid)
+void
+fbsd_nat_target::post_startup_inferior (ptid_t pid)
 {
   fbsd_enable_proc_events (ptid_get_pid (pid));
 }
 
-/* Implement the "to_post_attach" target_ops method.  */
+/* Implement the "post_attach" target_ops method.  */
 
-static void
-fbsd_post_attach (struct target_ops *self, int pid)
+void
+fbsd_nat_target::post_attach (int pid)
 {
   fbsd_enable_proc_events (pid);
   fbsd_add_threads (pid);
@@ -1455,24 +1573,24 @@ fbsd_post_attach (struct target_ops *self, int pid)
 /* If the FreeBSD kernel supports PL_FLAG_EXEC, then traced processes
    will always stop after exec.  */
 
-static int
-fbsd_insert_exec_catchpoint (struct target_ops *self, int pid)
+int
+fbsd_nat_target::insert_exec_catchpoint (int pid)
 {
   return 0;
 }
 
-static int
-fbsd_remove_exec_catchpoint (struct target_ops *self, int pid)
+int
+fbsd_nat_target::remove_exec_catchpoint (int pid)
 {
   return 0;
 }
 #endif
 
 #ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE
-static int
-fbsd_set_syscall_catchpoint (struct target_ops *self, int pid, bool needed,
-                            int any_count,
-                            gdb::array_view<const int> syscall_counts)
+int
+fbsd_nat_target::set_syscall_catchpoint (int pid, bool needed,
+                                        int any_count,
+                                        gdb::array_view<const int> syscall_counts)
 {
 
   /* Ignore the arguments.  inf-ptrace.c will use PT_SYSCALL which
@@ -1483,48 +1601,6 @@ fbsd_set_syscall_catchpoint (struct target_ops *self, int pid, bool needed,
 #endif
 #endif
 
-void
-fbsd_nat_add_target (struct target_ops *t)
-{
-  t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
-  t->to_find_memory_regions = fbsd_find_memory_regions;
-  t->to_info_proc = fbsd_info_proc;
-#ifdef KERN_PROC_AUXV
-  super_xfer_partial = t->to_xfer_partial;
-  t->to_xfer_partial = fbsd_xfer_partial;
-#endif
-#ifdef PT_LWPINFO
-  t->to_thread_alive = fbsd_thread_alive;
-  t->to_pid_to_str = fbsd_pid_to_str;
-#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME
-  t->to_thread_name = fbsd_thread_name;
-#endif
-  t->to_update_thread_list = fbsd_update_thread_list;
-  t->to_has_thread_control = tc_schedlock;
-  super_resume = t->to_resume;
-  t->to_resume = fbsd_resume;
-  super_wait = t->to_wait;
-  t->to_wait = fbsd_wait;
-  t->to_post_startup_inferior = fbsd_post_startup_inferior;
-  t->to_post_attach = fbsd_post_attach;
-#ifdef TDP_RFPPWAIT
-  t->to_follow_fork = fbsd_follow_fork;
-  t->to_insert_fork_catchpoint = fbsd_insert_fork_catchpoint;
-  t->to_remove_fork_catchpoint = fbsd_remove_fork_catchpoint;
-  t->to_insert_vfork_catchpoint = fbsd_insert_vfork_catchpoint;
-  t->to_remove_vfork_catchpoint = fbsd_remove_vfork_catchpoint;
-#endif
-#ifdef PL_FLAG_EXEC
-  t->to_insert_exec_catchpoint = fbsd_insert_exec_catchpoint;
-  t->to_remove_exec_catchpoint = fbsd_remove_exec_catchpoint;
-#endif
-#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE
-  t->to_set_syscall_catchpoint = fbsd_set_syscall_catchpoint;
-#endif
-#endif
-  add_target (t);
-}
-
 void
 _initialize_fbsd_nat (void)
 {
@@ -1537,5 +1613,13 @@ Enables printf debugging output."),
                           NULL,
                           &show_fbsd_lwp_debug,
                           &setdebuglist, &showdebuglist);
+  add_setshow_boolean_cmd ("fbsd-nat", class_maintenance,
+                          &debug_fbsd_nat, _("\
+Set debugging of FreeBSD native target."), _("\
+Show debugging of FreeBSD native target."), _("\
+Enables printf debugging output."),
+                          NULL,
+                          &show_fbsd_nat_debug,
+                          &setdebuglist, &showdebuglist);
 #endif
 }
This page took 0.031207 seconds and 4 git commands to generate.