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 void hpux_thread_resume (ptid_t ptid
, int step
,
66 enum target_signal signo
);
68 static void init_hpux_thread_ops (void);
70 static struct target_ops hpux_thread_ops
;
72 static int find_active_thread (void);
74 static int cached_thread
;
75 static int cached_active_thread
;
76 static cma__t_int_tcb cached_tcb
;
79 find_active_thread (void)
81 static cma__t_int_tcb tcb
;
84 if (cached_active_thread
!= 0)
85 return cached_active_thread
;
87 read_memory ((CORE_ADDR
) P_cma__g_current_thread
,
91 read_memory (tcb_ptr
, (char *) &tcb
, sizeof tcb
);
93 return (cma_thread_get_unique (&tcb
.prolog
.client_thread
) << 16)
97 static cma__t_int_tcb
*find_tcb (int thread
);
99 static cma__t_int_tcb
*
100 find_tcb (int thread
)
102 cma__t_known_object queue_header
;
103 cma__t_queue
*queue_ptr
;
105 if (thread
== cached_thread
)
108 read_memory ((CORE_ADDR
) P_cma__g_known_threads
,
109 (char *) &queue_header
,
110 sizeof queue_header
);
112 for (queue_ptr
= queue_header
.queue
.flink
;
113 queue_ptr
!= (cma__t_queue
*) P_cma__g_known_threads
;
114 queue_ptr
= cached_tcb
.threads
.flink
)
116 cma__t_int_tcb
*tcb_ptr
;
118 tcb_ptr
= cma__base (queue_ptr
, threads
, cma__t_int_tcb
);
120 read_memory ((CORE_ADDR
) tcb_ptr
, (char *) &cached_tcb
, sizeof cached_tcb
);
122 if (cached_tcb
.header
.type
== cma__c_obj_tcb
)
123 if (cma_thread_get_unique (&cached_tcb
.prolog
.client_thread
) == thread
>> 16)
125 cached_thread
= thread
;
130 error ("Can't find TCB %d,%d", thread
>> 16, thread
& 0xffff);
134 /* Most target vector functions from here on actually just pass through to
135 inftarg.c, as they don't need to do anything specific for threads. */
139 hpux_thread_open (char *arg
, int from_tty
)
141 child_ops
.to_open (arg
, from_tty
);
144 /* Attach to process PID, then initialize for debugging it
145 and wait for the trace-trap that results from attaching. */
148 hpux_thread_attach (char *args
, int from_tty
)
150 child_ops
.to_attach (args
, from_tty
);
152 /* XXX - might want to iterate over all the threads and register them. */
155 /* Take a program previously attached to and detaches it.
156 The program resumes execution and will no longer stop
157 on signals, etc. We'd better not have left any breakpoints
158 in the program or it'll die when it hits one. For this
159 to work, it may be necessary for the process to have been
160 previously attached. It *might* work if the program was
161 started via the normal ptrace (PTRACE_TRACEME). */
164 hpux_thread_detach (char *args
, int from_tty
)
166 child_ops
.to_detach (args
, from_tty
);
169 /* Resume execution of process PID. If STEP is nozero, then
170 just single step it. If SIGNAL is nonzero, restart it with that
171 signal activated. We may have to convert pid from a thread-id to an LWP id
175 hpux_thread_resume (ptid_t ptid
, int step
, enum target_signal signo
)
177 struct cleanup
*old_chain
;
179 old_chain
= save_inferior_ptid ();
182 inferior_ptid
= main_ptid
;
187 pid
= thread_to_lwp (pid
, -2);
188 if (pid
== -2) /* Inactive thread */
189 error ("This version of Solaris can't start inactive threads.");
193 child_ops
.to_resume (ptid
, step
, signo
);
196 cached_active_thread
= 0;
198 do_cleanups (old_chain
);
201 /* Wait for any threads to stop. We may have to convert PID from a thread id
202 to a LWP id, and vice versa on the way out. */
205 hpux_thread_wait (ptid_t ptid
, struct target_waitstatus
*ourstatus
)
208 struct cleanup
*old_chain
;
210 old_chain
= save_inferior_ptid ();
212 inferior_ptid
= main_ptid
;
214 if (!ptid_equal (ptid
, minus_one_ptid
))
217 rtnval
= child_ops
.to_wait (ptid
, ourstatus
);
219 rtnval
= find_active_thread ();
221 do_cleanups (old_chain
);
226 static char regmap
[NUM_REGS
] =
228 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
229 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
230 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
232 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
233 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
235 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
236 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
238 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
239 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
241 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
242 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
243 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
244 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
245 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
246 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
247 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
248 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
249 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
253 hpux_thread_fetch_registers (int regno
)
255 cma__t_int_tcb tcb
, *tcb_ptr
;
256 struct cleanup
*old_chain
;
258 int first_regno
, last_regno
;
260 tcb_ptr
= find_tcb (PIDGET (inferior_ptid
));
262 old_chain
= save_inferior_ptid ();
264 inferior_ptid
= main_ptid
;
266 if (tcb_ptr
->state
== cma__c_state_running
)
268 child_ops
.to_fetch_registers (regno
);
270 do_cleanups (old_chain
);
278 last_regno
= NUM_REGS
- 1;
286 for (regno
= first_regno
; regno
<= last_regno
; regno
++)
288 if (regmap
[regno
] == -1)
289 child_ops
.to_fetch_registers (regno
);
292 unsigned char buf
[MAX_REGISTER_RAW_SIZE
];
295 sp
= (CORE_ADDR
) tcb_ptr
->static_ctx
.sp
- 160;
297 if (regno
== FLAGS_REGNUM
)
298 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
299 memset (buf
, '\000', REGISTER_RAW_SIZE (regno
));
300 else if (regno
== SP_REGNUM
)
301 store_address (buf
, sizeof sp
, sp
);
302 else if (regno
== PC_REGNUM
)
303 read_memory (sp
- 20, buf
, REGISTER_RAW_SIZE (regno
));
305 read_memory (sp
+ regmap
[regno
], buf
, REGISTER_RAW_SIZE (regno
));
307 supply_register (regno
, buf
);
311 do_cleanups (old_chain
);
315 hpux_thread_store_registers (int regno
)
317 cma__t_int_tcb tcb
, *tcb_ptr
;
318 struct cleanup
*old_chain
;
320 int first_regno
, last_regno
;
322 tcb_ptr
= find_tcb (PIDGET (inferior_ptid
));
324 old_chain
= save_inferior_ptid ();
326 inferior_ptid
= main_ptid
;
328 if (tcb_ptr
->state
== cma__c_state_running
)
330 child_ops
.to_store_registers (regno
);
332 do_cleanups (old_chain
);
340 last_regno
= NUM_REGS
- 1;
348 for (regno
= first_regno
; regno
<= last_regno
; regno
++)
350 if (regmap
[regno
] == -1)
351 child_ops
.to_store_registers (regno
);
354 unsigned char buf
[MAX_REGISTER_RAW_SIZE
];
357 sp
= (CORE_ADDR
) tcb_ptr
->static_ctx
.sp
- 160;
359 if (regno
== FLAGS_REGNUM
)
360 child_ops
.to_store_registers (regno
); /* Let lower layer handle this... */
361 else if (regno
== SP_REGNUM
)
363 write_memory ((CORE_ADDR
) & tcb_ptr
->static_ctx
.sp
,
364 registers
+ REGISTER_BYTE (regno
),
365 REGISTER_RAW_SIZE (regno
));
366 tcb_ptr
->static_ctx
.sp
= (cma__t_hppa_regs
*)
367 (extract_address (registers
+ REGISTER_BYTE (regno
), REGISTER_RAW_SIZE (regno
)) + 160);
369 else if (regno
== PC_REGNUM
)
370 write_memory (sp
- 20,
371 registers
+ REGISTER_BYTE (regno
),
372 REGISTER_RAW_SIZE (regno
));
374 write_memory (sp
+ regmap
[regno
],
375 registers
+ REGISTER_BYTE (regno
),
376 REGISTER_RAW_SIZE (regno
));
380 do_cleanups (old_chain
);
383 /* Get ready to modify the registers array. On machines which store
384 individual registers, this doesn't need to do anything. On machines
385 which store all the registers in one fell swoop, this makes sure
386 that registers contains all the registers from the program being
390 hpux_thread_prepare_to_store (void)
392 child_ops
.to_prepare_to_store ();
396 hpux_thread_xfer_memory (CORE_ADDR memaddr
, char *myaddr
, int len
,
397 int dowrite
, struct mem_attrib
*attribs
,
398 struct target_ops
*target
)
401 struct cleanup
*old_chain
;
403 old_chain
= save_inferior_ptid ();
405 inferior_ptid
= main_ptid
;
408 child_ops
.to_xfer_memory (memaddr
, myaddr
, len
, dowrite
, attribs
, target
);
410 do_cleanups (old_chain
);
415 /* Print status information about what we're accessing. */
418 hpux_thread_files_info (struct target_ops
*ignore
)
420 child_ops
.to_files_info (ignore
);
424 hpux_thread_kill_inferior (void)
426 child_ops
.to_kill ();
430 hpux_thread_notice_signals (ptid_t ptid
)
432 child_ops
.to_notice_signals (ptid
);
435 /* Fork an inferior process, and start debugging it with /proc. */
438 hpux_thread_create_inferior (char *exec_file
, char *allargs
, char **env
)
440 child_ops
.to_create_inferior (exec_file
, allargs
, env
);
442 if (hpux_thread_active
)
444 main_ptid
= inferior_ptid
;
446 push_target (&hpux_thread_ops
);
448 inferior_ptid
= find_active_thread ();
450 add_thread (inferior_ptid
);
454 /* This routine is called whenever a new symbol table is read in, or when all
455 symbol tables are removed. libthread_db can only be initialized when it
456 finds the right variables in libthread.so. Since it's a shared library,
457 those variables don't show up until the library gets mapped and the symbol
460 /* This new_objfile event is now managed by a chained function pointer.
461 * It is the callee's responsability to call the next client on the chain.
464 /* Saved pointer to previous owner of the new_objfile event. */
465 static void (*target_new_objfile_chain
) (struct objfile
*);
468 hpux_thread_new_objfile (struct objfile
*objfile
)
470 struct minimal_symbol
*ms
;
474 hpux_thread_active
= 0;
478 ms
= lookup_minimal_symbol ("cma__g_known_threads", NULL
, objfile
);
483 P_cma__g_known_threads
= SYMBOL_VALUE_ADDRESS (ms
);
485 ms
= lookup_minimal_symbol ("cma__g_current_thread", NULL
, objfile
);
490 P_cma__g_current_thread
= SYMBOL_VALUE_ADDRESS (ms
);
492 hpux_thread_active
= 1;
494 /* Call predecessor on chain, if any. */
495 if (target_new_objfile_chain
)
496 target_new_objfile_chain (objfile
);
499 /* Clean up after the inferior dies. */
502 hpux_thread_mourn_inferior (void)
504 child_ops
.to_mourn_inferior ();
507 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
510 hpux_thread_can_run (void)
512 return child_suppress_run
;
516 hpux_thread_alive (ptid_t ptid
)
522 hpux_thread_stop (void)
524 child_ops
.to_stop ();
527 /* Convert a pid to printable form. */
530 hpux_pid_to_str (ptid_t ptid
)
532 static char buf
[100];
533 int pid
= PIDGET (ptid
);
535 sprintf (buf
, "Thread %d", pid
>> 16);
541 init_hpux_thread_ops (void)
543 hpux_thread_ops
.to_shortname
= "hpux-threads";
544 hpux_thread_ops
.to_longname
= "HPUX threads and pthread.";
545 hpux_thread_ops
.to_doc
= "HPUX threads and pthread support.";
546 hpux_thread_ops
.to_open
= hpux_thread_open
;
547 hpux_thread_ops
.to_attach
= hpux_thread_attach
;
548 hpux_thread_ops
.to_detach
= hpux_thread_detach
;
549 hpux_thread_ops
.to_resume
= hpux_thread_resume
;
550 hpux_thread_ops
.to_wait
= hpux_thread_wait
;
551 hpux_thread_ops
.to_fetch_registers
= hpux_thread_fetch_registers
;
552 hpux_thread_ops
.to_store_registers
= hpux_thread_store_registers
;
553 hpux_thread_ops
.to_prepare_to_store
= hpux_thread_prepare_to_store
;
554 hpux_thread_ops
.to_xfer_memory
= hpux_thread_xfer_memory
;
555 hpux_thread_ops
.to_files_info
= hpux_thread_files_info
;
556 hpux_thread_ops
.to_insert_breakpoint
= memory_insert_breakpoint
;
557 hpux_thread_ops
.to_remove_breakpoint
= memory_remove_breakpoint
;
558 hpux_thread_ops
.to_terminal_init
= terminal_init_inferior
;
559 hpux_thread_ops
.to_terminal_inferior
= terminal_inferior
;
560 hpux_thread_ops
.to_terminal_ours_for_output
= terminal_ours_for_output
;
561 hpux_thread_ops
.to_terminal_ours
= terminal_ours
;
562 hpux_thread_ops
.to_terminal_info
= child_terminal_info
;
563 hpux_thread_ops
.to_kill
= hpux_thread_kill_inferior
;
564 hpux_thread_ops
.to_create_inferior
= hpux_thread_create_inferior
;
565 hpux_thread_ops
.to_mourn_inferior
= hpux_thread_mourn_inferior
;
566 hpux_thread_ops
.to_can_run
= hpux_thread_can_run
;
567 hpux_thread_ops
.to_notice_signals
= hpux_thread_notice_signals
;
568 hpux_thread_ops
.to_thread_alive
= hpux_thread_alive
;
569 hpux_thread_ops
.to_stop
= hpux_thread_stop
;
570 hpux_thread_ops
.to_stratum
= process_stratum
;
571 hpux_thread_ops
.to_has_all_memory
= 1;
572 hpux_thread_ops
.to_has_memory
= 1;
573 hpux_thread_ops
.to_has_stack
= 1;
574 hpux_thread_ops
.to_has_registers
= 1;
575 hpux_thread_ops
.to_has_execution
= 1;
576 hpux_thread_ops
.to_magic
= OPS_MAGIC
;
580 _initialize_hpux_thread (void)
582 init_hpux_thread_ops ();
583 add_target (&hpux_thread_ops
);
585 child_suppress_run
= 1;
586 /* Hook into new_objfile notification. */
587 target_new_objfile_chain
= target_new_objfile_hook
;
588 target_new_objfile_hook
= hpux_thread_new_objfile
;