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