2012-07-19 Pedro Alves <palves@redhat.com>
[deliverable/binutils-gdb.git] / gdb / sol-thread.c
CommitLineData
8d027a04
MK
1/* Solaris threads debugging interface.
2
0b302171 3 Copyright (C) 1996-2005, 2007-2012 Free Software Foundation, Inc.
c906108c 4
c5aa993b 5 This file is part of GDB.
c906108c 6
c5aa993b
JM
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
c5aa993b 10 (at your option) any later version.
c906108c 11
c5aa993b
JM
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
c906108c 16
c5aa993b 17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
20/* This module implements a sort of half target that sits between the
8d027a04
MK
21 machine-independent parts of GDB and the /proc interface (procfs.c)
22 to provide access to the Solaris user-mode thread implementation.
23
24 Solaris threads are true user-mode threads, which are invoked via
25 the thr_* and pthread_* (native and POSIX respectivly) interfaces.
26 These are mostly implemented in user-space, with all thread context
27 kept in various structures that live in the user's heap. These
28 should not be confused with lightweight processes (LWPs), which are
29 implemented by the kernel, and scheduled without explicit
30 intervention by the process.
31
32 Just to confuse things a little, Solaris threads (both native and
33 POSIX) are actually implemented using LWPs. In general, there are
34 going to be more threads than LWPs. There is no fixed
35 correspondence between a thread and an LWP. When a thread wants to
36 run, it gets scheduled onto the first available LWP and can
37 therefore migrate from one LWP to another as time goes on. A
c906108c
SS
38 sleeping thread may not be associated with an LWP at all!
39
8d027a04
MK
40 To make it possible to mess with threads, Sun provides a library
41 called libthread_db.so.1 (not to be confused with
42 libthread_db.so.0, which doesn't have a published interface). This
43 interface has an upper part, which it provides, and a lower part
44 which we provide. The upper part consists of the td_* routines,
45 which allow us to find all the threads, query their state, etc...
46 The lower part consists of all of the ps_*, which are used by the
47 td_* routines to read/write memory, manipulate LWPs, lookup
48 symbols, etc... The ps_* routines actually do most of their work
49 by calling functions in procfs.c. */
c906108c
SS
50
51#include "defs.h"
52#include <thread.h>
53#include <proc_service.h>
54#include <thread_db.h>
55#include "gdbthread.h"
56#include "target.h"
57#include "inferior.h"
58#include <fcntl.h>
b8a92b82 59#include "gdb_stat.h"
c906108c
SS
60#include <dlfcn.h>
61#include "gdbcmd.h"
23e04971 62#include "gdbcore.h"
4e052eda 63#include "regcache.h"
d45b6f32 64#include "solib.h"
990f9fe3 65#include "symfile.h"
06d3b283 66#include "observer.h"
6f4492c8 67#include "gdb_string.h"
d1a7880c 68#include "procfs.h"
6f4492c8 69
c906108c 70struct target_ops sol_thread_ops;
c906108c 71
c378eb4e 72/* Prototypes for supply_gregset etc. */
c60c0f5f 73#include "gregset.h"
c906108c 74
8d027a04
MK
75/* This struct is defined by us, but mainly used for the proc_service
76 interface. We don't have much use for it, except as a handy place
77 to get a real PID for memory accesses. */
c906108c
SS
78
79struct ps_prochandle
8d027a04
MK
80{
81 ptid_t ptid;
82};
c906108c
SS
83
84struct string_map
8d027a04
MK
85{
86 int num;
87 char *str;
88};
c906108c
SS
89
90static struct ps_prochandle main_ph;
91static td_thragent_t *main_ta;
92static int sol_thread_active = 0;
93
a14ed312 94static void init_sol_thread_ops (void);
c906108c 95
8d027a04
MK
96/* Default definitions: These must be defined in tm.h if they are to
97 be shared with a process module such as procfs. */
d4f3574e 98
ca6724c1
KB
99#define GET_PID(ptid) ptid_get_pid (ptid)
100#define GET_LWP(ptid) ptid_get_lwp (ptid)
101#define GET_THREAD(ptid) ptid_get_tid (ptid)
102
103#define is_lwp(ptid) (GET_LWP (ptid) != 0)
104#define is_thread(ptid) (GET_THREAD (ptid) != 0)
105
106#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0)
107#define BUILD_THREAD(tid, pid) ptid_build (pid, 0, tid)
c906108c 108
8d027a04
MK
109/* Pointers to routines from libthread_db resolved by dlopen(). */
110
111static void (*p_td_log)(const int on_off);
112static td_err_e (*p_td_ta_new)(const struct ps_prochandle *ph_p,
113 td_thragent_t **ta_pp);
114static td_err_e (*p_td_ta_delete)(td_thragent_t *ta_p);
115static td_err_e (*p_td_init)(void);
116static td_err_e (*p_td_ta_get_ph)(const td_thragent_t *ta_p,
117 struct ps_prochandle **ph_pp);
118static td_err_e (*p_td_ta_get_nthreads)(const td_thragent_t *ta_p,
119 int *nthread_p);
120static td_err_e (*p_td_ta_tsd_iter)(const td_thragent_t *ta_p,
121 td_key_iter_f *cb, void *cbdata_p);
122static td_err_e (*p_td_ta_thr_iter)(const td_thragent_t *ta_p,
123 td_thr_iter_f *cb, void *cbdata_p,
124 td_thr_state_e state, int ti_pri,
125 sigset_t *ti_sigmask_p,
126 unsigned ti_user_flags);
127static td_err_e (*p_td_thr_validate)(const td_thrhandle_t *th_p);
128static td_err_e (*p_td_thr_tsd)(const td_thrhandle_t * th_p,
129 const thread_key_t key, void **data_pp);
130static td_err_e (*p_td_thr_get_info)(const td_thrhandle_t *th_p,
131 td_thrinfo_t *ti_p);
132static td_err_e (*p_td_thr_getfpregs)(const td_thrhandle_t *th_p,
133 prfpregset_t *fpregset);
134static td_err_e (*p_td_thr_getxregsize)(const td_thrhandle_t *th_p,
135 int *xregsize);
136static td_err_e (*p_td_thr_getxregs)(const td_thrhandle_t *th_p,
137 const caddr_t xregset);
138static td_err_e (*p_td_thr_sigsetmask)(const td_thrhandle_t *th_p,
139 const sigset_t ti_sigmask);
140static td_err_e (*p_td_thr_setprio)(const td_thrhandle_t *th_p,
141 const int ti_pri);
142static td_err_e (*p_td_thr_setsigpending)(const td_thrhandle_t *th_p,
143 const uchar_t ti_pending_flag,
144 const sigset_t ti_pending);
145static td_err_e (*p_td_thr_setfpregs)(const td_thrhandle_t *th_p,
146 const prfpregset_t *fpregset);
147static td_err_e (*p_td_thr_setxregs)(const td_thrhandle_t *th_p,
148 const caddr_t xregset);
149static td_err_e (*p_td_ta_map_id2thr)(const td_thragent_t *ta_p,
150 thread_t tid,
151 td_thrhandle_t *th_p);
152static td_err_e (*p_td_ta_map_lwp2thr)(const td_thragent_t *ta_p,
153 lwpid_t lwpid,
154 td_thrhandle_t *th_p);
155static td_err_e (*p_td_thr_getgregs)(const td_thrhandle_t *th_p,
156 prgregset_t regset);
157static td_err_e (*p_td_thr_setgregs)(const td_thrhandle_t *th_p,
158 const prgregset_t regset);
159\f
c906108c 160
8d027a04
MK
161/* Return the libthread_db error string associated with ERRCODE. If
162 ERRCODE is unknown, return an appropriate message. */
c906108c
SS
163
164static char *
fba45db2 165td_err_string (td_err_e errcode)
c906108c 166{
8d027a04 167 static struct string_map td_err_table[] =
c5aa993b 168 {
8d027a04
MK
169 { TD_OK, "generic \"call succeeded\"" },
170 { TD_ERR, "generic error." },
171 { TD_NOTHR, "no thread can be found to satisfy query" },
172 { TD_NOSV, "no synch. variable can be found to satisfy query" },
173 { TD_NOLWP, "no lwp can be found to satisfy query" },
174 { TD_BADPH, "invalid process handle" },
175 { TD_BADTH, "invalid thread handle" },
176 { TD_BADSH, "invalid synchronization handle" },
177 { TD_BADTA, "invalid thread agent" },
178 { TD_BADKEY, "invalid key" },
179 { TD_NOMSG, "td_thr_event_getmsg() called when there was no message" },
180 { TD_NOFPREGS, "FPU register set not available for given thread" },
181 { TD_NOLIBTHREAD, "application not linked with libthread" },
182 { TD_NOEVENT, "requested event is not supported" },
183 { TD_NOCAPAB, "capability not available" },
184 { TD_DBERR, "Debugger service failed" },
185 { TD_NOAPLIC, "Operation not applicable to" },
186 { TD_NOTSD, "No thread specific data for this thread" },
187 { TD_MALLOC, "Malloc failed" },
188 { TD_PARTIALREG, "Only part of register set was written/read" },
189 { TD_NOXREGS, "X register set not available for given thread" }
c5aa993b 190 };
c906108c
SS
191 const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
192 int i;
193 static char buf[50];
194
195 for (i = 0; i < td_err_size; i++)
196 if (td_err_table[i].num == errcode)
197 return td_err_table[i].str;
c5aa993b 198
8d027a04 199 sprintf (buf, "Unknown libthread_db error code: %d", errcode);
c906108c
SS
200
201 return buf;
202}
c906108c 203
b021a221 204/* Return the libthread_db state string assicoated with STATECODE.
8d027a04 205 If STATECODE is unknown, return an appropriate message. */
c906108c
SS
206
207static char *
fba45db2 208td_state_string (td_thr_state_e statecode)
c906108c 209{
8d027a04 210 static struct string_map td_thr_state_table[] =
c5aa993b 211 {
8d027a04
MK
212 { TD_THR_ANY_STATE, "any state" },
213 { TD_THR_UNKNOWN, "unknown" },
214 { TD_THR_STOPPED, "stopped" },
215 { TD_THR_RUN, "run" },
216 { TD_THR_ACTIVE, "active" },
217 { TD_THR_ZOMBIE, "zombie" },
218 { TD_THR_SLEEP, "sleep" },
219 { TD_THR_STOPPED_ASLEEP, "stopped asleep" }
c5aa993b 220 };
8d027a04
MK
221 const int td_thr_state_table_size =
222 sizeof td_thr_state_table / sizeof (struct string_map);
c906108c
SS
223 int i;
224 static char buf[50];
225
226 for (i = 0; i < td_thr_state_table_size; i++)
227 if (td_thr_state_table[i].num == statecode)
228 return td_thr_state_table[i].str;
c5aa993b 229
8d027a04 230 sprintf (buf, "Unknown libthread_db state code: %d", statecode);
c906108c
SS
231
232 return buf;
233}
234\f
c906108c 235
8d027a04
MK
236/* Convert a POSIX or Solaris thread ID into a LWP ID. If THREAD_ID
237 doesn't exist, that's an error. If it's an inactive thread, return
2689673f 238 DEFAULT_LWP.
c906108c 239
8d027a04 240 NOTE: This function probably shouldn't call error(). */
c906108c 241
39f77062
KB
242static ptid_t
243thread_to_lwp (ptid_t thread_id, int default_lwp)
c906108c
SS
244{
245 td_thrinfo_t ti;
246 td_thrhandle_t th;
247 td_err_e val;
248
249 if (is_lwp (thread_id))
8d027a04 250 return thread_id; /* It's already an LWP ID. */
c906108c 251
8d027a04 252 /* It's a thread. Convert to LWP. */
c906108c
SS
253
254 val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
255 if (val == TD_NOTHR)
8d027a04 256 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 257 else if (val != TD_OK)
8a3fe4f8 258 error (_("thread_to_lwp: td_ta_map_id2thr %s"), td_err_string (val));
c906108c
SS
259
260 val = p_td_thr_get_info (&th, &ti);
261 if (val == TD_NOTHR)
8d027a04 262 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 263 else if (val != TD_OK)
8a3fe4f8 264 error (_("thread_to_lwp: td_thr_get_info: %s"), td_err_string (val));
c906108c
SS
265
266 if (ti.ti_state != TD_THR_ACTIVE)
267 {
268 if (default_lwp != -1)
39f77062 269 return pid_to_ptid (default_lwp);
8a3fe4f8 270 error (_("thread_to_lwp: thread state not active: %s"),
c906108c
SS
271 td_state_string (ti.ti_state));
272 }
273
274 return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
275}
c906108c 276
8d027a04
MK
277/* Convert an LWP ID into a POSIX or Solaris thread ID. If LWP_ID
278 doesn't exists, that's an error.
c906108c 279
8d027a04 280 NOTE: This function probably shouldn't call error(). */
c906108c 281
39f77062
KB
282static ptid_t
283lwp_to_thread (ptid_t lwp)
c906108c
SS
284{
285 td_thrinfo_t ti;
286 td_thrhandle_t th;
287 td_err_e val;
288
289 if (is_thread (lwp))
8d027a04 290 return lwp; /* It's already a thread ID. */
c906108c 291
8d027a04 292 /* It's an LWP. Convert it to a thread ID. */
c906108c 293
28439f5e 294 if (!target_thread_alive (lwp))
8d027a04 295 return pid_to_ptid (-1); /* Must be a defunct LPW. */
c906108c
SS
296
297 val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
298 if (val == TD_NOTHR)
8d027a04 299 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 300 else if (val != TD_OK)
8a3fe4f8 301 error (_("lwp_to_thread: td_ta_map_lwp2thr: %s."), td_err_string (val));
c906108c
SS
302
303 val = p_td_thr_validate (&th);
304 if (val == TD_NOTHR)
8d027a04 305 return lwp; /* Unknown to libthread; just return LPW, */
c906108c 306 else if (val != TD_OK)
8a3fe4f8 307 error (_("lwp_to_thread: td_thr_validate: %s."), td_err_string (val));
c906108c
SS
308
309 val = p_td_thr_get_info (&th, &ti);
310 if (val == TD_NOTHR)
8d027a04 311 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 312 else if (val != TD_OK)
8a3fe4f8 313 error (_("lwp_to_thread: td_thr_get_info: %s."), td_err_string (val));
c906108c
SS
314
315 return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
316}
317\f
c906108c 318
8d027a04 319/* Most target vector functions from here on actually just pass
28439f5e
PA
320 through to the layer beneath, as they don't need to do anything
321 specific for threads. */
c906108c 322
8d027a04
MK
323/* Take a program previously attached to and detaches it. The program
324 resumes execution and will no longer stop on signals, etc. We'd
325 better not have left any breakpoints in the program or it'll die
326 when it hits one. For this to work, it may be necessary for the
327 process to have been previously attached. It *might* work if the
328 program was started via the normal ptrace (PTRACE_TRACEME). */
c906108c
SS
329
330static void
136d6dae 331sol_thread_detach (struct target_ops *ops, char *args, int from_tty)
c906108c 332{
28439f5e
PA
333 struct target_ops *beneath = find_target_beneath (ops);
334
2689673f 335 sol_thread_active = 0;
39f77062 336 inferior_ptid = pid_to_ptid (PIDGET (main_ph.ptid));
28439f5e
PA
337 unpush_target (ops);
338 beneath->to_detach (beneath, args, from_tty);
c906108c
SS
339}
340
8d027a04
MK
341/* Resume execution of process PTID. If STEP is nozero, then just
342 single step it. If SIGNAL is nonzero, restart it with that signal
343 activated. We may have to convert PTID from a thread ID to an LWP
344 ID for procfs. */
c906108c
SS
345
346static void
28439f5e 347sol_thread_resume (struct target_ops *ops,
2ea28649 348 ptid_t ptid, int step, enum gdb_signal signo)
c906108c
SS
349{
350 struct cleanup *old_chain;
28439f5e 351 struct target_ops *beneath = find_target_beneath (ops);
c906108c 352
39f77062 353 old_chain = save_inferior_ptid ();
c906108c 354
39f77062
KB
355 inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
356 if (PIDGET (inferior_ptid) == -1)
357 inferior_ptid = procfs_first_available ();
c906108c 358
39f77062 359 if (PIDGET (ptid) != -1)
c906108c 360 {
39f77062 361 ptid_t save_ptid = ptid;
c906108c 362
39f77062 363 ptid = thread_to_lwp (ptid, -2);
8d027a04 364 if (PIDGET (ptid) == -2) /* Inactive thread. */
8a3fe4f8 365 error (_("This version of Solaris can't start inactive threads."));
39f77062 366 if (info_verbose && PIDGET (ptid) == -1)
8a3fe4f8 367 warning (_("Specified thread %ld seems to have terminated"),
39f77062 368 GET_THREAD (save_ptid));
c906108c
SS
369 }
370
28439f5e 371 beneath->to_resume (beneath, ptid, step, signo);
c906108c
SS
372
373 do_cleanups (old_chain);
374}
375
2689673f 376/* Wait for any threads to stop. We may have to convert PTID from a
8d027a04 377 thread ID to an LWP ID, and vice versa on the way out. */
c906108c 378
39f77062 379static ptid_t
117de6a9 380sol_thread_wait (struct target_ops *ops,
47608cb1 381 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
c906108c 382{
39f77062
KB
383 ptid_t rtnval;
384 ptid_t save_ptid;
28439f5e 385 struct target_ops *beneath = find_target_beneath (ops);
c906108c
SS
386 struct cleanup *old_chain;
387
39f77062
KB
388 save_ptid = inferior_ptid;
389 old_chain = save_inferior_ptid ();
c906108c 390
39f77062
KB
391 inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
392 if (PIDGET (inferior_ptid) == -1)
393 inferior_ptid = procfs_first_available ();
c906108c 394
39f77062 395 if (PIDGET (ptid) != -1)
c906108c 396 {
39f77062 397 ptid_t save_ptid = ptid;
c906108c 398
39f77062 399 ptid = thread_to_lwp (ptid, -2);
8d027a04 400 if (PIDGET (ptid) == -2) /* Inactive thread. */
8a3fe4f8 401 error (_("This version of Solaris can't start inactive threads."));
39f77062 402 if (info_verbose && PIDGET (ptid) == -1)
8a3fe4f8 403 warning (_("Specified thread %ld seems to have terminated"),
39f77062 404 GET_THREAD (save_ptid));
c906108c
SS
405 }
406
47608cb1 407 rtnval = beneath->to_wait (beneath, ptid, ourstatus, options);
c906108c
SS
408
409 if (ourstatus->kind != TARGET_WAITKIND_EXITED)
410 {
8d027a04 411 /* Map the LWP of interest back to the appropriate thread ID. */
c906108c 412 rtnval = lwp_to_thread (rtnval);
39f77062
KB
413 if (PIDGET (rtnval) == -1)
414 rtnval = save_ptid;
c906108c 415
8d027a04 416 /* See if we have a new thread. */
c906108c 417 if (is_thread (rtnval)
39f77062 418 && !ptid_equal (rtnval, save_ptid)
2689673f
PA
419 && (!in_thread_list (rtnval)
420 || is_exited (rtnval)))
93815fbf 421 add_thread (rtnval);
c906108c
SS
422 }
423
8d027a04
MK
424 /* During process initialization, we may get here without the thread
425 package being initialized, since that can only happen after we've
426 found the shared libs. */
c906108c
SS
427
428 do_cleanups (old_chain);
429
430 return rtnval;
431}
432
433static void
28439f5e
PA
434sol_thread_fetch_registers (struct target_ops *ops,
435 struct regcache *regcache, int regnum)
c906108c
SS
436{
437 thread_t thread;
438 td_thrhandle_t thandle;
439 td_err_e val;
440 prgregset_t gregset;
441 prfpregset_t fpregset;
e71c308d
DJ
442 gdb_gregset_t *gregset_p = &gregset;
443 gdb_fpregset_t *fpregset_p = &fpregset;
28439f5e 444 struct target_ops *beneath = find_target_beneath (ops);
e71c308d 445
c906108c
SS
446#if 0
447 int xregsize;
448 caddr_t xregset;
449#endif
450
39f77062 451 if (!is_thread (inferior_ptid))
8d027a04 452 {
28439f5e
PA
453 /* It's an LWP; pass the request on to the layer beneath. */
454 beneath->to_fetch_registers (beneath, regcache, regnum);
c906108c
SS
455 return;
456 }
457
8d027a04 458 /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t. */
39f77062 459 thread = GET_THREAD (inferior_ptid);
c906108c 460 if (thread == 0)
8a3fe4f8 461 error (_("sol_thread_fetch_registers: thread == 0"));
c906108c
SS
462
463 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
464 if (val != TD_OK)
8a3fe4f8 465 error (_("sol_thread_fetch_registers: td_ta_map_id2thr: %s"),
c906108c
SS
466 td_err_string (val));
467
8d027a04 468 /* Get the general-purpose registers. */
c906108c
SS
469
470 val = p_td_thr_getgregs (&thandle, gregset);
8d027a04 471 if (val != TD_OK && val != TD_PARTIALREG)
8a3fe4f8 472 error (_("sol_thread_fetch_registers: td_thr_getgregs %s"),
c906108c
SS
473 td_err_string (val));
474
8d027a04
MK
475 /* For SPARC, TD_PARTIALREG means that only %i0...%i7, %l0..%l7, %pc
476 and %sp are saved (by a thread context switch). */
c906108c 477
8d027a04 478 /* And, now the floating-point registers. */
c906108c
SS
479
480 val = p_td_thr_getfpregs (&thandle, &fpregset);
8d027a04 481 if (val != TD_OK && val != TD_NOFPREGS)
8a3fe4f8 482 error (_("sol_thread_fetch_registers: td_thr_getfpregs %s"),
c906108c
SS
483 td_err_string (val));
484
8d027a04
MK
485 /* Note that we must call supply_gregset and supply_fpregset *after*
486 calling the td routines because the td routines call ps_lget*
487 which affect the values stored in the registers array. */
c906108c 488
e71c308d
DJ
489 supply_gregset (regcache, (const gdb_gregset_t *) gregset_p);
490 supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset_p);
c906108c
SS
491
492#if 0
8d027a04 493 /* FIXME: libthread_db doesn't seem to handle this right. */
c906108c
SS
494 val = td_thr_getxregsize (&thandle, &xregsize);
495 if (val != TD_OK && val != TD_NOXREGS)
8a3fe4f8 496 error (_("sol_thread_fetch_registers: td_thr_getxregsize %s"),
c906108c
SS
497 td_err_string (val));
498
499 if (val == TD_OK)
500 {
501 xregset = alloca (xregsize);
502 val = td_thr_getxregs (&thandle, xregset);
503 if (val != TD_OK)
8a3fe4f8 504 error (_("sol_thread_fetch_registers: td_thr_getxregs %s"),
c906108c
SS
505 td_err_string (val));
506 }
507#endif
508}
509
510static void
28439f5e
PA
511sol_thread_store_registers (struct target_ops *ops,
512 struct regcache *regcache, int regnum)
c906108c
SS
513{
514 thread_t thread;
515 td_thrhandle_t thandle;
516 td_err_e val;
8d027a04 517 prgregset_t gregset;
c906108c
SS
518 prfpregset_t fpregset;
519#if 0
520 int xregsize;
521 caddr_t xregset;
522#endif
523
39f77062 524 if (!is_thread (inferior_ptid))
8d027a04 525 {
28439f5e
PA
526 struct target_ops *beneath = find_target_beneath (ops);
527
528 /* It's an LWP; pass the request on to the layer beneath. */
529 beneath->to_store_registers (beneath, regcache, regnum);
c906108c
SS
530 return;
531 }
532
8d027a04 533 /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t. */
39f77062 534 thread = GET_THREAD (inferior_ptid);
c906108c
SS
535
536 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
537 if (val != TD_OK)
8a3fe4f8 538 error (_("sol_thread_store_registers: td_ta_map_id2thr %s"),
c906108c
SS
539 td_err_string (val));
540
8d027a04
MK
541 if (regnum != -1)
542 {
543 /* Not writing all the registers. */
87232496 544 char old_value[MAX_REGISTER_SIZE];
6034ae49 545
87232496 546 /* Save new register value. */
56be3814 547 regcache_raw_collect (regcache, regnum, old_value);
c906108c 548
c60c0f5f 549 val = p_td_thr_getgregs (&thandle, gregset);
c906108c 550 if (val != TD_OK)
8a3fe4f8 551 error (_("sol_thread_store_registers: td_thr_getgregs %s"),
c906108c
SS
552 td_err_string (val));
553 val = p_td_thr_getfpregs (&thandle, &fpregset);
554 if (val != TD_OK)
8a3fe4f8 555 error (_("sol_thread_store_registers: td_thr_getfpregs %s"),
c906108c
SS
556 td_err_string (val));
557
87232496 558 /* Restore new register value. */
56be3814 559 regcache_raw_supply (regcache, regnum, old_value);
c906108c
SS
560
561#if 0
8d027a04 562 /* FIXME: libthread_db doesn't seem to handle this right. */
c906108c
SS
563 val = td_thr_getxregsize (&thandle, &xregsize);
564 if (val != TD_OK && val != TD_NOXREGS)
8a3fe4f8 565 error (_("sol_thread_store_registers: td_thr_getxregsize %s"),
c906108c
SS
566 td_err_string (val));
567
568 if (val == TD_OK)
569 {
570 xregset = alloca (xregsize);
571 val = td_thr_getxregs (&thandle, xregset);
572 if (val != TD_OK)
8a3fe4f8 573 error (_("sol_thread_store_registers: td_thr_getxregs %s"),
c906108c
SS
574 td_err_string (val));
575 }
576#endif
577 }
578
56be3814
UW
579 fill_gregset (regcache, (gdb_gregset_t *) &gregset, regnum);
580 fill_fpregset (regcache, (gdb_fpregset_t *) &fpregset, regnum);
c906108c 581
c60c0f5f 582 val = p_td_thr_setgregs (&thandle, gregset);
c906108c 583 if (val != TD_OK)
8a3fe4f8 584 error (_("sol_thread_store_registers: td_thr_setgregs %s"),
c906108c
SS
585 td_err_string (val));
586 val = p_td_thr_setfpregs (&thandle, &fpregset);
587 if (val != TD_OK)
8a3fe4f8 588 error (_("sol_thread_store_registers: td_thr_setfpregs %s"),
c906108c
SS
589 td_err_string (val));
590
591#if 0
8d027a04 592 /* FIXME: libthread_db doesn't seem to handle this right. */
c906108c
SS
593 val = td_thr_getxregsize (&thandle, &xregsize);
594 if (val != TD_OK && val != TD_NOXREGS)
8a3fe4f8 595 error (_("sol_thread_store_registers: td_thr_getxregsize %s"),
c906108c
SS
596 td_err_string (val));
597
8d027a04
MK
598 /* ??? Should probably do something about writing the xregs here,
599 but what are they? */
c906108c
SS
600#endif
601}
602
8d027a04
MK
603/* Perform partial transfers on OBJECT. See target_read_partial and
604 target_write_partial for details of each variant. One, and only
605 one, of readbuf or writebuf must be non-NULL. */
6034ae49
RM
606
607static LONGEST
608sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
b6958cfb
MK
609 const char *annex, gdb_byte *readbuf,
610 const gdb_byte *writebuf,
611 ULONGEST offset, LONGEST len)
6034ae49
RM
612{
613 int retval;
614 struct cleanup *old_chain;
28439f5e 615 struct target_ops *beneath = find_target_beneath (ops);
6034ae49
RM
616
617 old_chain = save_inferior_ptid ();
618
8d027a04
MK
619 if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
620 {
621 /* It's either a thread or an LWP that isn't alive. Any live
622 LWP will do so use the first available.
623
624 NOTE: We don't need to call switch_to_thread; we're just
625 reading memory. */
626 inferior_ptid = procfs_first_available ();
627 }
6034ae49 628
28439f5e
PA
629 retval = beneath->to_xfer_partial (beneath, object, annex,
630 readbuf, writebuf, offset, len);
6034ae49
RM
631
632 do_cleanups (old_chain);
633
634 return retval;
635}
636
c906108c 637static void
28439f5e 638check_for_thread_db (void)
c906108c 639{
28439f5e
PA
640 td_err_e err;
641 ptid_t ptid;
c906108c 642
28439f5e
PA
643 /* Do nothing if we couldn't load libthread_db.so.1. */
644 if (p_td_ta_new == NULL)
645 return;
c906108c 646
28439f5e
PA
647 if (sol_thread_active)
648 /* Nothing to do. The thread library was already detected and the
649 target vector was already activated. */
650 return;
c906108c 651
28439f5e
PA
652 /* Now, initialize libthread_db. This needs to be done after the
653 shared libraries are located because it needs information from
654 the user's thread library. */
c906108c 655
28439f5e
PA
656 err = p_td_init ();
657 if (err != TD_OK)
658 {
659 warning (_("sol_thread_new_objfile: td_init: %s"), td_err_string (err));
660 return;
661 }
c906108c 662
28439f5e
PA
663 /* Now attempt to open a connection to the thread library. */
664 err = p_td_ta_new (&main_ph, &main_ta);
665 switch (err)
c906108c 666 {
28439f5e
PA
667 case TD_NOLIBTHREAD:
668 /* No thread library was detected. */
669 break;
2689673f 670
28439f5e
PA
671 case TD_OK:
672 printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
c906108c 673
28439f5e 674 /* The thread library was detected. Activate the sol_thread target. */
c906108c 675 push_target (&sol_thread_ops);
28439f5e 676 sol_thread_active = 1;
c906108c 677
28439f5e 678 main_ph.ptid = inferior_ptid; /* Save for xfer_memory. */
2689673f
PA
679 ptid = lwp_to_thread (inferior_ptid);
680 if (PIDGET (ptid) != -1)
28439f5e
PA
681 inferior_ptid = ptid;
682
683 target_find_new_threads ();
684 break;
685
686 default:
687 warning (_("Cannot initialize thread debugging library: %s"),
688 td_err_string (err));
689 break;
c906108c
SS
690 }
691}
692
8d027a04
MK
693/* This routine is called whenever a new symbol table is read in, or
694 when all symbol tables are removed. libthread_db can only be
695 initialized when it finds the right variables in libthread.so.
696 Since it's a shared library, those variables don't show up until
06d3b283 697 the library gets mapped and the symbol table is read in. */
c906108c 698
06d3b283 699static void
fba45db2 700sol_thread_new_objfile (struct objfile *objfile)
c906108c 701{
28439f5e
PA
702 if (objfile != NULL)
703 check_for_thread_db ();
c906108c
SS
704}
705
706/* Clean up after the inferior dies. */
707
708static void
136d6dae 709sol_thread_mourn_inferior (struct target_ops *ops)
c906108c 710{
28439f5e
PA
711 struct target_ops *beneath = find_target_beneath (ops);
712
2689673f 713 sol_thread_active = 0;
c906108c 714
28439f5e 715 unpush_target (ops);
c906108c 716
28439f5e 717 beneath->to_mourn_inferior (beneath);
c906108c
SS
718}
719
8d027a04
MK
720/* Return true if PTID is still active in the inferior. */
721
c906108c 722static int
28439f5e 723sol_thread_alive (struct target_ops *ops, ptid_t ptid)
c906108c 724{
8d027a04 725 if (is_thread (ptid))
c906108c 726 {
8d027a04 727 /* It's a (user-level) thread. */
c906108c
SS
728 td_err_e val;
729 td_thrhandle_t th;
39f77062 730 int pid;
c906108c 731
39f77062 732 pid = GET_THREAD (ptid);
c906108c 733 if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
8d027a04 734 return 0; /* Thread not found. */
c906108c 735 if ((val = p_td_thr_validate (&th)) != TD_OK)
8d027a04
MK
736 return 0; /* Thread not valid. */
737 return 1; /* Known thread. */
c906108c 738 }
c5aa993b 739 else
c906108c 740 {
28439f5e
PA
741 struct target_ops *beneath = find_target_beneath (ops);
742
743 /* It's an LPW; pass the request on to the layer below. */
744 return beneath->to_thread_alive (beneath, ptid);
c906108c
SS
745 }
746}
747
c906108c 748\f
8d027a04
MK
749/* These routines implement the lower half of the thread_db interface,
750 i.e. the ps_* routines. */
c906108c 751
8d027a04
MK
752/* Various versions of <proc_service.h> have slightly different
753 function prototypes. In particular, we have
c906108c 754
c5aa993b
JM
755 NEWER OLDER
756 struct ps_prochandle * const struct ps_prochandle *
757 void* char*
8d027a04
MK
758 const void* char*
759 int size_t
c906108c 760
8d027a04
MK
761 Which one you have depends on the Solaris version and what patches
762 you've applied. On the theory that there are only two major
763 variants, we have configure check the prototype of ps_pdwrite (),
c378eb4e 764 and use that info to make appropriate typedefs here. */
c906108c
SS
765
766#ifdef PROC_SERVICE_IS_OLD
c5aa993b
JM
767typedef const struct ps_prochandle *gdb_ps_prochandle_t;
768typedef char *gdb_ps_read_buf_t;
769typedef char *gdb_ps_write_buf_t;
c906108c 770typedef int gdb_ps_size_t;
76e1ee85 771typedef psaddr_t gdb_ps_addr_t;
c906108c 772#else
c5aa993b
JM
773typedef struct ps_prochandle *gdb_ps_prochandle_t;
774typedef void *gdb_ps_read_buf_t;
775typedef const void *gdb_ps_write_buf_t;
c906108c 776typedef size_t gdb_ps_size_t;
291dcb3e 777typedef psaddr_t gdb_ps_addr_t;
c906108c
SS
778#endif
779
8d027a04
MK
780/* The next four routines are called by libthread_db to tell us to
781 stop and stop a particular process or lwp. Since GDB ensures that
782 these are all stopped by the time we call anything in thread_db,
783 these routines need to do nothing. */
c906108c 784
8d027a04 785/* Process stop. */
d4f3574e 786
c906108c
SS
787ps_err_e
788ps_pstop (gdb_ps_prochandle_t ph)
789{
790 return PS_OK;
791}
792
8d027a04 793/* Process continue. */
d4f3574e 794
c906108c
SS
795ps_err_e
796ps_pcontinue (gdb_ps_prochandle_t ph)
797{
798 return PS_OK;
799}
800
8d027a04 801/* LWP stop. */
d4f3574e 802
c906108c
SS
803ps_err_e
804ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
805{
806 return PS_OK;
807}
808
8d027a04 809/* LWP continue. */
d4f3574e 810
c906108c
SS
811ps_err_e
812ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
813{
814 return PS_OK;
815}
816
d4f3574e
SS
817/* Looks up the symbol LD_SYMBOL_NAME in the debugger's symbol table. */
818
c906108c
SS
819ps_err_e
820ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name,
8d027a04 821 const char *ld_symbol_name, gdb_ps_addr_t *ld_symbol_addr)
c906108c
SS
822{
823 struct minimal_symbol *ms;
824
825 ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
c906108c
SS
826 if (!ms)
827 return PS_NOSYM;
828
829 *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
c906108c
SS
830 return PS_OK;
831}
832
833/* Common routine for reading and writing memory. */
834
835static ps_err_e
291dcb3e 836rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr,
c906108c
SS
837 char *buf, int size)
838{
28439f5e 839 int ret;
c906108c
SS
840 struct cleanup *old_chain;
841
39f77062 842 old_chain = save_inferior_ptid ();
c906108c 843
8d027a04
MK
844 if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
845 {
846 /* It's either a thread or an LWP that isn't alive. Any live
847 LWP will do so use the first available.
848
849 NOTE: We don't need to call switch_to_thread; we're just
850 reading memory. */
851 inferior_ptid = procfs_first_available ();
852 }
c906108c 853
23e04971
MS
854#if defined (__sparcv9)
855 /* For Sparc64 cross Sparc32, make sure the address has not been
856 accidentally sign-extended (or whatever) to beyond 32 bits. */
359431fb 857 if (bfd_get_arch_size (exec_bfd) == 32)
23e04971
MS
858 addr &= 0xffffffff;
859#endif
860
28439f5e
PA
861 if (dowrite)
862 ret = target_write_memory (addr, buf, size);
863 else
864 ret = target_read_memory (addr, buf, size);
c906108c
SS
865
866 do_cleanups (old_chain);
867
28439f5e 868 return (ret == 0 ? PS_OK : PS_ERR);
c906108c
SS
869}
870
d4f3574e
SS
871/* Copies SIZE bytes from target process .data segment to debugger memory. */
872
c906108c 873ps_err_e
291dcb3e 874ps_pdread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
875 gdb_ps_read_buf_t buf, gdb_ps_size_t size)
876{
877 return rw_common (0, ph, addr, buf, size);
878}
879
d4f3574e
SS
880/* Copies SIZE bytes from debugger memory .data segment to target process. */
881
c906108c 882ps_err_e
291dcb3e 883ps_pdwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
884 gdb_ps_write_buf_t buf, gdb_ps_size_t size)
885{
c5aa993b 886 return rw_common (1, ph, addr, (char *) buf, size);
c906108c
SS
887}
888
d4f3574e
SS
889/* Copies SIZE bytes from target process .text segment to debugger memory. */
890
c906108c 891ps_err_e
291dcb3e 892ps_ptread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
893 gdb_ps_read_buf_t buf, gdb_ps_size_t size)
894{
895 return rw_common (0, ph, addr, buf, size);
896}
897
d4f3574e
SS
898/* Copies SIZE bytes from debugger memory .text segment to target process. */
899
c906108c 900ps_err_e
291dcb3e 901ps_ptwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
902 gdb_ps_write_buf_t buf, gdb_ps_size_t size)
903{
c5aa993b 904 return rw_common (1, ph, addr, (char *) buf, size);
c906108c
SS
905}
906
8d027a04 907/* Get general-purpose registers for LWP. */
c906108c
SS
908
909ps_err_e
8d027a04 910ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
c906108c
SS
911{
912 struct cleanup *old_chain;
594f7785 913 struct regcache *regcache;
c906108c 914
39f77062 915 old_chain = save_inferior_ptid ();
c906108c 916
39f77062 917 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
c2250ad1 918 regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
c5aa993b 919
28439f5e 920 target_fetch_registers (regcache, -1);
594f7785 921 fill_gregset (regcache, (gdb_gregset_t *) gregset, -1);
c906108c
SS
922
923 do_cleanups (old_chain);
924
925 return PS_OK;
926}
927
8d027a04 928/* Set general-purpose registers for LWP. */
c906108c
SS
929
930ps_err_e
931ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
932 const prgregset_t gregset)
933{
934 struct cleanup *old_chain;
594f7785 935 struct regcache *regcache;
c906108c 936
39f77062 937 old_chain = save_inferior_ptid ();
c906108c 938
39f77062 939 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
c2250ad1 940 regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
c5aa993b 941
594f7785 942 supply_gregset (regcache, (const gdb_gregset_t *) gregset);
28439f5e 943 target_store_registers (regcache, -1);
c906108c
SS
944
945 do_cleanups (old_chain);
946
947 return PS_OK;
948}
949
d4f3574e
SS
950/* Log a message (sends to gdb_stderr). */
951
c906108c 952void
8d027a04 953ps_plog (const char *fmt, ...)
c906108c
SS
954{
955 va_list args;
956
957 va_start (args, fmt);
958
959 vfprintf_filtered (gdb_stderr, fmt, args);
960}
961
962/* Get size of extra register set. Currently a noop. */
963
964ps_err_e
965ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
966{
967#if 0
968 int lwp_fd;
969 int regsize;
970 ps_err_e val;
971
972 val = get_lwp_fd (ph, lwpid, &lwp_fd);
973 if (val != PS_OK)
974 return val;
975
976 if (ioctl (lwp_fd, PIOCGXREGSIZE, &regsize))
977 {
978 if (errno == EINVAL)
979 return PS_NOFREGS; /* XXX Wrong code, but this is the closest
980 thing in proc_service.h */
981
982 print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
983 return PS_ERR;
984 }
985#endif
986
987 return PS_OK;
988}
989
990/* Get extra register set. Currently a noop. */
991
992ps_err_e
993ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
994{
995#if 0
996 int lwp_fd;
997 ps_err_e val;
998
999 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1000 if (val != PS_OK)
1001 return val;
1002
1003 if (ioctl (lwp_fd, PIOCGXREG, xregset))
1004 {
1005 print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
1006 return PS_ERR;
1007 }
1008#endif
1009
1010 return PS_OK;
1011}
1012
1013/* Set extra register set. Currently a noop. */
1014
1015ps_err_e
1016ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
1017{
1018#if 0
1019 int lwp_fd;
1020 ps_err_e val;
1021
1022 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1023 if (val != PS_OK)
1024 return val;
1025
1026 if (ioctl (lwp_fd, PIOCSXREG, xregset))
1027 {
1028 print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
1029 return PS_ERR;
1030 }
1031#endif
1032
1033 return PS_OK;
1034}
1035
8d027a04 1036/* Get floating-point registers for LWP. */
c906108c
SS
1037
1038ps_err_e
1039ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
8d027a04 1040 prfpregset_t *fpregset)
c906108c
SS
1041{
1042 struct cleanup *old_chain;
594f7785 1043 struct regcache *regcache;
c906108c 1044
39f77062 1045 old_chain = save_inferior_ptid ();
c906108c 1046
39f77062 1047 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
c2250ad1 1048 regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
c906108c 1049
28439f5e 1050 target_fetch_registers (regcache, -1);
594f7785 1051 fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1);
c906108c
SS
1052
1053 do_cleanups (old_chain);
1054
1055 return PS_OK;
1056}
1057
c378eb4e 1058/* Set floating-point regs for LWP. */
c906108c
SS
1059
1060ps_err_e
1061ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
c5aa993b 1062 const prfpregset_t * fpregset)
c906108c
SS
1063{
1064 struct cleanup *old_chain;
594f7785 1065 struct regcache *regcache;
c906108c 1066
39f77062 1067 old_chain = save_inferior_ptid ();
c906108c 1068
39f77062 1069 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
c2250ad1 1070 regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
c5aa993b 1071
594f7785 1072 supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset);
28439f5e 1073 target_store_registers (regcache, -1);
c906108c
SS
1074
1075 do_cleanups (old_chain);
1076
1077 return PS_OK;
1078}
1079
23715f29 1080#ifdef PR_MODEL_LP64
8d027a04
MK
1081/* Identify process as 32-bit or 64-bit. At the moment we're using
1082 BFD to do this. There might be a more Solaris-specific
1083 (e.g. procfs) method, but this ought to work. */
23e04971
MS
1084
1085ps_err_e
1086ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model)
1087{
1088 if (exec_bfd == 0)
a95ac8b6
PS
1089 *data_model = PR_MODEL_UNKNOWN;
1090 else if (bfd_get_arch_size (exec_bfd) == 32)
23e04971
MS
1091 *data_model = PR_MODEL_ILP32;
1092 else
1093 *data_model = PR_MODEL_LP64;
1094
1095 return PS_OK;
1096}
23715f29 1097#endif /* PR_MODEL_LP64 */
23e04971 1098
965b60ee 1099#if (defined(__i386__) || defined(__x86_64__)) && defined (sun)
c906108c 1100
965b60ee
JB
1101/* Reads the local descriptor table of a LWP.
1102
1103 This function is necessary on x86-solaris only. Without it, the loading
1104 of libthread_db would fail because of ps_lgetLDT being undefined. */
d4f3574e 1105
c906108c
SS
1106ps_err_e
1107ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1108 struct ssd *pldt)
1109{
8d027a04 1110 /* NOTE: only used on Solaris, therefore OK to refer to procfs.c. */
39f77062 1111 extern struct ssd *procfs_find_LDT_entry (ptid_t);
05e28a7b 1112 struct ssd *ret;
c906108c 1113
8d027a04
MK
1114 /* FIXME: can't I get the process ID from the prochandle or
1115 something? */
2f09097b 1116
39f77062 1117 if (PIDGET (inferior_ptid) <= 0 || lwpid <= 0)
2f09097b
ND
1118 return PS_BADLID;
1119
39f77062 1120 ret = procfs_find_LDT_entry (BUILD_LWP (lwpid, PIDGET (inferior_ptid)));
05e28a7b 1121 if (ret)
c906108c 1122 {
05e28a7b
AC
1123 memcpy (pldt, ret, sizeof (struct ssd));
1124 return PS_OK;
c906108c 1125 }
8d027a04
MK
1126 else
1127 /* LDT not found. */
c906108c 1128 return PS_ERR;
c5aa993b 1129}
965b60ee 1130#endif
c906108c 1131\f
8d027a04
MK
1132
1133/* Convert PTID to printable form. */
c906108c 1134
02f1df11 1135static char *
117de6a9 1136solaris_pid_to_str (struct target_ops *ops, ptid_t ptid)
c906108c
SS
1137{
1138 static char buf[100];
1139
39f77062 1140 if (is_thread (ptid))
c906108c 1141 {
39f77062 1142 ptid_t lwp;
c906108c 1143
39f77062 1144 lwp = thread_to_lwp (ptid, -2);
c906108c 1145
39f77062
KB
1146 if (PIDGET (lwp) == -1)
1147 sprintf (buf, "Thread %ld (defunct)", GET_THREAD (ptid));
1148 else if (PIDGET (lwp) != -2)
8d027a04
MK
1149 sprintf (buf, "Thread %ld (LWP %ld)",
1150 GET_THREAD (ptid), GET_LWP (lwp));
c906108c 1151 else
39f77062 1152 sprintf (buf, "Thread %ld ", GET_THREAD (ptid));
c906108c 1153 }
39f77062
KB
1154 else if (GET_LWP (ptid) != 0)
1155 sprintf (buf, "LWP %ld ", GET_LWP (ptid));
c906108c 1156 else
39f77062 1157 sprintf (buf, "process %d ", PIDGET (ptid));
c906108c
SS
1158
1159 return buf;
1160}
1161\f
1162
8d027a04
MK
1163/* Worker bee for find_new_threads. Callback function that gets
1164 called once per user-level thread (i.e. not for LWP's). */
c906108c
SS
1165
1166static int
fba45db2 1167sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
c906108c
SS
1168{
1169 td_err_e retval;
1170 td_thrinfo_t ti;
39f77062 1171 ptid_t ptid;
c906108c 1172
8d027a04
MK
1173 retval = p_td_thr_get_info (th, &ti);
1174 if (retval != TD_OK)
1175 return -1;
1176
39f77062 1177 ptid = BUILD_THREAD (ti.ti_tid, PIDGET (inferior_ptid));
2689673f 1178 if (!in_thread_list (ptid) || is_exited (ptid))
39f77062 1179 add_thread (ptid);
c906108c
SS
1180
1181 return 0;
1182}
1183
d4f3574e 1184static void
28439f5e 1185sol_find_new_threads (struct target_ops *ops)
c906108c 1186{
28439f5e 1187 struct target_ops *beneath = find_target_beneath (ops);
8d027a04
MK
1188
1189 /* First Find any new LWP's. */
28439f5e
PA
1190 if (beneath->to_find_new_threads != NULL)
1191 beneath->to_find_new_threads (beneath);
8d027a04
MK
1192
1193 /* Then find any new user-level threads. */
c5aa993b 1194 p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *) 0,
c906108c
SS
1195 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1196 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1197}
1198
8d027a04
MK
1199/* Worker bee for the "info sol-thread" command. This is a callback
1200 function that gets called once for each Solaris user-level thread
1201 (i.e. not for LWPs) in the inferior. Print anything interesting
1202 that we can think of. */
c906108c 1203
c5aa993b 1204static int
fba45db2 1205info_cb (const td_thrhandle_t *th, void *s)
c906108c
SS
1206{
1207 td_err_e ret;
1208 td_thrinfo_t ti;
c906108c 1209
8d027a04
MK
1210 ret = p_td_thr_get_info (th, &ti);
1211 if (ret == TD_OK)
c906108c 1212 {
c5aa993b
JM
1213 printf_filtered ("%s thread #%d, lwp %d, ",
1214 ti.ti_type == TD_THR_SYSTEM ? "system" : "user ",
c906108c 1215 ti.ti_tid, ti.ti_lid);
c5aa993b
JM
1216 switch (ti.ti_state)
1217 {
c906108c 1218 default:
c5aa993b
JM
1219 case TD_THR_UNKNOWN:
1220 printf_filtered ("<unknown state>");
1221 break;
1222 case TD_THR_STOPPED:
1223 printf_filtered ("(stopped)");
1224 break;
1225 case TD_THR_RUN:
1226 printf_filtered ("(run) ");
1227 break;
1228 case TD_THR_ACTIVE:
1229 printf_filtered ("(active) ");
1230 break;
1231 case TD_THR_ZOMBIE:
1232 printf_filtered ("(zombie) ");
1233 break;
1234 case TD_THR_SLEEP:
1235 printf_filtered ("(asleep) ");
1236 break;
1237 case TD_THR_STOPPED_ASLEEP:
1238 printf_filtered ("(stopped asleep)");
1239 break;
1240 }
8d027a04 1241 /* Print thr_create start function. */
c906108c 1242 if (ti.ti_startfunc != 0)
4ce44c66
JM
1243 {
1244 struct minimal_symbol *msym;
1245 msym = lookup_minimal_symbol_by_pc (ti.ti_startfunc);
1246 if (msym)
8d027a04 1247 printf_filtered (" startfunc: %s\n",
3567439c 1248 SYMBOL_PRINT_NAME (msym));
4ce44c66 1249 else
5af949e3
UW
1250 printf_filtered (" startfunc: %s\n",
1251 paddress (target_gdbarch, ti.ti_startfunc));
4ce44c66 1252 }
c906108c 1253
8d027a04 1254 /* If thread is asleep, print function that went to sleep. */
c906108c 1255 if (ti.ti_state == TD_THR_SLEEP)
4ce44c66
JM
1256 {
1257 struct minimal_symbol *msym;
1258 msym = lookup_minimal_symbol_by_pc (ti.ti_pc);
1259 if (msym)
8d027a04 1260 printf_filtered (" - Sleep func: %s\n",
3567439c 1261 SYMBOL_PRINT_NAME (msym));
4ce44c66 1262 else
5af949e3
UW
1263 printf_filtered (" - Sleep func: %s\n",
1264 paddress (target_gdbarch, ti.ti_startfunc));
4ce44c66 1265 }
c906108c 1266
8d027a04 1267 /* Wrap up line, if necessary. */
c906108c 1268 if (ti.ti_state != TD_THR_SLEEP && ti.ti_startfunc == 0)
c378eb4e 1269 printf_filtered ("\n"); /* don't you hate counting newlines? */
c906108c
SS
1270 }
1271 else
8a3fe4f8 1272 warning (_("info sol-thread: failed to get info for thread."));
c906108c 1273
c5aa993b 1274 return 0;
c906108c
SS
1275}
1276
8d027a04
MK
1277/* List some state about each Solaris user-level thread in the
1278 inferior. */
c906108c
SS
1279
1280static void
fba45db2 1281info_solthreads (char *args, int from_tty)
c906108c 1282{
c5aa993b 1283 p_td_ta_thr_iter (main_ta, info_cb, args,
c906108c
SS
1284 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1285 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1286}
c906108c 1287
3caf13b4
JB
1288/* Callback routine used to find a thread based on the TID part of
1289 its PTID. */
1290
1291static int
1292thread_db_find_thread_from_tid (struct thread_info *thread, void *data)
1293{
1294 long *tid = (long *) data;
1295
1296 if (ptid_get_tid (thread->ptid) == *tid)
1297 return 1;
1298
1299 return 0;
1300}
1301
1302static ptid_t
1303sol_get_ada_task_ptid (long lwp, long thread)
1304{
1305 struct thread_info *thread_info =
1306 iterate_over_threads (thread_db_find_thread_from_tid, &thread);
1307
1308 if (thread_info == NULL)
1309 {
1310 /* The list of threads is probably not up to date. Find any
1311 thread that is missing from the list, and try again. */
1312 sol_find_new_threads (&current_target);
1313 thread_info = iterate_over_threads (thread_db_find_thread_from_tid,
1314 &thread);
1315 }
1316
1317 gdb_assert (thread_info != NULL);
1318
1319 return (thread_info->ptid);
1320}
1321
c906108c 1322static void
fba45db2 1323init_sol_thread_ops (void)
c906108c
SS
1324{
1325 sol_thread_ops.to_shortname = "solaris-threads";
1326 sol_thread_ops.to_longname = "Solaris threads and pthread.";
1327 sol_thread_ops.to_doc = "Solaris threads and pthread support.";
c906108c
SS
1328 sol_thread_ops.to_detach = sol_thread_detach;
1329 sol_thread_ops.to_resume = sol_thread_resume;
1330 sol_thread_ops.to_wait = sol_thread_wait;
1331 sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
1332 sol_thread_ops.to_store_registers = sol_thread_store_registers;
6034ae49 1333 sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial;
c906108c 1334 sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
c906108c 1335 sol_thread_ops.to_thread_alive = sol_thread_alive;
ed9a39eb 1336 sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
b83266a0 1337 sol_thread_ops.to_find_new_threads = sol_find_new_threads;
28439f5e 1338 sol_thread_ops.to_stratum = thread_stratum;
3caf13b4 1339 sol_thread_ops.to_get_ada_task_ptid = sol_get_ada_task_ptid;
c906108c
SS
1340 sol_thread_ops.to_magic = OPS_MAGIC;
1341}
1342
02f1df11
JB
1343/* Silence -Wmissing-prototypes. */
1344extern void _initialize_sol_thread (void);
1345
c906108c 1346void
fba45db2 1347_initialize_sol_thread (void)
c906108c
SS
1348{
1349 void *dlhandle;
1350
1351 init_sol_thread_ops ();
c906108c
SS
1352
1353 dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
1354 if (!dlhandle)
1355 goto die;
1356
1357#define resolve(X) \
1358 if (!(p_##X = dlsym (dlhandle, #X))) \
1359 goto die;
1360
1361 resolve (td_log);
1362 resolve (td_ta_new);
1363 resolve (td_ta_delete);
1364 resolve (td_init);
1365 resolve (td_ta_get_ph);
1366 resolve (td_ta_get_nthreads);
1367 resolve (td_ta_tsd_iter);
1368 resolve (td_ta_thr_iter);
1369 resolve (td_thr_validate);
1370 resolve (td_thr_tsd);
1371 resolve (td_thr_get_info);
1372 resolve (td_thr_getfpregs);
1373 resolve (td_thr_getxregsize);
1374 resolve (td_thr_getxregs);
1375 resolve (td_thr_sigsetmask);
1376 resolve (td_thr_setprio);
1377 resolve (td_thr_setsigpending);
1378 resolve (td_thr_setfpregs);
1379 resolve (td_thr_setxregs);
1380 resolve (td_ta_map_id2thr);
1381 resolve (td_ta_map_lwp2thr);
1382 resolve (td_thr_getgregs);
1383 resolve (td_thr_setgregs);
1384
1385 add_target (&sol_thread_ops);
1386
c5aa993b 1387 add_cmd ("sol-threads", class_maintenance, info_solthreads,
1a966eab 1388 _("Show info on Solaris user threads."), &maintenanceinfolist);
c906108c 1389
8d027a04 1390 /* Hook into new_objfile notification. */
06d3b283 1391 observer_attach_new_objfile (sol_thread_new_objfile);
c906108c
SS
1392 return;
1393
8d027a04
MK
1394 die:
1395 fprintf_unfiltered (gdb_stderr, "\
1396[GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
c906108c
SS
1397
1398 if (dlhandle)
1399 dlclose (dlhandle);
1400
c906108c
SS
1401 return;
1402}
This page took 1.376644 seconds and 4 git commands to generate.