]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/procfs.c
2003-02-06 Andrew Cagney <ac131313@redhat.com>
[thirdparty/binutils-gdb.git] / gdb / procfs.c
index 1714970e961674397333d54f9e1c2d2370098834..969bbcb2b614aa921cf8610a35ec6f9728e13abf 100644 (file)
@@ -23,6 +23,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "inferior.h"
 #include "target.h"
 #include "gdbcore.h"
+#include "elf-bfd.h"           /* for elfcore_write_* */
 #include "gdbcmd.h"
 #include "gdbthread.h"
 
@@ -41,6 +42,8 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include <sys/wait.h>
 #include <signal.h>
 #include <ctype.h>
+#include "gdb_assert.h"
+#include "inflow.h"
 
 /* 
  * PROCFS.C
@@ -55,7 +58,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  *   Unixware
  *   AIX5
  *
- * /proc works by immitating a file system: you open a simulated file
+ * /proc works by imitating a file system: you open a simulated file
  * that represents the process you wish to interact with, and
  * perform operations on that "file" in order to examine or change
  * the state of the other process.
@@ -135,6 +138,8 @@ static int proc_find_memory_regions (int (*) (CORE_ADDR,
 
 static char * procfs_make_note_section (bfd *, int *);
 
+static int procfs_can_use_hw_breakpoint (int, int, int);
+
 struct target_ops procfs_ops;          /* the target vector */
 
 static void
@@ -167,6 +172,7 @@ init_procfs_ops (void)
   procfs_ops.to_terminal_inferior   = terminal_inferior;
   procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
   procfs_ops.to_terminal_ours       = terminal_ours;
+  procfs_ops.to_terminal_save_ours  = terminal_save_ours;
   procfs_ops.to_terminal_info       = child_terminal_info;
 
   procfs_ops.to_find_new_threads    = procfs_find_new_threads;
@@ -182,6 +188,7 @@ init_procfs_ops (void)
   procfs_ops.to_has_thread_control  = tc_schedlock;
   procfs_ops.to_find_memory_regions = proc_find_memory_regions;
   procfs_ops.to_make_corefile_notes = procfs_make_note_section;
+  procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
   procfs_ops.to_magic               = OPS_MAGIC;
 }
 
@@ -2836,6 +2843,19 @@ proc_parent_pid (procinfo *pi)
 }
 
 
+/* Convert a target address (a.k.a. CORE_ADDR) into a host address
+   (a.k.a void pointer)!  */
+
+static void *
+procfs_address_to_host_pointer (CORE_ADDR addr)
+{
+  void *ptr;
+
+  gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr));
+  ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr);
+  return ptr;
+}
+
 /*
  * Function: proc_set_watchpoint
  *
@@ -2858,10 +2878,13 @@ proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags)
   prwatch_t *pwatch;
 
   pwatch            = (prwatch_t *) &arg.watch;
+  /* NOTE: cagney/2003-02-01: Even more horrible hack.  Need to
+     convert a target address into something that can be stored in a
+     native data structure.  */
 #ifdef PCAGENT /* Horrible hack: only defined on Solaris 2.6+ */
-  pwatch->pr_vaddr  = (uintptr_t) address_to_host_pointer (addr);
+  pwatch->pr_vaddr  = (uintptr_t) procfs_address_to_host_pointer (addr);
 #else
-  pwatch->pr_vaddr  = (caddr_t) address_to_host_pointer (addr);
+  pwatch->pr_vaddr  = (caddr_t) procfs_address_to_host_pointer (addr);
 #endif
   pwatch->pr_size   = len;
   pwatch->pr_wflags = wflags;
@@ -3622,6 +3645,9 @@ do_detach (int signo)
        if (!proc_clear_current_fault (pi))
          proc_warn (pi, "do_detach, clear_current_fault", __LINE__);
 
+       if (signo == 0 && !proc_clear_current_signal (pi))
+         proc_warn (pi, "do_detach, clear_current_signal", __LINE__);
+
        if (!proc_set_run_on_last_close (pi))
          proc_warn (pi, "do_detach, set_rlc", __LINE__);
       }
@@ -4581,8 +4607,6 @@ procfs_can_run (void)
 static void
 procfs_stop (void)
 {
-  extern pid_t inferior_process_group;
-
   kill (-inferior_process_group, SIGINT);
 }
 
@@ -5137,6 +5161,38 @@ procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag,
   return 0;
 }
 
+/* Return non-zero if we can set a hardware watchpoint of type TYPE.  TYPE
+   is one of bp_hardware_watchpoint, bp_read_watchpoint, bp_write_watchpoint,
+   or bp_hardware_watchpoint.  CNT is the number of watchpoints used so
+   far.
+   
+   Note:  procfs_can_use_hw_breakpoint() is not yet used by all
+   procfs.c targets due to the fact that some of them still define
+   TARGET_CAN_USE_HARDWARE_WATCHPOINT.  */
+
+static int
+procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
+{
+#ifndef TARGET_HAS_HARDWARE_WATCHPOINTS
+  return 0;
+#else
+  /* Due to the way that proc_set_watchpoint() is implemented, host
+     and target pointers must be of the same size.  If they are not,
+     we can't use hardware watchpoints.  This limitation is due to the
+     fact that proc_set_watchpoint() calls
+     procfs_address_to_host_pointer(); a close inspection of
+     procfs_address_to_host_pointer will reveal that an internal error
+     will be generated when the host and target pointer sizes are
+     different.  */
+  if (sizeof (void *) != TYPE_LENGTH (builtin_type_void_data_ptr))
+    return 0;
+
+  /* Other tests here???  */
+
+  return 1;
+#endif
+}
+
 /*
  * Function: stopped_by_watchpoint
  *
@@ -5387,7 +5443,7 @@ find_memory_regions_callback (struct prmap *map,
                                           void *),
                              void *data)
 {
-  return (*func) (host_pointer_to_address ((void *) map->pr_vaddr),
+  return (*func) ((CORE_ADDR) map->pr_vaddr,
                  map->pr_size, 
                  (map->pr_mflags & MA_READ) != 0,
                  (map->pr_mflags & MA_WRITE) != 0,
@@ -5430,8 +5486,7 @@ proc_find_memory_regions (int (*func) (CORE_ADDR,
  */
 
 static char *
-mappingflags (flags)
-     long flags;
+mappingflags (long flags)
 {
   static char asciiflags[8];
 
@@ -5704,7 +5759,7 @@ Specify keyword 'mappings' for detailed info on memory mappings.");
 
 
 
-/* miscelaneous stubs:                                             */
+/* miscellaneous stubs:                                             */
 /* The following satisfy a few random symbols mostly created by    */
 /* the solaris threads implementation, which I will chase down     */
 /* later.        */
@@ -5721,6 +5776,8 @@ procfs_first_available (void)
 }
 
 /* ===================  GCORE .NOTE "MODULE" =================== */
+#if defined (UNIXWARE) || defined (PIOCOPENLWP) || defined (PCAGENT)
+/* gcore only implemented on solaris and unixware (so far) */
 
 static char *
 procfs_do_thread_registers (bfd *obfd, ptid_t ptid, 
@@ -5733,12 +5790,21 @@ procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
   merged_pid = TIDGET (ptid) << 16 | PIDGET (ptid);
 
   fill_gregset (&gregs, -1);
+#if defined (UNIXWARE)
+  note_data = (char *) elfcore_write_lwpstatus (obfd,
+                                               note_data,
+                                               note_size,
+                                               merged_pid, 
+                                               stop_signal,
+                                               &gregs);
+#else
   note_data = (char *) elfcore_write_prstatus (obfd,
-                                               note_data,
-                                               note_size,
+                                              note_data,
+                                              note_size,
                                               merged_pid, 
                                               stop_signal,
-                                               &gregs);
+                                              &gregs);
+#endif
   fill_fpregset (&fpregs, -1);
   note_data = (char *) elfcore_write_prfpreg (obfd,
                                              note_data,
@@ -5755,16 +5821,15 @@ struct procfs_corefile_thread_data {
 };
 
 static int
-procfs_corefile_thread_callback (struct thread_info *ti, void *data)
+procfs_corefile_thread_callback (procinfo *pi, procinfo *thread, void *data)
 {
   struct procfs_corefile_thread_data *args = data;
-  procinfo *pi = find_procinfo (PIDGET (ti->ptid), TIDGET (ti->ptid));
 
-  if (pi != NULL && TIDGET (ti->ptid) != 0)
+  if (pi != NULL && thread->tid != 0)
     {
       ptid_t saved_ptid = inferior_ptid;
-      inferior_ptid = ti->ptid;
-      args->note_data = procfs_do_thread_registers (args->obfd, ti->ptid, 
+      inferior_ptid = MERGEPID (pi->pid, thread->tid);
+      args->note_data = procfs_do_thread_registers (args->obfd, inferior_ptid, 
                                                    args->note_data, 
                                                    args->note_size);
       inferior_ptid = saved_ptid;
@@ -5782,6 +5847,7 @@ procfs_make_note_section (bfd *obfd, int *note_size)
   char psargs[80] = {'\0'};
   procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
   char *note_data = NULL;
+  char *inf_args;
   struct procfs_corefile_thread_data thread_args;
 
   if (get_exec_file (0))
@@ -5789,11 +5855,14 @@ procfs_make_note_section (bfd *obfd, int *note_size)
       strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
       strncpy (psargs, get_exec_file (0), 
               sizeof (psargs));
-      if (get_inferior_args ())
+
+      inf_args = get_inferior_args ();
+      if (inf_args && *inf_args &&
+         strlen (inf_args) < ((int) sizeof (psargs) - (int) strlen (psargs)))
        {
          strncat (psargs, " ", 
                   sizeof (psargs) - strlen (psargs));
-         strncat (psargs, get_inferior_args ()
+         strncat (psargs, inf_args
                   sizeof (psargs) - strlen (psargs));
        }
     }
@@ -5804,10 +5873,18 @@ procfs_make_note_section (bfd *obfd, int *note_size)
                                               fname, 
                                               psargs);
 
+#ifdef UNIXWARE
+  fill_gregset (&gregs, -1);
+  note_data = elfcore_write_pstatus (obfd, note_data, note_size, 
+                                    PIDGET (inferior_ptid), 
+                                    stop_signal, &gregs);
+#endif
+
   thread_args.obfd = obfd;
   thread_args.note_data = note_data;
   thread_args.note_size = note_size;
-  iterate_over_threads (procfs_corefile_thread_callback, &thread_args);
+  proc_iterate_over_threads (pi, procfs_corefile_thread_callback, &thread_args);
+
   if (thread_args.note_data == note_data)
     {
       /* iterate_over_threads didn't come up with any threads;
@@ -5823,5 +5900,12 @@ procfs_make_note_section (bfd *obfd, int *note_size)
   make_cleanup (xfree, note_data);
   return note_data;
 }
-
+#else /* !(Solaris or Unixware) */
+static char *
+procfs_make_note_section (bfd *obfd, int *note_size)
+{
+  error ("gcore not implemented for this host.");
+  return NULL; /* lint */
+}
+#endif /* Solaris or Unixware */
 /* ===================  END GCORE .NOTE "MODULE" =================== */