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
*
103 save_inferior_pid (void)
105 return make_cleanup (restore_inferior_pid
, inferior_pid
);
109 restore_inferior_pid (int pid
)
114 static int find_active_thread (void);
116 static int cached_thread
;
117 static int cached_active_thread
;
118 static cma__t_int_tcb cached_tcb
;
121 find_active_thread (void)
123 static cma__t_int_tcb tcb
;
126 if (cached_active_thread
!= 0)
127 return cached_active_thread
;
129 read_memory ((CORE_ADDR
) P_cma__g_current_thread
,
133 read_memory (tcb_ptr
, (char *) &tcb
, sizeof tcb
);
135 return (cma_thread_get_unique (&tcb
.prolog
.client_thread
) << 16) | main_pid
;
138 static cma__t_int_tcb
*find_tcb (int thread
);
140 static cma__t_int_tcb
*
141 find_tcb (int thread
)
143 cma__t_known_object queue_header
;
144 cma__t_queue
*queue_ptr
;
146 if (thread
== cached_thread
)
149 read_memory ((CORE_ADDR
) P_cma__g_known_threads
,
150 (char *) &queue_header
,
151 sizeof queue_header
);
153 for (queue_ptr
= queue_header
.queue
.flink
;
154 queue_ptr
!= (cma__t_queue
*) P_cma__g_known_threads
;
155 queue_ptr
= cached_tcb
.threads
.flink
)
157 cma__t_int_tcb
*tcb_ptr
;
159 tcb_ptr
= cma__base (queue_ptr
, threads
, cma__t_int_tcb
);
161 read_memory ((CORE_ADDR
) tcb_ptr
, (char *) &cached_tcb
, sizeof cached_tcb
);
163 if (cached_tcb
.header
.type
== cma__c_obj_tcb
)
164 if (cma_thread_get_unique (&cached_tcb
.prolog
.client_thread
) == thread
>> 16)
166 cached_thread
= thread
;
171 error ("Can't find TCB %d,%d", thread
>> 16, thread
& 0xffff);
175 /* Most target vector functions from here on actually just pass through to
176 inftarg.c, as they don't need to do anything specific for threads. */
180 hpux_thread_open (char *arg
, int from_tty
)
182 child_ops
.to_open (arg
, from_tty
);
185 /* Attach to process PID, then initialize for debugging it
186 and wait for the trace-trap that results from attaching. */
189 hpux_thread_attach (char *args
, int from_tty
)
191 child_ops
.to_attach (args
, from_tty
);
193 /* XXX - might want to iterate over all the threads and register them. */
196 /* Take a program previously attached to and detaches it.
197 The program resumes execution and will no longer stop
198 on signals, etc. We'd better not have left any breakpoints
199 in the program or it'll die when it hits one. For this
200 to work, it may be necessary for the process to have been
201 previously attached. It *might* work if the program was
202 started via the normal ptrace (PTRACE_TRACEME). */
205 hpux_thread_detach (char *args
, int from_tty
)
207 child_ops
.to_detach (args
, from_tty
);
210 /* Resume execution of process PID. If STEP is nozero, then
211 just single step it. If SIGNAL is nonzero, restart it with that
212 signal activated. We may have to convert pid from a thread-id to an LWP id
216 hpux_thread_resume (int pid
, int step
, enum target_signal signo
)
218 struct cleanup
*old_chain
;
220 old_chain
= save_inferior_pid ();
222 pid
= inferior_pid
= main_pid
;
227 pid
= thread_to_lwp (pid
, -2);
228 if (pid
== -2) /* Inactive thread */
229 error ("This version of Solaris can't start inactive threads.");
233 child_ops
.to_resume (pid
, step
, signo
);
236 cached_active_thread
= 0;
238 do_cleanups (old_chain
);
241 /* Wait for any threads to stop. We may have to convert PID from a thread id
242 to a LWP id, and vice versa on the way out. */
245 hpux_thread_wait (int pid
, struct target_waitstatus
*ourstatus
)
248 struct cleanup
*old_chain
;
250 old_chain
= save_inferior_pid ();
252 inferior_pid
= main_pid
;
257 rtnval
= child_ops
.to_wait (pid
, ourstatus
);
259 rtnval
= find_active_thread ();
261 do_cleanups (old_chain
);
266 static char regmap
[NUM_REGS
] =
268 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
269 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
270 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
272 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
273 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
275 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
276 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
278 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
279 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
281 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
282 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
283 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
284 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
285 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
286 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
287 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
288 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
289 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
293 hpux_thread_fetch_registers (int regno
)
295 cma__t_int_tcb tcb
, *tcb_ptr
;
296 struct cleanup
*old_chain
;
298 int first_regno
, last_regno
;
300 tcb_ptr
= find_tcb (inferior_pid
);
302 old_chain
= save_inferior_pid ();
304 inferior_pid
= main_pid
;
306 if (tcb_ptr
->state
== cma__c_state_running
)
308 child_ops
.to_fetch_registers (regno
);
310 do_cleanups (old_chain
);
318 last_regno
= NUM_REGS
- 1;
326 for (regno
= first_regno
; regno
<= last_regno
; regno
++)
328 if (regmap
[regno
] == -1)
329 child_ops
.to_fetch_registers (regno
);
332 unsigned char buf
[MAX_REGISTER_RAW_SIZE
];
335 sp
= (CORE_ADDR
) tcb_ptr
->static_ctx
.sp
- 160;
337 if (regno
== FLAGS_REGNUM
)
338 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
339 memset (buf
, '\000', REGISTER_RAW_SIZE (regno
));
340 else if (regno
== SP_REGNUM
)
341 store_address (buf
, sizeof sp
, sp
);
342 else if (regno
== PC_REGNUM
)
343 read_memory (sp
- 20, buf
, REGISTER_RAW_SIZE (regno
));
345 read_memory (sp
+ regmap
[regno
], buf
, REGISTER_RAW_SIZE (regno
));
347 supply_register (regno
, buf
);
351 do_cleanups (old_chain
);
355 hpux_thread_store_registers (int regno
)
357 cma__t_int_tcb tcb
, *tcb_ptr
;
358 struct cleanup
*old_chain
;
360 int first_regno
, last_regno
;
362 tcb_ptr
= find_tcb (inferior_pid
);
364 old_chain
= save_inferior_pid ();
366 inferior_pid
= main_pid
;
368 if (tcb_ptr
->state
== cma__c_state_running
)
370 child_ops
.to_store_registers (regno
);
372 do_cleanups (old_chain
);
380 last_regno
= NUM_REGS
- 1;
388 for (regno
= first_regno
; regno
<= last_regno
; regno
++)
390 if (regmap
[regno
] == -1)
391 child_ops
.to_store_registers (regno
);
394 unsigned char buf
[MAX_REGISTER_RAW_SIZE
];
397 sp
= (CORE_ADDR
) tcb_ptr
->static_ctx
.sp
- 160;
399 if (regno
== FLAGS_REGNUM
)
400 child_ops
.to_store_registers (regno
); /* Let lower layer handle this... */
401 else if (regno
== SP_REGNUM
)
403 write_memory ((CORE_ADDR
) & tcb_ptr
->static_ctx
.sp
,
404 registers
+ REGISTER_BYTE (regno
),
405 REGISTER_RAW_SIZE (regno
));
406 tcb_ptr
->static_ctx
.sp
= (cma__t_hppa_regs
*)
407 (extract_address (registers
+ REGISTER_BYTE (regno
), REGISTER_RAW_SIZE (regno
)) + 160);
409 else if (regno
== PC_REGNUM
)
410 write_memory (sp
- 20,
411 registers
+ REGISTER_BYTE (regno
),
412 REGISTER_RAW_SIZE (regno
));
414 write_memory (sp
+ regmap
[regno
],
415 registers
+ REGISTER_BYTE (regno
),
416 REGISTER_RAW_SIZE (regno
));
420 do_cleanups (old_chain
);
423 /* Get ready to modify the registers array. On machines which store
424 individual registers, this doesn't need to do anything. On machines
425 which store all the registers in one fell swoop, this makes sure
426 that registers contains all the registers from the program being
430 hpux_thread_prepare_to_store (void)
432 child_ops
.to_prepare_to_store ();
436 hpux_thread_xfer_memory (memaddr
, myaddr
, len
, dowrite
, target
)
441 struct target_ops
*target
; /* ignored */
444 struct cleanup
*old_chain
;
446 old_chain
= save_inferior_pid ();
448 inferior_pid
= main_pid
;
450 retval
= child_ops
.to_xfer_memory (memaddr
, myaddr
, len
, dowrite
, target
);
452 do_cleanups (old_chain
);
457 /* Print status information about what we're accessing. */
460 hpux_thread_files_info (struct target_ops
*ignore
)
462 child_ops
.to_files_info (ignore
);
466 hpux_thread_kill_inferior (void)
468 child_ops
.to_kill ();
472 hpux_thread_notice_signals (int pid
)
474 child_ops
.to_notice_signals (pid
);
477 /* Fork an inferior process, and start debugging it with /proc. */
480 hpux_thread_create_inferior (char *exec_file
, char *allargs
, char **env
)
482 child_ops
.to_create_inferior (exec_file
, allargs
, env
);
484 if (hpux_thread_active
)
486 main_pid
= inferior_pid
;
488 push_target (&hpux_thread_ops
);
490 inferior_pid
= find_active_thread ();
492 add_thread (inferior_pid
);
496 /* This routine is called whenever a new symbol table is read in, or when all
497 symbol tables are removed. libthread_db can only be initialized when it
498 finds the right variables in libthread.so. Since it's a shared library,
499 those variables don't show up until the library gets mapped and the symbol
502 /* This new_objfile event is now managed by a chained function pointer.
503 * It is the callee's responsability to call the next client on the chain.
506 /* Saved pointer to previous owner of the new_objfile event. */
507 static void (*target_new_objfile_chain
) (struct objfile
*);
510 hpux_thread_new_objfile (struct objfile
*objfile
)
512 struct minimal_symbol
*ms
;
516 hpux_thread_active
= 0;
520 ms
= lookup_minimal_symbol ("cma__g_known_threads", NULL
, objfile
);
525 P_cma__g_known_threads
= SYMBOL_VALUE_ADDRESS (ms
);
527 ms
= lookup_minimal_symbol ("cma__g_current_thread", NULL
, objfile
);
532 P_cma__g_current_thread
= SYMBOL_VALUE_ADDRESS (ms
);
534 hpux_thread_active
= 1;
536 /* Call predecessor on chain, if any. */
537 if (target_new_objfile_chain
)
538 target_new_objfile_chain (objfile
);
541 /* Clean up after the inferior dies. */
544 hpux_thread_mourn_inferior (void)
546 child_ops
.to_mourn_inferior ();
549 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
552 hpux_thread_can_run (void)
554 return child_suppress_run
;
558 hpux_thread_alive (int pid
)
564 hpux_thread_stop (void)
566 child_ops
.to_stop ();
569 /* Convert a pid to printable form. */
572 hpux_pid_to_str (int pid
)
574 static char buf
[100];
576 sprintf (buf
, "Thread %d", pid
>> 16);
582 init_hpux_thread_ops (void)
584 hpux_thread_ops
.to_shortname
= "hpux-threads";
585 hpux_thread_ops
.to_longname
= "HPUX threads and pthread.";
586 hpux_thread_ops
.to_doc
= "HPUX threads and pthread support.";
587 hpux_thread_ops
.to_open
= hpux_thread_open
;
588 hpux_thread_ops
.to_attach
= hpux_thread_attach
;
589 hpux_thread_ops
.to_detach
= hpux_thread_detach
;
590 hpux_thread_ops
.to_resume
= hpux_thread_resume
;
591 hpux_thread_ops
.to_wait
= hpux_thread_wait
;
592 hpux_thread_ops
.to_fetch_registers
= hpux_thread_fetch_registers
;
593 hpux_thread_ops
.to_store_registers
= hpux_thread_store_registers
;
594 hpux_thread_ops
.to_prepare_to_store
= hpux_thread_prepare_to_store
;
595 hpux_thread_ops
.to_xfer_memory
= hpux_thread_xfer_memory
;
596 hpux_thread_ops
.to_files_info
= hpux_thread_files_info
;
597 hpux_thread_ops
.to_insert_breakpoint
= memory_insert_breakpoint
;
598 hpux_thread_ops
.to_remove_breakpoint
= memory_remove_breakpoint
;
599 hpux_thread_ops
.to_terminal_init
= terminal_init_inferior
;
600 hpux_thread_ops
.to_terminal_inferior
= terminal_inferior
;
601 hpux_thread_ops
.to_terminal_ours_for_output
= terminal_ours_for_output
;
602 hpux_thread_ops
.to_terminal_ours
= terminal_ours
;
603 hpux_thread_ops
.to_terminal_info
= child_terminal_info
;
604 hpux_thread_ops
.to_kill
= hpux_thread_kill_inferior
;
605 hpux_thread_ops
.to_create_inferior
= hpux_thread_create_inferior
;
606 hpux_thread_ops
.to_mourn_inferior
= hpux_thread_mourn_inferior
;
607 hpux_thread_ops
.to_can_run
= hpux_thread_can_run
;
608 hpux_thread_ops
.to_notice_signals
= hpux_thread_notice_signals
;
609 hpux_thread_ops
.to_thread_alive
= hpux_thread_alive
;
610 hpux_thread_ops
.to_stop
= hpux_thread_stop
;
611 hpux_thread_ops
.to_stratum
= process_stratum
;
612 hpux_thread_ops
.to_has_all_memory
= 1;
613 hpux_thread_ops
.to_has_memory
= 1;
614 hpux_thread_ops
.to_has_stack
= 1;
615 hpux_thread_ops
.to_has_registers
= 1;
616 hpux_thread_ops
.to_has_execution
= 1;
617 hpux_thread_ops
.to_magic
= OPS_MAGIC
;
621 _initialize_hpux_thread (void)
623 init_hpux_thread_ops ();
624 add_target (&hpux_thread_ops
);
626 child_suppress_run
= 1;
627 /* Hook into new_objfile notification. */
628 target_new_objfile_chain
= target_new_objfile_hook
;
629 target_new_objfile_hook
= hpux_thread_new_objfile
;