* symtab.c (symbol_search_name): Minor reformatting.
[deliverable/binutils-gdb.git] / gdb / hpux-thread.c
CommitLineData
1df84f13
AC
1/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU
2 debugger.
3
4 Copyright 1996, 1998, 1999, 2000, 2001, 2004 Free Software
5 Foundation, Inc.
c906108c 6
c5aa993b 7 This file is part of GDB.
c906108c 8
c5aa993b
JM
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
c906108c 13
c5aa993b
JM
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
c906108c 18
c5aa993b
JM
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
c906108c
SS
23
24/* This module implements a sort of half target that sits between the
25 machine-independent parts of GDB and the ptrace interface (infptrace.c) to
26 provide access to the HPUX user-mode thread implementation.
27
28 HPUX threads are true user-mode threads, which are invoked via the cma_*
29 and pthread_* (DCE and Posix respectivly) interfaces. These are mostly
30 implemented in user-space, with all thread context kept in various
31 structures that live in the user's heap. For the most part, the kernel has
32 no knowlege of these threads.
33
c5aa993b 34 */
c906108c
SS
35
36#include "defs.h"
37
38#define _CMA_NOWRAPPERS_
39
40#include <cma_tcb_defs.h>
41#include <cma_deb_core.h>
42#include "gdbthread.h"
43#include "target.h"
44#include "inferior.h"
4e052eda 45#include "regcache.h"
c906108c 46#include <fcntl.h>
b8a92b82 47#include "gdb_stat.h"
c906108c
SS
48#include "gdbcore.h"
49
50extern int child_suppress_run;
c906108c 51
a14ed312 52extern void _initialize_hpux_thread (void);
c906108c
SS
53
54struct string_map
c5aa993b
JM
55 {
56 int num;
57 char *str;
58 };
c906108c
SS
59
60static int hpux_thread_active = 0;
61
39f77062 62static ptid_t main_ptid; /* Real process ID */
c906108c
SS
63
64static CORE_ADDR P_cma__g_known_threads;
65static CORE_ADDR P_cma__g_current_thread;
66
39f77062
KB
67static void hpux_thread_resume (ptid_t ptid, int step,
68 enum target_signal signo);
c906108c 69
a14ed312 70static void init_hpux_thread_ops (void);
c906108c
SS
71
72static struct target_ops hpux_thread_ops;
73\f
f7926acf 74static ptid_t find_active_thread (void);
c906108c
SS
75
76static int cached_thread;
c906108c
SS
77static cma__t_int_tcb cached_tcb;
78
f7926acf 79static ptid_t
fba45db2 80find_active_thread (void)
c906108c
SS
81{
82 static cma__t_int_tcb tcb;
83 CORE_ADDR tcb_ptr;
84
c5aa993b
JM
85 read_memory ((CORE_ADDR) P_cma__g_current_thread,
86 (char *) &tcb_ptr,
c906108c
SS
87 sizeof tcb_ptr);
88
c5aa993b 89 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
c906108c 90
f7926acf
JB
91 return (ptid_build (PIDGET (main_ptid), 0,
92 cma_thread_get_unique (&tcb.prolog.client_thread)));
c906108c
SS
93}
94
f7926acf 95static cma__t_int_tcb *find_tcb (ptid_t ptid);
c906108c
SS
96
97static cma__t_int_tcb *
f7926acf 98find_tcb (ptid_t ptid)
c906108c
SS
99{
100 cma__t_known_object queue_header;
101 cma__t_queue *queue_ptr;
f7926acf 102 int thread = ptid_get_tid (ptid);
c906108c
SS
103
104 if (thread == cached_thread)
105 return &cached_tcb;
106
c5aa993b
JM
107 read_memory ((CORE_ADDR) P_cma__g_known_threads,
108 (char *) &queue_header,
c906108c
SS
109 sizeof queue_header);
110
111 for (queue_ptr = queue_header.queue.flink;
c5aa993b 112 queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
c906108c
SS
113 queue_ptr = cached_tcb.threads.flink)
114 {
115 cma__t_int_tcb *tcb_ptr;
116
117 tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
118
c5aa993b 119 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
c906108c
SS
120
121 if (cached_tcb.header.type == cma__c_obj_tcb)
f7926acf 122 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
c906108c
SS
123 {
124 cached_thread = thread;
125 return &cached_tcb;
126 }
127 }
128
f7926acf 129 error ("Can't find TCB %d", thread);
c906108c
SS
130 return NULL;
131}
132\f
133/* Most target vector functions from here on actually just pass through to
134 inftarg.c, as they don't need to do anything specific for threads. */
135
c906108c 136static void
fba45db2 137hpux_thread_open (char *arg, int from_tty)
c906108c 138{
1df84f13 139 deprecated_child_ops.to_open (arg, from_tty);
c906108c
SS
140}
141
142/* Attach to process PID, then initialize for debugging it
143 and wait for the trace-trap that results from attaching. */
144
145static void
fba45db2 146hpux_thread_attach (char *args, int from_tty)
c906108c 147{
1df84f13 148 deprecated_child_ops.to_attach (args, from_tty);
c906108c
SS
149
150 /* XXX - might want to iterate over all the threads and register them. */
151}
152
153/* Take a program previously attached to and detaches it.
154 The program resumes execution and will no longer stop
155 on signals, etc. We'd better not have left any breakpoints
156 in the program or it'll die when it hits one. For this
157 to work, it may be necessary for the process to have been
158 previously attached. It *might* work if the program was
159 started via the normal ptrace (PTRACE_TRACEME). */
160
161static void
fba45db2 162hpux_thread_detach (char *args, int from_tty)
c906108c 163{
1df84f13 164 deprecated_child_ops.to_detach (args, from_tty);
c906108c
SS
165}
166
167/* Resume execution of process PID. If STEP is nozero, then
168 just single step it. If SIGNAL is nonzero, restart it with that
169 signal activated. We may have to convert pid from a thread-id to an LWP id
170 for procfs. */
171
172static void
39f77062 173hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
c906108c
SS
174{
175 struct cleanup *old_chain;
176
39f77062 177 old_chain = save_inferior_ptid ();
c906108c 178
39f77062
KB
179 ptid = main_ptid;
180 inferior_ptid = main_ptid;
c906108c
SS
181
182#if 0
183 if (pid != -1)
184 {
185 pid = thread_to_lwp (pid, -2);
186 if (pid == -2) /* Inactive thread */
187 error ("This version of Solaris can't start inactive threads.");
188 }
189#endif
190
1df84f13 191 deprecated_child_ops.to_resume (ptid, step, signo);
c906108c
SS
192
193 cached_thread = 0;
c906108c
SS
194
195 do_cleanups (old_chain);
196}
197
198/* Wait for any threads to stop. We may have to convert PID from a thread id
199 to a LWP id, and vice versa on the way out. */
200
39f77062
KB
201static ptid_t
202hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c 203{
39f77062 204 ptid_t rtnval;
c906108c
SS
205 struct cleanup *old_chain;
206
39f77062 207 old_chain = save_inferior_ptid ();
c906108c 208
39f77062 209 inferior_ptid = main_ptid;
c906108c 210
39f77062
KB
211 if (!ptid_equal (ptid, minus_one_ptid))
212 ptid = main_ptid;
c906108c 213
1df84f13 214 rtnval = deprecated_child_ops.to_wait (ptid, ourstatus);
c906108c
SS
215
216 rtnval = find_active_thread ();
217
218 do_cleanups (old_chain);
219
220 return rtnval;
221}
222
223static char regmap[NUM_REGS] =
224{
c5aa993b
JM
225 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
226 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
227 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
c906108c
SS
228
229 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
230 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
231
232 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
233 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
234
235 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
236 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
237
238 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
c5aa993b
JM
239 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
240 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
241 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
242 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
243 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
244 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
245 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
246 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
c906108c
SS
247};
248
249static void
fba45db2 250hpux_thread_fetch_registers (int regno)
c906108c
SS
251{
252 cma__t_int_tcb tcb, *tcb_ptr;
253 struct cleanup *old_chain;
254 int i;
255 int first_regno, last_regno;
256
f7926acf 257 tcb_ptr = find_tcb (inferior_ptid);
c906108c 258
39f77062 259 old_chain = save_inferior_ptid ();
c906108c 260
39f77062 261 inferior_ptid = main_ptid;
c906108c
SS
262
263 if (tcb_ptr->state == cma__c_state_running)
264 {
1df84f13 265 deprecated_child_ops.to_fetch_registers (regno);
c906108c
SS
266
267 do_cleanups (old_chain);
268
269 return;
270 }
271
272 if (regno == -1)
273 {
274 first_regno = 0;
275 last_regno = NUM_REGS - 1;
276 }
277 else
278 {
279 first_regno = regno;
280 last_regno = regno;
281 }
282
283 for (regno = first_regno; regno <= last_regno; regno++)
284 {
285 if (regmap[regno] == -1)
1df84f13 286 deprecated_child_ops.to_fetch_registers (regno);
c906108c
SS
287 else
288 {
123a958e 289 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
290 CORE_ADDR sp;
291
c5aa993b 292 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
293
294 if (regno == FLAGS_REGNUM)
295 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
3acba339 296 memset (buf, '\000', register_size (current_gdbarch, regno));
c906108c 297 else if (regno == SP_REGNUM)
fbd9dcd3 298 store_unsigned_integer (buf, sizeof sp, sp);
c906108c 299 else if (regno == PC_REGNUM)
3acba339 300 read_memory (sp - 20, buf, register_size (current_gdbarch, regno));
c906108c 301 else
3acba339 302 read_memory (sp + regmap[regno], buf, register_size (current_gdbarch, regno));
c906108c 303
23a6d369 304 regcache_raw_supply (current_regcache, regno, buf);
c906108c
SS
305 }
306 }
307
308 do_cleanups (old_chain);
309}
310
311static void
fba45db2 312hpux_thread_store_registers (int regno)
c906108c
SS
313{
314 cma__t_int_tcb tcb, *tcb_ptr;
315 struct cleanup *old_chain;
316 int i;
317 int first_regno, last_regno;
318
f7926acf 319 tcb_ptr = find_tcb (inferior_ptid);
c906108c 320
39f77062 321 old_chain = save_inferior_ptid ();
c906108c 322
39f77062 323 inferior_ptid = main_ptid;
c906108c
SS
324
325 if (tcb_ptr->state == cma__c_state_running)
326 {
1df84f13 327 deprecated_child_ops.to_store_registers (regno);
c906108c
SS
328
329 do_cleanups (old_chain);
330
331 return;
332 }
333
334 if (regno == -1)
335 {
336 first_regno = 0;
337 last_regno = NUM_REGS - 1;
338 }
339 else
340 {
341 first_regno = regno;
342 last_regno = regno;
343 }
344
345 for (regno = first_regno; regno <= last_regno; regno++)
346 {
347 if (regmap[regno] == -1)
1df84f13 348 deprecated_child_ops.to_store_registers (regno);
c906108c
SS
349 else
350 {
123a958e 351 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
352 CORE_ADDR sp;
353
c5aa993b 354 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
355
356 if (regno == FLAGS_REGNUM)
1df84f13 357 deprecated_child_ops.to_store_registers (regno); /* Let lower layer handle this... */
c906108c
SS
358 else if (regno == SP_REGNUM)
359 {
c5aa993b 360 write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
62700349 361 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
3acba339 362 register_size (current_gdbarch, regno));
c906108c 363 tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
62700349 364 (extract_unsigned_integer (&deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
3acba339 365 register_size (current_gdbarch, regno)) + 160);
c906108c
SS
366 }
367 else if (regno == PC_REGNUM)
368 write_memory (sp - 20,
62700349 369 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
3acba339 370 register_size (current_gdbarch, regno));
c906108c
SS
371 else
372 write_memory (sp + regmap[regno],
62700349 373 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
3acba339 374 register_size (current_gdbarch, regno));
c906108c
SS
375 }
376 }
377
378 do_cleanups (old_chain);
379}
380
381/* Get ready to modify the registers array. On machines which store
382 individual registers, this doesn't need to do anything. On machines
383 which store all the registers in one fell swoop, this makes sure
384 that registers contains all the registers from the program being
385 debugged. */
386
387static void
fba45db2 388hpux_thread_prepare_to_store (void)
c906108c 389{
1df84f13 390 deprecated_child_ops.to_prepare_to_store ();
c906108c
SS
391}
392
393static int
165a58fe 394hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
971429b4
AC
395 int dowrite, struct mem_attrib *attribs,
396 struct target_ops *target)
c906108c
SS
397{
398 int retval;
399 struct cleanup *old_chain;
400
39f77062 401 old_chain = save_inferior_ptid ();
c906108c 402
39f77062 403 inferior_ptid = main_ptid;
c906108c 404
971429b4 405 retval =
c8e73a31 406 deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
c906108c
SS
407
408 do_cleanups (old_chain);
409
410 return retval;
411}
412
413/* Print status information about what we're accessing. */
414
415static void
fba45db2 416hpux_thread_files_info (struct target_ops *ignore)
c906108c 417{
1df84f13 418 deprecated_child_ops.to_files_info (ignore);
c906108c
SS
419}
420
421static void
fba45db2 422hpux_thread_kill_inferior (void)
c906108c 423{
1df84f13 424 deprecated_child_ops.to_kill ();
c906108c
SS
425}
426
427static void
39f77062 428hpux_thread_notice_signals (ptid_t ptid)
c906108c 429{
1df84f13 430 deprecated_child_ops.to_notice_signals (ptid);
c906108c
SS
431}
432
433/* Fork an inferior process, and start debugging it with /proc. */
434
435static void
c27cda74
AC
436hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
437 int from_tty)
c906108c 438{
1df84f13 439 deprecated_child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
c906108c
SS
440
441 if (hpux_thread_active)
442 {
39f77062 443 main_ptid = inferior_ptid;
c906108c
SS
444
445 push_target (&hpux_thread_ops);
446
39f77062 447 inferior_ptid = find_active_thread ();
c906108c 448
39f77062 449 add_thread (inferior_ptid);
c906108c
SS
450 }
451}
452
453/* This routine is called whenever a new symbol table is read in, or when all
454 symbol tables are removed. libthread_db can only be initialized when it
455 finds the right variables in libthread.so. Since it's a shared library,
456 those variables don't show up until the library gets mapped and the symbol
457 table is read in. */
458
11cf8741
JM
459/* This new_objfile event is now managed by a chained function pointer.
460 * It is the callee's responsability to call the next client on the chain.
461 */
462
463/* Saved pointer to previous owner of the new_objfile event. */
507f3c78 464static void (*target_new_objfile_chain) (struct objfile *);
11cf8741 465
c906108c 466void
fba45db2 467hpux_thread_new_objfile (struct objfile *objfile)
c906108c
SS
468{
469 struct minimal_symbol *ms;
470
471 if (!objfile)
472 {
473 hpux_thread_active = 0;
11cf8741 474 goto quit;
c906108c
SS
475 }
476
477 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
478
479 if (!ms)
11cf8741 480 goto quit;
c906108c
SS
481
482 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
483
484 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
485
486 if (!ms)
11cf8741 487 goto quit;
c906108c
SS
488
489 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
490
491 hpux_thread_active = 1;
11cf8741
JM
492quit:
493 /* Call predecessor on chain, if any. */
494 if (target_new_objfile_chain)
495 target_new_objfile_chain (objfile);
c906108c
SS
496}
497
498/* Clean up after the inferior dies. */
499
500static void
fba45db2 501hpux_thread_mourn_inferior (void)
c906108c 502{
1df84f13 503 deprecated_child_ops.to_mourn_inferior ();
c906108c
SS
504}
505
506/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
507
508static int
fba45db2 509hpux_thread_can_run (void)
c906108c
SS
510{
511 return child_suppress_run;
512}
513
514static int
39f77062 515hpux_thread_alive (ptid_t ptid)
c906108c
SS
516{
517 return 1;
518}
519
520static void
fba45db2 521hpux_thread_stop (void)
c906108c 522{
1df84f13 523 deprecated_child_ops.to_stop ();
c906108c
SS
524}
525\f
526/* Convert a pid to printable form. */
527
528char *
39f77062 529hpux_pid_to_str (ptid_t ptid)
c906108c
SS
530{
531 static char buf[100];
39f77062 532 int pid = PIDGET (ptid);
c906108c 533
f7926acf 534 sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
c906108c
SS
535
536 return buf;
537}
538\f
539static void
fba45db2 540init_hpux_thread_ops (void)
c906108c
SS
541{
542 hpux_thread_ops.to_shortname = "hpux-threads";
543 hpux_thread_ops.to_longname = "HPUX threads and pthread.";
544 hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
545 hpux_thread_ops.to_open = hpux_thread_open;
546 hpux_thread_ops.to_attach = hpux_thread_attach;
547 hpux_thread_ops.to_detach = hpux_thread_detach;
548 hpux_thread_ops.to_resume = hpux_thread_resume;
549 hpux_thread_ops.to_wait = hpux_thread_wait;
550 hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
551 hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
552 hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
c8e73a31 553 hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
c906108c
SS
554 hpux_thread_ops.to_files_info = hpux_thread_files_info;
555 hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
556 hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
557 hpux_thread_ops.to_terminal_init = terminal_init_inferior;
558 hpux_thread_ops.to_terminal_inferior = terminal_inferior;
559 hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
a790ad35 560 hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
c906108c
SS
561 hpux_thread_ops.to_terminal_ours = terminal_ours;
562 hpux_thread_ops.to_terminal_info = child_terminal_info;
563 hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
564 hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
565 hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
566 hpux_thread_ops.to_can_run = hpux_thread_can_run;
567 hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
b83266a0 568 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
c906108c
SS
569 hpux_thread_ops.to_stop = hpux_thread_stop;
570 hpux_thread_ops.to_stratum = process_stratum;
571 hpux_thread_ops.to_has_all_memory = 1;
572 hpux_thread_ops.to_has_memory = 1;
573 hpux_thread_ops.to_has_stack = 1;
574 hpux_thread_ops.to_has_registers = 1;
575 hpux_thread_ops.to_has_execution = 1;
576 hpux_thread_ops.to_magic = OPS_MAGIC;
577}
578
579void
fba45db2 580_initialize_hpux_thread (void)
c906108c
SS
581{
582 init_hpux_thread_ops ();
583 add_target (&hpux_thread_ops);
584
585 child_suppress_run = 1;
11cf8741 586 /* Hook into new_objfile notification. */
9a4105ab
AC
587 target_new_objfile_chain = deprecated_target_new_objfile_hook;
588 deprecated_target_new_objfile_hook = hpux_thread_new_objfile;
c906108c 589}
This page took 0.447549 seconds and 4 git commands to generate.