/* 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.
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
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)
registers array. */
supply_gregset (gregset);
- supply_fpregset (fpregset);
+ supply_fpregset (&fpregset);
#if 0
/* thread_db doesn't seem to handle this right */
error ("sol_thread_store_registers: td_thr_getfpregs %s",
td_err_string (val));
- /* restore register value */
+ /* restore new register value */
memcpy(& registers[REGISTER_BYTE(regno)], old_value, REGISTER_SIZE);
#if 0
}
fill_gregset (regset, regno);
- fill_fpregset (fpregset, regno);
+ fill_fpregset (&fpregset, regno);
val = p_td_thr_setgregs (&thandle, regset);
if (val != TD_OK)
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. */
/* 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;
}
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;
/* 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;
/* 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;
/* 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;
/* 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;
/* 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;
procfs_ops.to_fetch_registers (-1);
else
orig_core_ops.to_fetch_registers (-1);
- fill_fpregset (*fpregset, -1);
+ fill_fpregset (fpregset, -1);
do_cleanups (old_chain);
/* 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;
inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
- supply_fpregset (*fpregset);
+ supply_fpregset (fpregset);
if (target_has_execution)
procfs_ops.to_store_registers (-1);
else
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. */
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");