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