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