1 /* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
2 Copyright 1996, 1998, 1999, 2000, 2001 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 (void);
58 static int hpux_thread_active
= 0;
60 static ptid_t main_ptid
; /* 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_ptid (void);
67 static void restore_inferior_ptid (ptid_t pid
);
69 static void hpux_thread_resume (ptid_t ptid
, int step
,
70 enum target_signal signo
);
72 static void init_hpux_thread_ops (void);
74 static struct target_ops hpux_thread_ops
;
80 save_inferior_ptid - Save inferior_ptid on the cleanup list
81 restore_inferior_ptid - Restore inferior_ptid from the cleanup list
85 struct cleanup *save_inferior_ptid ()
86 void restore_inferior_ptid (int pid)
90 These two functions act in unison to restore inferior_ptid in
95 inferior_ptid 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_ptid gets restored (in case of errors), you
98 need to call save_inferior_ptid before changing it. At the end of the
99 function, you should invoke do_cleanups to restore it.
104 static struct cleanup
*
105 save_inferior_ptid (void)
107 return make_cleanup (restore_inferior_ptid
, inferior_ptid
);
111 restore_inferior_ptid (ptid_t ptid
)
113 inferior_ptid
= ptid
;
116 static int find_active_thread (void);
118 static int cached_thread
;
119 static int cached_active_thread
;
120 static cma__t_int_tcb cached_tcb
;
123 find_active_thread (void)
125 static cma__t_int_tcb tcb
;
128 if (cached_active_thread
!= 0)
129 return cached_active_thread
;
131 read_memory ((CORE_ADDR
) P_cma__g_current_thread
,
135 read_memory (tcb_ptr
, (char *) &tcb
, sizeof tcb
);
137 return (cma_thread_get_unique (&tcb
.prolog
.client_thread
) << 16)
138 | PIDGET (main_ptid
);
141 static cma__t_int_tcb
*find_tcb (int thread
);
143 static cma__t_int_tcb
*
144 find_tcb (int thread
)
146 cma__t_known_object queue_header
;
147 cma__t_queue
*queue_ptr
;
149 if (thread
== cached_thread
)
152 read_memory ((CORE_ADDR
) P_cma__g_known_threads
,
153 (char *) &queue_header
,
154 sizeof queue_header
);
156 for (queue_ptr
= queue_header
.queue
.flink
;
157 queue_ptr
!= (cma__t_queue
*) P_cma__g_known_threads
;
158 queue_ptr
= cached_tcb
.threads
.flink
)
160 cma__t_int_tcb
*tcb_ptr
;
162 tcb_ptr
= cma__base (queue_ptr
, threads
, cma__t_int_tcb
);
164 read_memory ((CORE_ADDR
) tcb_ptr
, (char *) &cached_tcb
, sizeof cached_tcb
);
166 if (cached_tcb
.header
.type
== cma__c_obj_tcb
)
167 if (cma_thread_get_unique (&cached_tcb
.prolog
.client_thread
) == thread
>> 16)
169 cached_thread
= thread
;
174 error ("Can't find TCB %d,%d", thread
>> 16, thread
& 0xffff);
178 /* Most target vector functions from here on actually just pass through to
179 inftarg.c, as they don't need to do anything specific for threads. */
183 hpux_thread_open (char *arg
, int from_tty
)
185 child_ops
.to_open (arg
, from_tty
);
188 /* Attach to process PID, then initialize for debugging it
189 and wait for the trace-trap that results from attaching. */
192 hpux_thread_attach (char *args
, int from_tty
)
194 child_ops
.to_attach (args
, from_tty
);
196 /* XXX - might want to iterate over all the threads and register them. */
199 /* Take a program previously attached to and detaches it.
200 The program resumes execution and will no longer stop
201 on signals, etc. We'd better not have left any breakpoints
202 in the program or it'll die when it hits one. For this
203 to work, it may be necessary for the process to have been
204 previously attached. It *might* work if the program was
205 started via the normal ptrace (PTRACE_TRACEME). */
208 hpux_thread_detach (char *args
, int from_tty
)
210 child_ops
.to_detach (args
, from_tty
);
213 /* Resume execution of process PID. If STEP is nozero, then
214 just single step it. If SIGNAL is nonzero, restart it with that
215 signal activated. We may have to convert pid from a thread-id to an LWP id
219 hpux_thread_resume (ptid_t ptid
, int step
, enum target_signal signo
)
221 struct cleanup
*old_chain
;
223 old_chain
= save_inferior_ptid ();
226 inferior_ptid
= main_ptid
;
231 pid
= thread_to_lwp (pid
, -2);
232 if (pid
== -2) /* Inactive thread */
233 error ("This version of Solaris can't start inactive threads.");
237 child_ops
.to_resume (ptid
, step
, signo
);
240 cached_active_thread
= 0;
242 do_cleanups (old_chain
);
245 /* Wait for any threads to stop. We may have to convert PID from a thread id
246 to a LWP id, and vice versa on the way out. */
249 hpux_thread_wait (ptid_t ptid
, struct target_waitstatus
*ourstatus
)
252 struct cleanup
*old_chain
;
254 old_chain
= save_inferior_ptid ();
256 inferior_ptid
= main_ptid
;
258 if (!ptid_equal (ptid
, minus_one_ptid
))
261 rtnval
= child_ops
.to_wait (ptid
, ourstatus
);
263 rtnval
= find_active_thread ();
265 do_cleanups (old_chain
);
270 static char regmap
[NUM_REGS
] =
272 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
273 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
274 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
276 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
277 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
279 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
280 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
282 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
283 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
285 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
286 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
287 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
288 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
289 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
290 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
291 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
292 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
293 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
297 hpux_thread_fetch_registers (int regno
)
299 cma__t_int_tcb tcb
, *tcb_ptr
;
300 struct cleanup
*old_chain
;
302 int first_regno
, last_regno
;
304 tcb_ptr
= find_tcb (PIDGET (inferior_ptid
));
306 old_chain
= save_inferior_ptid ();
308 inferior_ptid
= main_ptid
;
310 if (tcb_ptr
->state
== cma__c_state_running
)
312 child_ops
.to_fetch_registers (regno
);
314 do_cleanups (old_chain
);
322 last_regno
= NUM_REGS
- 1;
330 for (regno
= first_regno
; regno
<= last_regno
; regno
++)
332 if (regmap
[regno
] == -1)
333 child_ops
.to_fetch_registers (regno
);
336 unsigned char buf
[MAX_REGISTER_RAW_SIZE
];
339 sp
= (CORE_ADDR
) tcb_ptr
->static_ctx
.sp
- 160;
341 if (regno
== FLAGS_REGNUM
)
342 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
343 memset (buf
, '\000', REGISTER_RAW_SIZE (regno
));
344 else if (regno
== SP_REGNUM
)
345 store_address (buf
, sizeof sp
, sp
);
346 else if (regno
== PC_REGNUM
)
347 read_memory (sp
- 20, buf
, REGISTER_RAW_SIZE (regno
));
349 read_memory (sp
+ regmap
[regno
], buf
, REGISTER_RAW_SIZE (regno
));
351 supply_register (regno
, buf
);
355 do_cleanups (old_chain
);
359 hpux_thread_store_registers (int regno
)
361 cma__t_int_tcb tcb
, *tcb_ptr
;
362 struct cleanup
*old_chain
;
364 int first_regno
, last_regno
;
366 tcb_ptr
= find_tcb (PIDGET (inferior_ptid
));
368 old_chain
= save_inferior_ptid ();
370 inferior_ptid
= main_ptid
;
372 if (tcb_ptr
->state
== cma__c_state_running
)
374 child_ops
.to_store_registers (regno
);
376 do_cleanups (old_chain
);
384 last_regno
= NUM_REGS
- 1;
392 for (regno
= first_regno
; regno
<= last_regno
; regno
++)
394 if (regmap
[regno
] == -1)
395 child_ops
.to_store_registers (regno
);
398 unsigned char buf
[MAX_REGISTER_RAW_SIZE
];
401 sp
= (CORE_ADDR
) tcb_ptr
->static_ctx
.sp
- 160;
403 if (regno
== FLAGS_REGNUM
)
404 child_ops
.to_store_registers (regno
); /* Let lower layer handle this... */
405 else if (regno
== SP_REGNUM
)
407 write_memory ((CORE_ADDR
) & tcb_ptr
->static_ctx
.sp
,
408 registers
+ REGISTER_BYTE (regno
),
409 REGISTER_RAW_SIZE (regno
));
410 tcb_ptr
->static_ctx
.sp
= (cma__t_hppa_regs
*)
411 (extract_address (registers
+ REGISTER_BYTE (regno
), REGISTER_RAW_SIZE (regno
)) + 160);
413 else if (regno
== PC_REGNUM
)
414 write_memory (sp
- 20,
415 registers
+ REGISTER_BYTE (regno
),
416 REGISTER_RAW_SIZE (regno
));
418 write_memory (sp
+ regmap
[regno
],
419 registers
+ REGISTER_BYTE (regno
),
420 REGISTER_RAW_SIZE (regno
));
424 do_cleanups (old_chain
);
427 /* Get ready to modify the registers array. On machines which store
428 individual registers, this doesn't need to do anything. On machines
429 which store all the registers in one fell swoop, this makes sure
430 that registers contains all the registers from the program being
434 hpux_thread_prepare_to_store (void)
436 child_ops
.to_prepare_to_store ();
440 hpux_thread_xfer_memory (CORE_ADDR memaddr
, char *myaddr
, int len
,
441 int dowrite
, struct mem_attrib
*attribs
,
442 struct target_ops
*target
)
445 struct cleanup
*old_chain
;
447 old_chain
= save_inferior_ptid ();
449 inferior_ptid
= main_ptid
;
452 child_ops
.to_xfer_memory (memaddr
, myaddr
, len
, dowrite
, attribs
, target
);
454 do_cleanups (old_chain
);
459 /* Print status information about what we're accessing. */
462 hpux_thread_files_info (struct target_ops
*ignore
)
464 child_ops
.to_files_info (ignore
);
468 hpux_thread_kill_inferior (void)
470 child_ops
.to_kill ();
474 hpux_thread_notice_signals (ptid_t ptid
)
476 child_ops
.to_notice_signals (ptid
);
479 /* Fork an inferior process, and start debugging it with /proc. */
482 hpux_thread_create_inferior (char *exec_file
, char *allargs
, char **env
)
484 child_ops
.to_create_inferior (exec_file
, allargs
, env
);
486 if (hpux_thread_active
)
488 main_ptid
= inferior_ptid
;
490 push_target (&hpux_thread_ops
);
492 inferior_ptid
= find_active_thread ();
494 add_thread (inferior_ptid
);
498 /* This routine is called whenever a new symbol table is read in, or when all
499 symbol tables are removed. libthread_db can only be initialized when it
500 finds the right variables in libthread.so. Since it's a shared library,
501 those variables don't show up until the library gets mapped and the symbol
504 /* This new_objfile event is now managed by a chained function pointer.
505 * It is the callee's responsability to call the next client on the chain.
508 /* Saved pointer to previous owner of the new_objfile event. */
509 static void (*target_new_objfile_chain
) (struct objfile
*);
512 hpux_thread_new_objfile (struct objfile
*objfile
)
514 struct minimal_symbol
*ms
;
518 hpux_thread_active
= 0;
522 ms
= lookup_minimal_symbol ("cma__g_known_threads", NULL
, objfile
);
527 P_cma__g_known_threads
= SYMBOL_VALUE_ADDRESS (ms
);
529 ms
= lookup_minimal_symbol ("cma__g_current_thread", NULL
, objfile
);
534 P_cma__g_current_thread
= SYMBOL_VALUE_ADDRESS (ms
);
536 hpux_thread_active
= 1;
538 /* Call predecessor on chain, if any. */
539 if (target_new_objfile_chain
)
540 target_new_objfile_chain (objfile
);
543 /* Clean up after the inferior dies. */
546 hpux_thread_mourn_inferior (void)
548 child_ops
.to_mourn_inferior ();
551 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
554 hpux_thread_can_run (void)
556 return child_suppress_run
;
560 hpux_thread_alive (ptid_t ptid
)
566 hpux_thread_stop (void)
568 child_ops
.to_stop ();
571 /* Convert a pid to printable form. */
574 hpux_pid_to_str (ptid_t ptid
)
576 static char buf
[100];
577 int pid
= PIDGET (ptid
);
579 sprintf (buf
, "Thread %d", pid
>> 16);
585 init_hpux_thread_ops (void)
587 hpux_thread_ops
.to_shortname
= "hpux-threads";
588 hpux_thread_ops
.to_longname
= "HPUX threads and pthread.";
589 hpux_thread_ops
.to_doc
= "HPUX threads and pthread support.";
590 hpux_thread_ops
.to_open
= hpux_thread_open
;
591 hpux_thread_ops
.to_attach
= hpux_thread_attach
;
592 hpux_thread_ops
.to_detach
= hpux_thread_detach
;
593 hpux_thread_ops
.to_resume
= hpux_thread_resume
;
594 hpux_thread_ops
.to_wait
= hpux_thread_wait
;
595 hpux_thread_ops
.to_fetch_registers
= hpux_thread_fetch_registers
;
596 hpux_thread_ops
.to_store_registers
= hpux_thread_store_registers
;
597 hpux_thread_ops
.to_prepare_to_store
= hpux_thread_prepare_to_store
;
598 hpux_thread_ops
.to_xfer_memory
= hpux_thread_xfer_memory
;
599 hpux_thread_ops
.to_files_info
= hpux_thread_files_info
;
600 hpux_thread_ops
.to_insert_breakpoint
= memory_insert_breakpoint
;
601 hpux_thread_ops
.to_remove_breakpoint
= memory_remove_breakpoint
;
602 hpux_thread_ops
.to_terminal_init
= terminal_init_inferior
;
603 hpux_thread_ops
.to_terminal_inferior
= terminal_inferior
;
604 hpux_thread_ops
.to_terminal_ours_for_output
= terminal_ours_for_output
;
605 hpux_thread_ops
.to_terminal_ours
= terminal_ours
;
606 hpux_thread_ops
.to_terminal_info
= child_terminal_info
;
607 hpux_thread_ops
.to_kill
= hpux_thread_kill_inferior
;
608 hpux_thread_ops
.to_create_inferior
= hpux_thread_create_inferior
;
609 hpux_thread_ops
.to_mourn_inferior
= hpux_thread_mourn_inferior
;
610 hpux_thread_ops
.to_can_run
= hpux_thread_can_run
;
611 hpux_thread_ops
.to_notice_signals
= hpux_thread_notice_signals
;
612 hpux_thread_ops
.to_thread_alive
= hpux_thread_alive
;
613 hpux_thread_ops
.to_stop
= hpux_thread_stop
;
614 hpux_thread_ops
.to_stratum
= process_stratum
;
615 hpux_thread_ops
.to_has_all_memory
= 1;
616 hpux_thread_ops
.to_has_memory
= 1;
617 hpux_thread_ops
.to_has_stack
= 1;
618 hpux_thread_ops
.to_has_registers
= 1;
619 hpux_thread_ops
.to_has_execution
= 1;
620 hpux_thread_ops
.to_magic
= OPS_MAGIC
;
624 _initialize_hpux_thread (void)
626 init_hpux_thread_ops ();
627 add_target (&hpux_thread_ops
);
629 child_suppress_run
= 1;
630 /* Hook into new_objfile notification. */
631 target_new_objfile_chain
= target_new_objfile_hook
;
632 target_new_objfile_hook
= hpux_thread_new_objfile
;