1 /* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
2 Copyright 1996, 1999 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
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.
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.
35 #define _CMA_NOWRAPPERS_
37 #include <cma_tcb_defs.h>
38 #include <cma_deb_core.h>
39 #include "gdbthread.h"
46 extern int child_suppress_run;
47 extern struct target_ops child_ops; /* target vector for inftarg.c */
49 extern void _initialize_hpux_thread (void);
57 static int hpux_thread_active = 0;
59 static int main_pid; /* Real process ID */
61 static CORE_ADDR P_cma__g_known_threads;
62 static CORE_ADDR P_cma__g_current_thread;
64 static struct cleanup *save_inferior_pid (void);
66 static void restore_inferior_pid (int pid);
68 static void hpux_thread_resume (int pid, int step, enum target_signal signo);
70 static void init_hpux_thread_ops (void);
72 static struct target_ops hpux_thread_ops;
78 save_inferior_pid - Save inferior_pid on the cleanup list
79 restore_inferior_pid - Restore inferior_pid from the cleanup list
83 struct cleanup *save_inferior_pid ()
84 void restore_inferior_pid (int pid)
88 These two functions act in unison to restore inferior_pid in
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.
102 static struct cleanup *
105 return make_cleanup (restore_inferior_pid, inferior_pid);
109 restore_inferior_pid (pid)
115 static int find_active_thread (void);
117 static int cached_thread;
118 static int cached_active_thread;
119 static cma__t_int_tcb cached_tcb;
122 find_active_thread ()
124 static cma__t_int_tcb tcb;
127 if (cached_active_thread != 0)
128 return cached_active_thread;
130 read_memory ((CORE_ADDR) P_cma__g_current_thread,
134 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
136 return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid;
139 static cma__t_int_tcb *find_tcb (int thread);
141 static cma__t_int_tcb *
145 cma__t_known_object queue_header;
146 cma__t_queue *queue_ptr;
148 if (thread == cached_thread)
151 read_memory ((CORE_ADDR) P_cma__g_known_threads,
152 (char *) &queue_header,
153 sizeof queue_header);
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)
159 cma__t_int_tcb *tcb_ptr;
161 tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
163 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
165 if (cached_tcb.header.type == cma__c_obj_tcb)
166 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
168 cached_thread = thread;
173 error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
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. */
182 hpux_thread_open (arg, from_tty)
186 child_ops.to_open (arg, from_tty);
189 /* Attach to process PID, then initialize for debugging it
190 and wait for the trace-trap that results from attaching. */
193 hpux_thread_attach (args, from_tty)
197 child_ops.to_attach (args, from_tty);
199 /* XXX - might want to iterate over all the threads and register them. */
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). */
211 hpux_thread_detach (args, from_tty)
215 child_ops.to_detach (args, from_tty);
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
224 hpux_thread_resume (pid, step, signo)
227 enum target_signal signo;
229 struct cleanup *old_chain;
231 old_chain = save_inferior_pid ();
233 pid = inferior_pid = main_pid;
238 pid = thread_to_lwp (pid, -2);
239 if (pid == -2) /* Inactive thread */
240 error ("This version of Solaris can't start inactive threads.");
244 child_ops.to_resume (pid, step, signo);
247 cached_active_thread = 0;
249 do_cleanups (old_chain);
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. */
256 hpux_thread_wait (pid, ourstatus)
258 struct target_waitstatus *ourstatus;
261 struct cleanup *old_chain;
263 old_chain = save_inferior_pid ();
265 inferior_pid = main_pid;
270 rtnval = child_ops.to_wait (pid, ourstatus);
272 rtnval = find_active_thread ();
274 do_cleanups (old_chain);
279 static char regmap[NUM_REGS] =
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 */
285 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
286 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
288 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
289 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
291 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
292 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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 */
306 hpux_thread_fetch_registers (regno)
309 cma__t_int_tcb tcb, *tcb_ptr;
310 struct cleanup *old_chain;
312 int first_regno, last_regno;
314 tcb_ptr = find_tcb (inferior_pid);
316 old_chain = save_inferior_pid ();
318 inferior_pid = main_pid;
320 if (tcb_ptr->state == cma__c_state_running)
322 child_ops.to_fetch_registers (regno);
324 do_cleanups (old_chain);
332 last_regno = NUM_REGS - 1;
340 for (regno = first_regno; regno <= last_regno; regno++)
342 if (regmap[regno] == -1)
343 child_ops.to_fetch_registers (regno);
346 unsigned char buf[MAX_REGISTER_RAW_SIZE];
349 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
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));
359 read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
361 supply_register (regno, buf);
365 do_cleanups (old_chain);
369 hpux_thread_store_registers (regno)
372 cma__t_int_tcb tcb, *tcb_ptr;
373 struct cleanup *old_chain;
375 int first_regno, last_regno;
377 tcb_ptr = find_tcb (inferior_pid);
379 old_chain = save_inferior_pid ();
381 inferior_pid = main_pid;
383 if (tcb_ptr->state == cma__c_state_running)
385 child_ops.to_store_registers (regno);
387 do_cleanups (old_chain);
395 last_regno = NUM_REGS - 1;
403 for (regno = first_regno; regno <= last_regno; regno++)
405 if (regmap[regno] == -1)
406 child_ops.to_store_registers (regno);
409 unsigned char buf[MAX_REGISTER_RAW_SIZE];
412 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
414 if (regno == FLAGS_REGNUM)
415 child_ops.to_store_registers (regno); /* Let lower layer handle this... */
416 else if (regno == SP_REGNUM)
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);
424 else if (regno == PC_REGNUM)
425 write_memory (sp - 20,
426 registers + REGISTER_BYTE (regno),
427 REGISTER_RAW_SIZE (regno));
429 write_memory (sp + regmap[regno],
430 registers + REGISTER_BYTE (regno),
431 REGISTER_RAW_SIZE (regno));
435 do_cleanups (old_chain);
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
445 hpux_thread_prepare_to_store ()
447 child_ops.to_prepare_to_store ();
451 hpux_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
456 struct target_ops *target; /* ignored */
459 struct cleanup *old_chain;
461 old_chain = save_inferior_pid ();
463 inferior_pid = main_pid;
465 retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
467 do_cleanups (old_chain);
472 /* Print status information about what we're accessing. */
475 hpux_thread_files_info (ignore)
476 struct target_ops *ignore;
478 child_ops.to_files_info (ignore);
482 hpux_thread_kill_inferior ()
484 child_ops.to_kill ();
488 hpux_thread_notice_signals (pid)
491 child_ops.to_notice_signals (pid);
494 /* Fork an inferior process, and start debugging it with /proc. */
497 hpux_thread_create_inferior (exec_file, allargs, env)
502 child_ops.to_create_inferior (exec_file, allargs, env);
504 if (hpux_thread_active)
506 main_pid = inferior_pid;
508 push_target (&hpux_thread_ops);
510 inferior_pid = find_active_thread ();
512 add_thread (inferior_pid);
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
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.
526 /* Saved pointer to previous owner of the new_objfile event. */
527 static void (*target_new_objfile_chain) PARAMS ((struct objfile *));
530 hpux_thread_new_objfile (objfile)
531 struct objfile *objfile;
533 struct minimal_symbol *ms;
537 hpux_thread_active = 0;
541 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
546 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
548 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
553 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
555 hpux_thread_active = 1;
557 /* Call predecessor on chain, if any. */
558 if (target_new_objfile_chain)
559 target_new_objfile_chain (objfile);
562 /* Clean up after the inferior dies. */
565 hpux_thread_mourn_inferior ()
567 child_ops.to_mourn_inferior ();
570 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
573 hpux_thread_can_run ()
575 return child_suppress_run;
579 hpux_thread_alive (pid)
588 child_ops.to_stop ();
591 /* Convert a pid to printable form. */
594 hpux_pid_to_str (pid)
597 static char buf[100];
599 sprintf (buf, "Thread %d", pid >> 16);
605 init_hpux_thread_ops ()
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;
644 _initialize_hpux_thread ()
646 init_hpux_thread_ops ();
647 add_target (&hpux_thread_ops);
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;