X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsol-thread.c;h=62d839cd418d6cff14dfb881f2d929d0582922c2;hb=76727919ceb590f03ff0f6db08b7ceab5b7aeaff;hp=518f17f8a3fe6ff7875216be22fb28722accf1a3;hpb=6aba47ca06d9150c6196a374b745c2711b46e045;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c index 518f17f8a3..62d839cd41 100644 --- a/gdb/sol-thread.c +++ b/gdb/sol-thread.c @@ -1,13 +1,12 @@ /* Solaris threads debugging interface. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,9 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* This module implements a sort of half target that sits between the machine-independent parts of GDB and the /proc interface (procfs.c) @@ -59,31 +56,22 @@ #include "target.h" #include "inferior.h" #include -#include "gdb_stat.h" +#include #include #include "gdbcmd.h" #include "gdbcore.h" #include "regcache.h" #include "solib.h" #include "symfile.h" - -#include "gdb_string.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; +#include "observable.h" +#include "procfs.h" +#include "symtab.h" +#include "minsyms.h" +#include "objfiles.h" 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 (ptid_t ptid); -/* Prototypes for supply_gregset etc. */ +/* Prototypes for supply_gregset etc. */ #include "gregset.h" /* This struct is defined by us, but mainly used for the proc_service @@ -98,89 +86,100 @@ struct ps_prochandle struct string_map { int num; - char *str; + const char *str; }; static struct ps_prochandle main_ph; static td_thragent_t *main_ta; static int sol_thread_active = 0; -static void sol_thread_resume (ptid_t ptid, int step, enum target_signal signo); -static int sol_thread_alive (ptid_t ptid); -static void sol_core_close (int quitting); - static void init_sol_thread_ops (void); -static void init_sol_core_ops (void); /* Default definitions: These must be defined in tm.h if they are to be shared with a process module such as procfs. */ -#define GET_PID(ptid) ptid_get_pid (ptid) -#define GET_LWP(ptid) ptid_get_lwp (ptid) -#define GET_THREAD(ptid) ptid_get_tid (ptid) - -#define is_lwp(ptid) (GET_LWP (ptid) != 0) -#define is_thread(ptid) (GET_THREAD (ptid) != 0) - -#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0) -#define BUILD_THREAD(tid, pid) ptid_build (pid, 0, tid) +/* Types of the libthread_db functions. */ + +typedef void (td_log_ftype)(const int on_off); +typedef td_err_e (td_ta_new_ftype)(const struct ps_prochandle *ph_p, + td_thragent_t **ta_pp); +typedef td_err_e (td_ta_delete_ftype)(td_thragent_t *ta_p); +typedef td_err_e (td_init_ftype)(void); +typedef td_err_e (td_ta_get_ph_ftype)(const td_thragent_t *ta_p, + struct ps_prochandle **ph_pp); +typedef td_err_e (td_ta_get_nthreads_ftype)(const td_thragent_t *ta_p, + int *nthread_p); +typedef td_err_e (td_ta_tsd_iter_ftype)(const td_thragent_t *ta_p, + td_key_iter_f *cb, void *cbdata_p); +typedef td_err_e (td_ta_thr_iter_ftype)(const td_thragent_t *ta_p, + td_thr_iter_f *cb, void *cbdata_p, + td_thr_state_e state, int ti_pri, + sigset_t *ti_sigmask_p, + unsigned ti_user_flags); +typedef td_err_e (td_thr_validate_ftype)(const td_thrhandle_t *th_p); +typedef td_err_e (td_thr_tsd_ftype)(const td_thrhandle_t * th_p, + const thread_key_t key, void **data_pp); +typedef td_err_e (td_thr_get_info_ftype)(const td_thrhandle_t *th_p, + td_thrinfo_t *ti_p); +typedef td_err_e (td_thr_getfpregs_ftype)(const td_thrhandle_t *th_p, + prfpregset_t *fpregset); +typedef td_err_e (td_thr_getxregsize_ftype)(const td_thrhandle_t *th_p, + int *xregsize); +typedef td_err_e (td_thr_getxregs_ftype)(const td_thrhandle_t *th_p, + const caddr_t xregset); +typedef td_err_e (td_thr_sigsetmask_ftype)(const td_thrhandle_t *th_p, + const sigset_t ti_sigmask); +typedef td_err_e (td_thr_setprio_ftype)(const td_thrhandle_t *th_p, + const int ti_pri); +typedef td_err_e (td_thr_setsigpending_ftype)(const td_thrhandle_t *th_p, + const uchar_t ti_pending_flag, + const sigset_t ti_pending); +typedef td_err_e (td_thr_setfpregs_ftype)(const td_thrhandle_t *th_p, + const prfpregset_t *fpregset); +typedef td_err_e (td_thr_setxregs_ftype)(const td_thrhandle_t *th_p, + const caddr_t xregset); +typedef td_err_e (td_ta_map_id2thr_ftype)(const td_thragent_t *ta_p, + thread_t tid, + td_thrhandle_t *th_p); +typedef td_err_e (td_ta_map_lwp2thr_ftype)(const td_thragent_t *ta_p, + lwpid_t lwpid, + td_thrhandle_t *th_p); +typedef td_err_e (td_thr_getgregs_ftype)(const td_thrhandle_t *th_p, + prgregset_t regset); +typedef td_err_e (td_thr_setgregs_ftype)(const td_thrhandle_t *th_p, + const prgregset_t regset); /* Pointers to routines from libthread_db resolved by dlopen(). */ -static void (*p_td_log)(const int on_off); -static td_err_e (*p_td_ta_new)(const struct ps_prochandle *ph_p, - td_thragent_t **ta_pp); -static td_err_e (*p_td_ta_delete)(td_thragent_t *ta_p); -static td_err_e (*p_td_init)(void); -static td_err_e (*p_td_ta_get_ph)(const td_thragent_t *ta_p, - struct ps_prochandle **ph_pp); -static td_err_e (*p_td_ta_get_nthreads)(const td_thragent_t *ta_p, - int *nthread_p); -static td_err_e (*p_td_ta_tsd_iter)(const td_thragent_t *ta_p, - td_key_iter_f *cb, void *cbdata_p); -static td_err_e (*p_td_ta_thr_iter)(const td_thragent_t *ta_p, - td_thr_iter_f *cb, void *cbdata_p, - td_thr_state_e state, int ti_pri, - sigset_t *ti_sigmask_p, - unsigned ti_user_flags); -static td_err_e (*p_td_thr_validate)(const td_thrhandle_t *th_p); -static td_err_e (*p_td_thr_tsd)(const td_thrhandle_t * th_p, - const thread_key_t key, void **data_pp); -static td_err_e (*p_td_thr_get_info)(const td_thrhandle_t *th_p, - td_thrinfo_t *ti_p); -static td_err_e (*p_td_thr_getfpregs)(const td_thrhandle_t *th_p, - prfpregset_t *fpregset); -static td_err_e (*p_td_thr_getxregsize)(const td_thrhandle_t *th_p, - int *xregsize); -static td_err_e (*p_td_thr_getxregs)(const td_thrhandle_t *th_p, - const caddr_t xregset); -static td_err_e (*p_td_thr_sigsetmask)(const td_thrhandle_t *th_p, - const sigset_t ti_sigmask); -static td_err_e (*p_td_thr_setprio)(const td_thrhandle_t *th_p, - const int ti_pri); -static td_err_e (*p_td_thr_setsigpending)(const td_thrhandle_t *th_p, - const uchar_t ti_pending_flag, - const sigset_t ti_pending); -static td_err_e (*p_td_thr_setfpregs)(const td_thrhandle_t *th_p, - const prfpregset_t *fpregset); -static td_err_e (*p_td_thr_setxregs)(const td_thrhandle_t *th_p, - const caddr_t xregset); -static td_err_e (*p_td_ta_map_id2thr)(const td_thragent_t *ta_p, - thread_t tid, - td_thrhandle_t *th_p); -static td_err_e (*p_td_ta_map_lwp2thr)(const td_thragent_t *ta_p, - lwpid_t lwpid, - td_thrhandle_t *th_p); -static td_err_e (*p_td_thr_getgregs)(const td_thrhandle_t *th_p, - prgregset_t regset); -static td_err_e (*p_td_thr_setgregs)(const td_thrhandle_t *th_p, - const prgregset_t regset); +static td_log_ftype *p_td_log; +static td_ta_new_ftype *p_td_ta_new; +static td_ta_delete_ftype *p_td_ta_delete; +static td_init_ftype *p_td_init; +static td_ta_get_ph_ftype *p_td_ta_get_ph; +static td_ta_get_nthreads_ftype *p_td_ta_get_nthreads; +static td_ta_tsd_iter_ftype *p_td_ta_tsd_iter; +static td_ta_thr_iter_ftype *p_td_ta_thr_iter; +static td_thr_validate_ftype *p_td_thr_validate; +static td_thr_tsd_ftype *p_td_thr_tsd; +static td_thr_get_info_ftype *p_td_thr_get_info; +static td_thr_getfpregs_ftype *p_td_thr_getfpregs; +static td_thr_getxregsize_ftype *p_td_thr_getxregsize; +static td_thr_getxregs_ftype *p_td_thr_getxregs; +static td_thr_sigsetmask_ftype *p_td_thr_sigsetmask; +static td_thr_setprio_ftype *p_td_thr_setprio; +static td_thr_setsigpending_ftype *p_td_thr_setsigpending; +static td_thr_setfpregs_ftype *p_td_thr_setfpregs; +static td_thr_setxregs_ftype *p_td_thr_setxregs; +static td_ta_map_id2thr_ftype *p_td_ta_map_id2thr; +static td_ta_map_lwp2thr_ftype *p_td_ta_map_lwp2thr; +static td_thr_getgregs_ftype *p_td_thr_getgregs; +static td_thr_setgregs_ftype *p_td_thr_setgregs; /* Return the libthread_db error string associated with ERRCODE. If ERRCODE is unknown, return an appropriate message. */ -static char * +static const char * td_err_string (td_err_e errcode) { static struct string_map td_err_table[] = @@ -215,15 +214,16 @@ td_err_string (td_err_e errcode) if (td_err_table[i].num == errcode) return td_err_table[i].str; - sprintf (buf, "Unknown libthread_db error code: %d", errcode); + xsnprintf (buf, sizeof (buf), "Unknown libthread_db error code: %d", + errcode); return buf; } -/* Return the the libthread_db state string assicoated with STATECODE. +/* Return the libthread_db state string assicoated with STATECODE. If STATECODE is unknown, return an appropriate message. */ -static char * +static const char * td_state_string (td_thr_state_e statecode) { static struct string_map td_thr_state_table[] = @@ -246,7 +246,8 @@ td_state_string (td_thr_state_e statecode) if (td_thr_state_table[i].num == statecode) return td_thr_state_table[i].str; - sprintf (buf, "Unknown libthread_db state code: %d", statecode); + xsnprintf (buf, sizeof (buf), "Unknown libthread_db state code: %d", + statecode); return buf; } @@ -254,7 +255,7 @@ td_state_string (td_thr_state_e statecode) /* Convert a POSIX or Solaris thread ID into a LWP ID. If THREAD_ID doesn't exist, that's an error. If it's an inactive thread, return - DEFAULT_LPW. + DEFAULT_LWP. NOTE: This function probably shouldn't call error(). */ @@ -265,12 +266,12 @@ thread_to_lwp (ptid_t thread_id, int default_lwp) td_thrhandle_t th; td_err_e val; - if (is_lwp (thread_id)) + if (ptid_lwp_p (thread_id)) return thread_id; /* It's already an LWP ID. */ /* It's a thread. Convert to LWP. */ - val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th); + val = p_td_ta_map_id2thr (main_ta, ptid_get_tid (thread_id), &th); if (val == TD_NOTHR) return pid_to_ptid (-1); /* Thread must have terminated. */ else if (val != TD_OK) @@ -290,7 +291,7 @@ thread_to_lwp (ptid_t thread_id, int default_lwp) td_state_string (ti.ti_state)); } - return BUILD_LWP (ti.ti_lid, PIDGET (thread_id)); + return ptid_build (ptid_get_pid (thread_id), ti.ti_lid, 0); } /* Convert an LWP ID into a POSIX or Solaris thread ID. If LWP_ID @@ -305,15 +306,15 @@ lwp_to_thread (ptid_t lwp) td_thrhandle_t th; td_err_e val; - if (is_thread (lwp)) + if (ptid_tid_p (lwp)) return lwp; /* It's already a thread ID. */ /* It's an LWP. Convert it to a thread ID. */ - if (!sol_thread_alive (lwp)) + if (!target_thread_alive (lwp)) return pid_to_ptid (-1); /* Must be a defunct LPW. */ - val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th); + val = p_td_ta_map_lwp2thr (main_ta, ptid_get_lwp (lwp), &th); if (val == TD_NOTHR) return pid_to_ptid (-1); /* Thread must have terminated. */ else if (val != TD_OK) @@ -331,46 +332,13 @@ lwp_to_thread (ptid_t lwp) else if (val != TD_OK) error (_("lwp_to_thread: td_thr_get_info: %s."), td_err_string (val)); - return BUILD_THREAD (ti.ti_tid, PIDGET (lwp)); + return ptid_build (ptid_get_pid (lwp), 0 , ti.ti_tid); } /* Most target vector functions from here on actually just pass - through to procfs.c, as they don't need to do anything specific for - threads. */ - -static void -sol_thread_open (char *arg, int from_tty) -{ - procfs_ops.to_open (arg, from_tty); -} - -/* Attach to process PID, then initialize for debugging it and wait - for the trace-trap that results from attaching. */ - -static void -sol_thread_attach (char *args, int from_tty) -{ - procfs_ops.to_attach (args, from_tty); - - /* Must get symbols from shared libraries before libthread_db can run! */ - solib_add (NULL, from_tty, (struct target_ops *) 0, auto_solib_add); - - if (sol_thread_active) - { - printf_filtered ("sol-thread active.\n"); - main_ph.ptid = inferior_ptid; /* Save for xfer_memory. */ - push_target (&sol_thread_ops); - inferior_ptid = lwp_to_thread (inferior_ptid); - if (PIDGET (inferior_ptid) == -1) - inferior_ptid = main_ph.ptid; - else - add_thread (inferior_ptid); - } - - /* FIXME: Might want to iterate over all the threads and register - them. */ -} + through to the layer beneath, as they don't need to do anything + specific for threads. */ /* Take a program previously attached to and detaches it. The program resumes execution and will no longer stop on signals, etc. We'd @@ -380,11 +348,14 @@ sol_thread_attach (char *args, int from_tty) program was started via the normal ptrace (PTRACE_TRACEME). */ static void -sol_thread_detach (char *args, int from_tty) +sol_thread_detach (struct target_ops *ops, inferior *inf, int from_tty) { - inferior_ptid = pid_to_ptid (PIDGET (main_ph.ptid)); - unpush_target (&sol_thread_ops); - procfs_ops.to_detach (args, from_tty); + struct target_ops *beneath = find_target_beneath (ops); + + sol_thread_active = 0; + inferior_ptid = pid_to_ptid (ptid_get_pid (main_ph.ptid)); + unpush_target (ops); + beneath->to_detach (beneath, inf, from_tty); } /* Resume execution of process PTID. If STEP is nozero, then just @@ -393,115 +364,109 @@ sol_thread_detach (char *args, int from_tty) ID for procfs. */ static void -sol_thread_resume (ptid_t ptid, int step, enum target_signal signo) +sol_thread_resume (struct target_ops *ops, + ptid_t ptid, int step, enum gdb_signal signo) { - struct cleanup *old_chain; + struct target_ops *beneath = find_target_beneath (ops); - old_chain = save_inferior_ptid (); + scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid); - inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid)); - if (PIDGET (inferior_ptid) == -1) + inferior_ptid = thread_to_lwp (inferior_ptid, ptid_get_pid (main_ph.ptid)); + if (ptid_get_pid (inferior_ptid) == -1) inferior_ptid = procfs_first_available (); - if (PIDGET (ptid) != -1) + if (ptid_get_pid (ptid) != -1) { ptid_t save_ptid = ptid; ptid = thread_to_lwp (ptid, -2); - if (PIDGET (ptid) == -2) /* Inactive thread. */ + if (ptid_get_pid (ptid) == -2) /* Inactive thread. */ error (_("This version of Solaris can't start inactive threads.")); - if (info_verbose && PIDGET (ptid) == -1) + if (info_verbose && ptid_get_pid (ptid) == -1) warning (_("Specified thread %ld seems to have terminated"), - GET_THREAD (save_ptid)); + ptid_get_tid (save_ptid)); } - procfs_ops.to_resume (ptid, step, signo); - - do_cleanups (old_chain); + beneath->to_resume (beneath, ptid, step, signo); } -/* Wait for any threads to stop. We may have to convert PIID from a +/* Wait for any threads to stop. We may have to convert PTID from a thread ID to an LWP ID, and vice versa on the way out. */ static ptid_t -sol_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus) +sol_thread_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *ourstatus, int options) { ptid_t rtnval; ptid_t save_ptid; - struct cleanup *old_chain; + struct target_ops *beneath = find_target_beneath (ops); save_ptid = inferior_ptid; - old_chain = save_inferior_ptid (); + scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid); - inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid)); - if (PIDGET (inferior_ptid) == -1) + inferior_ptid = thread_to_lwp (inferior_ptid, ptid_get_pid (main_ph.ptid)); + if (ptid_get_pid (inferior_ptid) == -1) inferior_ptid = procfs_first_available (); - if (PIDGET (ptid) != -1) + if (ptid_get_pid (ptid) != -1) { ptid_t save_ptid = ptid; ptid = thread_to_lwp (ptid, -2); - if (PIDGET (ptid) == -2) /* Inactive thread. */ + if (ptid_get_pid (ptid) == -2) /* Inactive thread. */ error (_("This version of Solaris can't start inactive threads.")); - if (info_verbose && PIDGET (ptid) == -1) + if (info_verbose && ptid_get_pid (ptid) == -1) warning (_("Specified thread %ld seems to have terminated"), - GET_THREAD (save_ptid)); + ptid_get_tid (save_ptid)); } - rtnval = procfs_ops.to_wait (ptid, ourstatus); + rtnval = beneath->to_wait (beneath, ptid, ourstatus, options); if (ourstatus->kind != TARGET_WAITKIND_EXITED) { /* Map the LWP of interest back to the appropriate thread ID. */ rtnval = lwp_to_thread (rtnval); - if (PIDGET (rtnval) == -1) + if (ptid_get_pid (rtnval) == -1) rtnval = save_ptid; /* See if we have a new thread. */ - if (is_thread (rtnval) + if (ptid_tid_p (rtnval) && !ptid_equal (rtnval, save_ptid) - && !in_thread_list (rtnval)) - { - printf_filtered ("[New %s]\n", target_pid_to_str (rtnval)); - add_thread (rtnval); - } + && (!in_thread_list (rtnval) + || is_exited (rtnval))) + add_thread (rtnval); } /* During process initialization, we may get here without the thread package being initialized, since that can only happen after we've found the shared libs. */ - do_cleanups (old_chain); - return rtnval; } static void -sol_thread_fetch_registers (int regnum) +sol_thread_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { thread_t thread; td_thrhandle_t thandle; td_err_e val; prgregset_t gregset; prfpregset_t fpregset; -#if 0 - int xregsize; - caddr_t xregset; -#endif + gdb_gregset_t *gregset_p = &gregset; + gdb_fpregset_t *fpregset_p = &fpregset; + struct target_ops *beneath = find_target_beneath (ops); + ptid_t ptid = regcache_get_ptid (regcache); - if (!is_thread (inferior_ptid)) + if (!ptid_tid_p (ptid)) { - /* It's an LWP; pass the request on to procfs. */ - if (target_has_execution) - procfs_ops.to_fetch_registers (regnum); - else - orig_core_ops.to_fetch_registers (regnum); + /* It's an LWP; pass the request on to the layer beneath. */ + beneath->to_fetch_registers (beneath, regcache, regnum); return; } - /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t. */ - thread = GET_THREAD (inferior_ptid); + /* Solaris thread: convert PTID into a td_thrhandle_t. */ + thread = ptid_get_tid (ptid); if (thread == 0) error (_("sol_thread_fetch_registers: thread == 0")); @@ -531,49 +496,32 @@ sol_thread_fetch_registers (int regnum) calling the td routines because the td routines call ps_lget* which affect the values stored in the registers array. */ - supply_gregset ((gdb_gregset_t *) &gregset); - supply_fpregset ((gdb_fpregset_t *) &fpregset); - -#if 0 - /* FIXME: libthread_db doesn't seem to handle this right. */ - val = td_thr_getxregsize (&thandle, &xregsize); - if (val != TD_OK && val != TD_NOXREGS) - error (_("sol_thread_fetch_registers: td_thr_getxregsize %s"), - td_err_string (val)); - - if (val == TD_OK) - { - xregset = alloca (xregsize); - val = td_thr_getxregs (&thandle, xregset); - if (val != TD_OK) - error (_("sol_thread_fetch_registers: td_thr_getxregs %s"), - td_err_string (val)); - } -#endif + supply_gregset (regcache, (const gdb_gregset_t *) gregset_p); + supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset_p); } static void -sol_thread_store_registers (int regnum) +sol_thread_store_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { thread_t thread; td_thrhandle_t thandle; td_err_e val; prgregset_t gregset; prfpregset_t fpregset; -#if 0 - int xregsize; - caddr_t xregset; -#endif + ptid_t ptid = regcache_get_ptid (regcache); - if (!is_thread (inferior_ptid)) + if (!ptid_tid_p (ptid)) { - /* It's an LWP; pass the request on to procfs.c. */ - procfs_ops.to_store_registers (regnum); + struct target_ops *beneath = find_target_beneath (ops); + + /* It's an LWP; pass the request on to the layer beneath. */ + beneath->to_store_registers (beneath, regcache, regnum); return; } - /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t. */ - thread = GET_THREAD (inferior_ptid); + /* Solaris thread: convert PTID into a td_thrhandle_t. */ + thread = ptid_get_tid (ptid); val = p_td_ta_map_id2thr (main_ta, thread, &thandle); if (val != TD_OK) @@ -582,12 +530,6 @@ sol_thread_store_registers (int regnum) if (regnum != -1) { - /* Not writing all the registers. */ - char old_value[MAX_REGISTER_SIZE]; - - /* Save new register value. */ - regcache_raw_collect (current_regcache, regnum, old_value); - val = p_td_thr_getgregs (&thandle, gregset); if (val != TD_OK) error (_("sol_thread_store_registers: td_thr_getgregs %s"), @@ -596,30 +538,10 @@ sol_thread_store_registers (int regnum) if (val != TD_OK) error (_("sol_thread_store_registers: td_thr_getfpregs %s"), td_err_string (val)); - - /* Restore new register value. */ - regcache_raw_supply (current_regcache, regnum, old_value); - -#if 0 - /* FIXME: libthread_db doesn't seem to handle this right. */ - val = td_thr_getxregsize (&thandle, &xregsize); - if (val != TD_OK && val != TD_NOXREGS) - error (_("sol_thread_store_registers: td_thr_getxregsize %s"), - td_err_string (val)); - - if (val == TD_OK) - { - xregset = alloca (xregsize); - val = td_thr_getxregs (&thandle, xregset); - if (val != TD_OK) - error (_("sol_thread_store_registers: td_thr_getxregs %s"), - td_err_string (val)); - } -#endif } - fill_gregset ((gdb_gregset_t *) &gregset, regnum); - fill_fpregset ((gdb_fpregset_t *) &fpregset, regnum); + fill_gregset (regcache, (gdb_gregset_t *) &gregset, regnum); + fill_fpregset (regcache, (gdb_fpregset_t *) &fpregset, regnum); val = p_td_thr_setgregs (&thandle, gregset); if (val != TD_OK) @@ -629,85 +551,23 @@ sol_thread_store_registers (int regnum) if (val != TD_OK) error (_("sol_thread_store_registers: td_thr_setfpregs %s"), td_err_string (val)); - -#if 0 - /* FIXME: libthread_db doesn't seem to handle this right. */ - val = td_thr_getxregsize (&thandle, &xregsize); - if (val != TD_OK && val != TD_NOXREGS) - error (_("sol_thread_store_registers: td_thr_getxregsize %s"), - td_err_string (val)); - - /* ??? Should probably do something about writing the xregs here, - but what are they? */ -#endif -} - -/* Get ready to modify the registers array. On machines which store - individual registers, this doesn't need to do anything. On - machines which store all the registers in one fell swoop, this - makes sure that registers contains all the registers from the - program being debugged. */ - -static void -sol_thread_prepare_to_store (void) -{ - procfs_ops.to_prepare_to_store (); -} - -/* Transfer LEN bytes between GDB address MYADDR and target address - MEMADDR. If DOWRITE is non-zero, transfer them to the target, - otherwise transfer them from the target. TARGET is unused. - - Returns the number of bytes transferred. */ - -static int -sol_thread_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, - int dowrite, struct mem_attrib *attrib, - struct target_ops *target) -{ - int retval; - struct cleanup *old_chain; - - old_chain = save_inferior_ptid (); - - if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid)) - { - /* It's either a thread or an LWP that isn't alive. Any live - LWP will do so use the first available. - - NOTE: We don't need to call switch_to_thread; we're just - reading memory. */ - inferior_ptid = procfs_first_available (); - } - - if (target_has_execution) - retval = procfs_ops.deprecated_xfer_memory (memaddr, myaddr, len, - dowrite, attrib, target); - else - retval = orig_core_ops.deprecated_xfer_memory (memaddr, myaddr, len, - dowrite, attrib, target); - - do_cleanups (old_chain); - - return retval; } /* Perform partial transfers on OBJECT. See target_read_partial and target_write_partial for details of each variant. One, and only one, of readbuf or writebuf must be non-NULL. */ -static LONGEST +static enum target_xfer_status sol_thread_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, LONGEST len) + ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { - int retval; - struct cleanup *old_chain; + struct target_ops *beneath = find_target_beneath (ops); - old_chain = save_inferior_ptid (); + scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid); - if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid)) + if (ptid_tid_p (inferior_ptid) || !target_thread_alive (inferior_ptid)) { /* It's either a thread or an LWP that isn't alive. Any live LWP will do so use the first available. @@ -717,59 +577,67 @@ sol_thread_xfer_partial (struct target_ops *ops, enum target_object object, inferior_ptid = procfs_first_available (); } - if (target_has_execution) - retval = procfs_ops.to_xfer_partial (ops, object, annex, - readbuf, writebuf, offset, len); - else - retval = orig_core_ops.to_xfer_partial (ops, object, annex, - readbuf, writebuf, offset, len); - - do_cleanups (old_chain); - - return retval; + return beneath->to_xfer_partial (beneath, object, annex, readbuf, + writebuf, offset, len, xfered_len); } -/* Print status information about what we're accessing. */ - static void -sol_thread_files_info (struct target_ops *ignore) +check_for_thread_db (void) { - procfs_ops.to_files_info (ignore); -} + td_err_e err; + ptid_t ptid; -static void -sol_thread_kill_inferior (void) -{ - procfs_ops.to_kill (); -} + /* Don't attempt to use thread_db for remote targets. */ + if (!(target_can_run (¤t_target) || core_bfd)) + return; -static void -sol_thread_notice_signals (ptid_t ptid) -{ - procfs_ops.to_notice_signals (pid_to_ptid (PIDGET (ptid))); -} + /* Do nothing if we couldn't load libthread_db.so.1. */ + if (p_td_ta_new == NULL) + return; -/* Fork an inferior process, and start debugging it with /proc. */ + if (sol_thread_active) + /* Nothing to do. The thread library was already detected and the + target vector was already activated. */ + return; -static void -sol_thread_create_inferior (char *exec_file, char *allargs, char **env, - int from_tty) -{ - procfs_ops.to_create_inferior (exec_file, allargs, env, from_tty); + /* Now, initialize libthread_db. This needs to be done after the + shared libraries are located because it needs information from + the user's thread library. */ + + err = p_td_init (); + if (err != TD_OK) + { + warning (_("sol_thread_new_objfile: td_init: %s"), td_err_string (err)); + return; + } - if (sol_thread_active && !ptid_equal (inferior_ptid, null_ptid)) + /* Now attempt to open a connection to the thread library. */ + err = p_td_ta_new (&main_ph, &main_ta); + switch (err) { - /* Save for xfer_memory. */ - main_ph.ptid = inferior_ptid; + case TD_NOLIBTHREAD: + /* No thread library was detected. */ + break; + + case TD_OK: + printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n")); + /* The thread library was detected. Activate the sol_thread target. */ push_target (&sol_thread_ops); + sol_thread_active = 1; - inferior_ptid = lwp_to_thread (inferior_ptid); - if (PIDGET (inferior_ptid) == -1) - inferior_ptid = main_ph.ptid; + main_ph.ptid = inferior_ptid; /* Save for xfer_memory. */ + ptid = lwp_to_thread (inferior_ptid); + if (ptid_get_pid (ptid) != -1) + inferior_ptid = ptid; + + target_update_thread_list (); + break; - if (!in_thread_list (inferior_ptid)) - add_thread (inferior_ptid); + default: + warning (_("Cannot initialize thread debugging library: %s"), + td_err_string (err)); + break; } } @@ -777,106 +645,42 @@ sol_thread_create_inferior (char *exec_file, char *allargs, char **env, when all symbol tables are removed. libthread_db can only be initialized when it finds the right variables in libthread.so. Since it's a shared library, those variables don't show up until - the library gets mapped and the symbol table is read in. - - This new_objfile event is managed by a chained function pointer. - It is the callee's responsability to call the next client on the - chain. */ - -/* Saved pointer to previous owner of the new_objfile event. */ -static void (*target_new_objfile_chain) (struct objfile *); + the library gets mapped and the symbol table is read in. */ -void +static void sol_thread_new_objfile (struct objfile *objfile) { - td_err_e val; - - if (!objfile) - { - sol_thread_active = 0; - goto quit; - } - - /* Don't do anything if init failed to resolve the libthread_db - library. */ - if (!procfs_suppress_run) - goto quit; - - /* Now, initialize libthread_db. This needs to be done after the - shared libraries are located because it needs information from - the user's thread library. */ - - val = p_td_init (); - if (val != TD_OK) - { - warning (_("sol_thread_new_objfile: td_init: %s"), td_err_string (val)); - goto quit; - } - - val = p_td_ta_new (&main_ph, &main_ta); - if (val == TD_NOLIBTHREAD) - goto quit; - else if (val != TD_OK) - { - warning (_("sol_thread_new_objfile: td_ta_new: %s"), td_err_string (val)); - goto quit; - } - - sol_thread_active = 1; - -quit: - /* Call predecessor on chain, if any. */ - if (target_new_objfile_chain) - target_new_objfile_chain (objfile); + if (objfile != NULL) + check_for_thread_db (); } /* Clean up after the inferior dies. */ static void -sol_thread_mourn_inferior (void) -{ - unpush_target (&sol_thread_ops); - procfs_ops.to_mourn_inferior (); -} - -/* Mark our target-struct as eligible for stray "run" and "attach" - commands. */ - -static int -sol_thread_can_run (void) +sol_thread_mourn_inferior (struct target_ops *ops) { - return procfs_suppress_run; -} - -/* - - LOCAL FUNCTION - - sol_thread_alive - test thread for "aliveness" - - SYNOPSIS + struct target_ops *beneath = find_target_beneath (ops); - static bool sol_thread_alive (ptid_t ptid); + sol_thread_active = 0; - DESCRIPTION + unpush_target (ops); - returns true if thread still active in inferior. - - */ + beneath->to_mourn_inferior (beneath); +} /* Return true if PTID is still active in the inferior. */ static int -sol_thread_alive (ptid_t ptid) +sol_thread_alive (struct target_ops *ops, ptid_t ptid) { - if (is_thread (ptid)) + if (ptid_tid_p (ptid)) { /* It's a (user-level) thread. */ td_err_e val; td_thrhandle_t th; int pid; - pid = GET_THREAD (ptid); + pid = ptid_get_tid (ptid); if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK) return 0; /* Thread not found. */ if ((val = p_td_thr_validate (&th)) != TD_OK) @@ -885,51 +689,17 @@ sol_thread_alive (ptid_t ptid) } else { - /* It's an LPW; pass the request on to procfs. */ - if (target_has_execution) - return procfs_ops.to_thread_alive (ptid); - else - return orig_core_ops.to_thread_alive (ptid); + struct target_ops *beneath = find_target_beneath (ops); + + /* It's an LPW; pass the request on to the layer below. */ + return beneath->to_thread_alive (beneath, ptid); } } -static void -sol_thread_stop (void) -{ - procfs_ops.to_stop (); -} /* These routines implement the lower half of the thread_db interface, i.e. the ps_* routines. */ -/* Various versions of 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 the 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; -typedef paddr_t gdb_ps_addr_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; -typedef psaddr_t gdb_ps_addr_t; -#endif - /* The next four routines are called by libthread_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, @@ -938,7 +708,7 @@ typedef psaddr_t gdb_ps_addr_t; /* Process stop. */ ps_err_e -ps_pstop (gdb_ps_prochandle_t ph) +ps_pstop (struct ps_prochandle *ph) { return PS_OK; } @@ -946,7 +716,7 @@ ps_pstop (gdb_ps_prochandle_t ph) /* Process continue. */ ps_err_e -ps_pcontinue (gdb_ps_prochandle_t ph) +ps_pcontinue (struct ps_prochandle *ph) { return PS_OK; } @@ -954,7 +724,7 @@ ps_pcontinue (gdb_ps_prochandle_t ph) /* LWP stop. */ ps_err_e -ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid) +ps_lstop (struct ps_prochandle *ph, lwpid_t lwpid) { return PS_OK; } @@ -962,7 +732,7 @@ ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid) /* LWP continue. */ ps_err_e -ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid) +ps_lcontinue (struct ps_prochandle *ph, lwpid_t lwpid) { return PS_OK; } @@ -970,30 +740,30 @@ ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid) /* Looks up the symbol LD_SYMBOL_NAME in the debugger's symbol table. */ ps_err_e -ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name, - const char *ld_symbol_name, gdb_ps_addr_t *ld_symbol_addr) +ps_pglobal_lookup (struct ps_prochandle *ph, const char *ld_object_name, + const char *ld_symbol_name, psaddr_t *ld_symbol_addr) { - struct minimal_symbol *ms; + struct bound_minimal_symbol ms; ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL); - if (!ms) + if (!ms.minsym) return PS_NOSYM; - *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms); + *ld_symbol_addr = BMSYMBOL_VALUE_ADDRESS (ms); return PS_OK; } /* Common routine for reading and writing memory. */ static ps_err_e -rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr, - char *buf, int size) +rw_common (int dowrite, const struct ps_prochandle *ph, psaddr_t addr, + gdb_byte *buf, int size) { - struct cleanup *old_chain; + int ret; - old_chain = save_inferior_ptid (); + scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid); - if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid)) + if (ptid_tid_p (inferior_ptid) || !target_thread_alive (inferior_ptid)) { /* It's either a thread or an LWP that isn't alive. Any live LWP will do so use the first available. @@ -1010,106 +780,59 @@ rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr, addr &= 0xffffffff; #endif - while (size > 0) - { - int cc; - - /* FIXME: passing 0 as attrib argument. */ - if (target_has_execution) - cc = procfs_ops.deprecated_xfer_memory (addr, buf, size, - dowrite, 0, &procfs_ops); - else - cc = orig_core_ops.deprecated_xfer_memory (addr, buf, size, - dowrite, 0, &core_ops); - - if (cc < 0) - { - if (dowrite == 0) - print_sys_errmsg ("rw_common (): read", errno); - else - print_sys_errmsg ("rw_common (): write", errno); - - do_cleanups (old_chain); - - return PS_ERR; - } - else if (cc == 0) - { - if (dowrite == 0) - warning (_("rw_common (): unable to read at addr 0x%lx"), - (long) addr); - else - warning (_("rw_common (): unable to write at addr 0x%lx"), - (long) addr); - - do_cleanups (old_chain); - - return PS_ERR; - } - - size -= cc; - buf += cc; - } - - do_cleanups (old_chain); + if (dowrite) + ret = target_write_memory (addr, (gdb_byte *) buf, size); + else + ret = target_read_memory (addr, (gdb_byte *) buf, size); - return PS_OK; + return (ret == 0 ? PS_OK : PS_ERR); } /* Copies SIZE bytes from target process .data segment to debugger memory. */ ps_err_e -ps_pdread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr, - gdb_ps_read_buf_t buf, gdb_ps_size_t size) +ps_pdread (struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t size) { - return rw_common (0, ph, addr, buf, size); + return rw_common (0, ph, addr, (gdb_byte *) buf, size); } /* Copies SIZE bytes from debugger memory .data segment to target process. */ ps_err_e -ps_pdwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr, - gdb_ps_write_buf_t buf, gdb_ps_size_t size) +ps_pdwrite (struct ps_prochandle *ph, psaddr_t addr, + const void *buf, size_t size) { - return rw_common (1, ph, addr, (char *) buf, size); + return rw_common (1, ph, addr, (gdb_byte *) buf, size); } /* Copies SIZE bytes from target process .text segment to debugger memory. */ ps_err_e -ps_ptread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr, - gdb_ps_read_buf_t buf, gdb_ps_size_t size) +ps_ptread (struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t size) { - return rw_common (0, ph, addr, buf, size); + return rw_common (0, ph, addr, (gdb_byte *) buf, size); } /* Copies SIZE bytes from debugger memory .text segment to target process. */ ps_err_e -ps_ptwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr, - gdb_ps_write_buf_t buf, gdb_ps_size_t size) +ps_ptwrite (struct ps_prochandle *ph, psaddr_t addr, + const void *buf, size_t size) { - return rw_common (1, ph, addr, (char *) buf, size); + return rw_common (1, ph, addr, (gdb_byte *) buf, size); } /* Get general-purpose registers for LWP. */ ps_err_e -ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset) +ps_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, prgregset_t gregset) { - struct cleanup *old_chain; - - old_chain = save_inferior_ptid (); + ptid_t ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0); + struct regcache *regcache + = get_thread_arch_regcache (ptid, target_gdbarch ()); - inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); - - if (target_has_execution) - procfs_ops.to_fetch_registers (-1); - else - orig_core_ops.to_fetch_registers (-1); - fill_gregset ((gdb_gregset_t *) gregset, -1); - - do_cleanups (old_chain); + target_fetch_registers (regcache, -1); + fill_gregset (regcache, (gdb_gregset_t *) gregset, -1); return PS_OK; } @@ -1117,22 +840,15 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset) /* Set general-purpose registers for LWP. */ ps_err_e -ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, +ps_lsetregs (struct ps_prochandle *ph, lwpid_t lwpid, const prgregset_t gregset) { - struct cleanup *old_chain; - - old_chain = save_inferior_ptid (); + ptid_t ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0); + struct regcache *regcache + = get_thread_arch_regcache (ptid, target_gdbarch ()); - inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); - - supply_gregset ((gdb_gregset_t *) gregset); - if (target_has_execution) - procfs_ops.to_store_registers (-1); - else - orig_core_ops.to_store_registers (-1); - - do_cleanups (old_chain); + supply_gregset (regcache, (const gdb_gregset_t *) gregset); + target_store_registers (regcache, -1); return PS_OK; } @@ -1152,119 +868,55 @@ ps_plog (const char *fmt, ...) /* Get size of extra register set. Currently a noop. */ ps_err_e -ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize) +ps_lgetxregsize (struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize) { -#if 0 - int lwp_fd; - int regsize; - ps_err_e val; - - val = get_lwp_fd (ph, lwpid, &lwp_fd); - if (val != PS_OK) - return val; - - if (ioctl (lwp_fd, PIOCGXREGSIZE, ®size)) - { - if (errno == EINVAL) - return PS_NOFREGS; /* XXX Wrong code, but this is the closest - thing in proc_service.h */ - - print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno); - return PS_ERR; - } -#endif - return PS_OK; } /* Get extra register set. Currently a noop. */ ps_err_e -ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset) +ps_lgetxregs (struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset) { -#if 0 - int lwp_fd; - ps_err_e val; - - val = get_lwp_fd (ph, lwpid, &lwp_fd); - if (val != PS_OK) - return val; - - if (ioctl (lwp_fd, PIOCGXREG, xregset)) - { - print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno); - return PS_ERR; - } -#endif - return PS_OK; } /* Set extra register set. Currently a noop. */ ps_err_e -ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset) +ps_lsetxregs (struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset) { -#if 0 - int lwp_fd; - ps_err_e val; - - val = get_lwp_fd (ph, lwpid, &lwp_fd); - if (val != PS_OK) - return val; - - if (ioctl (lwp_fd, PIOCSXREG, xregset)) - { - print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno); - return PS_ERR; - } -#endif - return PS_OK; } /* Get floating-point registers for LWP. */ ps_err_e -ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, +ps_lgetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, prfpregset_t *fpregset) { - struct cleanup *old_chain; - - old_chain = save_inferior_ptid (); + ptid_t ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0); + struct regcache *regcache + = get_thread_arch_regcache (ptid, target_gdbarch ()); - inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); - - if (target_has_execution) - procfs_ops.to_fetch_registers (-1); - else - orig_core_ops.to_fetch_registers (-1); - fill_fpregset ((gdb_fpregset_t *) fpregset, -1); - - do_cleanups (old_chain); + target_fetch_registers (regcache, -1); + fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1); return PS_OK; } -/* Set floating-point regs for LWP */ +/* Set floating-point regs for LWP. */ ps_err_e -ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, +ps_lsetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, const prfpregset_t * fpregset) { - struct cleanup *old_chain; - - old_chain = save_inferior_ptid (); + ptid_t ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0); + struct regcache *regcache + = get_thread_arch_regcache (ptid, target_gdbarch ()); - inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); - - supply_fpregset ((gdb_fpregset_t *) fpregset); - if (target_has_execution) - procfs_ops.to_store_registers (-1); - else - orig_core_ops.to_store_registers (-1); - - do_cleanups (old_chain); + supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset); + target_store_registers (regcache, -1); return PS_OK; } @@ -1275,7 +927,7 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, (e.g. procfs) method, but this ought to work. */ ps_err_e -ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model) +ps_pdmodel (struct ps_prochandle *ph, int *data_model) { if (exec_bfd == 0) *data_model = PR_MODEL_UNKNOWN; @@ -1288,25 +940,28 @@ ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model) } #endif /* PR_MODEL_LP64 */ -#ifdef TM_I386SOL2_H +#if (defined(__i386__) || defined(__x86_64__)) && defined (sun) + +/* Reads the local descriptor table of a LWP. -/* Reads the local descriptor table of a LWP. */ + This function is necessary on x86-solaris only. Without it, the loading + of libthread_db would fail because of ps_lgetLDT being undefined. */ ps_err_e -ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid, +ps_lgetLDT (struct ps_prochandle *ph, lwpid_t lwpid, struct ssd *pldt) { /* NOTE: only used on Solaris, therefore OK to refer to procfs.c. */ - extern struct ssd *procfs_find_LDT_entry (ptid_t); struct ssd *ret; /* FIXME: can't I get the process ID from the prochandle or something? */ - if (PIDGET (inferior_ptid) <= 0 || lwpid <= 0) + if (ptid_get_pid (inferior_ptid) <= 0 || lwpid <= 0) return PS_BADLID; - ret = procfs_find_LDT_entry (BUILD_LWP (lwpid, PIDGET (inferior_ptid))); + ret = procfs_find_LDT_entry (ptid_build (ptid_get_pid (inferior_ptid), + lwpid, 0)); if (ret) { memcpy (pldt, ret, sizeof (struct ssd)); @@ -1316,48 +971,46 @@ ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid, /* LDT not found. */ return PS_ERR; } -#endif /* TM_I386SOL2_H */ +#endif /* Convert PTID to printable form. */ -char * -solaris_pid_to_str (ptid_t ptid) +static const char * +solaris_pid_to_str (struct target_ops *ops, ptid_t ptid) { static char buf[100]; - /* In case init failed to resolve the libthread_db library. */ - if (!procfs_suppress_run) - return procfs_pid_to_str (ptid); - - if (is_thread (ptid)) + if (ptid_tid_p (ptid)) { ptid_t lwp; lwp = thread_to_lwp (ptid, -2); - if (PIDGET (lwp) == -1) - sprintf (buf, "Thread %ld (defunct)", GET_THREAD (ptid)); - else if (PIDGET (lwp) != -2) - sprintf (buf, "Thread %ld (LWP %ld)", - GET_THREAD (ptid), GET_LWP (lwp)); + if (ptid_get_pid (lwp) == -1) + xsnprintf (buf, sizeof (buf), "Thread %ld (defunct)", + ptid_get_tid (ptid)); + else if (ptid_get_pid (lwp) != -2) + xsnprintf (buf, sizeof (buf), "Thread %ld (LWP %ld)", + ptid_get_tid (ptid), ptid_get_lwp (lwp)); else - sprintf (buf, "Thread %ld ", GET_THREAD (ptid)); + xsnprintf (buf, sizeof (buf), "Thread %ld ", + ptid_get_tid (ptid)); } - else if (GET_LWP (ptid) != 0) - sprintf (buf, "LWP %ld ", GET_LWP (ptid)); + else if (ptid_get_lwp (ptid) != 0) + xsnprintf (buf, sizeof (buf), "LWP %ld ", ptid_get_lwp (ptid)); else - sprintf (buf, "process %d ", PIDGET (ptid)); + xsnprintf (buf, sizeof (buf), "process %d ", ptid_get_pid (ptid)); return buf; } -/* Worker bee for find_new_threads. Callback function that gets +/* Worker bee for update_thread_list. Callback function that gets called once per user-level thread (i.e. not for LWP's). */ static int -sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored) +sol_update_thread_list_callback (const td_thrhandle_t *th, void *ignored) { td_err_e retval; td_thrinfo_t ti; @@ -1367,61 +1020,30 @@ sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored) if (retval != TD_OK) return -1; - ptid = BUILD_THREAD (ti.ti_tid, PIDGET (inferior_ptid)); - if (!in_thread_list (ptid)) + ptid = ptid_build (ptid_get_pid (inferior_ptid), 0, ti.ti_tid); + if (!in_thread_list (ptid) || is_exited (ptid)) add_thread (ptid); return 0; } static void -sol_find_new_threads (void) +sol_update_thread_list (struct target_ops *ops) { - /* Don't do anything if init failed to resolve the libthread_db - library. */ - if (!procfs_suppress_run) - return; + struct target_ops *beneath = find_target_beneath (ops); - if (PIDGET (inferior_ptid) == -1) - { - printf_filtered ("No process.\n"); - return; - } + /* Delete dead threads. */ + prune_threads (); - /* First Find any new LWP's. */ - procfs_ops.to_find_new_threads (); + /* Find any new LWP's. */ + beneath->to_update_thread_list (beneath); /* Then find any new user-level threads. */ - p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *) 0, + p_td_ta_thr_iter (main_ta, sol_update_thread_list_callback, (void *) 0, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); } -static void -sol_core_open (char *filename, int from_tty) -{ - orig_core_ops.to_open (filename, from_tty); -} - -static void -sol_core_close (int quitting) -{ - orig_core_ops.to_close (quitting); -} - -static void -sol_core_detach (char *args, int from_tty) -{ - unpush_target (&core_ops); - orig_core_ops.to_detach (args, from_tty); -} - -static void -sol_core_files_info (struct target_ops *t) -{ - orig_core_ops.to_files_info (t); -} - /* Worker bee for the "info sol-thread" command. This is a callback function that gets called once for each Solaris user-level thread (i.e. not for LWPs) in the inferior. Print anything interesting @@ -1467,30 +1089,28 @@ info_cb (const td_thrhandle_t *th, void *s) /* Print thr_create start function. */ if (ti.ti_startfunc != 0) { - struct minimal_symbol *msym; - msym = lookup_minimal_symbol_by_pc (ti.ti_startfunc); - if (msym) - printf_filtered (" startfunc: %s\n", - DEPRECATED_SYMBOL_NAME (msym)); - else - printf_filtered (" startfunc: 0x%s\n", paddr (ti.ti_startfunc)); + const struct bound_minimal_symbol msym + = lookup_minimal_symbol_by_pc (ti.ti_startfunc); + + printf_filtered (" startfunc=%s", + msym.minsym + ? MSYMBOL_PRINT_NAME (msym.minsym) + : paddress (target_gdbarch (), ti.ti_startfunc)); } /* If thread is asleep, print function that went to sleep. */ if (ti.ti_state == TD_THR_SLEEP) { - struct minimal_symbol *msym; - msym = lookup_minimal_symbol_by_pc (ti.ti_pc); - if (msym) - printf_filtered (" - Sleep func: %s\n", - DEPRECATED_SYMBOL_NAME (msym)); - else - printf_filtered (" - Sleep func: 0x%s\n", paddr (ti.ti_startfunc)); + const struct bound_minimal_symbol msym + = lookup_minimal_symbol_by_pc (ti.ti_pc); + + printf_filtered (" sleepfunc=%s", + msym.minsym + ? MSYMBOL_PRINT_NAME (msym.minsym) + : paddress (target_gdbarch (), ti.ti_pc)); } - /* Wrap up line, if necessary. */ - if (ti.ti_state != TD_THR_SLEEP && ti.ti_startfunc == 0) - printf_filtered ("\n"); /* don't you hate counting newlines? */ + printf_filtered ("\n"); } else warning (_("info sol-thread: failed to get info for thread.")); @@ -1502,31 +1122,45 @@ info_cb (const td_thrhandle_t *th, void *s) inferior. */ static void -info_solthreads (char *args, int from_tty) +info_solthreads (const char *args, int from_tty) { - p_td_ta_thr_iter (main_ta, info_cb, args, + p_td_ta_thr_iter (main_ta, info_cb, (void *) args, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); } +/* Callback routine used to find a thread based on the TID part of + its PTID. */ + static int -sol_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, - int, int, int, void *), - void *data) +thread_db_find_thread_from_tid (struct thread_info *thread, void *data) { - return procfs_ops.to_find_memory_regions (func, data); -} + long *tid = (long *) data; -static char * -sol_make_note_section (bfd *obfd, int *note_size) -{ - return procfs_ops.to_make_corefile_notes (obfd, note_size); + if (ptid_get_tid (thread->ptid) == *tid) + return 1; + + return 0; } -static int -ignore (struct bp_target_info *bp_tgt) +static ptid_t +sol_get_ada_task_ptid (struct target_ops *self, long lwp, long thread) { - return 0; + struct thread_info *thread_info = + iterate_over_threads (thread_db_find_thread_from_tid, &thread); + + if (thread_info == NULL) + { + /* The list of threads is probably not up to date. Find any + thread that is missing from the list, and try again. */ + sol_update_thread_list (¤t_target); + thread_info = iterate_over_threads (thread_db_find_thread_from_tid, + &thread); + } + + gdb_assert (thread_info != NULL); + + return (thread_info->ptid); } static void @@ -1535,100 +1169,34 @@ init_sol_thread_ops (void) 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_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.deprecated_xfer_memory = sol_thread_xfer_memory; sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial; - 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_save_ours = terminal_save_ours; - sol_thread_ops.to_terminal_info = child_terminal_info; - sol_thread_ops.to_kill = sol_thread_kill_inferior; - 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_pid_to_str = solaris_pid_to_str; - 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_find_memory_regions = sol_find_memory_regions; - sol_thread_ops.to_make_corefile_notes = sol_make_note_section; + sol_thread_ops.to_update_thread_list = sol_update_thread_list; + sol_thread_ops.to_stratum = thread_stratum; + sol_thread_ops.to_get_ada_task_ptid = sol_get_ada_task_ptid; sol_thread_ops.to_magic = OPS_MAGIC; } -static void -init_sol_core_ops (void) -{ - 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_fetch_registers = sol_thread_fetch_registers; - sol_core_ops.deprecated_xfer_memory = sol_thread_xfer_memory; - sol_core_ops.to_xfer_partial = sol_thread_xfer_partial; - 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_create_inferior = sol_thread_create_inferior; - sol_core_ops.to_stratum = core_stratum; - 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_thread_control = tc_none; - sol_core_ops.to_thread_alive = sol_thread_alive; - sol_core_ops.to_pid_to_str = solaris_pid_to_str; - /* On Solaris/x86, when debugging a threaded core file from process - , the following causes "info threads" to produce "procfs: - couldn't find pid in procinfo list" where is the pid of - the process that produced the core file. Disable it for now. */ -#if 0 - sol_core_ops.to_find_new_threads = sol_find_new_threads; -#endif - 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) { void *dlhandle; init_sol_thread_ops (); - init_sol_core_ops (); dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW); if (!dlhandle) goto die; #define resolve(X) \ - if (!(p_##X = dlsym (dlhandle, #X))) \ + if (!(p_##X = (X ## _ftype *) dlsym (dlhandle, #X))) \ goto die; resolve (td_log); @@ -1655,20 +1223,13 @@ _initialize_sol_thread (void) resolve (td_thr_getgregs); resolve (td_thr_setgregs); - add_target (&sol_thread_ops); - - procfs_suppress_run = 1; + complete_target_initialization (&sol_thread_ops); add_cmd ("sol-threads", class_maintenance, info_solthreads, _("Show info on Solaris user threads."), &maintenanceinfolist); - memcpy (&orig_core_ops, &core_ops, sizeof (struct target_ops)); - memcpy (&core_ops, &sol_core_ops, sizeof (struct target_ops)); - add_target (&core_ops); - /* Hook into new_objfile notification. */ - target_new_objfile_chain = deprecated_target_new_objfile_hook; - deprecated_target_new_objfile_hook = sol_thread_new_objfile; + gdb::observers::new_objfile.attach (sol_thread_new_objfile); return; die: @@ -1678,8 +1239,5 @@ _initialize_sol_thread (void) if (dlhandle) dlclose (dlhandle); - /* Allow the user to debug non-threaded core files. */ - add_target (&core_ops); - return; }