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"
47 extern int child_suppress_run;
48 extern struct target_ops child_ops; /* target vector for inftarg.c */
50 extern void _initialize_hpux_thread PARAMS ((void));
58 static int hpux_thread_active = 0;
60 static int main_pid; /* Real process ID */
62 static CORE_ADDR P_cma__g_known_threads;
63 static CORE_ADDR P_cma__g_current_thread;
65 static struct cleanup *save_inferior_pid PARAMS ((void));
67 static void restore_inferior_pid PARAMS ((int pid));
69 static void hpux_thread_resume PARAMS ((int pid, int step,
70 enum target_signal signo));
72 static void init_hpux_thread_ops PARAMS ((void));
74 static struct target_ops hpux_thread_ops;
80 save_inferior_pid - Save inferior_pid on the cleanup list
81 restore_inferior_pid - Restore inferior_pid from the cleanup list
85 struct cleanup *save_inferior_pid ()
86 void restore_inferior_pid (int pid)
90 These two functions act in unison to restore inferior_pid in
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.
104 static struct cleanup *
107 return make_cleanup (restore_inferior_pid, inferior_pid);
111 restore_inferior_pid (pid)
117 static int find_active_thread PARAMS ((void));
119 static int cached_thread;
120 static int cached_active_thread;
121 static cma__t_int_tcb cached_tcb;
124 find_active_thread ()
126 static cma__t_int_tcb tcb;
129 if (cached_active_thread != 0)
130 return cached_active_thread;
132 read_memory ((CORE_ADDR) P_cma__g_current_thread,
136 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
138 return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid;
141 static cma__t_int_tcb *find_tcb PARAMS ((int thread));
143 static cma__t_int_tcb *
147 cma__t_known_object queue_header;
148 cma__t_queue *queue_ptr;
150 if (thread == cached_thread)
153 read_memory ((CORE_ADDR) P_cma__g_known_threads,
154 (char *) &queue_header,
155 sizeof queue_header);
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)
161 cma__t_int_tcb *tcb_ptr;
163 tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
165 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
167 if (cached_tcb.header.type == cma__c_obj_tcb)
168 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
170 cached_thread = thread;
175 error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
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. */
184 hpux_thread_open (arg, from_tty)
188 child_ops.to_open (arg, from_tty);
191 /* Attach to process PID, then initialize for debugging it
192 and wait for the trace-trap that results from attaching. */
195 hpux_thread_attach (args, from_tty)
199 child_ops.to_attach (args, from_tty);
201 /* XXX - might want to iterate over all the threads and register them. */
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). */
213 hpux_thread_detach (args, from_tty)
217 child_ops.to_detach (args, from_tty);
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
226 hpux_thread_resume (pid, step, signo)
229 enum target_signal signo;
231 struct cleanup *old_chain;
233 old_chain = save_inferior_pid ();
235 pid = inferior_pid = main_pid;
240 pid = thread_to_lwp (pid, -2);
241 if (pid == -2) /* Inactive thread */
242 error ("This version of Solaris can't start inactive threads.");
246 child_ops.to_resume (pid, step, signo);
249 cached_active_thread = 0;
251 do_cleanups (old_chain);
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. */
258 hpux_thread_wait (pid, ourstatus)
260 struct target_waitstatus *ourstatus;
263 struct cleanup *old_chain;
265 old_chain = save_inferior_pid ();
267 inferior_pid = main_pid;
272 rtnval = child_ops.to_wait (pid, ourstatus);
274 rtnval = find_active_thread ();
276 do_cleanups (old_chain);
281 static char regmap[NUM_REGS] =
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 */
287 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
288 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
290 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
291 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
293 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
294 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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 */
308 hpux_thread_fetch_registers (regno)
311 cma__t_int_tcb tcb, *tcb_ptr;
312 struct cleanup *old_chain;
314 int first_regno, last_regno;
316 tcb_ptr = find_tcb (inferior_pid);
318 old_chain = save_inferior_pid ();
320 inferior_pid = main_pid;
322 if (tcb_ptr->state == cma__c_state_running)
324 child_ops.to_fetch_registers (regno);
326 do_cleanups (old_chain);
334 last_regno = NUM_REGS - 1;
342 for (regno = first_regno; regno <= last_regno; regno++)
344 if (regmap[regno] == -1)
345 child_ops.to_fetch_registers (regno);
348 unsigned char buf[MAX_REGISTER_RAW_SIZE];
351 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
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));
361 read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
363 supply_register (regno, buf);
367 do_cleanups (old_chain);
371 hpux_thread_store_registers (regno)
374 cma__t_int_tcb tcb, *tcb_ptr;
375 struct cleanup *old_chain;
377 int first_regno, last_regno;
379 tcb_ptr = find_tcb (inferior_pid);
381 old_chain = save_inferior_pid ();
383 inferior_pid = main_pid;
385 if (tcb_ptr->state == cma__c_state_running)
387 child_ops.to_store_registers (regno);
389 do_cleanups (old_chain);
397 last_regno = NUM_REGS - 1;
405 for (regno = first_regno; regno <= last_regno; regno++)
407 if (regmap[regno] == -1)
408 child_ops.to_store_registers (regno);
411 unsigned char buf[MAX_REGISTER_RAW_SIZE];
414 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
416 if (regno == FLAGS_REGNUM)
417 child_ops.to_store_registers (regno); /* Let lower layer handle this... */
418 else if (regno == SP_REGNUM)
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);
426 else if (regno == PC_REGNUM)
427 write_memory (sp - 20,
428 registers + REGISTER_BYTE (regno),
429 REGISTER_RAW_SIZE (regno));
431 write_memory (sp + regmap[regno],
432 registers + REGISTER_BYTE (regno),
433 REGISTER_RAW_SIZE (regno));
437 do_cleanups (old_chain);
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
447 hpux_thread_prepare_to_store ()
449 child_ops.to_prepare_to_store ();
453 hpux_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
458 struct target_ops *target; /* ignored */
461 struct cleanup *old_chain;
463 old_chain = save_inferior_pid ();
465 inferior_pid = main_pid;
467 retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
469 do_cleanups (old_chain);
474 /* Print status information about what we're accessing. */
477 hpux_thread_files_info (ignore)
478 struct target_ops *ignore;
480 child_ops.to_files_info (ignore);
484 hpux_thread_kill_inferior ()
486 child_ops.to_kill ();
490 hpux_thread_notice_signals (pid)
493 child_ops.to_notice_signals (pid);
496 /* Fork an inferior process, and start debugging it with /proc. */
499 hpux_thread_create_inferior (exec_file, allargs, env)
504 child_ops.to_create_inferior (exec_file, allargs, env);
506 if (hpux_thread_active)
508 main_pid = inferior_pid;
510 push_target (&hpux_thread_ops);
512 inferior_pid = find_active_thread ();
514 add_thread (inferior_pid);
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
525 hpux_thread_new_objfile (objfile)
526 struct objfile *objfile;
528 struct minimal_symbol *ms;
532 hpux_thread_active = 0;
537 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
542 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
544 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
549 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
551 hpux_thread_active = 1;
554 /* Clean up after the inferior dies. */
557 hpux_thread_mourn_inferior ()
559 child_ops.to_mourn_inferior ();
562 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
565 hpux_thread_can_run ()
567 return child_suppress_run;
571 hpux_thread_alive (pid)
580 child_ops.to_stop ();
583 /* Convert a pid to printable form. */
586 hpux_pid_to_str (pid)
589 static char buf[100];
591 sprintf (buf, "Thread %d", pid >> 16);
597 init_hpux_thread_ops ()
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;
636 _initialize_hpux_thread ()
638 init_hpux_thread_ops ();
639 add_target (&hpux_thread_ops);
641 child_suppress_run = 1;