Add detection of IMB and IMBRange SWIs.
[deliverable/binutils-gdb.git] / gdb / sol-thread.c
index cc61c6a0f4f3fb19d4501f9afcd7ca05057a5137..afc8d0c2eed990d216caa5500e5a4ff9d3bec315 100644 (file)
@@ -1,5 +1,5 @@
 /* Low level interface for debugging Solaris threads for GDB, the GNU debugger.
-   Copyright 1996 Free Software Foundation, Inc.
+   Copyright 1996, 1997, 1998 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -46,17 +46,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    procfs.c.  */
 
 #include "defs.h"
-
-/* Undefine gregset_t and fpregset_t to avoid conflict with defs in xm file. */
-
-#ifdef gregset_t
-#undef gregset_t
-#endif
-
-#ifdef fpregset_t
-#undef fpregset_t
-#endif
-
 #include <thread.h>
 #include <proc_service.h>
 #include <thread_db.h>
@@ -70,9 +59,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "gdbcmd.h"
 
 extern struct target_ops sol_thread_ops; /* Forward declaration */
+extern struct target_ops sol_core_ops; /* Forward declaration */
+
+/* place to store core_ops before we overwrite it */
+static struct target_ops orig_core_ops;
+
+struct target_ops sol_thread_ops;
+struct target_ops sol_core_ops;
 
 extern int procfs_suppress_run;
 extern struct target_ops procfs_ops; /* target vector for procfs.c */
+extern struct target_ops core_ops; /* target vector for corelow.c */
 extern char *procfs_pid_to_str PARAMS ((int pid));
 
 /* Note that these prototypes differ slightly from those used in procfs.c
@@ -86,8 +83,8 @@ extern char *procfs_pid_to_str PARAMS ((int pid));
 
 extern void supply_gregset PARAMS ((const prgregset_t));
 extern void fill_gregset PARAMS ((prgregset_t, int));
-extern void supply_fpregset PARAMS ((const prfpregset_t));
-extern void fill_fpregset PARAMS ((prfpregset_t, int));
+extern void supply_fpregset PARAMS ((const prfpregset_t *));
+extern void fill_fpregset PARAMS ((prfpregset_t *, int));
 
 /* This struct is defined by us, but mainly used for the proc_service interface.
    We don't have much use for it, except as a handy place to get a real pid
@@ -109,7 +106,7 @@ static td_thragent_t *main_ta;
 static int sol_thread_active = 0;
 
 static struct cleanup * save_inferior_pid PARAMS ((void));
-static void restore_inferior_pid PARAMS ((int pid));
+static void restore_inferior_pid PARAMS ((void *pid));
 static char *td_err_string PARAMS ((td_err_e errcode));
 static char *td_state_string PARAMS ((td_thr_state_e statecode));
 static int  thread_to_lwp PARAMS ((int thread_id, int default_lwp));
@@ -117,6 +114,10 @@ static void sol_thread_resume PARAMS ((int pid, int step,
                                       enum target_signal signo));
 static int lwp_to_thread PARAMS ((int lwp));
 static int sol_thread_alive PARAMS ((int pid));
+static void sol_core_close PARAMS ((int quitting));
+
+static void init_sol_thread_ops PARAMS ((void));
+static void init_sol_core_ops PARAMS ((void));
 
 #define THREAD_FLAG 0x80000000
 #define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
@@ -379,7 +380,7 @@ lwp_to_thread (lwp)
   if (val == TD_NOTHR)
     return -1;         /* thread must have terminated */
   else if (val != TD_OK)
-    error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
+    error ("lwp_to_thread: td_ta_map_lwp2thr: %s.", td_err_string (val));
 
   val = p_td_thr_validate (&th);
   if (val == TD_NOTHR)
@@ -427,14 +428,14 @@ NOTES
 static struct cleanup *
 save_inferior_pid ()
 {
-  return make_cleanup (restore_inferior_pid, inferior_pid);
+  return make_cleanup (restore_inferior_pid, (void*) inferior_pid);
 }
 
 static void
 restore_inferior_pid (pid)
-     int pid;
+     void *pid;
 {
-  inferior_pid = pid;
+  inferior_pid = (int) pid;
 }
 \f
 
@@ -604,7 +605,10 @@ sol_thread_fetch_registers (regno)
 
   if (!is_thread (inferior_pid))
     { /* LWP: pass the request on to procfs.c */
-      procfs_ops.to_fetch_registers (regno);
+      if (target_has_execution)
+       procfs_ops.to_fetch_registers (regno);
+      else
+       orig_core_ops.to_fetch_registers (regno);
       return;
     }
 
@@ -644,7 +648,7 @@ sol_thread_fetch_registers (regno)
    registers array.  */
 
   supply_gregset (gregset);
-  supply_fpregset (fpregset);
+  supply_fpregset (&fpregset);
 
 #if 0
 /* thread_db doesn't seem to handle this right */
@@ -695,6 +699,10 @@ sol_thread_store_registers (regno)
 
   if (regno != -1)
     {                          /* Not writing all the regs */
+      /* save new register value */
+      char old_value[REGISTER_SIZE];
+      memcpy(old_value, & registers[REGISTER_BYTE(regno)], REGISTER_SIZE);
+
       val = p_td_thr_getgregs (&thandle, regset);
       if (val != TD_OK)
        error ("sol_thread_store_registers: td_thr_getgregs %s",
@@ -704,6 +712,9 @@ sol_thread_store_registers (regno)
        error ("sol_thread_store_registers: td_thr_getfpregs %s",
               td_err_string (val));
 
+      /* restore new register value */
+      memcpy(& registers[REGISTER_BYTE(regno)], old_value, REGISTER_SIZE);
+
 #if 0
 /* thread_db doesn't seem to handle this right */
       val = td_thr_getxregsize (&thandle, &xregsize);
@@ -723,7 +734,7 @@ sol_thread_store_registers (regno)
     }
 
   fill_gregset (regset, regno);
-  fill_fpregset (fpregset, regno);
+  fill_fpregset (&fpregset, regno);
 
   val = p_td_thr_setgregs (&thandle, regset);
   if (val != TD_OK)
@@ -776,7 +787,11 @@ sol_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
     inferior_pid = procfs_first_available ();  /* Find any live lwp.  */
   /* Note: don't need to call switch_to_thread; we're just reading memory.  */
 
-  retval = procfs_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
+  if (target_has_execution)
+    retval = procfs_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
+  else
+    retval = orig_core_ops.to_xfer_memory (memaddr, myaddr, len,
+                                          dowrite, target);
 
   do_cleanups (old_chain);
 
@@ -802,7 +817,7 @@ static void
 sol_thread_notice_signals (pid)
      int pid;
 {
-  procfs_ops.to_notice_signals (pid);
+  procfs_ops.to_notice_signals (PIDGET (pid));
 }
 
 /* Fork an inferior process, and start debugging it with /proc.  */
@@ -919,7 +934,12 @@ sol_thread_alive (pid)
       return 1;                /* known thread: return true */
     }
   else                 /* kernel thread (LWP): let procfs test it */
-    return procfs_ops.to_thread_alive (pid);
+    {
+      if (target_has_execution)
+       return procfs_ops.to_thread_alive (pid);
+      else
+       return orig_core_ops.to_thread_alive (pid);
+    }
 }
 
 static void
@@ -931,37 +951,65 @@ sol_thread_stop ()
 /* These routines implement the lower half of the thread_db interface.  Ie: the
    ps_* routines.  */
 
+/* Various versions of <proc_service.h> have slightly
+   different function prototypes.  In particular, we have
+
+      NEWER                    OLDER
+      struct ps_prochandle *   const struct ps_prochandle *
+      void*                    char*
+      const void*              char*
+      int                      size_t
+
+   Which one you have depends on solaris version and what
+   patches you've applied.  On the theory that there are
+   only two major variants, we have configure check the
+   prototype of ps_pdwrite (), and use that info to make
+   appropriate typedefs here. */
+
+#ifdef PROC_SERVICE_IS_OLD
+typedef const struct ps_prochandle * gdb_ps_prochandle_t;
+typedef char * gdb_ps_read_buf_t;
+typedef char * gdb_ps_write_buf_t;
+typedef int gdb_ps_size_t;
+#else
+typedef struct ps_prochandle * gdb_ps_prochandle_t;
+typedef void * gdb_ps_read_buf_t;
+typedef const void * gdb_ps_write_buf_t;
+typedef size_t gdb_ps_size_t;
+#endif
+
+
 /* The next four routines are called by thread_db to tell us to stop and stop
    a particular process or lwp.  Since GDB ensures that these are all stopped
    by the time we call anything in thread_db, these routines need to do
    nothing.  */
 
 ps_err_e
-ps_pstop (const struct ps_prochandle *ph)
+ps_pstop (gdb_ps_prochandle_t ph)
 {
   return PS_OK;
 }
 
 ps_err_e
-ps_pcontinue (const struct ps_prochandle *ph)
+ps_pcontinue (gdb_ps_prochandle_t ph)
 {
   return PS_OK;
 }
 
 ps_err_e
-ps_lstop (const struct ps_prochandle *ph, lwpid_t lwpid)
+ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
 {
   return PS_OK;
 }
 
 ps_err_e
-ps_lcontinue (const struct ps_prochandle *ph, lwpid_t lwpid)
+ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
 {
   return PS_OK;
 }
 
 ps_err_e
-ps_pglobal_lookup (const struct ps_prochandle *ph, const char *ld_object_name,
+ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name,
                   const char *ld_symbol_name, paddr_t *ld_symbol_addr)
 {
   struct minimal_symbol *ms;
@@ -995,7 +1043,10 @@ rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
     {
       int cc;
 
-      cc = procfs_ops.to_xfer_memory (addr, buf, size, dowrite, &procfs_ops);
+      if (target_has_execution)
+       cc = procfs_ops.to_xfer_memory (addr, buf, size, dowrite, &procfs_ops);
+      else
+       cc = orig_core_ops.to_xfer_memory (addr, buf, size, dowrite, &core_ops);
 
       if (cc < 0)
        {
@@ -1018,33 +1069,37 @@ rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
 }
 
 ps_err_e
-ps_pdread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
+ps_pdread (gdb_ps_prochandle_t ph, paddr_t addr,
+          gdb_ps_read_buf_t buf, gdb_ps_size_t size)
 {
   return rw_common (0, ph, addr, buf, size);
 }
 
 ps_err_e
-ps_pdwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
+ps_pdwrite (gdb_ps_prochandle_t ph, paddr_t addr,
+           gdb_ps_write_buf_t buf, gdb_ps_size_t size)
 {
-  return rw_common (1, ph, addr, buf, size);
+  return rw_common (1, ph, addr, (char*) buf, size);
 }
 
 ps_err_e
-ps_ptread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
+ps_ptread (gdb_ps_prochandle_t ph, paddr_t addr,
+          gdb_ps_read_buf_t buf, gdb_ps_size_t size)
 {
   return rw_common (0, ph, addr, buf, size);
 }
 
 ps_err_e
-ps_ptwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
+ps_ptwrite (gdb_ps_prochandle_t ph, paddr_t addr,
+           gdb_ps_write_buf_t buf, gdb_ps_size_t size)
 {
-  return rw_common (1, ph, addr, buf, size);
+  return rw_common (1, ph, addr, (char*) buf, size);
 }
 
 /* Get integer regs */
 
 ps_err_e
-ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
+ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
             prgregset_t gregset)
 {
   struct cleanup *old_chain;
@@ -1053,7 +1108,10 @@ ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
 
   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
   
-  procfs_ops.to_fetch_registers (-1);
+  if (target_has_execution)
+    procfs_ops.to_fetch_registers (-1);
+  else
+    orig_core_ops.to_fetch_registers (-1);
   fill_gregset (gregset, -1);
 
   do_cleanups (old_chain);
@@ -1064,7 +1122,7 @@ ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
 /* Set integer regs */
 
 ps_err_e
-ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
+ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
             const prgregset_t gregset)
 {
   struct cleanup *old_chain;
@@ -1074,7 +1132,10 @@ ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
   
   supply_gregset (gregset);
-  procfs_ops.to_store_registers (-1);
+  if (target_has_execution)
+    procfs_ops.to_store_registers (-1);
+  else
+    orig_core_ops.to_store_registers (-1);
 
   do_cleanups (old_chain);
 
@@ -1094,7 +1155,7 @@ ps_plog (const char *fmt, ...)
 /* Get size of extra register set.  Currently a noop.  */
 
 ps_err_e
-ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
+ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
 {
 #if 0
   int lwp_fd;
@@ -1122,7 +1183,7 @@ ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
 /* Get extra register set.  Currently a noop.  */
 
 ps_err_e
-ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
+ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
 {
 #if 0
   int lwp_fd;
@@ -1145,7 +1206,7 @@ ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
 /* Set extra register set.  Currently a noop.  */
 
 ps_err_e
-ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
+ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
 {
 #if 0
   int lwp_fd;
@@ -1168,7 +1229,7 @@ ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
 /* Get floating-point regs.  */
 
 ps_err_e
-ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
+ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
               prfpregset_t *fpregset)
 {
   struct cleanup *old_chain;
@@ -1177,8 +1238,11 @@ ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
 
   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
 
-  procfs_ops.to_fetch_registers (-1);
-  fill_fpregset (*fpregset, -1);
+  if (target_has_execution)
+    procfs_ops.to_fetch_registers (-1);
+  else
+    orig_core_ops.to_fetch_registers (-1);
+  fill_fpregset (fpregset, -1);
 
   do_cleanups (old_chain);
 
@@ -1188,7 +1252,7 @@ ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
 /* Set floating-point regs.  */
 
 ps_err_e
-ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
+ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
               const prfpregset_t *fpregset)
 {
   struct cleanup *old_chain;
@@ -1197,13 +1261,74 @@ ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
 
   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
   
-  supply_fpregset (*fpregset);
-  procfs_ops.to_store_registers (-1);
+  supply_fpregset (fpregset);
+  if (target_has_execution)
+    procfs_ops.to_store_registers (-1);
+  else
+    orig_core_ops.to_store_registers (-1);
 
   do_cleanups (old_chain);
 
   return PS_OK;
 }
+
+#ifdef TM_I386SOL2_H
+
+/* Get local descriptor table.  */
+
+#include <sys/procfs.h>
+#include <sys/reg.h>
+#include <sys/sysi86.h>
+
+static int nldt_allocated = 0;
+static struct ssd *ldt_bufp = NULL;
+
+ps_err_e
+ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid,
+           struct ssd *pldt)
+{
+  gregset_t gregset;
+  int lwp_fd;
+  ps_err_e val;
+  int nldt;
+  int i;
+
+  /* Get procfs file descriptor for the LWP.  */
+  lwp_fd = procfs_get_pid_fd (BUILD_LWP (lwpid, PIDGET (inferior_pid)));
+  if (lwp_fd < 0)
+    return PS_BADLID;
+
+  /* Fetch registers und LDT descriptors.  */
+  if (ioctl (lwp_fd, PIOCGREG, &gregset) == -1)
+    return PS_ERR;
+
+  if (ioctl (lwp_fd, PIOCNLDT, &nldt) == -1)
+    return PS_ERR;
+
+  if (nldt_allocated < nldt)
+    {
+      ldt_bufp
+       = (struct ssd *) xrealloc (ldt_bufp, (nldt + 1) * sizeof (struct ssd));
+      nldt_allocated = nldt;
+    }
+
+  if (ioctl (lwp_fd, PIOCLDT, ldt_bufp) == -1)
+    return PS_ERR;
+
+  /* Search LDT for the LWP via register GS.  */
+  for (i = 0; i < nldt; i++)
+    {
+      if (ldt_bufp[i].sel == (gregset[GS] & 0xffff))
+       {
+         *pldt = ldt_bufp[i];
+         return PS_OK;
+       }
+    }
+
+  /* LDT not found.  */
+  return PS_ERR;
+}        
+#endif /* TM_I386SOL2_H */
 \f
 /* Convert a pid to printable form. */
 
@@ -1239,7 +1364,78 @@ solaris_pid_to_str (pid)
 }
 \f
 
-#ifdef MAINTENANCE_CMDS
+/* Worker bee for find_new_threads
+   Callback function that gets called once per USER thread (i.e., not
+   kernel) thread. */
+
+static int
+sol_find_new_threads_callback(th, ignored)
+     const td_thrhandle_t *th;
+     void *ignored;
+{
+  td_err_e retval;
+  td_thrinfo_t ti;
+  int pid;
+
+  if ((retval = p_td_thr_get_info(th, &ti)) != TD_OK)
+    {
+      return -1;
+    }
+  pid = BUILD_THREAD(ti.ti_tid, PIDGET(inferior_pid));
+  if (!in_thread_list(pid))
+    add_thread(pid);
+
+  return 0;
+}
+
+void
+sol_find_new_threads ()
+{
+  /* don't do anything if init failed to resolve the libthread_db library */
+  if (!procfs_suppress_run)
+    return;
+
+  if (inferior_pid == -1)
+    {
+      printf_filtered("No process.\n");
+      return;
+    }
+  p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *)0,
+                   TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
+                   TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+}
+
+static void
+sol_core_open (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  orig_core_ops.to_open (filename, from_tty);
+}
+
+static void
+sol_core_close (quitting)
+     int quitting;
+{
+  orig_core_ops.to_close (quitting);
+}
+
+static void
+sol_core_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  unpush_target (&core_ops);
+  orig_core_ops.to_detach (args, from_tty);
+}
+
+static void
+sol_core_files_info (t)
+     struct target_ops *t;
+{
+  orig_core_ops.to_files_info (t);
+}
+
 /* Worker bee for info sol-thread command.  This is a callback function that
    gets called once for each Solaris thread (ie. not kernel thread) in the 
    inferior.  Print anything interesting that we can think of.  */
@@ -1304,56 +1500,117 @@ info_solthreads (args, from_tty)
                    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
                    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
 }
-#endif /* MAINTENANCE_CMDS */
-
-struct target_ops sol_thread_ops = {
-  "solaris-threads",           /* to_shortname */
-  "Solaris threads and pthread.", /* to_longname */
-  "Solaris threads and pthread support.", /* to_doc */
-  sol_thread_open,             /* to_open */
-  0,                           /* to_close */
-  sol_thread_attach,           /* to_attach */
-  sol_thread_detach,           /* to_detach */
-  sol_thread_resume,           /* to_resume */
-  sol_thread_wait,             /* to_wait */
-  sol_thread_fetch_registers,  /* to_fetch_registers */
-  sol_thread_store_registers,  /* to_store_registers */
-  sol_thread_prepare_to_store, /* to_prepare_to_store */
-  sol_thread_xfer_memory,      /* to_xfer_memory */
-  sol_thread_files_info,       /* to_files_info */
-  memory_insert_breakpoint,    /* to_insert_breakpoint */
-  memory_remove_breakpoint,    /* to_remove_breakpoint */
-  terminal_init_inferior,      /* to_terminal_init */
-  terminal_inferior,           /* to_terminal_inferior */
-  terminal_ours_for_output,    /* to_terminal_ours_for_output */
-  terminal_ours,               /* to_terminal_ours */
-  child_terminal_info,         /* to_terminal_info */
-  sol_thread_kill_inferior,    /* to_kill */
-  0,                           /* to_load */
-  0,                           /* to_lookup_symbol */
-  sol_thread_create_inferior,  /* to_create_inferior */
-  sol_thread_mourn_inferior,   /* to_mourn_inferior */
-  sol_thread_can_run,          /* to_can_run */
-  sol_thread_notice_signals,   /* to_notice_signals */
-  sol_thread_alive,            /* to_thread_alive */
-  sol_thread_stop,             /* to_stop */
-  process_stratum,             /* to_stratum */
-  0,                           /* to_next */
-  1,                           /* to_has_all_memory */
-  1,                           /* to_has_memory */
-  1,                           /* to_has_stack */
-  1,                           /* to_has_registers */
-  1,                           /* to_has_execution */
-  0,                           /* sections */
-  0,                           /* sections_end */
-  OPS_MAGIC                    /* to_magic */
-};
+
+static int
+ignore (addr, contents)
+     CORE_ADDR addr;
+     char *contents;
+{
+  return 0;
+}
+
+
+static void
+init_sol_thread_ops ()
+{
+  sol_thread_ops.to_shortname = "solaris-threads";
+  sol_thread_ops.to_longname = "Solaris threads and pthread.";
+  sol_thread_ops.to_doc = "Solaris threads and pthread support.";
+  sol_thread_ops.to_open = sol_thread_open;
+  sol_thread_ops.to_close = 0;
+  sol_thread_ops.to_attach = sol_thread_attach;
+  sol_thread_ops.to_detach = sol_thread_detach;
+  sol_thread_ops.to_resume = sol_thread_resume;
+  sol_thread_ops.to_wait = sol_thread_wait;
+  sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
+  sol_thread_ops.to_store_registers = sol_thread_store_registers;
+  sol_thread_ops.to_prepare_to_store = sol_thread_prepare_to_store;
+  sol_thread_ops.to_xfer_memory = sol_thread_xfer_memory;
+  sol_thread_ops.to_files_info = sol_thread_files_info;
+  sol_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
+  sol_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
+  sol_thread_ops.to_terminal_init = terminal_init_inferior;
+  sol_thread_ops.to_terminal_inferior = terminal_inferior;
+  sol_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+  sol_thread_ops.to_terminal_ours = terminal_ours;
+  sol_thread_ops.to_terminal_info = child_terminal_info;
+  sol_thread_ops.to_kill = sol_thread_kill_inferior;
+  sol_thread_ops.to_load = 0;
+  sol_thread_ops.to_lookup_symbol = 0;
+  sol_thread_ops.to_create_inferior = sol_thread_create_inferior;
+  sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
+  sol_thread_ops.to_can_run = sol_thread_can_run;
+  sol_thread_ops.to_notice_signals = sol_thread_notice_signals;
+  sol_thread_ops.to_thread_alive = sol_thread_alive;
+  sol_thread_ops.to_find_new_threads = sol_find_new_threads;
+  sol_thread_ops.to_stop = sol_thread_stop;
+  sol_thread_ops.to_stratum = process_stratum;
+  sol_thread_ops.to_has_all_memory = 1;
+  sol_thread_ops.to_has_memory = 1;
+  sol_thread_ops.to_has_stack = 1;
+  sol_thread_ops.to_has_registers = 1;
+  sol_thread_ops.to_has_execution = 1;
+  sol_thread_ops.to_has_thread_control = tc_none;
+  sol_thread_ops.to_sections = 0;
+  sol_thread_ops.to_sections_end = 0;
+  sol_thread_ops.to_magic = OPS_MAGIC;
+}
+
+
+static void
+init_sol_core_ops ()
+{
+  sol_core_ops.to_shortname  = "solaris-core";
+  sol_core_ops.to_longname  = "Solaris core threads and pthread.";
+  sol_core_ops.to_doc  = "Solaris threads and pthread support for core files.";
+  sol_core_ops.to_open  = sol_core_open;
+  sol_core_ops.to_close  = sol_core_close;
+  sol_core_ops.to_attach  = sol_thread_attach;
+  sol_core_ops.to_detach  = sol_core_detach;
+  /* sol_core_ops.to_resume  = 0; */
+  /* sol_core_ops.to_wait  = 0;         */
+  sol_core_ops.to_fetch_registers  = sol_thread_fetch_registers;
+  /* sol_core_ops.to_store_registers  = 0; */
+  /* sol_core_ops.to_prepare_to_store  = 0; */
+  sol_core_ops.to_xfer_memory  = sol_thread_xfer_memory;
+  sol_core_ops.to_files_info  = sol_core_files_info;
+  sol_core_ops.to_insert_breakpoint  = ignore;
+  sol_core_ops.to_remove_breakpoint  = ignore;
+  /* sol_core_ops.to_terminal_init  = 0; */
+  /* sol_core_ops.to_terminal_inferior  = 0; */
+  /* sol_core_ops.to_terminal_ours_for_output  = 0; */
+  /* sol_core_ops.to_terminal_ours  = 0; */
+  /* sol_core_ops.to_terminal_info  = 0; */
+  /* sol_core_ops.to_kill  = 0; */
+  /* sol_core_ops.to_load  = 0; */
+  /* sol_core_ops.to_lookup_symbol  = 0; */
+  sol_core_ops.to_create_inferior  = sol_thread_create_inferior;
+  sol_core_ops.to_stratum  = core_stratum;
+  sol_core_ops.to_has_all_memory  = 0;
+  sol_core_ops.to_has_memory  = 1;
+  sol_core_ops.to_has_stack  = 1;
+  sol_core_ops.to_has_registers  = 1;
+  sol_core_ops.to_has_execution  = 0;
+  sol_core_ops.to_has_thread_control  = tc_none;
+  sol_core_ops.to_sections  = 0;
+  sol_core_ops.to_sections_end  = 0;
+  sol_core_ops.to_magic  = OPS_MAGIC;
+}
+
+/* we suppress the call to add_target of core_ops in corelow because
+   if there are two targets in the stratum core_stratum, find_core_target
+   won't know which one to return.  see corelow.c for an additonal
+   comment on coreops_suppress_target. */
+int coreops_suppress_target = 1;
 
 void
 _initialize_sol_thread ()
 {
   void *dlhandle;
 
+  init_sol_thread_ops ();
+  init_sol_core_ops ();
+
   dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
   if (!dlhandle)
     goto die;
@@ -1390,10 +1647,12 @@ _initialize_sol_thread ()
 
   procfs_suppress_run = 1;
 
-#ifdef MAINTENANCE_CMDS
   add_cmd ("sol-threads", class_maintenance, info_solthreads, 
            "Show info on Solaris user threads.\n", &maintenanceinfolist);
-#endif /* MAINTENANCE_CMDS */
+
+  memcpy(&orig_core_ops, &core_ops, sizeof (struct target_ops));
+  memcpy(&core_ops, &sol_core_ops, sizeof (struct target_ops));
+  add_target (&core_ops);
 
   return;
 
@@ -1404,5 +1663,8 @@ _initialize_sol_thread ()
   if (dlhandle)
     dlclose (dlhandle);
 
+  /* allow the user to debug non-threaded core files */
+  add_target(&core_ops);
+
   return;
 }
This page took 0.031098 seconds and 4 git commands to generate.