* symfile.h (struct sym_fns): Delete member "sym_flavour".
[deliverable/binutils-gdb.git] / gdb / sol-thread.c
CommitLineData
8d027a04
MK
1/* Solaris threads debugging interface.
2
28e7fd62 3 Copyright (C) 1996-2013 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
8c042590
PM
199 xsnprintf (buf, sizeof (buf), "Unknown libthread_db error code: %d",
200 errcode);
c906108c
SS
201
202 return buf;
203}
c906108c 204
b021a221 205/* Return the libthread_db state string assicoated with STATECODE.
8d027a04 206 If STATECODE is unknown, return an appropriate message. */
c906108c
SS
207
208static char *
fba45db2 209td_state_string (td_thr_state_e statecode)
c906108c 210{
8d027a04 211 static struct string_map td_thr_state_table[] =
c5aa993b 212 {
8d027a04
MK
213 { TD_THR_ANY_STATE, "any state" },
214 { TD_THR_UNKNOWN, "unknown" },
215 { TD_THR_STOPPED, "stopped" },
216 { TD_THR_RUN, "run" },
217 { TD_THR_ACTIVE, "active" },
218 { TD_THR_ZOMBIE, "zombie" },
219 { TD_THR_SLEEP, "sleep" },
220 { TD_THR_STOPPED_ASLEEP, "stopped asleep" }
c5aa993b 221 };
8d027a04
MK
222 const int td_thr_state_table_size =
223 sizeof td_thr_state_table / sizeof (struct string_map);
c906108c
SS
224 int i;
225 static char buf[50];
226
227 for (i = 0; i < td_thr_state_table_size; i++)
228 if (td_thr_state_table[i].num == statecode)
229 return td_thr_state_table[i].str;
c5aa993b 230
8c042590
PM
231 xsnprintf (buf, sizeof (buf), "Unknown libthread_db state code: %d",
232 statecode);
c906108c
SS
233
234 return buf;
235}
236\f
c906108c 237
8d027a04
MK
238/* Convert a POSIX or Solaris thread ID into a LWP ID. If THREAD_ID
239 doesn't exist, that's an error. If it's an inactive thread, return
2689673f 240 DEFAULT_LWP.
c906108c 241
8d027a04 242 NOTE: This function probably shouldn't call error(). */
c906108c 243
39f77062
KB
244static ptid_t
245thread_to_lwp (ptid_t thread_id, int default_lwp)
c906108c
SS
246{
247 td_thrinfo_t ti;
248 td_thrhandle_t th;
249 td_err_e val;
250
251 if (is_lwp (thread_id))
8d027a04 252 return thread_id; /* It's already an LWP ID. */
c906108c 253
8d027a04 254 /* It's a thread. Convert to LWP. */
c906108c
SS
255
256 val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
257 if (val == TD_NOTHR)
8d027a04 258 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 259 else if (val != TD_OK)
8a3fe4f8 260 error (_("thread_to_lwp: td_ta_map_id2thr %s"), td_err_string (val));
c906108c
SS
261
262 val = p_td_thr_get_info (&th, &ti);
263 if (val == TD_NOTHR)
8d027a04 264 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 265 else if (val != TD_OK)
8a3fe4f8 266 error (_("thread_to_lwp: td_thr_get_info: %s"), td_err_string (val));
c906108c
SS
267
268 if (ti.ti_state != TD_THR_ACTIVE)
269 {
270 if (default_lwp != -1)
39f77062 271 return pid_to_ptid (default_lwp);
8a3fe4f8 272 error (_("thread_to_lwp: thread state not active: %s"),
c906108c
SS
273 td_state_string (ti.ti_state));
274 }
275
276 return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
277}
c906108c 278
8d027a04
MK
279/* Convert an LWP ID into a POSIX or Solaris thread ID. If LWP_ID
280 doesn't exists, that's an error.
c906108c 281
8d027a04 282 NOTE: This function probably shouldn't call error(). */
c906108c 283
39f77062
KB
284static ptid_t
285lwp_to_thread (ptid_t lwp)
c906108c
SS
286{
287 td_thrinfo_t ti;
288 td_thrhandle_t th;
289 td_err_e val;
290
291 if (is_thread (lwp))
8d027a04 292 return lwp; /* It's already a thread ID. */
c906108c 293
8d027a04 294 /* It's an LWP. Convert it to a thread ID. */
c906108c 295
28439f5e 296 if (!target_thread_alive (lwp))
8d027a04 297 return pid_to_ptid (-1); /* Must be a defunct LPW. */
c906108c
SS
298
299 val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
300 if (val == TD_NOTHR)
8d027a04 301 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 302 else if (val != TD_OK)
8a3fe4f8 303 error (_("lwp_to_thread: td_ta_map_lwp2thr: %s."), td_err_string (val));
c906108c
SS
304
305 val = p_td_thr_validate (&th);
306 if (val == TD_NOTHR)
8d027a04 307 return lwp; /* Unknown to libthread; just return LPW, */
c906108c 308 else if (val != TD_OK)
8a3fe4f8 309 error (_("lwp_to_thread: td_thr_validate: %s."), td_err_string (val));
c906108c
SS
310
311 val = p_td_thr_get_info (&th, &ti);
312 if (val == TD_NOTHR)
8d027a04 313 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 314 else if (val != TD_OK)
8a3fe4f8 315 error (_("lwp_to_thread: td_thr_get_info: %s."), td_err_string (val));
c906108c
SS
316
317 return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
318}
319\f
c906108c 320
8d027a04 321/* Most target vector functions from here on actually just pass
28439f5e
PA
322 through to the layer beneath, as they don't need to do anything
323 specific for threads. */
c906108c 324
8d027a04
MK
325/* Take a program previously attached to and detaches it. The program
326 resumes execution and will no longer stop on signals, etc. We'd
327 better not have left any breakpoints in the program or it'll die
328 when it hits one. For this to work, it may be necessary for the
329 process to have been previously attached. It *might* work if the
330 program was started via the normal ptrace (PTRACE_TRACEME). */
c906108c
SS
331
332static void
136d6dae 333sol_thread_detach (struct target_ops *ops, char *args, int from_tty)
c906108c 334{
28439f5e
PA
335 struct target_ops *beneath = find_target_beneath (ops);
336
2689673f 337 sol_thread_active = 0;
39f77062 338 inferior_ptid = pid_to_ptid (PIDGET (main_ph.ptid));
28439f5e
PA
339 unpush_target (ops);
340 beneath->to_detach (beneath, args, from_tty);
c906108c
SS
341}
342
8d027a04
MK
343/* Resume execution of process PTID. If STEP is nozero, then just
344 single step it. If SIGNAL is nonzero, restart it with that signal
345 activated. We may have to convert PTID from a thread ID to an LWP
346 ID for procfs. */
c906108c
SS
347
348static void
28439f5e 349sol_thread_resume (struct target_ops *ops,
2ea28649 350 ptid_t ptid, int step, enum gdb_signal signo)
c906108c
SS
351{
352 struct cleanup *old_chain;
28439f5e 353 struct target_ops *beneath = find_target_beneath (ops);
c906108c 354
39f77062 355 old_chain = save_inferior_ptid ();
c906108c 356
39f77062
KB
357 inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
358 if (PIDGET (inferior_ptid) == -1)
359 inferior_ptid = procfs_first_available ();
c906108c 360
39f77062 361 if (PIDGET (ptid) != -1)
c906108c 362 {
39f77062 363 ptid_t save_ptid = ptid;
c906108c 364
39f77062 365 ptid = thread_to_lwp (ptid, -2);
8d027a04 366 if (PIDGET (ptid) == -2) /* Inactive thread. */
8a3fe4f8 367 error (_("This version of Solaris can't start inactive threads."));
39f77062 368 if (info_verbose && PIDGET (ptid) == -1)
8a3fe4f8 369 warning (_("Specified thread %ld seems to have terminated"),
39f77062 370 GET_THREAD (save_ptid));
c906108c
SS
371 }
372
28439f5e 373 beneath->to_resume (beneath, ptid, step, signo);
c906108c
SS
374
375 do_cleanups (old_chain);
376}
377
2689673f 378/* Wait for any threads to stop. We may have to convert PTID from a
8d027a04 379 thread ID to an LWP ID, and vice versa on the way out. */
c906108c 380
39f77062 381static ptid_t
117de6a9 382sol_thread_wait (struct target_ops *ops,
47608cb1 383 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
c906108c 384{
39f77062
KB
385 ptid_t rtnval;
386 ptid_t save_ptid;
28439f5e 387 struct target_ops *beneath = find_target_beneath (ops);
c906108c
SS
388 struct cleanup *old_chain;
389
39f77062
KB
390 save_ptid = inferior_ptid;
391 old_chain = save_inferior_ptid ();
c906108c 392
39f77062
KB
393 inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
394 if (PIDGET (inferior_ptid) == -1)
395 inferior_ptid = procfs_first_available ();
c906108c 396
39f77062 397 if (PIDGET (ptid) != -1)
c906108c 398 {
39f77062 399 ptid_t save_ptid = ptid;
c906108c 400
39f77062 401 ptid = thread_to_lwp (ptid, -2);
8d027a04 402 if (PIDGET (ptid) == -2) /* Inactive thread. */
8a3fe4f8 403 error (_("This version of Solaris can't start inactive threads."));
39f77062 404 if (info_verbose && PIDGET (ptid) == -1)
8a3fe4f8 405 warning (_("Specified thread %ld seems to have terminated"),
39f77062 406 GET_THREAD (save_ptid));
c906108c
SS
407 }
408
47608cb1 409 rtnval = beneath->to_wait (beneath, ptid, ourstatus, options);
c906108c
SS
410
411 if (ourstatus->kind != TARGET_WAITKIND_EXITED)
412 {
8d027a04 413 /* Map the LWP of interest back to the appropriate thread ID. */
c906108c 414 rtnval = lwp_to_thread (rtnval);
39f77062
KB
415 if (PIDGET (rtnval) == -1)
416 rtnval = save_ptid;
c906108c 417
8d027a04 418 /* See if we have a new thread. */
c906108c 419 if (is_thread (rtnval)
39f77062 420 && !ptid_equal (rtnval, save_ptid)
2689673f
PA
421 && (!in_thread_list (rtnval)
422 || is_exited (rtnval)))
93815fbf 423 add_thread (rtnval);
c906108c
SS
424 }
425
8d027a04
MK
426 /* During process initialization, we may get here without the thread
427 package being initialized, since that can only happen after we've
428 found the shared libs. */
c906108c
SS
429
430 do_cleanups (old_chain);
431
432 return rtnval;
433}
434
435static void
28439f5e
PA
436sol_thread_fetch_registers (struct target_ops *ops,
437 struct regcache *regcache, int regnum)
c906108c
SS
438{
439 thread_t thread;
440 td_thrhandle_t thandle;
441 td_err_e val;
442 prgregset_t gregset;
443 prfpregset_t fpregset;
e71c308d
DJ
444 gdb_gregset_t *gregset_p = &gregset;
445 gdb_fpregset_t *fpregset_p = &fpregset;
28439f5e 446 struct target_ops *beneath = find_target_beneath (ops);
e71c308d 447
39f77062 448 if (!is_thread (inferior_ptid))
8d027a04 449 {
28439f5e
PA
450 /* It's an LWP; pass the request on to the layer beneath. */
451 beneath->to_fetch_registers (beneath, regcache, regnum);
c906108c
SS
452 return;
453 }
454
8d027a04 455 /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t. */
39f77062 456 thread = GET_THREAD (inferior_ptid);
c906108c 457 if (thread == 0)
8a3fe4f8 458 error (_("sol_thread_fetch_registers: thread == 0"));
c906108c
SS
459
460 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
461 if (val != TD_OK)
8a3fe4f8 462 error (_("sol_thread_fetch_registers: td_ta_map_id2thr: %s"),
c906108c
SS
463 td_err_string (val));
464
8d027a04 465 /* Get the general-purpose registers. */
c906108c
SS
466
467 val = p_td_thr_getgregs (&thandle, gregset);
8d027a04 468 if (val != TD_OK && val != TD_PARTIALREG)
8a3fe4f8 469 error (_("sol_thread_fetch_registers: td_thr_getgregs %s"),
c906108c
SS
470 td_err_string (val));
471
8d027a04
MK
472 /* For SPARC, TD_PARTIALREG means that only %i0...%i7, %l0..%l7, %pc
473 and %sp are saved (by a thread context switch). */
c906108c 474
8d027a04 475 /* And, now the floating-point registers. */
c906108c
SS
476
477 val = p_td_thr_getfpregs (&thandle, &fpregset);
8d027a04 478 if (val != TD_OK && val != TD_NOFPREGS)
8a3fe4f8 479 error (_("sol_thread_fetch_registers: td_thr_getfpregs %s"),
c906108c
SS
480 td_err_string (val));
481
8d027a04
MK
482 /* Note that we must call supply_gregset and supply_fpregset *after*
483 calling the td routines because the td routines call ps_lget*
484 which affect the values stored in the registers array. */
c906108c 485
e71c308d
DJ
486 supply_gregset (regcache, (const gdb_gregset_t *) gregset_p);
487 supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset_p);
c906108c
SS
488}
489
490static void
28439f5e
PA
491sol_thread_store_registers (struct target_ops *ops,
492 struct regcache *regcache, int regnum)
c906108c
SS
493{
494 thread_t thread;
495 td_thrhandle_t thandle;
496 td_err_e val;
8d027a04 497 prgregset_t gregset;
c906108c 498 prfpregset_t fpregset;
c906108c 499
39f77062 500 if (!is_thread (inferior_ptid))
8d027a04 501 {
28439f5e
PA
502 struct target_ops *beneath = find_target_beneath (ops);
503
504 /* It's an LWP; pass the request on to the layer beneath. */
505 beneath->to_store_registers (beneath, regcache, regnum);
c906108c
SS
506 return;
507 }
508
8d027a04 509 /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t. */
39f77062 510 thread = GET_THREAD (inferior_ptid);
c906108c
SS
511
512 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
513 if (val != TD_OK)
8a3fe4f8 514 error (_("sol_thread_store_registers: td_ta_map_id2thr %s"),
c906108c
SS
515 td_err_string (val));
516
8d027a04
MK
517 if (regnum != -1)
518 {
519 /* Not writing all the registers. */
87232496 520 char old_value[MAX_REGISTER_SIZE];
6034ae49 521
87232496 522 /* Save new register value. */
56be3814 523 regcache_raw_collect (regcache, regnum, old_value);
c906108c 524
c60c0f5f 525 val = p_td_thr_getgregs (&thandle, gregset);
c906108c 526 if (val != TD_OK)
8a3fe4f8 527 error (_("sol_thread_store_registers: td_thr_getgregs %s"),
c906108c
SS
528 td_err_string (val));
529 val = p_td_thr_getfpregs (&thandle, &fpregset);
530 if (val != TD_OK)
8a3fe4f8 531 error (_("sol_thread_store_registers: td_thr_getfpregs %s"),
c906108c
SS
532 td_err_string (val));
533
87232496 534 /* Restore new register value. */
56be3814 535 regcache_raw_supply (regcache, regnum, old_value);
c906108c
SS
536 }
537
56be3814
UW
538 fill_gregset (regcache, (gdb_gregset_t *) &gregset, regnum);
539 fill_fpregset (regcache, (gdb_fpregset_t *) &fpregset, regnum);
c906108c 540
c60c0f5f 541 val = p_td_thr_setgregs (&thandle, gregset);
c906108c 542 if (val != TD_OK)
8a3fe4f8 543 error (_("sol_thread_store_registers: td_thr_setgregs %s"),
c906108c
SS
544 td_err_string (val));
545 val = p_td_thr_setfpregs (&thandle, &fpregset);
546 if (val != TD_OK)
8a3fe4f8 547 error (_("sol_thread_store_registers: td_thr_setfpregs %s"),
c906108c 548 td_err_string (val));
c906108c
SS
549}
550
8d027a04
MK
551/* Perform partial transfers on OBJECT. See target_read_partial and
552 target_write_partial for details of each variant. One, and only
553 one, of readbuf or writebuf must be non-NULL. */
6034ae49
RM
554
555static LONGEST
556sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
b6958cfb
MK
557 const char *annex, gdb_byte *readbuf,
558 const gdb_byte *writebuf,
559 ULONGEST offset, LONGEST len)
6034ae49
RM
560{
561 int retval;
562 struct cleanup *old_chain;
28439f5e 563 struct target_ops *beneath = find_target_beneath (ops);
6034ae49
RM
564
565 old_chain = save_inferior_ptid ();
566
8d027a04
MK
567 if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
568 {
569 /* It's either a thread or an LWP that isn't alive. Any live
570 LWP will do so use the first available.
571
572 NOTE: We don't need to call switch_to_thread; we're just
573 reading memory. */
574 inferior_ptid = procfs_first_available ();
575 }
6034ae49 576
28439f5e
PA
577 retval = beneath->to_xfer_partial (beneath, object, annex,
578 readbuf, writebuf, offset, len);
6034ae49
RM
579
580 do_cleanups (old_chain);
581
582 return retval;
583}
584
c906108c 585static void
28439f5e 586check_for_thread_db (void)
c906108c 587{
28439f5e
PA
588 td_err_e err;
589 ptid_t ptid;
c906108c 590
28439f5e
PA
591 /* Do nothing if we couldn't load libthread_db.so.1. */
592 if (p_td_ta_new == NULL)
593 return;
c906108c 594
28439f5e
PA
595 if (sol_thread_active)
596 /* Nothing to do. The thread library was already detected and the
597 target vector was already activated. */
598 return;
c906108c 599
28439f5e
PA
600 /* Now, initialize libthread_db. This needs to be done after the
601 shared libraries are located because it needs information from
602 the user's thread library. */
c906108c 603
28439f5e
PA
604 err = p_td_init ();
605 if (err != TD_OK)
606 {
607 warning (_("sol_thread_new_objfile: td_init: %s"), td_err_string (err));
608 return;
609 }
c906108c 610
28439f5e
PA
611 /* Now attempt to open a connection to the thread library. */
612 err = p_td_ta_new (&main_ph, &main_ta);
613 switch (err)
c906108c 614 {
28439f5e
PA
615 case TD_NOLIBTHREAD:
616 /* No thread library was detected. */
617 break;
2689673f 618
28439f5e
PA
619 case TD_OK:
620 printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
c906108c 621
28439f5e 622 /* The thread library was detected. Activate the sol_thread target. */
c906108c 623 push_target (&sol_thread_ops);
28439f5e 624 sol_thread_active = 1;
c906108c 625
28439f5e 626 main_ph.ptid = inferior_ptid; /* Save for xfer_memory. */
2689673f
PA
627 ptid = lwp_to_thread (inferior_ptid);
628 if (PIDGET (ptid) != -1)
28439f5e
PA
629 inferior_ptid = ptid;
630
631 target_find_new_threads ();
632 break;
633
634 default:
635 warning (_("Cannot initialize thread debugging library: %s"),
636 td_err_string (err));
637 break;
c906108c
SS
638 }
639}
640
8d027a04
MK
641/* This routine is called whenever a new symbol table is read in, or
642 when all symbol tables are removed. libthread_db can only be
643 initialized when it finds the right variables in libthread.so.
644 Since it's a shared library, those variables don't show up until
06d3b283 645 the library gets mapped and the symbol table is read in. */
c906108c 646
06d3b283 647static void
fba45db2 648sol_thread_new_objfile (struct objfile *objfile)
c906108c 649{
28439f5e
PA
650 if (objfile != NULL)
651 check_for_thread_db ();
c906108c
SS
652}
653
654/* Clean up after the inferior dies. */
655
656static void
136d6dae 657sol_thread_mourn_inferior (struct target_ops *ops)
c906108c 658{
28439f5e
PA
659 struct target_ops *beneath = find_target_beneath (ops);
660
2689673f 661 sol_thread_active = 0;
c906108c 662
28439f5e 663 unpush_target (ops);
c906108c 664
28439f5e 665 beneath->to_mourn_inferior (beneath);
c906108c
SS
666}
667
8d027a04
MK
668/* Return true if PTID is still active in the inferior. */
669
c906108c 670static int
28439f5e 671sol_thread_alive (struct target_ops *ops, ptid_t ptid)
c906108c 672{
8d027a04 673 if (is_thread (ptid))
c906108c 674 {
8d027a04 675 /* It's a (user-level) thread. */
c906108c
SS
676 td_err_e val;
677 td_thrhandle_t th;
39f77062 678 int pid;
c906108c 679
39f77062 680 pid = GET_THREAD (ptid);
c906108c 681 if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
8d027a04 682 return 0; /* Thread not found. */
c906108c 683 if ((val = p_td_thr_validate (&th)) != TD_OK)
8d027a04
MK
684 return 0; /* Thread not valid. */
685 return 1; /* Known thread. */
c906108c 686 }
c5aa993b 687 else
c906108c 688 {
28439f5e
PA
689 struct target_ops *beneath = find_target_beneath (ops);
690
691 /* It's an LPW; pass the request on to the layer below. */
692 return beneath->to_thread_alive (beneath, ptid);
c906108c
SS
693 }
694}
695
c906108c 696\f
8d027a04
MK
697/* These routines implement the lower half of the thread_db interface,
698 i.e. the ps_* routines. */
c906108c 699
8d027a04
MK
700/* Various versions of <proc_service.h> have slightly different
701 function prototypes. In particular, we have
c906108c 702
c5aa993b
JM
703 NEWER OLDER
704 struct ps_prochandle * const struct ps_prochandle *
705 void* char*
8d027a04
MK
706 const void* char*
707 int size_t
c906108c 708
8d027a04
MK
709 Which one you have depends on the Solaris version and what patches
710 you've applied. On the theory that there are only two major
711 variants, we have configure check the prototype of ps_pdwrite (),
c378eb4e 712 and use that info to make appropriate typedefs here. */
c906108c
SS
713
714#ifdef PROC_SERVICE_IS_OLD
c5aa993b
JM
715typedef const struct ps_prochandle *gdb_ps_prochandle_t;
716typedef char *gdb_ps_read_buf_t;
717typedef char *gdb_ps_write_buf_t;
c906108c 718typedef int gdb_ps_size_t;
76e1ee85 719typedef psaddr_t gdb_ps_addr_t;
c906108c 720#else
c5aa993b
JM
721typedef struct ps_prochandle *gdb_ps_prochandle_t;
722typedef void *gdb_ps_read_buf_t;
723typedef const void *gdb_ps_write_buf_t;
c906108c 724typedef size_t gdb_ps_size_t;
291dcb3e 725typedef psaddr_t gdb_ps_addr_t;
c906108c
SS
726#endif
727
8d027a04
MK
728/* The next four routines are called by libthread_db to tell us to
729 stop and stop a particular process or lwp. Since GDB ensures that
730 these are all stopped by the time we call anything in thread_db,
731 these routines need to do nothing. */
c906108c 732
8d027a04 733/* Process stop. */
d4f3574e 734
c906108c
SS
735ps_err_e
736ps_pstop (gdb_ps_prochandle_t ph)
737{
738 return PS_OK;
739}
740
8d027a04 741/* Process continue. */
d4f3574e 742
c906108c
SS
743ps_err_e
744ps_pcontinue (gdb_ps_prochandle_t ph)
745{
746 return PS_OK;
747}
748
8d027a04 749/* LWP stop. */
d4f3574e 750
c906108c
SS
751ps_err_e
752ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
753{
754 return PS_OK;
755}
756
8d027a04 757/* LWP continue. */
d4f3574e 758
c906108c
SS
759ps_err_e
760ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
761{
762 return PS_OK;
763}
764
d4f3574e
SS
765/* Looks up the symbol LD_SYMBOL_NAME in the debugger's symbol table. */
766
c906108c
SS
767ps_err_e
768ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name,
8d027a04 769 const char *ld_symbol_name, gdb_ps_addr_t *ld_symbol_addr)
c906108c
SS
770{
771 struct minimal_symbol *ms;
772
773 ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
c906108c
SS
774 if (!ms)
775 return PS_NOSYM;
776
777 *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
c906108c
SS
778 return PS_OK;
779}
780
781/* Common routine for reading and writing memory. */
782
783static ps_err_e
291dcb3e 784rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr,
019c1128 785 gdb_byte *buf, int size)
c906108c 786{
28439f5e 787 int ret;
c906108c
SS
788 struct cleanup *old_chain;
789
39f77062 790 old_chain = save_inferior_ptid ();
c906108c 791
8d027a04
MK
792 if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
793 {
794 /* It's either a thread or an LWP that isn't alive. Any live
795 LWP will do so use the first available.
796
797 NOTE: We don't need to call switch_to_thread; we're just
798 reading memory. */
799 inferior_ptid = procfs_first_available ();
800 }
c906108c 801
23e04971
MS
802#if defined (__sparcv9)
803 /* For Sparc64 cross Sparc32, make sure the address has not been
804 accidentally sign-extended (or whatever) to beyond 32 bits. */
359431fb 805 if (bfd_get_arch_size (exec_bfd) == 32)
23e04971
MS
806 addr &= 0xffffffff;
807#endif
808
28439f5e 809 if (dowrite)
0c4f667c 810 ret = target_write_memory (addr, (gdb_byte *) buf, size);
28439f5e 811 else
0c4f667c 812 ret = target_read_memory (addr, (gdb_byte *) buf, size);
c906108c
SS
813
814 do_cleanups (old_chain);
815
28439f5e 816 return (ret == 0 ? PS_OK : PS_ERR);
c906108c
SS
817}
818
d4f3574e
SS
819/* Copies SIZE bytes from target process .data segment to debugger memory. */
820
c906108c 821ps_err_e
291dcb3e 822ps_pdread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
823 gdb_ps_read_buf_t buf, gdb_ps_size_t size)
824{
825 return rw_common (0, ph, addr, buf, size);
826}
827
d4f3574e
SS
828/* Copies SIZE bytes from debugger memory .data segment to target process. */
829
c906108c 830ps_err_e
291dcb3e 831ps_pdwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
832 gdb_ps_write_buf_t buf, gdb_ps_size_t size)
833{
019c1128 834 return rw_common (1, ph, addr, (gdb_byte *) buf, size);
c906108c
SS
835}
836
d4f3574e
SS
837/* Copies SIZE bytes from target process .text segment to debugger memory. */
838
c906108c 839ps_err_e
291dcb3e 840ps_ptread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
841 gdb_ps_read_buf_t buf, gdb_ps_size_t size)
842{
843 return rw_common (0, ph, addr, buf, size);
844}
845
d4f3574e
SS
846/* Copies SIZE bytes from debugger memory .text segment to target process. */
847
c906108c 848ps_err_e
291dcb3e 849ps_ptwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
850 gdb_ps_write_buf_t buf, gdb_ps_size_t size)
851{
019c1128 852 return rw_common (1, ph, addr, (gdb_byte *) buf, size);
c906108c
SS
853}
854
8d027a04 855/* Get general-purpose registers for LWP. */
c906108c
SS
856
857ps_err_e
8d027a04 858ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
c906108c
SS
859{
860 struct cleanup *old_chain;
594f7785 861 struct regcache *regcache;
c906108c 862
39f77062 863 old_chain = save_inferior_ptid ();
c906108c 864
39f77062 865 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
f5656ead 866 regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
c5aa993b 867
28439f5e 868 target_fetch_registers (regcache, -1);
594f7785 869 fill_gregset (regcache, (gdb_gregset_t *) gregset, -1);
c906108c
SS
870
871 do_cleanups (old_chain);
872
873 return PS_OK;
874}
875
8d027a04 876/* Set general-purpose registers for LWP. */
c906108c
SS
877
878ps_err_e
879ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
880 const prgregset_t gregset)
881{
882 struct cleanup *old_chain;
594f7785 883 struct regcache *regcache;
c906108c 884
39f77062 885 old_chain = save_inferior_ptid ();
c906108c 886
39f77062 887 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
f5656ead 888 regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
c5aa993b 889
594f7785 890 supply_gregset (regcache, (const gdb_gregset_t *) gregset);
28439f5e 891 target_store_registers (regcache, -1);
c906108c
SS
892
893 do_cleanups (old_chain);
894
895 return PS_OK;
896}
897
d4f3574e
SS
898/* Log a message (sends to gdb_stderr). */
899
c906108c 900void
8d027a04 901ps_plog (const char *fmt, ...)
c906108c
SS
902{
903 va_list args;
904
905 va_start (args, fmt);
906
907 vfprintf_filtered (gdb_stderr, fmt, args);
908}
909
c1357578
JB
910/* Get size of extra register set. Currently a noop. */
911
912ps_err_e
913ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
914{
915 return PS_OK;
916}
917
918/* Get extra register set. Currently a noop. */
919
920ps_err_e
921ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
922{
923 return PS_OK;
924}
925
926/* Set extra register set. Currently a noop. */
927
928ps_err_e
929ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
930{
931 return PS_OK;
932}
933
8d027a04 934/* Get floating-point registers for LWP. */
c906108c
SS
935
936ps_err_e
937ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
8d027a04 938 prfpregset_t *fpregset)
c906108c
SS
939{
940 struct cleanup *old_chain;
594f7785 941 struct regcache *regcache;
c906108c 942
39f77062 943 old_chain = save_inferior_ptid ();
c906108c 944
39f77062 945 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
f5656ead 946 regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
c906108c 947
28439f5e 948 target_fetch_registers (regcache, -1);
594f7785 949 fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1);
c906108c
SS
950
951 do_cleanups (old_chain);
952
953 return PS_OK;
954}
955
c378eb4e 956/* Set floating-point regs for LWP. */
c906108c
SS
957
958ps_err_e
959ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
c5aa993b 960 const prfpregset_t * fpregset)
c906108c
SS
961{
962 struct cleanup *old_chain;
594f7785 963 struct regcache *regcache;
c906108c 964
39f77062 965 old_chain = save_inferior_ptid ();
c906108c 966
39f77062 967 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
f5656ead 968 regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
c5aa993b 969
594f7785 970 supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset);
28439f5e 971 target_store_registers (regcache, -1);
c906108c
SS
972
973 do_cleanups (old_chain);
974
975 return PS_OK;
976}
977
23715f29 978#ifdef PR_MODEL_LP64
8d027a04
MK
979/* Identify process as 32-bit or 64-bit. At the moment we're using
980 BFD to do this. There might be a more Solaris-specific
981 (e.g. procfs) method, but this ought to work. */
23e04971
MS
982
983ps_err_e
984ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model)
985{
986 if (exec_bfd == 0)
a95ac8b6
PS
987 *data_model = PR_MODEL_UNKNOWN;
988 else if (bfd_get_arch_size (exec_bfd) == 32)
23e04971
MS
989 *data_model = PR_MODEL_ILP32;
990 else
991 *data_model = PR_MODEL_LP64;
992
993 return PS_OK;
994}
23715f29 995#endif /* PR_MODEL_LP64 */
23e04971 996
965b60ee 997#if (defined(__i386__) || defined(__x86_64__)) && defined (sun)
c906108c 998
965b60ee
JB
999/* Reads the local descriptor table of a LWP.
1000
1001 This function is necessary on x86-solaris only. Without it, the loading
1002 of libthread_db would fail because of ps_lgetLDT being undefined. */
d4f3574e 1003
c906108c
SS
1004ps_err_e
1005ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1006 struct ssd *pldt)
1007{
8d027a04 1008 /* NOTE: only used on Solaris, therefore OK to refer to procfs.c. */
05e28a7b 1009 struct ssd *ret;
c906108c 1010
8d027a04
MK
1011 /* FIXME: can't I get the process ID from the prochandle or
1012 something? */
2f09097b 1013
39f77062 1014 if (PIDGET (inferior_ptid) <= 0 || lwpid <= 0)
2f09097b
ND
1015 return PS_BADLID;
1016
39f77062 1017 ret = procfs_find_LDT_entry (BUILD_LWP (lwpid, PIDGET (inferior_ptid)));
05e28a7b 1018 if (ret)
c906108c 1019 {
05e28a7b
AC
1020 memcpy (pldt, ret, sizeof (struct ssd));
1021 return PS_OK;
c906108c 1022 }
8d027a04
MK
1023 else
1024 /* LDT not found. */
c906108c 1025 return PS_ERR;
c5aa993b 1026}
965b60ee 1027#endif
c906108c 1028\f
8d027a04
MK
1029
1030/* Convert PTID to printable form. */
c906108c 1031
02f1df11 1032static char *
117de6a9 1033solaris_pid_to_str (struct target_ops *ops, ptid_t ptid)
c906108c
SS
1034{
1035 static char buf[100];
1036
39f77062 1037 if (is_thread (ptid))
c906108c 1038 {
39f77062 1039 ptid_t lwp;
c906108c 1040
39f77062 1041 lwp = thread_to_lwp (ptid, -2);
c906108c 1042
39f77062 1043 if (PIDGET (lwp) == -1)
8c042590
PM
1044 xsnprintf (buf, sizeof (buf), "Thread %ld (defunct)",
1045 GET_THREAD (ptid));
39f77062 1046 else if (PIDGET (lwp) != -2)
8c042590 1047 xsnprintf (buf, sizeof (buf), "Thread %ld (LWP %ld)",
8d027a04 1048 GET_THREAD (ptid), GET_LWP (lwp));
c906108c 1049 else
8c042590 1050 xsnprintf (buf, sizeof (buf), "Thread %ld ", GET_THREAD (ptid));
c906108c 1051 }
39f77062 1052 else if (GET_LWP (ptid) != 0)
8c042590 1053 xsnprintf (buf, sizeof (buf), "LWP %ld ", GET_LWP (ptid));
c906108c 1054 else
8c042590 1055 xsnprintf (buf, sizeof (buf), "process %d ", PIDGET (ptid));
c906108c
SS
1056
1057 return buf;
1058}
1059\f
1060
8d027a04
MK
1061/* Worker bee for find_new_threads. Callback function that gets
1062 called once per user-level thread (i.e. not for LWP's). */
c906108c
SS
1063
1064static int
fba45db2 1065sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
c906108c
SS
1066{
1067 td_err_e retval;
1068 td_thrinfo_t ti;
39f77062 1069 ptid_t ptid;
c906108c 1070
8d027a04
MK
1071 retval = p_td_thr_get_info (th, &ti);
1072 if (retval != TD_OK)
1073 return -1;
1074
39f77062 1075 ptid = BUILD_THREAD (ti.ti_tid, PIDGET (inferior_ptid));
2689673f 1076 if (!in_thread_list (ptid) || is_exited (ptid))
39f77062 1077 add_thread (ptid);
c906108c
SS
1078
1079 return 0;
1080}
1081
d4f3574e 1082static void
28439f5e 1083sol_find_new_threads (struct target_ops *ops)
c906108c 1084{
28439f5e 1085 struct target_ops *beneath = find_target_beneath (ops);
8d027a04
MK
1086
1087 /* First Find any new LWP's. */
28439f5e
PA
1088 if (beneath->to_find_new_threads != NULL)
1089 beneath->to_find_new_threads (beneath);
8d027a04
MK
1090
1091 /* Then find any new user-level threads. */
c5aa993b 1092 p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *) 0,
c906108c
SS
1093 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1094 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1095}
1096
8d027a04
MK
1097/* Worker bee for the "info sol-thread" command. This is a callback
1098 function that gets called once for each Solaris user-level thread
1099 (i.e. not for LWPs) in the inferior. Print anything interesting
1100 that we can think of. */
c906108c 1101
c5aa993b 1102static int
fba45db2 1103info_cb (const td_thrhandle_t *th, void *s)
c906108c
SS
1104{
1105 td_err_e ret;
1106 td_thrinfo_t ti;
c906108c 1107
8d027a04
MK
1108 ret = p_td_thr_get_info (th, &ti);
1109 if (ret == TD_OK)
c906108c 1110 {
c5aa993b
JM
1111 printf_filtered ("%s thread #%d, lwp %d, ",
1112 ti.ti_type == TD_THR_SYSTEM ? "system" : "user ",
c906108c 1113 ti.ti_tid, ti.ti_lid);
c5aa993b
JM
1114 switch (ti.ti_state)
1115 {
c906108c 1116 default:
c5aa993b
JM
1117 case TD_THR_UNKNOWN:
1118 printf_filtered ("<unknown state>");
1119 break;
1120 case TD_THR_STOPPED:
1121 printf_filtered ("(stopped)");
1122 break;
1123 case TD_THR_RUN:
1124 printf_filtered ("(run) ");
1125 break;
1126 case TD_THR_ACTIVE:
1127 printf_filtered ("(active) ");
1128 break;
1129 case TD_THR_ZOMBIE:
1130 printf_filtered ("(zombie) ");
1131 break;
1132 case TD_THR_SLEEP:
1133 printf_filtered ("(asleep) ");
1134 break;
1135 case TD_THR_STOPPED_ASLEEP:
1136 printf_filtered ("(stopped asleep)");
1137 break;
1138 }
8d027a04 1139 /* Print thr_create start function. */
c906108c 1140 if (ti.ti_startfunc != 0)
4ce44c66 1141 {
5812197c
JB
1142 const struct bound_minimal_symbol msym
1143 = lookup_minimal_symbol_by_pc (ti.ti_startfunc);
1144
17e760ae
JB
1145 printf_filtered (" startfunc=%s",
1146 msym.minsym
1147 ? SYMBOL_PRINT_NAME (msym.minsym)
1148 : paddress (target_gdbarch (), ti.ti_startfunc));
4ce44c66 1149 }
c906108c 1150
8d027a04 1151 /* If thread is asleep, print function that went to sleep. */
c906108c 1152 if (ti.ti_state == TD_THR_SLEEP)
4ce44c66 1153 {
5812197c
JB
1154 const struct bound_minimal_symbol msym
1155 = lookup_minimal_symbol_by_pc (ti.ti_pc);
1156
17e760ae
JB
1157 printf_filtered (" sleepfunc=%s",
1158 msym.minsym
1159 ? SYMBOL_PRINT_NAME (msym.minsym)
1160 : paddress (target_gdbarch (), ti.ti_pc));
4ce44c66 1161 }
c906108c 1162
c0f5f490 1163 printf_filtered ("\n");
c906108c
SS
1164 }
1165 else
8a3fe4f8 1166 warning (_("info sol-thread: failed to get info for thread."));
c906108c 1167
c5aa993b 1168 return 0;
c906108c
SS
1169}
1170
8d027a04
MK
1171/* List some state about each Solaris user-level thread in the
1172 inferior. */
c906108c
SS
1173
1174static void
fba45db2 1175info_solthreads (char *args, int from_tty)
c906108c 1176{
c5aa993b 1177 p_td_ta_thr_iter (main_ta, info_cb, args,
c906108c
SS
1178 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1179 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1180}
c906108c 1181
3caf13b4
JB
1182/* Callback routine used to find a thread based on the TID part of
1183 its PTID. */
1184
1185static int
1186thread_db_find_thread_from_tid (struct thread_info *thread, void *data)
1187{
1188 long *tid = (long *) data;
1189
1190 if (ptid_get_tid (thread->ptid) == *tid)
1191 return 1;
1192
1193 return 0;
1194}
1195
1196static ptid_t
1197sol_get_ada_task_ptid (long lwp, long thread)
1198{
1199 struct thread_info *thread_info =
1200 iterate_over_threads (thread_db_find_thread_from_tid, &thread);
1201
1202 if (thread_info == NULL)
1203 {
1204 /* The list of threads is probably not up to date. Find any
1205 thread that is missing from the list, and try again. */
1206 sol_find_new_threads (&current_target);
1207 thread_info = iterate_over_threads (thread_db_find_thread_from_tid,
1208 &thread);
1209 }
1210
1211 gdb_assert (thread_info != NULL);
1212
1213 return (thread_info->ptid);
1214}
1215
c906108c 1216static void
fba45db2 1217init_sol_thread_ops (void)
c906108c
SS
1218{
1219 sol_thread_ops.to_shortname = "solaris-threads";
1220 sol_thread_ops.to_longname = "Solaris threads and pthread.";
1221 sol_thread_ops.to_doc = "Solaris threads and pthread support.";
c906108c
SS
1222 sol_thread_ops.to_detach = sol_thread_detach;
1223 sol_thread_ops.to_resume = sol_thread_resume;
1224 sol_thread_ops.to_wait = sol_thread_wait;
1225 sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
1226 sol_thread_ops.to_store_registers = sol_thread_store_registers;
6034ae49 1227 sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial;
c906108c 1228 sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
c906108c 1229 sol_thread_ops.to_thread_alive = sol_thread_alive;
ed9a39eb 1230 sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
b83266a0 1231 sol_thread_ops.to_find_new_threads = sol_find_new_threads;
28439f5e 1232 sol_thread_ops.to_stratum = thread_stratum;
3caf13b4 1233 sol_thread_ops.to_get_ada_task_ptid = sol_get_ada_task_ptid;
c906108c
SS
1234 sol_thread_ops.to_magic = OPS_MAGIC;
1235}
1236
02f1df11
JB
1237/* Silence -Wmissing-prototypes. */
1238extern void _initialize_sol_thread (void);
1239
c906108c 1240void
fba45db2 1241_initialize_sol_thread (void)
c906108c
SS
1242{
1243 void *dlhandle;
1244
1245 init_sol_thread_ops ();
c906108c
SS
1246
1247 dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
1248 if (!dlhandle)
1249 goto die;
1250
1251#define resolve(X) \
1252 if (!(p_##X = dlsym (dlhandle, #X))) \
1253 goto die;
1254
1255 resolve (td_log);
1256 resolve (td_ta_new);
1257 resolve (td_ta_delete);
1258 resolve (td_init);
1259 resolve (td_ta_get_ph);
1260 resolve (td_ta_get_nthreads);
1261 resolve (td_ta_tsd_iter);
1262 resolve (td_ta_thr_iter);
1263 resolve (td_thr_validate);
1264 resolve (td_thr_tsd);
1265 resolve (td_thr_get_info);
1266 resolve (td_thr_getfpregs);
1267 resolve (td_thr_getxregsize);
1268 resolve (td_thr_getxregs);
1269 resolve (td_thr_sigsetmask);
1270 resolve (td_thr_setprio);
1271 resolve (td_thr_setsigpending);
1272 resolve (td_thr_setfpregs);
1273 resolve (td_thr_setxregs);
1274 resolve (td_ta_map_id2thr);
1275 resolve (td_ta_map_lwp2thr);
1276 resolve (td_thr_getgregs);
1277 resolve (td_thr_setgregs);
1278
12070676 1279 complete_target_initialization (&sol_thread_ops);
c906108c 1280
c5aa993b 1281 add_cmd ("sol-threads", class_maintenance, info_solthreads,
1a966eab 1282 _("Show info on Solaris user threads."), &maintenanceinfolist);
c906108c 1283
8d027a04 1284 /* Hook into new_objfile notification. */
06d3b283 1285 observer_attach_new_objfile (sol_thread_new_objfile);
c906108c
SS
1286 return;
1287
8d027a04
MK
1288 die:
1289 fprintf_unfiltered (gdb_stderr, "\
1290[GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
c906108c
SS
1291
1292 if (dlhandle)
1293 dlclose (dlhandle);
1294
c906108c
SS
1295 return;
1296}
This page took 1.613491 seconds and 4 git commands to generate.