]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/sol-thread.c
Copyright updates for 2007.
[thirdparty/binutils-gdb.git] / gdb / sol-thread.c
CommitLineData
8d027a04
MK
1/* Solaris threads debugging interface.
2
6aba47ca
DJ
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2007 Free Software Foundation, Inc.
c906108c 5
c5aa993b 6 This file is part of GDB.
c906108c 7
c5aa993b
JM
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
c906108c 12
c5aa993b
JM
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
c906108c 17
c5aa993b
JM
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
197e01b6
EZ
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
c906108c
SS
22
23/* This module implements a sort of half target that sits between the
8d027a04
MK
24 machine-independent parts of GDB and the /proc interface (procfs.c)
25 to provide access to the Solaris user-mode thread implementation.
26
27 Solaris threads are true user-mode threads, which are invoked via
28 the thr_* and pthread_* (native and POSIX respectivly) interfaces.
29 These are mostly implemented in user-space, with all thread context
30 kept in various structures that live in the user's heap. These
31 should not be confused with lightweight processes (LWPs), which are
32 implemented by the kernel, and scheduled without explicit
33 intervention by the process.
34
35 Just to confuse things a little, Solaris threads (both native and
36 POSIX) are actually implemented using LWPs. In general, there are
37 going to be more threads than LWPs. There is no fixed
38 correspondence between a thread and an LWP. When a thread wants to
39 run, it gets scheduled onto the first available LWP and can
40 therefore migrate from one LWP to another as time goes on. A
c906108c
SS
41 sleeping thread may not be associated with an LWP at all!
42
8d027a04
MK
43 To make it possible to mess with threads, Sun provides a library
44 called libthread_db.so.1 (not to be confused with
45 libthread_db.so.0, which doesn't have a published interface). This
46 interface has an upper part, which it provides, and a lower part
47 which we provide. The upper part consists of the td_* routines,
48 which allow us to find all the threads, query their state, etc...
49 The lower part consists of all of the ps_*, which are used by the
50 td_* routines to read/write memory, manipulate LWPs, lookup
51 symbols, etc... The ps_* routines actually do most of their work
52 by calling functions in procfs.c. */
c906108c
SS
53
54#include "defs.h"
55#include <thread.h>
56#include <proc_service.h>
57#include <thread_db.h>
58#include "gdbthread.h"
59#include "target.h"
60#include "inferior.h"
61#include <fcntl.h>
b8a92b82 62#include "gdb_stat.h"
c906108c
SS
63#include <dlfcn.h>
64#include "gdbcmd.h"
23e04971 65#include "gdbcore.h"
4e052eda 66#include "regcache.h"
d45b6f32 67#include "solib.h"
990f9fe3 68#include "symfile.h"
c906108c 69
6f4492c8
MK
70#include "gdb_string.h"
71
c5aa993b
JM
72extern struct target_ops sol_thread_ops; /* Forward declaration */
73extern struct target_ops sol_core_ops; /* Forward declaration */
c906108c
SS
74
75/* place to store core_ops before we overwrite it */
76static struct target_ops orig_core_ops;
77
78struct target_ops sol_thread_ops;
79struct target_ops sol_core_ops;
80
81extern int procfs_suppress_run;
c5aa993b
JM
82extern struct target_ops procfs_ops; /* target vector for procfs.c */
83extern struct target_ops core_ops; /* target vector for corelow.c */
39f77062 84extern char *procfs_pid_to_str (ptid_t ptid);
c906108c 85
c60c0f5f
MS
86/* Prototypes for supply_gregset etc. */
87#include "gregset.h"
c906108c 88
8d027a04
MK
89/* This struct is defined by us, but mainly used for the proc_service
90 interface. We don't have much use for it, except as a handy place
91 to get a real PID for memory accesses. */
c906108c
SS
92
93struct ps_prochandle
8d027a04
MK
94{
95 ptid_t ptid;
96};
c906108c
SS
97
98struct string_map
8d027a04
MK
99{
100 int num;
101 char *str;
102};
c906108c
SS
103
104static struct ps_prochandle main_ph;
105static td_thragent_t *main_ta;
106static int sol_thread_active = 0;
107
39f77062 108static void sol_thread_resume (ptid_t ptid, int step, enum target_signal signo);
39f77062 109static int sol_thread_alive (ptid_t ptid);
a14ed312
KB
110static void sol_core_close (int quitting);
111
112static void init_sol_thread_ops (void);
113static void init_sol_core_ops (void);
c906108c 114
8d027a04
MK
115/* Default definitions: These must be defined in tm.h if they are to
116 be shared with a process module such as procfs. */
d4f3574e 117
ca6724c1
KB
118#define GET_PID(ptid) ptid_get_pid (ptid)
119#define GET_LWP(ptid) ptid_get_lwp (ptid)
120#define GET_THREAD(ptid) ptid_get_tid (ptid)
121
122#define is_lwp(ptid) (GET_LWP (ptid) != 0)
123#define is_thread(ptid) (GET_THREAD (ptid) != 0)
124
125#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0)
126#define BUILD_THREAD(tid, pid) ptid_build (pid, 0, tid)
c906108c 127
8d027a04
MK
128/* Pointers to routines from libthread_db resolved by dlopen(). */
129
130static void (*p_td_log)(const int on_off);
131static td_err_e (*p_td_ta_new)(const struct ps_prochandle *ph_p,
132 td_thragent_t **ta_pp);
133static td_err_e (*p_td_ta_delete)(td_thragent_t *ta_p);
134static td_err_e (*p_td_init)(void);
135static td_err_e (*p_td_ta_get_ph)(const td_thragent_t *ta_p,
136 struct ps_prochandle **ph_pp);
137static td_err_e (*p_td_ta_get_nthreads)(const td_thragent_t *ta_p,
138 int *nthread_p);
139static td_err_e (*p_td_ta_tsd_iter)(const td_thragent_t *ta_p,
140 td_key_iter_f *cb, void *cbdata_p);
141static td_err_e (*p_td_ta_thr_iter)(const td_thragent_t *ta_p,
142 td_thr_iter_f *cb, void *cbdata_p,
143 td_thr_state_e state, int ti_pri,
144 sigset_t *ti_sigmask_p,
145 unsigned ti_user_flags);
146static td_err_e (*p_td_thr_validate)(const td_thrhandle_t *th_p);
147static td_err_e (*p_td_thr_tsd)(const td_thrhandle_t * th_p,
148 const thread_key_t key, void **data_pp);
149static td_err_e (*p_td_thr_get_info)(const td_thrhandle_t *th_p,
150 td_thrinfo_t *ti_p);
151static td_err_e (*p_td_thr_getfpregs)(const td_thrhandle_t *th_p,
152 prfpregset_t *fpregset);
153static td_err_e (*p_td_thr_getxregsize)(const td_thrhandle_t *th_p,
154 int *xregsize);
155static td_err_e (*p_td_thr_getxregs)(const td_thrhandle_t *th_p,
156 const caddr_t xregset);
157static td_err_e (*p_td_thr_sigsetmask)(const td_thrhandle_t *th_p,
158 const sigset_t ti_sigmask);
159static td_err_e (*p_td_thr_setprio)(const td_thrhandle_t *th_p,
160 const int ti_pri);
161static td_err_e (*p_td_thr_setsigpending)(const td_thrhandle_t *th_p,
162 const uchar_t ti_pending_flag,
163 const sigset_t ti_pending);
164static td_err_e (*p_td_thr_setfpregs)(const td_thrhandle_t *th_p,
165 const prfpregset_t *fpregset);
166static td_err_e (*p_td_thr_setxregs)(const td_thrhandle_t *th_p,
167 const caddr_t xregset);
168static td_err_e (*p_td_ta_map_id2thr)(const td_thragent_t *ta_p,
169 thread_t tid,
170 td_thrhandle_t *th_p);
171static td_err_e (*p_td_ta_map_lwp2thr)(const td_thragent_t *ta_p,
172 lwpid_t lwpid,
173 td_thrhandle_t *th_p);
174static td_err_e (*p_td_thr_getgregs)(const td_thrhandle_t *th_p,
175 prgregset_t regset);
176static td_err_e (*p_td_thr_setgregs)(const td_thrhandle_t *th_p,
177 const prgregset_t regset);
178\f
c906108c 179
8d027a04
MK
180/* Return the libthread_db error string associated with ERRCODE. If
181 ERRCODE is unknown, return an appropriate message. */
c906108c
SS
182
183static char *
fba45db2 184td_err_string (td_err_e errcode)
c906108c 185{
8d027a04 186 static struct string_map td_err_table[] =
c5aa993b 187 {
8d027a04
MK
188 { TD_OK, "generic \"call succeeded\"" },
189 { TD_ERR, "generic error." },
190 { TD_NOTHR, "no thread can be found to satisfy query" },
191 { TD_NOSV, "no synch. variable can be found to satisfy query" },
192 { TD_NOLWP, "no lwp can be found to satisfy query" },
193 { TD_BADPH, "invalid process handle" },
194 { TD_BADTH, "invalid thread handle" },
195 { TD_BADSH, "invalid synchronization handle" },
196 { TD_BADTA, "invalid thread agent" },
197 { TD_BADKEY, "invalid key" },
198 { TD_NOMSG, "td_thr_event_getmsg() called when there was no message" },
199 { TD_NOFPREGS, "FPU register set not available for given thread" },
200 { TD_NOLIBTHREAD, "application not linked with libthread" },
201 { TD_NOEVENT, "requested event is not supported" },
202 { TD_NOCAPAB, "capability not available" },
203 { TD_DBERR, "Debugger service failed" },
204 { TD_NOAPLIC, "Operation not applicable to" },
205 { TD_NOTSD, "No thread specific data for this thread" },
206 { TD_MALLOC, "Malloc failed" },
207 { TD_PARTIALREG, "Only part of register set was written/read" },
208 { TD_NOXREGS, "X register set not available for given thread" }
c5aa993b 209 };
c906108c
SS
210 const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
211 int i;
212 static char buf[50];
213
214 for (i = 0; i < td_err_size; i++)
215 if (td_err_table[i].num == errcode)
216 return td_err_table[i].str;
c5aa993b 217
8d027a04 218 sprintf (buf, "Unknown libthread_db error code: %d", errcode);
c906108c
SS
219
220 return buf;
221}
c906108c 222
8d027a04
MK
223/* Return the the libthread_db state string assicoated with STATECODE.
224 If STATECODE is unknown, return an appropriate message. */
c906108c
SS
225
226static char *
fba45db2 227td_state_string (td_thr_state_e statecode)
c906108c 228{
8d027a04 229 static struct string_map td_thr_state_table[] =
c5aa993b 230 {
8d027a04
MK
231 { TD_THR_ANY_STATE, "any state" },
232 { TD_THR_UNKNOWN, "unknown" },
233 { TD_THR_STOPPED, "stopped" },
234 { TD_THR_RUN, "run" },
235 { TD_THR_ACTIVE, "active" },
236 { TD_THR_ZOMBIE, "zombie" },
237 { TD_THR_SLEEP, "sleep" },
238 { TD_THR_STOPPED_ASLEEP, "stopped asleep" }
c5aa993b 239 };
8d027a04
MK
240 const int td_thr_state_table_size =
241 sizeof td_thr_state_table / sizeof (struct string_map);
c906108c
SS
242 int i;
243 static char buf[50];
244
245 for (i = 0; i < td_thr_state_table_size; i++)
246 if (td_thr_state_table[i].num == statecode)
247 return td_thr_state_table[i].str;
c5aa993b 248
8d027a04 249 sprintf (buf, "Unknown libthread_db state code: %d", statecode);
c906108c
SS
250
251 return buf;
252}
253\f
c906108c 254
8d027a04
MK
255/* Convert a POSIX or Solaris thread ID into a LWP ID. If THREAD_ID
256 doesn't exist, that's an error. If it's an inactive thread, return
257 DEFAULT_LPW.
c906108c 258
8d027a04 259 NOTE: This function probably shouldn't call error(). */
c906108c 260
39f77062
KB
261static ptid_t
262thread_to_lwp (ptid_t thread_id, int default_lwp)
c906108c
SS
263{
264 td_thrinfo_t ti;
265 td_thrhandle_t th;
266 td_err_e val;
267
268 if (is_lwp (thread_id))
8d027a04 269 return thread_id; /* It's already an LWP ID. */
c906108c 270
8d027a04 271 /* It's a thread. Convert to LWP. */
c906108c
SS
272
273 val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
274 if (val == TD_NOTHR)
8d027a04 275 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 276 else if (val != TD_OK)
8a3fe4f8 277 error (_("thread_to_lwp: td_ta_map_id2thr %s"), td_err_string (val));
c906108c
SS
278
279 val = p_td_thr_get_info (&th, &ti);
280 if (val == TD_NOTHR)
8d027a04 281 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 282 else if (val != TD_OK)
8a3fe4f8 283 error (_("thread_to_lwp: td_thr_get_info: %s"), td_err_string (val));
c906108c
SS
284
285 if (ti.ti_state != TD_THR_ACTIVE)
286 {
287 if (default_lwp != -1)
39f77062 288 return pid_to_ptid (default_lwp);
8a3fe4f8 289 error (_("thread_to_lwp: thread state not active: %s"),
c906108c
SS
290 td_state_string (ti.ti_state));
291 }
292
293 return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
294}
c906108c 295
8d027a04
MK
296/* Convert an LWP ID into a POSIX or Solaris thread ID. If LWP_ID
297 doesn't exists, that's an error.
c906108c 298
8d027a04 299 NOTE: This function probably shouldn't call error(). */
c906108c 300
39f77062
KB
301static ptid_t
302lwp_to_thread (ptid_t lwp)
c906108c
SS
303{
304 td_thrinfo_t ti;
305 td_thrhandle_t th;
306 td_err_e val;
307
308 if (is_thread (lwp))
8d027a04 309 return lwp; /* It's already a thread ID. */
c906108c 310
8d027a04 311 /* It's an LWP. Convert it to a thread ID. */
c906108c
SS
312
313 if (!sol_thread_alive (lwp))
8d027a04 314 return pid_to_ptid (-1); /* Must be a defunct LPW. */
c906108c
SS
315
316 val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
317 if (val == TD_NOTHR)
8d027a04 318 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 319 else if (val != TD_OK)
8a3fe4f8 320 error (_("lwp_to_thread: td_ta_map_lwp2thr: %s."), td_err_string (val));
c906108c
SS
321
322 val = p_td_thr_validate (&th);
323 if (val == TD_NOTHR)
8d027a04 324 return lwp; /* Unknown to libthread; just return LPW, */
c906108c 325 else if (val != TD_OK)
8a3fe4f8 326 error (_("lwp_to_thread: td_thr_validate: %s."), td_err_string (val));
c906108c
SS
327
328 val = p_td_thr_get_info (&th, &ti);
329 if (val == TD_NOTHR)
8d027a04 330 return pid_to_ptid (-1); /* Thread must have terminated. */
c906108c 331 else if (val != TD_OK)
8a3fe4f8 332 error (_("lwp_to_thread: td_thr_get_info: %s."), td_err_string (val));
c906108c
SS
333
334 return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
335}
336\f
c906108c 337
8d027a04
MK
338/* Most target vector functions from here on actually just pass
339 through to procfs.c, as they don't need to do anything specific for
340 threads. */
c906108c 341
c906108c 342static void
fba45db2 343sol_thread_open (char *arg, int from_tty)
c906108c
SS
344{
345 procfs_ops.to_open (arg, from_tty);
346}
347
8d027a04
MK
348/* Attach to process PID, then initialize for debugging it and wait
349 for the trace-trap that results from attaching. */
c906108c
SS
350
351static void
fba45db2 352sol_thread_attach (char *args, int from_tty)
c906108c
SS
353{
354 procfs_ops.to_attach (args, from_tty);
23715f29 355
8d027a04 356 /* Must get symbols from shared libraries before libthread_db can run! */
d45b6f32 357 solib_add (NULL, from_tty, (struct target_ops *) 0, auto_solib_add);
71150974 358
c906108c
SS
359 if (sol_thread_active)
360 {
361 printf_filtered ("sol-thread active.\n");
8d027a04 362 main_ph.ptid = inferior_ptid; /* Save for xfer_memory. */
c906108c 363 push_target (&sol_thread_ops);
39f77062
KB
364 inferior_ptid = lwp_to_thread (inferior_ptid);
365 if (PIDGET (inferior_ptid) == -1)
366 inferior_ptid = main_ph.ptid;
c906108c 367 else
39f77062 368 add_thread (inferior_ptid);
c906108c 369 }
8d027a04
MK
370
371 /* FIXME: Might want to iterate over all the threads and register
372 them. */
c906108c
SS
373}
374
8d027a04
MK
375/* Take a program previously attached to and detaches it. The program
376 resumes execution and will no longer stop on signals, etc. We'd
377 better not have left any breakpoints in the program or it'll die
378 when it hits one. For this to work, it may be necessary for the
379 process to have been previously attached. It *might* work if the
380 program was started via the normal ptrace (PTRACE_TRACEME). */
c906108c
SS
381
382static void
fba45db2 383sol_thread_detach (char *args, int from_tty)
c906108c 384{
39f77062 385 inferior_ptid = pid_to_ptid (PIDGET (main_ph.ptid));
c906108c
SS
386 unpush_target (&sol_thread_ops);
387 procfs_ops.to_detach (args, from_tty);
388}
389
8d027a04
MK
390/* Resume execution of process PTID. If STEP is nozero, then just
391 single step it. If SIGNAL is nonzero, restart it with that signal
392 activated. We may have to convert PTID from a thread ID to an LWP
393 ID for procfs. */
c906108c
SS
394
395static void
39f77062 396sol_thread_resume (ptid_t ptid, int step, enum target_signal signo)
c906108c
SS
397{
398 struct cleanup *old_chain;
399
39f77062 400 old_chain = save_inferior_ptid ();
c906108c 401
39f77062
KB
402 inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
403 if (PIDGET (inferior_ptid) == -1)
404 inferior_ptid = procfs_first_available ();
c906108c 405
39f77062 406 if (PIDGET (ptid) != -1)
c906108c 407 {
39f77062 408 ptid_t save_ptid = ptid;
c906108c 409
39f77062 410 ptid = thread_to_lwp (ptid, -2);
8d027a04 411 if (PIDGET (ptid) == -2) /* Inactive thread. */
8a3fe4f8 412 error (_("This version of Solaris can't start inactive threads."));
39f77062 413 if (info_verbose && PIDGET (ptid) == -1)
8a3fe4f8 414 warning (_("Specified thread %ld seems to have terminated"),
39f77062 415 GET_THREAD (save_ptid));
c906108c
SS
416 }
417
39f77062 418 procfs_ops.to_resume (ptid, step, signo);
c906108c
SS
419
420 do_cleanups (old_chain);
421}
422
8d027a04
MK
423/* Wait for any threads to stop. We may have to convert PIID from a
424 thread ID to an LWP ID, and vice versa on the way out. */
c906108c 425
39f77062
KB
426static ptid_t
427sol_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c 428{
39f77062
KB
429 ptid_t rtnval;
430 ptid_t save_ptid;
c906108c
SS
431 struct cleanup *old_chain;
432
39f77062
KB
433 save_ptid = inferior_ptid;
434 old_chain = save_inferior_ptid ();
c906108c 435
39f77062
KB
436 inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
437 if (PIDGET (inferior_ptid) == -1)
438 inferior_ptid = procfs_first_available ();
c906108c 439
39f77062 440 if (PIDGET (ptid) != -1)
c906108c 441 {
39f77062 442 ptid_t save_ptid = ptid;
c906108c 443
39f77062 444 ptid = thread_to_lwp (ptid, -2);
8d027a04 445 if (PIDGET (ptid) == -2) /* Inactive thread. */
8a3fe4f8 446 error (_("This version of Solaris can't start inactive threads."));
39f77062 447 if (info_verbose && PIDGET (ptid) == -1)
8a3fe4f8 448 warning (_("Specified thread %ld seems to have terminated"),
39f77062 449 GET_THREAD (save_ptid));
c906108c
SS
450 }
451
39f77062 452 rtnval = procfs_ops.to_wait (ptid, ourstatus);
c906108c
SS
453
454 if (ourstatus->kind != TARGET_WAITKIND_EXITED)
455 {
8d027a04 456 /* Map the LWP of interest back to the appropriate thread ID. */
c906108c 457 rtnval = lwp_to_thread (rtnval);
39f77062
KB
458 if (PIDGET (rtnval) == -1)
459 rtnval = save_ptid;
c906108c 460
8d027a04 461 /* See if we have a new thread. */
c906108c 462 if (is_thread (rtnval)
39f77062 463 && !ptid_equal (rtnval, save_ptid)
c906108c
SS
464 && !in_thread_list (rtnval))
465 {
466 printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
467 add_thread (rtnval);
468 }
469 }
470
8d027a04
MK
471 /* During process initialization, we may get here without the thread
472 package being initialized, since that can only happen after we've
473 found the shared libs. */
c906108c
SS
474
475 do_cleanups (old_chain);
476
477 return rtnval;
478}
479
480static void
8d027a04 481sol_thread_fetch_registers (int regnum)
c906108c
SS
482{
483 thread_t thread;
484 td_thrhandle_t thandle;
485 td_err_e val;
486 prgregset_t gregset;
487 prfpregset_t fpregset;
488#if 0
489 int xregsize;
490 caddr_t xregset;
491#endif
492
39f77062 493 if (!is_thread (inferior_ptid))
8d027a04
MK
494 {
495 /* It's an LWP; pass the request on to procfs. */
c906108c 496 if (target_has_execution)
8d027a04 497 procfs_ops.to_fetch_registers (regnum);
c906108c 498 else
8d027a04 499 orig_core_ops.to_fetch_registers (regnum);
c906108c
SS
500 return;
501 }
502
8d027a04 503 /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t. */
39f77062 504 thread = GET_THREAD (inferior_ptid);
c906108c 505 if (thread == 0)
8a3fe4f8 506 error (_("sol_thread_fetch_registers: thread == 0"));
c906108c
SS
507
508 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
509 if (val != TD_OK)
8a3fe4f8 510 error (_("sol_thread_fetch_registers: td_ta_map_id2thr: %s"),
c906108c
SS
511 td_err_string (val));
512
8d027a04 513 /* Get the general-purpose registers. */
c906108c
SS
514
515 val = p_td_thr_getgregs (&thandle, gregset);
8d027a04 516 if (val != TD_OK && val != TD_PARTIALREG)
8a3fe4f8 517 error (_("sol_thread_fetch_registers: td_thr_getgregs %s"),
c906108c
SS
518 td_err_string (val));
519
8d027a04
MK
520 /* For SPARC, TD_PARTIALREG means that only %i0...%i7, %l0..%l7, %pc
521 and %sp are saved (by a thread context switch). */
c906108c 522
8d027a04 523 /* And, now the floating-point registers. */
c906108c
SS
524
525 val = p_td_thr_getfpregs (&thandle, &fpregset);
8d027a04 526 if (val != TD_OK && val != TD_NOFPREGS)
8a3fe4f8 527 error (_("sol_thread_fetch_registers: td_thr_getfpregs %s"),
c906108c
SS
528 td_err_string (val));
529
8d027a04
MK
530 /* Note that we must call supply_gregset and supply_fpregset *after*
531 calling the td routines because the td routines call ps_lget*
532 which affect the values stored in the registers array. */
c906108c 533
8d027a04 534 supply_gregset ((gdb_gregset_t *) &gregset);
c60c0f5f 535 supply_fpregset ((gdb_fpregset_t *) &fpregset);
c906108c
SS
536
537#if 0
8d027a04 538 /* FIXME: libthread_db doesn't seem to handle this right. */
c906108c
SS
539 val = td_thr_getxregsize (&thandle, &xregsize);
540 if (val != TD_OK && val != TD_NOXREGS)
8a3fe4f8 541 error (_("sol_thread_fetch_registers: td_thr_getxregsize %s"),
c906108c
SS
542 td_err_string (val));
543
544 if (val == TD_OK)
545 {
546 xregset = alloca (xregsize);
547 val = td_thr_getxregs (&thandle, xregset);
548 if (val != TD_OK)
8a3fe4f8 549 error (_("sol_thread_fetch_registers: td_thr_getxregs %s"),
c906108c
SS
550 td_err_string (val));
551 }
552#endif
553}
554
555static void
8d027a04 556sol_thread_store_registers (int regnum)
c906108c
SS
557{
558 thread_t thread;
559 td_thrhandle_t thandle;
560 td_err_e val;
8d027a04 561 prgregset_t gregset;
c906108c
SS
562 prfpregset_t fpregset;
563#if 0
564 int xregsize;
565 caddr_t xregset;
566#endif
567
39f77062 568 if (!is_thread (inferior_ptid))
8d027a04
MK
569 {
570 /* It's an LWP; pass the request on to procfs.c. */
571 procfs_ops.to_store_registers (regnum);
c906108c
SS
572 return;
573 }
574
8d027a04 575 /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t. */
39f77062 576 thread = GET_THREAD (inferior_ptid);
c906108c
SS
577
578 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
579 if (val != TD_OK)
8a3fe4f8 580 error (_("sol_thread_store_registers: td_ta_map_id2thr %s"),
c906108c
SS
581 td_err_string (val));
582
8d027a04
MK
583 if (regnum != -1)
584 {
585 /* Not writing all the registers. */
87232496 586 char old_value[MAX_REGISTER_SIZE];
6034ae49 587
87232496 588 /* Save new register value. */
822c9732 589 regcache_raw_collect (current_regcache, regnum, old_value);
c906108c 590
c60c0f5f 591 val = p_td_thr_getgregs (&thandle, gregset);
c906108c 592 if (val != TD_OK)
8a3fe4f8 593 error (_("sol_thread_store_registers: td_thr_getgregs %s"),
c906108c
SS
594 td_err_string (val));
595 val = p_td_thr_getfpregs (&thandle, &fpregset);
596 if (val != TD_OK)
8a3fe4f8 597 error (_("sol_thread_store_registers: td_thr_getfpregs %s"),
c906108c
SS
598 td_err_string (val));
599
87232496 600 /* Restore new register value. */
23a6d369 601 regcache_raw_supply (current_regcache, regnum, old_value);
c906108c
SS
602
603#if 0
8d027a04 604 /* FIXME: libthread_db doesn't seem to handle this right. */
c906108c
SS
605 val = td_thr_getxregsize (&thandle, &xregsize);
606 if (val != TD_OK && val != TD_NOXREGS)
8a3fe4f8 607 error (_("sol_thread_store_registers: td_thr_getxregsize %s"),
c906108c
SS
608 td_err_string (val));
609
610 if (val == TD_OK)
611 {
612 xregset = alloca (xregsize);
613 val = td_thr_getxregs (&thandle, xregset);
614 if (val != TD_OK)
8a3fe4f8 615 error (_("sol_thread_store_registers: td_thr_getxregs %s"),
c906108c
SS
616 td_err_string (val));
617 }
618#endif
619 }
620
8d027a04
MK
621 fill_gregset ((gdb_gregset_t *) &gregset, regnum);
622 fill_fpregset ((gdb_fpregset_t *) &fpregset, regnum);
c906108c 623
c60c0f5f 624 val = p_td_thr_setgregs (&thandle, gregset);
c906108c 625 if (val != TD_OK)
8a3fe4f8 626 error (_("sol_thread_store_registers: td_thr_setgregs %s"),
c906108c
SS
627 td_err_string (val));
628 val = p_td_thr_setfpregs (&thandle, &fpregset);
629 if (val != TD_OK)
8a3fe4f8 630 error (_("sol_thread_store_registers: td_thr_setfpregs %s"),
c906108c
SS
631 td_err_string (val));
632
633#if 0
8d027a04 634 /* FIXME: libthread_db doesn't seem to handle this right. */
c906108c
SS
635 val = td_thr_getxregsize (&thandle, &xregsize);
636 if (val != TD_OK && val != TD_NOXREGS)
8a3fe4f8 637 error (_("sol_thread_store_registers: td_thr_getxregsize %s"),
c906108c
SS
638 td_err_string (val));
639
8d027a04
MK
640 /* ??? Should probably do something about writing the xregs here,
641 but what are they? */
c906108c
SS
642#endif
643}
644
645/* Get ready to modify the registers array. On machines which store
8d027a04
MK
646 individual registers, this doesn't need to do anything. On
647 machines which store all the registers in one fell swoop, this
648 makes sure that registers contains all the registers from the
649 program being debugged. */
c906108c
SS
650
651static void
fba45db2 652sol_thread_prepare_to_store (void)
c906108c
SS
653{
654 procfs_ops.to_prepare_to_store ();
655}
656
c338868a
KB
657/* Transfer LEN bytes between GDB address MYADDR and target address
658 MEMADDR. If DOWRITE is non-zero, transfer them to the target,
659 otherwise transfer them from the target. TARGET is unused.
660
8d027a04 661 Returns the number of bytes transferred. */
c338868a 662
c906108c 663static int
b6958cfb
MK
664sol_thread_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len,
665 int dowrite, struct mem_attrib *attrib,
c338868a 666 struct target_ops *target)
c906108c
SS
667{
668 int retval;
669 struct cleanup *old_chain;
670
39f77062 671 old_chain = save_inferior_ptid ();
c906108c 672
8d027a04
MK
673 if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
674 {
675 /* It's either a thread or an LWP that isn't alive. Any live
676 LWP will do so use the first available.
677
678 NOTE: We don't need to call switch_to_thread; we're just
679 reading memory. */
680 inferior_ptid = procfs_first_available ();
681 }
c906108c
SS
682
683 if (target_has_execution)
c8e73a31
AC
684 retval = procfs_ops.deprecated_xfer_memory (memaddr, myaddr, len,
685 dowrite, attrib, target);
c906108c 686 else
c8e73a31
AC
687 retval = orig_core_ops.deprecated_xfer_memory (memaddr, myaddr, len,
688 dowrite, attrib, target);
c906108c
SS
689
690 do_cleanups (old_chain);
691
692 return retval;
693}
694
8d027a04
MK
695/* Perform partial transfers on OBJECT. See target_read_partial and
696 target_write_partial for details of each variant. One, and only
697 one, of readbuf or writebuf must be non-NULL. */
6034ae49
RM
698
699static LONGEST
700sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
b6958cfb
MK
701 const char *annex, gdb_byte *readbuf,
702 const gdb_byte *writebuf,
703 ULONGEST offset, LONGEST len)
6034ae49
RM
704{
705 int retval;
706 struct cleanup *old_chain;
707
708 old_chain = save_inferior_ptid ();
709
8d027a04
MK
710 if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
711 {
712 /* It's either a thread or an LWP that isn't alive. Any live
713 LWP will do so use the first available.
714
715 NOTE: We don't need to call switch_to_thread; we're just
716 reading memory. */
717 inferior_ptid = procfs_first_available ();
718 }
6034ae49
RM
719
720 if (target_has_execution)
721 retval = procfs_ops.to_xfer_partial (ops, object, annex,
722 readbuf, writebuf, offset, len);
723 else
724 retval = orig_core_ops.to_xfer_partial (ops, object, annex,
725 readbuf, writebuf, offset, len);
726
727 do_cleanups (old_chain);
728
729 return retval;
730}
731
c906108c
SS
732/* Print status information about what we're accessing. */
733
734static void
fba45db2 735sol_thread_files_info (struct target_ops *ignore)
c906108c
SS
736{
737 procfs_ops.to_files_info (ignore);
738}
739
740static void
fba45db2 741sol_thread_kill_inferior (void)
c906108c
SS
742{
743 procfs_ops.to_kill ();
744}
745
746static void
39f77062 747sol_thread_notice_signals (ptid_t ptid)
c906108c 748{
39f77062 749 procfs_ops.to_notice_signals (pid_to_ptid (PIDGET (ptid)));
c906108c
SS
750}
751
752/* Fork an inferior process, and start debugging it with /proc. */
753
754static void
c27cda74
AC
755sol_thread_create_inferior (char *exec_file, char *allargs, char **env,
756 int from_tty)
c906108c 757{
c27cda74 758 procfs_ops.to_create_inferior (exec_file, allargs, env, from_tty);
c906108c 759
39f77062 760 if (sol_thread_active && !ptid_equal (inferior_ptid, null_ptid))
c906108c 761 {
8d027a04
MK
762 /* Save for xfer_memory. */
763 main_ph.ptid = inferior_ptid;
c906108c
SS
764
765 push_target (&sol_thread_ops);
766
39f77062
KB
767 inferior_ptid = lwp_to_thread (inferior_ptid);
768 if (PIDGET (inferior_ptid) == -1)
769 inferior_ptid = main_ph.ptid;
c906108c 770
39f77062
KB
771 if (!in_thread_list (inferior_ptid))
772 add_thread (inferior_ptid);
c906108c
SS
773 }
774}
775
8d027a04
MK
776/* This routine is called whenever a new symbol table is read in, or
777 when all symbol tables are removed. libthread_db can only be
778 initialized when it finds the right variables in libthread.so.
779 Since it's a shared library, those variables don't show up until
780 the library gets mapped and the symbol table is read in.
c906108c 781
8d027a04
MK
782 This new_objfile event is managed by a chained function pointer.
783 It is the callee's responsability to call the next client on the
784 chain. */
11cf8741
JM
785
786/* Saved pointer to previous owner of the new_objfile event. */
507f3c78 787static void (*target_new_objfile_chain) (struct objfile *);
11cf8741 788
c906108c 789void
fba45db2 790sol_thread_new_objfile (struct objfile *objfile)
c906108c
SS
791{
792 td_err_e val;
793
794 if (!objfile)
795 {
796 sol_thread_active = 0;
11cf8741 797 goto quit;
c906108c
SS
798 }
799
8d027a04
MK
800 /* Don't do anything if init failed to resolve the libthread_db
801 library. */
c906108c 802 if (!procfs_suppress_run)
11cf8741 803 goto quit;
c906108c 804
8d027a04
MK
805 /* Now, initialize libthread_db. This needs to be done after the
806 shared libraries are located because it needs information from
807 the user's thread library. */
c906108c
SS
808
809 val = p_td_init ();
810 if (val != TD_OK)
11cf8741 811 {
8a3fe4f8 812 warning (_("sol_thread_new_objfile: td_init: %s"), td_err_string (val));
11cf8741
JM
813 goto quit;
814 }
c906108c
SS
815
816 val = p_td_ta_new (&main_ph, &main_ta);
817 if (val == TD_NOLIBTHREAD)
11cf8741 818 goto quit;
c906108c 819 else if (val != TD_OK)
11cf8741 820 {
8a3fe4f8 821 warning (_("sol_thread_new_objfile: td_ta_new: %s"), td_err_string (val));
11cf8741
JM
822 goto quit;
823 }
c906108c
SS
824
825 sol_thread_active = 1;
8d027a04 826
11cf8741 827quit:
8d027a04 828 /* Call predecessor on chain, if any. */
11cf8741
JM
829 if (target_new_objfile_chain)
830 target_new_objfile_chain (objfile);
c906108c
SS
831}
832
833/* Clean up after the inferior dies. */
834
835static void
fba45db2 836sol_thread_mourn_inferior (void)
c906108c
SS
837{
838 unpush_target (&sol_thread_ops);
839 procfs_ops.to_mourn_inferior ();
840}
841
8d027a04
MK
842/* Mark our target-struct as eligible for stray "run" and "attach"
843 commands. */
c906108c
SS
844
845static int
fba45db2 846sol_thread_can_run (void)
c906108c
SS
847{
848 return procfs_suppress_run;
849}
850
6034ae49 851/*
c906108c 852
c5aa993b 853 LOCAL FUNCTION
c906108c 854
c5aa993b 855 sol_thread_alive - test thread for "aliveness"
c906108c 856
c5aa993b 857 SYNOPSIS
c906108c 858
39f77062 859 static bool sol_thread_alive (ptid_t ptid);
c906108c 860
c5aa993b 861 DESCRIPTION
c906108c 862
c5aa993b 863 returns true if thread still active in inferior.
c906108c
SS
864
865 */
866
8d027a04
MK
867/* Return true if PTID is still active in the inferior. */
868
c906108c 869static int
39f77062 870sol_thread_alive (ptid_t ptid)
c906108c 871{
8d027a04 872 if (is_thread (ptid))
c906108c 873 {
8d027a04 874 /* It's a (user-level) thread. */
c906108c
SS
875 td_err_e val;
876 td_thrhandle_t th;
39f77062 877 int pid;
c906108c 878
39f77062 879 pid = GET_THREAD (ptid);
c906108c 880 if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
8d027a04 881 return 0; /* Thread not found. */
c906108c 882 if ((val = p_td_thr_validate (&th)) != TD_OK)
8d027a04
MK
883 return 0; /* Thread not valid. */
884 return 1; /* Known thread. */
c906108c 885 }
c5aa993b 886 else
c906108c 887 {
8d027a04 888 /* It's an LPW; pass the request on to procfs. */
c906108c 889 if (target_has_execution)
39f77062 890 return procfs_ops.to_thread_alive (ptid);
c906108c 891 else
39f77062 892 return orig_core_ops.to_thread_alive (ptid);
c906108c
SS
893 }
894}
895
896static void
fba45db2 897sol_thread_stop (void)
c906108c
SS
898{
899 procfs_ops.to_stop ();
900}
901\f
8d027a04
MK
902/* These routines implement the lower half of the thread_db interface,
903 i.e. the ps_* routines. */
c906108c 904
8d027a04
MK
905/* Various versions of <proc_service.h> have slightly different
906 function prototypes. In particular, we have
c906108c 907
c5aa993b
JM
908 NEWER OLDER
909 struct ps_prochandle * const struct ps_prochandle *
910 void* char*
8d027a04
MK
911 const void* char*
912 int size_t
c906108c 913
8d027a04
MK
914 Which one you have depends on the Solaris version and what patches
915 you've applied. On the theory that there are only two major
916 variants, we have configure check the prototype of ps_pdwrite (),
917 and use that info to make appropriate typedefs here. */
c906108c
SS
918
919#ifdef PROC_SERVICE_IS_OLD
c5aa993b
JM
920typedef const struct ps_prochandle *gdb_ps_prochandle_t;
921typedef char *gdb_ps_read_buf_t;
922typedef char *gdb_ps_write_buf_t;
c906108c 923typedef int gdb_ps_size_t;
291dcb3e 924typedef paddr_t gdb_ps_addr_t;
c906108c 925#else
c5aa993b
JM
926typedef struct ps_prochandle *gdb_ps_prochandle_t;
927typedef void *gdb_ps_read_buf_t;
928typedef const void *gdb_ps_write_buf_t;
c906108c 929typedef size_t gdb_ps_size_t;
291dcb3e 930typedef psaddr_t gdb_ps_addr_t;
c906108c
SS
931#endif
932
8d027a04
MK
933/* The next four routines are called by libthread_db to tell us to
934 stop and stop a particular process or lwp. Since GDB ensures that
935 these are all stopped by the time we call anything in thread_db,
936 these routines need to do nothing. */
c906108c 937
8d027a04 938/* Process stop. */
d4f3574e 939
c906108c
SS
940ps_err_e
941ps_pstop (gdb_ps_prochandle_t ph)
942{
943 return PS_OK;
944}
945
8d027a04 946/* Process continue. */
d4f3574e 947
c906108c
SS
948ps_err_e
949ps_pcontinue (gdb_ps_prochandle_t ph)
950{
951 return PS_OK;
952}
953
8d027a04 954/* LWP stop. */
d4f3574e 955
c906108c
SS
956ps_err_e
957ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
958{
959 return PS_OK;
960}
961
8d027a04 962/* LWP continue. */
d4f3574e 963
c906108c
SS
964ps_err_e
965ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
966{
967 return PS_OK;
968}
969
d4f3574e
SS
970/* Looks up the symbol LD_SYMBOL_NAME in the debugger's symbol table. */
971
c906108c
SS
972ps_err_e
973ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name,
8d027a04 974 const char *ld_symbol_name, gdb_ps_addr_t *ld_symbol_addr)
c906108c
SS
975{
976 struct minimal_symbol *ms;
977
978 ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
c906108c
SS
979 if (!ms)
980 return PS_NOSYM;
981
982 *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
c906108c
SS
983 return PS_OK;
984}
985
986/* Common routine for reading and writing memory. */
987
988static ps_err_e
291dcb3e 989rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr,
c906108c
SS
990 char *buf, int size)
991{
992 struct cleanup *old_chain;
993
39f77062 994 old_chain = save_inferior_ptid ();
c906108c 995
8d027a04
MK
996 if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
997 {
998 /* It's either a thread or an LWP that isn't alive. Any live
999 LWP will do so use the first available.
1000
1001 NOTE: We don't need to call switch_to_thread; we're just
1002 reading memory. */
1003 inferior_ptid = procfs_first_available ();
1004 }
c906108c 1005
23e04971
MS
1006#if defined (__sparcv9)
1007 /* For Sparc64 cross Sparc32, make sure the address has not been
1008 accidentally sign-extended (or whatever) to beyond 32 bits. */
359431fb 1009 if (bfd_get_arch_size (exec_bfd) == 32)
23e04971
MS
1010 addr &= 0xffffffff;
1011#endif
1012
c906108c
SS
1013 while (size > 0)
1014 {
1015 int cc;
1016
f4d650ec 1017 /* FIXME: passing 0 as attrib argument. */
c906108c 1018 if (target_has_execution)
c8e73a31
AC
1019 cc = procfs_ops.deprecated_xfer_memory (addr, buf, size,
1020 dowrite, 0, &procfs_ops);
c906108c 1021 else
c8e73a31
AC
1022 cc = orig_core_ops.deprecated_xfer_memory (addr, buf, size,
1023 dowrite, 0, &core_ops);
c906108c
SS
1024
1025 if (cc < 0)
1026 {
1027 if (dowrite == 0)
1028 print_sys_errmsg ("rw_common (): read", errno);
1029 else
1030 print_sys_errmsg ("rw_common (): write", errno);
1031
1032 do_cleanups (old_chain);
1033
1034 return PS_ERR;
1035 }
d5cb3e0e
MS
1036 else if (cc == 0)
1037 {
1038 if (dowrite == 0)
8a3fe4f8 1039 warning (_("rw_common (): unable to read at addr 0x%lx"),
d5cb3e0e
MS
1040 (long) addr);
1041 else
8a3fe4f8 1042 warning (_("rw_common (): unable to write at addr 0x%lx"),
d5cb3e0e
MS
1043 (long) addr);
1044
1045 do_cleanups (old_chain);
1046
1047 return PS_ERR;
1048 }
1049
c906108c
SS
1050 size -= cc;
1051 buf += cc;
1052 }
1053
1054 do_cleanups (old_chain);
1055
1056 return PS_OK;
1057}
1058
d4f3574e
SS
1059/* Copies SIZE bytes from target process .data segment to debugger memory. */
1060
c906108c 1061ps_err_e
291dcb3e 1062ps_pdread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
1063 gdb_ps_read_buf_t buf, gdb_ps_size_t size)
1064{
1065 return rw_common (0, ph, addr, buf, size);
1066}
1067
d4f3574e
SS
1068/* Copies SIZE bytes from debugger memory .data segment to target process. */
1069
c906108c 1070ps_err_e
291dcb3e 1071ps_pdwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
1072 gdb_ps_write_buf_t buf, gdb_ps_size_t size)
1073{
c5aa993b 1074 return rw_common (1, ph, addr, (char *) buf, size);
c906108c
SS
1075}
1076
d4f3574e
SS
1077/* Copies SIZE bytes from target process .text segment to debugger memory. */
1078
c906108c 1079ps_err_e
291dcb3e 1080ps_ptread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
1081 gdb_ps_read_buf_t buf, gdb_ps_size_t size)
1082{
1083 return rw_common (0, ph, addr, buf, size);
1084}
1085
d4f3574e
SS
1086/* Copies SIZE bytes from debugger memory .text segment to target process. */
1087
c906108c 1088ps_err_e
291dcb3e 1089ps_ptwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
c906108c
SS
1090 gdb_ps_write_buf_t buf, gdb_ps_size_t size)
1091{
c5aa993b 1092 return rw_common (1, ph, addr, (char *) buf, size);
c906108c
SS
1093}
1094
8d027a04 1095/* Get general-purpose registers for LWP. */
c906108c
SS
1096
1097ps_err_e
8d027a04 1098ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
c906108c
SS
1099{
1100 struct cleanup *old_chain;
1101
39f77062 1102 old_chain = save_inferior_ptid ();
c906108c 1103
39f77062 1104 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
c5aa993b 1105
c906108c
SS
1106 if (target_has_execution)
1107 procfs_ops.to_fetch_registers (-1);
1108 else
1109 orig_core_ops.to_fetch_registers (-1);
c60c0f5f 1110 fill_gregset ((gdb_gregset_t *) gregset, -1);
c906108c
SS
1111
1112 do_cleanups (old_chain);
1113
1114 return PS_OK;
1115}
1116
8d027a04 1117/* Set general-purpose registers for LWP. */
c906108c
SS
1118
1119ps_err_e
1120ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1121 const prgregset_t gregset)
1122{
1123 struct cleanup *old_chain;
1124
39f77062 1125 old_chain = save_inferior_ptid ();
c906108c 1126
39f77062 1127 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
c5aa993b 1128
c60c0f5f 1129 supply_gregset ((gdb_gregset_t *) gregset);
c906108c
SS
1130 if (target_has_execution)
1131 procfs_ops.to_store_registers (-1);
1132 else
1133 orig_core_ops.to_store_registers (-1);
1134
1135 do_cleanups (old_chain);
1136
1137 return PS_OK;
1138}
1139
d4f3574e
SS
1140/* Log a message (sends to gdb_stderr). */
1141
c906108c 1142void
8d027a04 1143ps_plog (const char *fmt, ...)
c906108c
SS
1144{
1145 va_list args;
1146
1147 va_start (args, fmt);
1148
1149 vfprintf_filtered (gdb_stderr, fmt, args);
1150}
1151
1152/* Get size of extra register set. Currently a noop. */
1153
1154ps_err_e
1155ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
1156{
1157#if 0
1158 int lwp_fd;
1159 int regsize;
1160 ps_err_e val;
1161
1162 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1163 if (val != PS_OK)
1164 return val;
1165
1166 if (ioctl (lwp_fd, PIOCGXREGSIZE, &regsize))
1167 {
1168 if (errno == EINVAL)
1169 return PS_NOFREGS; /* XXX Wrong code, but this is the closest
1170 thing in proc_service.h */
1171
1172 print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
1173 return PS_ERR;
1174 }
1175#endif
1176
1177 return PS_OK;
1178}
1179
1180/* Get extra register set. Currently a noop. */
1181
1182ps_err_e
1183ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
1184{
1185#if 0
1186 int lwp_fd;
1187 ps_err_e val;
1188
1189 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1190 if (val != PS_OK)
1191 return val;
1192
1193 if (ioctl (lwp_fd, PIOCGXREG, xregset))
1194 {
1195 print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
1196 return PS_ERR;
1197 }
1198#endif
1199
1200 return PS_OK;
1201}
1202
1203/* Set extra register set. Currently a noop. */
1204
1205ps_err_e
1206ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
1207{
1208#if 0
1209 int lwp_fd;
1210 ps_err_e val;
1211
1212 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1213 if (val != PS_OK)
1214 return val;
1215
1216 if (ioctl (lwp_fd, PIOCSXREG, xregset))
1217 {
1218 print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
1219 return PS_ERR;
1220 }
1221#endif
1222
1223 return PS_OK;
1224}
1225
8d027a04 1226/* Get floating-point registers for LWP. */
c906108c
SS
1227
1228ps_err_e
1229ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
8d027a04 1230 prfpregset_t *fpregset)
c906108c
SS
1231{
1232 struct cleanup *old_chain;
1233
39f77062 1234 old_chain = save_inferior_ptid ();
c906108c 1235
39f77062 1236 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
c906108c
SS
1237
1238 if (target_has_execution)
1239 procfs_ops.to_fetch_registers (-1);
1240 else
1241 orig_core_ops.to_fetch_registers (-1);
c60c0f5f 1242 fill_fpregset ((gdb_fpregset_t *) fpregset, -1);
c906108c
SS
1243
1244 do_cleanups (old_chain);
1245
1246 return PS_OK;
1247}
1248
d4f3574e 1249/* Set floating-point regs for LWP */
c906108c
SS
1250
1251ps_err_e
1252ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
c5aa993b 1253 const prfpregset_t * fpregset)
c906108c
SS
1254{
1255 struct cleanup *old_chain;
1256
39f77062 1257 old_chain = save_inferior_ptid ();
c906108c 1258
39f77062 1259 inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
c5aa993b 1260
c60c0f5f 1261 supply_fpregset ((gdb_fpregset_t *) fpregset);
c906108c
SS
1262 if (target_has_execution)
1263 procfs_ops.to_store_registers (-1);
1264 else
1265 orig_core_ops.to_store_registers (-1);
1266
1267 do_cleanups (old_chain);
1268
1269 return PS_OK;
1270}
1271
23715f29 1272#ifdef PR_MODEL_LP64
8d027a04
MK
1273/* Identify process as 32-bit or 64-bit. At the moment we're using
1274 BFD to do this. There might be a more Solaris-specific
1275 (e.g. procfs) method, but this ought to work. */
23e04971
MS
1276
1277ps_err_e
1278ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model)
1279{
1280 if (exec_bfd == 0)
a95ac8b6
PS
1281 *data_model = PR_MODEL_UNKNOWN;
1282 else if (bfd_get_arch_size (exec_bfd) == 32)
23e04971
MS
1283 *data_model = PR_MODEL_ILP32;
1284 else
1285 *data_model = PR_MODEL_LP64;
1286
1287 return PS_OK;
1288}
23715f29 1289#endif /* PR_MODEL_LP64 */
23e04971 1290
c906108c
SS
1291#ifdef TM_I386SOL2_H
1292
d4f3574e
SS
1293/* Reads the local descriptor table of a LWP. */
1294
c906108c
SS
1295ps_err_e
1296ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1297 struct ssd *pldt)
1298{
8d027a04 1299 /* NOTE: only used on Solaris, therefore OK to refer to procfs.c. */
39f77062 1300 extern struct ssd *procfs_find_LDT_entry (ptid_t);
05e28a7b 1301 struct ssd *ret;
c906108c 1302
8d027a04
MK
1303 /* FIXME: can't I get the process ID from the prochandle or
1304 something? */
2f09097b 1305
39f77062 1306 if (PIDGET (inferior_ptid) <= 0 || lwpid <= 0)
2f09097b
ND
1307 return PS_BADLID;
1308
39f77062 1309 ret = procfs_find_LDT_entry (BUILD_LWP (lwpid, PIDGET (inferior_ptid)));
05e28a7b 1310 if (ret)
c906108c 1311 {
05e28a7b
AC
1312 memcpy (pldt, ret, sizeof (struct ssd));
1313 return PS_OK;
c906108c 1314 }
8d027a04
MK
1315 else
1316 /* LDT not found. */
c906108c 1317 return PS_ERR;
c5aa993b 1318}
c906108c
SS
1319#endif /* TM_I386SOL2_H */
1320\f
8d027a04
MK
1321
1322/* Convert PTID to printable form. */
c906108c
SS
1323
1324char *
39f77062 1325solaris_pid_to_str (ptid_t ptid)
c906108c
SS
1326{
1327 static char buf[100];
1328
8d027a04 1329 /* In case init failed to resolve the libthread_db library. */
c906108c 1330 if (!procfs_suppress_run)
39f77062 1331 return procfs_pid_to_str (ptid);
c906108c 1332
39f77062 1333 if (is_thread (ptid))
c906108c 1334 {
39f77062 1335 ptid_t lwp;
c906108c 1336
39f77062 1337 lwp = thread_to_lwp (ptid, -2);
c906108c 1338
39f77062
KB
1339 if (PIDGET (lwp) == -1)
1340 sprintf (buf, "Thread %ld (defunct)", GET_THREAD (ptid));
1341 else if (PIDGET (lwp) != -2)
8d027a04
MK
1342 sprintf (buf, "Thread %ld (LWP %ld)",
1343 GET_THREAD (ptid), GET_LWP (lwp));
c906108c 1344 else
39f77062 1345 sprintf (buf, "Thread %ld ", GET_THREAD (ptid));
c906108c 1346 }
39f77062
KB
1347 else if (GET_LWP (ptid) != 0)
1348 sprintf (buf, "LWP %ld ", GET_LWP (ptid));
c906108c 1349 else
39f77062 1350 sprintf (buf, "process %d ", PIDGET (ptid));
c906108c
SS
1351
1352 return buf;
1353}
1354\f
1355
8d027a04
MK
1356/* Worker bee for find_new_threads. Callback function that gets
1357 called once per user-level thread (i.e. not for LWP's). */
c906108c
SS
1358
1359static int
fba45db2 1360sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
c906108c
SS
1361{
1362 td_err_e retval;
1363 td_thrinfo_t ti;
39f77062 1364 ptid_t ptid;
c906108c 1365
8d027a04
MK
1366 retval = p_td_thr_get_info (th, &ti);
1367 if (retval != TD_OK)
1368 return -1;
1369
39f77062
KB
1370 ptid = BUILD_THREAD (ti.ti_tid, PIDGET (inferior_ptid));
1371 if (!in_thread_list (ptid))
1372 add_thread (ptid);
c906108c
SS
1373
1374 return 0;
1375}
1376
d4f3574e 1377static void
fba45db2 1378sol_find_new_threads (void)
c906108c 1379{
8d027a04
MK
1380 /* Don't do anything if init failed to resolve the libthread_db
1381 library. */
c906108c
SS
1382 if (!procfs_suppress_run)
1383 return;
1384
39f77062 1385 if (PIDGET (inferior_ptid) == -1)
c906108c 1386 {
c5aa993b 1387 printf_filtered ("No process.\n");
c906108c
SS
1388 return;
1389 }
8d027a04
MK
1390
1391 /* First Find any new LWP's. */
1392 procfs_ops.to_find_new_threads ();
1393
1394 /* Then find any new user-level threads. */
c5aa993b 1395 p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *) 0,
c906108c
SS
1396 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1397 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1398}
1399
1400static void
fba45db2 1401sol_core_open (char *filename, int from_tty)
c906108c
SS
1402{
1403 orig_core_ops.to_open (filename, from_tty);
1404}
1405
1406static void
fba45db2 1407sol_core_close (int quitting)
c906108c
SS
1408{
1409 orig_core_ops.to_close (quitting);
1410}
1411
1412static void
fba45db2 1413sol_core_detach (char *args, int from_tty)
c906108c
SS
1414{
1415 unpush_target (&core_ops);
1416 orig_core_ops.to_detach (args, from_tty);
1417}
1418
1419static void
fba45db2 1420sol_core_files_info (struct target_ops *t)
c906108c
SS
1421{
1422 orig_core_ops.to_files_info (t);
1423}
1424
8d027a04
MK
1425/* Worker bee for the "info sol-thread" command. This is a callback
1426 function that gets called once for each Solaris user-level thread
1427 (i.e. not for LWPs) in the inferior. Print anything interesting
1428 that we can think of. */
c906108c 1429
c5aa993b 1430static int
fba45db2 1431info_cb (const td_thrhandle_t *th, void *s)
c906108c
SS
1432{
1433 td_err_e ret;
1434 td_thrinfo_t ti;
c906108c 1435
8d027a04
MK
1436 ret = p_td_thr_get_info (th, &ti);
1437 if (ret == TD_OK)
c906108c 1438 {
c5aa993b
JM
1439 printf_filtered ("%s thread #%d, lwp %d, ",
1440 ti.ti_type == TD_THR_SYSTEM ? "system" : "user ",
c906108c 1441 ti.ti_tid, ti.ti_lid);
c5aa993b
JM
1442 switch (ti.ti_state)
1443 {
c906108c 1444 default:
c5aa993b
JM
1445 case TD_THR_UNKNOWN:
1446 printf_filtered ("<unknown state>");
1447 break;
1448 case TD_THR_STOPPED:
1449 printf_filtered ("(stopped)");
1450 break;
1451 case TD_THR_RUN:
1452 printf_filtered ("(run) ");
1453 break;
1454 case TD_THR_ACTIVE:
1455 printf_filtered ("(active) ");
1456 break;
1457 case TD_THR_ZOMBIE:
1458 printf_filtered ("(zombie) ");
1459 break;
1460 case TD_THR_SLEEP:
1461 printf_filtered ("(asleep) ");
1462 break;
1463 case TD_THR_STOPPED_ASLEEP:
1464 printf_filtered ("(stopped asleep)");
1465 break;
1466 }
8d027a04 1467 /* Print thr_create start function. */
c906108c 1468 if (ti.ti_startfunc != 0)
4ce44c66
JM
1469 {
1470 struct minimal_symbol *msym;
1471 msym = lookup_minimal_symbol_by_pc (ti.ti_startfunc);
1472 if (msym)
8d027a04
MK
1473 printf_filtered (" startfunc: %s\n",
1474 DEPRECATED_SYMBOL_NAME (msym));
4ce44c66
JM
1475 else
1476 printf_filtered (" startfunc: 0x%s\n", paddr (ti.ti_startfunc));
1477 }
c906108c 1478
8d027a04 1479 /* If thread is asleep, print function that went to sleep. */
c906108c 1480 if (ti.ti_state == TD_THR_SLEEP)
4ce44c66
JM
1481 {
1482 struct minimal_symbol *msym;
1483 msym = lookup_minimal_symbol_by_pc (ti.ti_pc);
1484 if (msym)
8d027a04
MK
1485 printf_filtered (" - Sleep func: %s\n",
1486 DEPRECATED_SYMBOL_NAME (msym));
4ce44c66
JM
1487 else
1488 printf_filtered (" - Sleep func: 0x%s\n", paddr (ti.ti_startfunc));
1489 }
c906108c 1490
8d027a04 1491 /* Wrap up line, if necessary. */
c906108c
SS
1492 if (ti.ti_state != TD_THR_SLEEP && ti.ti_startfunc == 0)
1493 printf_filtered ("\n"); /* don't you hate counting newlines? */
1494 }
1495 else
8a3fe4f8 1496 warning (_("info sol-thread: failed to get info for thread."));
c906108c 1497
c5aa993b 1498 return 0;
c906108c
SS
1499}
1500
8d027a04
MK
1501/* List some state about each Solaris user-level thread in the
1502 inferior. */
c906108c
SS
1503
1504static void
fba45db2 1505info_solthreads (char *args, int from_tty)
c906108c 1506{
c5aa993b 1507 p_td_ta_thr_iter (main_ta, info_cb, args,
c906108c
SS
1508 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1509 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1510}
c906108c 1511
be4d1333 1512static int
8d027a04
MK
1513sol_find_memory_regions (int (*func) (CORE_ADDR, unsigned long,
1514 int, int, int, void *),
be4d1333
MS
1515 void *data)
1516{
1517 return procfs_ops.to_find_memory_regions (func, data);
1518}
1519
1520static char *
1521sol_make_note_section (bfd *obfd, int *note_size)
1522{
1523 return procfs_ops.to_make_corefile_notes (obfd, note_size);
1524}
1525
c906108c 1526static int
8181d85f 1527ignore (struct bp_target_info *bp_tgt)
c906108c
SS
1528{
1529 return 0;
1530}
1531
c906108c 1532static void
fba45db2 1533init_sol_thread_ops (void)
c906108c
SS
1534{
1535 sol_thread_ops.to_shortname = "solaris-threads";
1536 sol_thread_ops.to_longname = "Solaris threads and pthread.";
1537 sol_thread_ops.to_doc = "Solaris threads and pthread support.";
1538 sol_thread_ops.to_open = sol_thread_open;
c906108c
SS
1539 sol_thread_ops.to_attach = sol_thread_attach;
1540 sol_thread_ops.to_detach = sol_thread_detach;
1541 sol_thread_ops.to_resume = sol_thread_resume;
1542 sol_thread_ops.to_wait = sol_thread_wait;
1543 sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
1544 sol_thread_ops.to_store_registers = sol_thread_store_registers;
1545 sol_thread_ops.to_prepare_to_store = sol_thread_prepare_to_store;
c8e73a31 1546 sol_thread_ops.deprecated_xfer_memory = sol_thread_xfer_memory;
6034ae49 1547 sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial;
c906108c
SS
1548 sol_thread_ops.to_files_info = sol_thread_files_info;
1549 sol_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
1550 sol_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
1551 sol_thread_ops.to_terminal_init = terminal_init_inferior;
1552 sol_thread_ops.to_terminal_inferior = terminal_inferior;
1553 sol_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1554 sol_thread_ops.to_terminal_ours = terminal_ours;
a790ad35 1555 sol_thread_ops.to_terminal_save_ours = terminal_save_ours;
c906108c
SS
1556 sol_thread_ops.to_terminal_info = child_terminal_info;
1557 sol_thread_ops.to_kill = sol_thread_kill_inferior;
c906108c
SS
1558 sol_thread_ops.to_create_inferior = sol_thread_create_inferior;
1559 sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
1560 sol_thread_ops.to_can_run = sol_thread_can_run;
1561 sol_thread_ops.to_notice_signals = sol_thread_notice_signals;
1562 sol_thread_ops.to_thread_alive = sol_thread_alive;
ed9a39eb 1563 sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
b83266a0 1564 sol_thread_ops.to_find_new_threads = sol_find_new_threads;
c906108c
SS
1565 sol_thread_ops.to_stop = sol_thread_stop;
1566 sol_thread_ops.to_stratum = process_stratum;
1567 sol_thread_ops.to_has_all_memory = 1;
1568 sol_thread_ops.to_has_memory = 1;
1569 sol_thread_ops.to_has_stack = 1;
1570 sol_thread_ops.to_has_registers = 1;
1571 sol_thread_ops.to_has_execution = 1;
1572 sol_thread_ops.to_has_thread_control = tc_none;
be4d1333
MS
1573 sol_thread_ops.to_find_memory_regions = sol_find_memory_regions;
1574 sol_thread_ops.to_make_corefile_notes = sol_make_note_section;
c906108c
SS
1575 sol_thread_ops.to_magic = OPS_MAGIC;
1576}
1577
c906108c 1578static void
fba45db2 1579init_sol_core_ops (void)
c906108c 1580{
c5aa993b
JM
1581 sol_core_ops.to_shortname = "solaris-core";
1582 sol_core_ops.to_longname = "Solaris core threads and pthread.";
1583 sol_core_ops.to_doc = "Solaris threads and pthread support for core files.";
1584 sol_core_ops.to_open = sol_core_open;
1585 sol_core_ops.to_close = sol_core_close;
1586 sol_core_ops.to_attach = sol_thread_attach;
1587 sol_core_ops.to_detach = sol_core_detach;
c5aa993b 1588 sol_core_ops.to_fetch_registers = sol_thread_fetch_registers;
c8e73a31 1589 sol_core_ops.deprecated_xfer_memory = sol_thread_xfer_memory;
6034ae49 1590 sol_core_ops.to_xfer_partial = sol_thread_xfer_partial;
c5aa993b
JM
1591 sol_core_ops.to_files_info = sol_core_files_info;
1592 sol_core_ops.to_insert_breakpoint = ignore;
1593 sol_core_ops.to_remove_breakpoint = ignore;
c5aa993b
JM
1594 sol_core_ops.to_create_inferior = sol_thread_create_inferior;
1595 sol_core_ops.to_stratum = core_stratum;
c5aa993b
JM
1596 sol_core_ops.to_has_memory = 1;
1597 sol_core_ops.to_has_stack = 1;
1598 sol_core_ops.to_has_registers = 1;
c5aa993b 1599 sol_core_ops.to_has_thread_control = tc_none;
db348f27 1600 sol_core_ops.to_thread_alive = sol_thread_alive;
ed9a39eb 1601 sol_core_ops.to_pid_to_str = solaris_pid_to_str;
8d027a04
MK
1602 /* On Solaris/x86, when debugging a threaded core file from process
1603 <n>, the following causes "info threads" to produce "procfs:
1604 couldn't find pid <n> in procinfo list" where <n> is the pid of
1605 the process that produced the core file. Disable it for now. */
1606#if 0
1607 sol_core_ops.to_find_new_threads = sol_find_new_threads;
1608#endif
c5aa993b 1609 sol_core_ops.to_magic = OPS_MAGIC;
c906108c
SS
1610}
1611
8d027a04
MK
1612/* We suppress the call to add_target of core_ops in corelow because
1613 if there are two targets in the stratum core_stratum,
1614 find_core_target won't know which one to return. See corelow.c for
1615 an additonal comment on coreops_suppress_target. */
c906108c
SS
1616int coreops_suppress_target = 1;
1617
1618void
fba45db2 1619_initialize_sol_thread (void)
c906108c
SS
1620{
1621 void *dlhandle;
1622
1623 init_sol_thread_ops ();
1624 init_sol_core_ops ();
1625
1626 dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
1627 if (!dlhandle)
1628 goto die;
1629
1630#define resolve(X) \
1631 if (!(p_##X = dlsym (dlhandle, #X))) \
1632 goto die;
1633
1634 resolve (td_log);
1635 resolve (td_ta_new);
1636 resolve (td_ta_delete);
1637 resolve (td_init);
1638 resolve (td_ta_get_ph);
1639 resolve (td_ta_get_nthreads);
1640 resolve (td_ta_tsd_iter);
1641 resolve (td_ta_thr_iter);
1642 resolve (td_thr_validate);
1643 resolve (td_thr_tsd);
1644 resolve (td_thr_get_info);
1645 resolve (td_thr_getfpregs);
1646 resolve (td_thr_getxregsize);
1647 resolve (td_thr_getxregs);
1648 resolve (td_thr_sigsetmask);
1649 resolve (td_thr_setprio);
1650 resolve (td_thr_setsigpending);
1651 resolve (td_thr_setfpregs);
1652 resolve (td_thr_setxregs);
1653 resolve (td_ta_map_id2thr);
1654 resolve (td_ta_map_lwp2thr);
1655 resolve (td_thr_getgregs);
1656 resolve (td_thr_setgregs);
1657
1658 add_target (&sol_thread_ops);
1659
1660 procfs_suppress_run = 1;
1661
c5aa993b 1662 add_cmd ("sol-threads", class_maintenance, info_solthreads,
1a966eab 1663 _("Show info on Solaris user threads."), &maintenanceinfolist);
c906108c 1664
c5aa993b
JM
1665 memcpy (&orig_core_ops, &core_ops, sizeof (struct target_ops));
1666 memcpy (&core_ops, &sol_core_ops, sizeof (struct target_ops));
c906108c
SS
1667 add_target (&core_ops);
1668
8d027a04 1669 /* Hook into new_objfile notification. */
9a4105ab
AC
1670 target_new_objfile_chain = deprecated_target_new_objfile_hook;
1671 deprecated_target_new_objfile_hook = sol_thread_new_objfile;
c906108c
SS
1672 return;
1673
8d027a04
MK
1674 die:
1675 fprintf_unfiltered (gdb_stderr, "\
1676[GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
c906108c
SS
1677
1678 if (dlhandle)
1679 dlclose (dlhandle);
1680
8d027a04 1681 /* Allow the user to debug non-threaded core files. */
c5aa993b 1682 add_target (&core_ops);
c906108c
SS
1683
1684 return;
1685}