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, Boston, MA 02111-1307, USA. */
20 /* This module implements a sort of half target that sits between the
21 machine-independent parts of GDB and the ptrace interface (infptrace.c) to
22 provide access to the HPUX user-mode thread implementation.
24 HPUX threads are true user-mode threads, which are invoked via the cma_*
25 and pthread_* (DCE and Posix respectivly) interfaces. These are mostly
26 implemented in user-space, with all thread context kept in various
27 structures that live in the user's heap. For the most part, the kernel has
28 no knowlege of these threads.
34 #define _CMA_NOWRAPPERS_
36 #include <cma_tcb_defs.h>
37 #include <cma_deb_core.h>
38 #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
PARAMS ((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
PARAMS ((void));
66 static void restore_inferior_pid
PARAMS ((int pid
));
68 static void hpux_thread_resume
PARAMS ((int pid
, int step
,
69 enum target_signal signo
));
71 static void init_hpux_thread_ops
PARAMS ((void));
73 static struct target_ops hpux_thread_ops
;
79 save_inferior_pid - Save inferior_pid on the cleanup list
80 restore_inferior_pid - Restore inferior_pid from the cleanup list
84 struct cleanup *save_inferior_pid ()
85 void restore_inferior_pid (int pid)
89 These two functions act in unison to restore inferior_pid in
94 inferior_pid is a global variable that needs to be changed by many of
95 these routines before calling functions in procfs.c. In order to
96 guarantee that inferior_pid gets restored (in case of errors), you
97 need to call save_inferior_pid before changing it. At the end of the
98 function, you should invoke do_cleanups to restore it.
103 static struct cleanup
*
106 return make_cleanup (restore_inferior_pid
, inferior_pid
);
110 restore_inferior_pid (pid
)
116 static int find_active_thread
PARAMS ((void));
118 static int cached_thread
;
119 static int cached_active_thread
;
120 static cma__t_int_tcb cached_tcb
;
123 find_active_thread ()
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) | main_pid
;
140 static cma__t_int_tcb
* find_tcb
PARAMS ((int thread
));
142 static cma__t_int_tcb
*
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 (arg
, from_tty
)
187 child_ops
.to_open (arg
, from_tty
);
190 /* Attach to process PID, then initialize for debugging it
191 and wait for the trace-trap that results from attaching. */
194 hpux_thread_attach (args
, from_tty
)
198 child_ops
.to_attach (args
, from_tty
);
200 /* XXX - might want to iterate over all the threads and register them. */
203 /* Take a program previously attached to and detaches it.
204 The program resumes execution and will no longer stop
205 on signals, etc. We'd better not have left any breakpoints
206 in the program or it'll die when it hits one. For this
207 to work, it may be necessary for the process to have been
208 previously attached. It *might* work if the program was
209 started via the normal ptrace (PTRACE_TRACEME). */
212 hpux_thread_detach (args
, from_tty
)
216 child_ops
.to_detach (args
, from_tty
);
219 /* Resume execution of process PID. If STEP is nozero, then
220 just single step it. If SIGNAL is nonzero, restart it with that
221 signal activated. We may have to convert pid from a thread-id to an LWP id
225 hpux_thread_resume (pid
, step
, signo
)
228 enum target_signal signo
;
230 struct cleanup
*old_chain
;
232 old_chain
= save_inferior_pid ();
234 pid
= inferior_pid
= main_pid
;
239 pid
= thread_to_lwp (pid
, -2);
240 if (pid
== -2) /* Inactive thread */
241 error ("This version of Solaris can't start inactive threads.");
245 child_ops
.to_resume (pid
, step
, signo
);
248 cached_active_thread
= 0;
250 do_cleanups (old_chain
);
253 /* Wait for any threads to stop. We may have to convert PID from a thread id
254 to a LWP id, and vice versa on the way out. */
257 hpux_thread_wait (pid
, ourstatus
)
259 struct target_waitstatus
*ourstatus
;
262 struct cleanup
*old_chain
;
264 old_chain
= save_inferior_pid ();
266 inferior_pid
= main_pid
;
271 rtnval
= child_ops
.to_wait (pid
, ourstatus
);
273 rtnval
= find_active_thread ();
275 do_cleanups (old_chain
);
280 static char regmap
[NUM_REGS
] =
282 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
283 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
284 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
286 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
287 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
289 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
290 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
292 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
293 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
295 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
296 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
297 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
298 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
299 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
300 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
301 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
302 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
303 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
307 hpux_thread_fetch_registers (regno
)
310 cma__t_int_tcb tcb
, *tcb_ptr
;
311 struct cleanup
*old_chain
;
313 int first_regno
, last_regno
;
315 tcb_ptr
= find_tcb (inferior_pid
);
317 old_chain
= save_inferior_pid ();
319 inferior_pid
= main_pid
;
321 if (tcb_ptr
->state
== cma__c_state_running
)
323 child_ops
.to_fetch_registers (regno
);
325 do_cleanups (old_chain
);
333 last_regno
= NUM_REGS
- 1;
341 for (regno
= first_regno
; regno
<= last_regno
; regno
++)
343 if (regmap
[regno
] == -1)
344 child_ops
.to_fetch_registers (regno
);
347 unsigned char buf
[MAX_REGISTER_RAW_SIZE
];
350 sp
= (CORE_ADDR
)tcb_ptr
->static_ctx
.sp
- 160;
352 if (regno
== FLAGS_REGNUM
)
353 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
354 memset (buf
, '\000', REGISTER_RAW_SIZE (regno
));
355 else if (regno
== SP_REGNUM
)
356 store_address (buf
, sizeof sp
, sp
);
357 else if (regno
== PC_REGNUM
)
358 read_memory (sp
- 20, buf
, REGISTER_RAW_SIZE (regno
));
360 read_memory (sp
+ regmap
[regno
], buf
, REGISTER_RAW_SIZE (regno
));
362 supply_register (regno
, buf
);
366 do_cleanups (old_chain
);
370 hpux_thread_store_registers (regno
)
373 cma__t_int_tcb tcb
, *tcb_ptr
;
374 struct cleanup
*old_chain
;
376 int first_regno
, last_regno
;
378 tcb_ptr
= find_tcb (inferior_pid
);
380 old_chain
= save_inferior_pid ();
382 inferior_pid
= main_pid
;
384 if (tcb_ptr
->state
== cma__c_state_running
)
386 child_ops
.to_store_registers (regno
);
388 do_cleanups (old_chain
);
396 last_regno
= NUM_REGS
- 1;
404 for (regno
= first_regno
; regno
<= last_regno
; regno
++)
406 if (regmap
[regno
] == -1)
407 child_ops
.to_store_registers (regno
);
410 unsigned char buf
[MAX_REGISTER_RAW_SIZE
];
413 sp
= (CORE_ADDR
)tcb_ptr
->static_ctx
.sp
- 160;
415 if (regno
== FLAGS_REGNUM
)
416 child_ops
.to_store_registers (regno
); /* Let lower layer handle this... */
417 else if (regno
== SP_REGNUM
)
419 write_memory ((CORE_ADDR
)&tcb_ptr
->static_ctx
.sp
,
420 registers
+ REGISTER_BYTE (regno
),
421 REGISTER_RAW_SIZE (regno
));
422 tcb_ptr
->static_ctx
.sp
= (cma__t_hppa_regs
*)
423 (extract_address (registers
+ REGISTER_BYTE (regno
), REGISTER_RAW_SIZE (regno
)) + 160);
425 else if (regno
== PC_REGNUM
)
426 write_memory (sp
- 20,
427 registers
+ REGISTER_BYTE (regno
),
428 REGISTER_RAW_SIZE (regno
));
430 write_memory (sp
+ regmap
[regno
],
431 registers
+ REGISTER_BYTE (regno
),
432 REGISTER_RAW_SIZE (regno
));
436 do_cleanups (old_chain
);
439 /* Get ready to modify the registers array. On machines which store
440 individual registers, this doesn't need to do anything. On machines
441 which store all the registers in one fell swoop, this makes sure
442 that registers contains all the registers from the program being
446 hpux_thread_prepare_to_store ()
448 child_ops
.to_prepare_to_store ();
452 hpux_thread_xfer_memory (memaddr
, myaddr
, len
, dowrite
, target
)
457 struct target_ops
*target
; /* ignored */
460 struct cleanup
*old_chain
;
462 old_chain
= save_inferior_pid ();
464 inferior_pid
= main_pid
;
466 retval
= child_ops
.to_xfer_memory (memaddr
, myaddr
, len
, dowrite
, target
);
468 do_cleanups (old_chain
);
473 /* Print status information about what we're accessing. */
476 hpux_thread_files_info (ignore
)
477 struct target_ops
*ignore
;
479 child_ops
.to_files_info (ignore
);
483 hpux_thread_kill_inferior ()
485 child_ops
.to_kill ();
489 hpux_thread_notice_signals (pid
)
492 child_ops
.to_notice_signals (pid
);
495 /* Fork an inferior process, and start debugging it with /proc. */
498 hpux_thread_create_inferior (exec_file
, allargs
, env
)
503 child_ops
.to_create_inferior (exec_file
, allargs
, env
);
505 if (hpux_thread_active
)
507 main_pid
= inferior_pid
;
509 push_target (&hpux_thread_ops
);
511 inferior_pid
= find_active_thread ();
513 add_thread (inferior_pid
);
517 /* This routine is called whenever a new symbol table is read in, or when all
518 symbol tables are removed. libthread_db can only be initialized when it
519 finds the right variables in libthread.so. Since it's a shared library,
520 those variables don't show up until the library gets mapped and the symbol
524 hpux_thread_new_objfile (objfile
)
525 struct objfile
*objfile
;
527 struct minimal_symbol
*ms
;
531 hpux_thread_active
= 0;
536 ms
= lookup_minimal_symbol ("cma__g_known_threads", NULL
, objfile
);
541 P_cma__g_known_threads
= SYMBOL_VALUE_ADDRESS (ms
);
543 ms
= lookup_minimal_symbol ("cma__g_current_thread", NULL
, objfile
);
548 P_cma__g_current_thread
= SYMBOL_VALUE_ADDRESS (ms
);
550 hpux_thread_active
= 1;
553 /* Clean up after the inferior dies. */
556 hpux_thread_mourn_inferior ()
558 child_ops
.to_mourn_inferior ();
561 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
564 hpux_thread_can_run ()
566 return child_suppress_run
;
570 hpux_thread_alive (pid
)
579 child_ops
.to_stop ();
582 /* Convert a pid to printable form. */
585 hpux_pid_to_str (pid
)
588 static char buf
[100];
590 sprintf (buf
, "Thread %d", pid
>> 16);
596 init_hpux_thread_ops ()
598 hpux_thread_ops
.to_shortname
= "hpux-threads";
599 hpux_thread_ops
.to_longname
= "HPUX threads and pthread.";
600 hpux_thread_ops
.to_doc
= "HPUX threads and pthread support.";
601 hpux_thread_ops
.to_open
= hpux_thread_open
;
602 hpux_thread_ops
.to_attach
= hpux_thread_attach
;
603 hpux_thread_ops
.to_detach
= hpux_thread_detach
;
604 hpux_thread_ops
.to_resume
= hpux_thread_resume
;
605 hpux_thread_ops
.to_wait
= hpux_thread_wait
;
606 hpux_thread_ops
.to_fetch_registers
= hpux_thread_fetch_registers
;
607 hpux_thread_ops
.to_store_registers
= hpux_thread_store_registers
;
608 hpux_thread_ops
.to_prepare_to_store
= hpux_thread_prepare_to_store
;
609 hpux_thread_ops
.to_xfer_memory
= hpux_thread_xfer_memory
;
610 hpux_thread_ops
.to_files_info
= hpux_thread_files_info
;
611 hpux_thread_ops
.to_insert_breakpoint
= memory_insert_breakpoint
;
612 hpux_thread_ops
.to_remove_breakpoint
= memory_remove_breakpoint
;
613 hpux_thread_ops
.to_terminal_init
= terminal_init_inferior
;
614 hpux_thread_ops
.to_terminal_inferior
= terminal_inferior
;
615 hpux_thread_ops
.to_terminal_ours_for_output
= terminal_ours_for_output
;
616 hpux_thread_ops
.to_terminal_ours
= terminal_ours
;
617 hpux_thread_ops
.to_terminal_info
= child_terminal_info
;
618 hpux_thread_ops
.to_kill
= hpux_thread_kill_inferior
;
619 hpux_thread_ops
.to_create_inferior
= hpux_thread_create_inferior
;
620 hpux_thread_ops
.to_mourn_inferior
= hpux_thread_mourn_inferior
;
621 hpux_thread_ops
.to_can_run
= hpux_thread_can_run
;
622 hpux_thread_ops
.to_notice_signals
= hpux_thread_notice_signals
;
623 hpux_thread_ops
.to_thread_alive
= hpux_thread_thread_alive
;
624 hpux_thread_ops
.to_stop
= hpux_thread_stop
;
625 hpux_thread_ops
.to_stratum
= process_stratum
;
626 hpux_thread_ops
.to_has_all_memory
= 1;
627 hpux_thread_ops
.to_has_memory
= 1;
628 hpux_thread_ops
.to_has_stack
= 1;
629 hpux_thread_ops
.to_has_registers
= 1;
630 hpux_thread_ops
.to_has_execution
= 1;
631 hpux_thread_ops
.to_magic
= OPS_MAGIC
;
635 _initialize_hpux_thread ()
637 init_hpux_thread_ops ();
638 add_target (&hpux_thread_ops
);
640 child_suppress_run
= 1;