* externalize a function
[binutils-gdb.git] / gdb / hpux-thread.c
blobd7172eb85b762868c2eee2019d20d283acbb0c78
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.
33 #include "defs.h"
35 #define _CMA_NOWRAPPERS_
37 #include <cma_tcb_defs.h>
38 #include <cma_deb_core.h>
39 #include "gdbthread.h"
40 #include "target.h"
41 #include "inferior.h"
42 #include "regcache.h"
43 #include <fcntl.h>
44 #include <sys/stat.h>
45 #include "gdbcore.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);
52 struct string_map
54 int num;
55 char *str;
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 (void);
67 static void restore_inferior_pid (int pid);
69 static void hpux_thread_resume (int pid, int step, enum target_signal signo);
71 static void init_hpux_thread_ops (void);
73 static struct target_ops hpux_thread_ops;
77 LOCAL FUNCTION
79 save_inferior_pid - Save inferior_pid on the cleanup list
80 restore_inferior_pid - Restore inferior_pid from the cleanup list
82 SYNOPSIS
84 struct cleanup *save_inferior_pid ()
85 void restore_inferior_pid (int pid)
87 DESCRIPTION
89 These two functions act in unison to restore inferior_pid in
90 case of an error.
92 NOTES
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 *
104 save_inferior_pid (void)
106 return make_cleanup (restore_inferior_pid, inferior_pid);
109 static void
110 restore_inferior_pid (int pid)
112 inferior_pid = pid;
115 static int find_active_thread (void);
117 static int cached_thread;
118 static int cached_active_thread;
119 static cma__t_int_tcb cached_tcb;
121 static int
122 find_active_thread (void)
124 static cma__t_int_tcb tcb;
125 CORE_ADDR tcb_ptr;
127 if (cached_active_thread != 0)
128 return cached_active_thread;
130 read_memory ((CORE_ADDR) P_cma__g_current_thread,
131 (char *) &tcb_ptr,
132 sizeof tcb_ptr);
134 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
136 return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid;
139 static cma__t_int_tcb *find_tcb (int thread);
141 static cma__t_int_tcb *
142 find_tcb (int thread)
144 cma__t_known_object queue_header;
145 cma__t_queue *queue_ptr;
147 if (thread == cached_thread)
148 return &cached_tcb;
150 read_memory ((CORE_ADDR) P_cma__g_known_threads,
151 (char *) &queue_header,
152 sizeof queue_header);
154 for (queue_ptr = queue_header.queue.flink;
155 queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
156 queue_ptr = cached_tcb.threads.flink)
158 cma__t_int_tcb *tcb_ptr;
160 tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
162 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
164 if (cached_tcb.header.type == cma__c_obj_tcb)
165 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
167 cached_thread = thread;
168 return &cached_tcb;
172 error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
173 return NULL;
176 /* Most target vector functions from here on actually just pass through to
177 inftarg.c, as they don't need to do anything specific for threads. */
179 /* ARGSUSED */
180 static void
181 hpux_thread_open (char *arg, int from_tty)
183 child_ops.to_open (arg, from_tty);
186 /* Attach to process PID, then initialize for debugging it
187 and wait for the trace-trap that results from attaching. */
189 static void
190 hpux_thread_attach (char *args, int from_tty)
192 child_ops.to_attach (args, from_tty);
194 /* XXX - might want to iterate over all the threads and register them. */
197 /* Take a program previously attached to and detaches it.
198 The program resumes execution and will no longer stop
199 on signals, etc. We'd better not have left any breakpoints
200 in the program or it'll die when it hits one. For this
201 to work, it may be necessary for the process to have been
202 previously attached. It *might* work if the program was
203 started via the normal ptrace (PTRACE_TRACEME). */
205 static void
206 hpux_thread_detach (char *args, int from_tty)
208 child_ops.to_detach (args, from_tty);
211 /* Resume execution of process PID. If STEP is nozero, then
212 just single step it. If SIGNAL is nonzero, restart it with that
213 signal activated. We may have to convert pid from a thread-id to an LWP id
214 for procfs. */
216 static void
217 hpux_thread_resume (int pid, int step, enum target_signal signo)
219 struct cleanup *old_chain;
221 old_chain = save_inferior_pid ();
223 pid = inferior_pid = main_pid;
225 #if 0
226 if (pid != -1)
228 pid = thread_to_lwp (pid, -2);
229 if (pid == -2) /* Inactive thread */
230 error ("This version of Solaris can't start inactive threads.");
232 #endif
234 child_ops.to_resume (pid, step, signo);
236 cached_thread = 0;
237 cached_active_thread = 0;
239 do_cleanups (old_chain);
242 /* Wait for any threads to stop. We may have to convert PID from a thread id
243 to a LWP id, and vice versa on the way out. */
245 static int
246 hpux_thread_wait (int pid, struct target_waitstatus *ourstatus)
248 int rtnval;
249 struct cleanup *old_chain;
251 old_chain = save_inferior_pid ();
253 inferior_pid = main_pid;
255 if (pid != -1)
256 pid = main_pid;
258 rtnval = child_ops.to_wait (pid, ourstatus);
260 rtnval = find_active_thread ();
262 do_cleanups (old_chain);
264 return rtnval;
267 static char regmap[NUM_REGS] =
269 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
270 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
271 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
273 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
274 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
276 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
277 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
279 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
280 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
282 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
283 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
284 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
285 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
286 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
287 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
288 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
289 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
290 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
293 static void
294 hpux_thread_fetch_registers (int regno)
296 cma__t_int_tcb tcb, *tcb_ptr;
297 struct cleanup *old_chain;
298 int i;
299 int first_regno, last_regno;
301 tcb_ptr = find_tcb (inferior_pid);
303 old_chain = save_inferior_pid ();
305 inferior_pid = main_pid;
307 if (tcb_ptr->state == cma__c_state_running)
309 child_ops.to_fetch_registers (regno);
311 do_cleanups (old_chain);
313 return;
316 if (regno == -1)
318 first_regno = 0;
319 last_regno = NUM_REGS - 1;
321 else
323 first_regno = regno;
324 last_regno = regno;
327 for (regno = first_regno; regno <= last_regno; regno++)
329 if (regmap[regno] == -1)
330 child_ops.to_fetch_registers (regno);
331 else
333 unsigned char buf[MAX_REGISTER_RAW_SIZE];
334 CORE_ADDR sp;
336 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
338 if (regno == FLAGS_REGNUM)
339 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
340 memset (buf, '\000', REGISTER_RAW_SIZE (regno));
341 else if (regno == SP_REGNUM)
342 store_address (buf, sizeof sp, sp);
343 else if (regno == PC_REGNUM)
344 read_memory (sp - 20, buf, REGISTER_RAW_SIZE (regno));
345 else
346 read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
348 supply_register (regno, buf);
352 do_cleanups (old_chain);
355 static void
356 hpux_thread_store_registers (int regno)
358 cma__t_int_tcb tcb, *tcb_ptr;
359 struct cleanup *old_chain;
360 int i;
361 int first_regno, last_regno;
363 tcb_ptr = find_tcb (inferior_pid);
365 old_chain = save_inferior_pid ();
367 inferior_pid = main_pid;
369 if (tcb_ptr->state == cma__c_state_running)
371 child_ops.to_store_registers (regno);
373 do_cleanups (old_chain);
375 return;
378 if (regno == -1)
380 first_regno = 0;
381 last_regno = NUM_REGS - 1;
383 else
385 first_regno = regno;
386 last_regno = regno;
389 for (regno = first_regno; regno <= last_regno; regno++)
391 if (regmap[regno] == -1)
392 child_ops.to_store_registers (regno);
393 else
395 unsigned char buf[MAX_REGISTER_RAW_SIZE];
396 CORE_ADDR sp;
398 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
400 if (regno == FLAGS_REGNUM)
401 child_ops.to_store_registers (regno); /* Let lower layer handle this... */
402 else if (regno == SP_REGNUM)
404 write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
405 registers + REGISTER_BYTE (regno),
406 REGISTER_RAW_SIZE (regno));
407 tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
408 (extract_address (registers + REGISTER_BYTE (regno), REGISTER_RAW_SIZE (regno)) + 160);
410 else if (regno == PC_REGNUM)
411 write_memory (sp - 20,
412 registers + REGISTER_BYTE (regno),
413 REGISTER_RAW_SIZE (regno));
414 else
415 write_memory (sp + regmap[regno],
416 registers + REGISTER_BYTE (regno),
417 REGISTER_RAW_SIZE (regno));
421 do_cleanups (old_chain);
424 /* Get ready to modify the registers array. On machines which store
425 individual registers, this doesn't need to do anything. On machines
426 which store all the registers in one fell swoop, this makes sure
427 that registers contains all the registers from the program being
428 debugged. */
430 static void
431 hpux_thread_prepare_to_store (void)
433 child_ops.to_prepare_to_store ();
436 static int
437 hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
438 int dowrite, struct mem_attrib *attribs,
439 struct target_ops *target)
441 int retval;
442 struct cleanup *old_chain;
444 old_chain = save_inferior_pid ();
446 inferior_pid = main_pid;
448 retval =
449 child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
451 do_cleanups (old_chain);
453 return retval;
456 /* Print status information about what we're accessing. */
458 static void
459 hpux_thread_files_info (struct target_ops *ignore)
461 child_ops.to_files_info (ignore);
464 static void
465 hpux_thread_kill_inferior (void)
467 child_ops.to_kill ();
470 static void
471 hpux_thread_notice_signals (int pid)
473 child_ops.to_notice_signals (pid);
476 /* Fork an inferior process, and start debugging it with /proc. */
478 static void
479 hpux_thread_create_inferior (char *exec_file, char *allargs, char **env)
481 child_ops.to_create_inferior (exec_file, allargs, env);
483 if (hpux_thread_active)
485 main_pid = inferior_pid;
487 push_target (&hpux_thread_ops);
489 inferior_pid = find_active_thread ();
491 add_thread (inferior_pid);
495 /* This routine is called whenever a new symbol table is read in, or when all
496 symbol tables are removed. libthread_db can only be initialized when it
497 finds the right variables in libthread.so. Since it's a shared library,
498 those variables don't show up until the library gets mapped and the symbol
499 table is read in. */
501 /* This new_objfile event is now managed by a chained function pointer.
502 * It is the callee's responsability to call the next client on the chain.
505 /* Saved pointer to previous owner of the new_objfile event. */
506 static void (*target_new_objfile_chain) (struct objfile *);
508 void
509 hpux_thread_new_objfile (struct objfile *objfile)
511 struct minimal_symbol *ms;
513 if (!objfile)
515 hpux_thread_active = 0;
516 goto quit;
519 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
521 if (!ms)
522 goto quit;
524 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
526 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
528 if (!ms)
529 goto quit;
531 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
533 hpux_thread_active = 1;
534 quit:
535 /* Call predecessor on chain, if any. */
536 if (target_new_objfile_chain)
537 target_new_objfile_chain (objfile);
540 /* Clean up after the inferior dies. */
542 static void
543 hpux_thread_mourn_inferior (void)
545 child_ops.to_mourn_inferior ();
548 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
550 static int
551 hpux_thread_can_run (void)
553 return child_suppress_run;
556 static int
557 hpux_thread_alive (int pid)
559 return 1;
562 static void
563 hpux_thread_stop (void)
565 child_ops.to_stop ();
568 /* Convert a pid to printable form. */
570 char *
571 hpux_pid_to_str (int pid)
573 static char buf[100];
575 sprintf (buf, "Thread %d", pid >> 16);
577 return buf;
580 static void
581 init_hpux_thread_ops (void)
583 hpux_thread_ops.to_shortname = "hpux-threads";
584 hpux_thread_ops.to_longname = "HPUX threads and pthread.";
585 hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
586 hpux_thread_ops.to_open = hpux_thread_open;
587 hpux_thread_ops.to_attach = hpux_thread_attach;
588 hpux_thread_ops.to_detach = hpux_thread_detach;
589 hpux_thread_ops.to_resume = hpux_thread_resume;
590 hpux_thread_ops.to_wait = hpux_thread_wait;
591 hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
592 hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
593 hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
594 hpux_thread_ops.to_xfer_memory = hpux_thread_xfer_memory;
595 hpux_thread_ops.to_files_info = hpux_thread_files_info;
596 hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
597 hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
598 hpux_thread_ops.to_terminal_init = terminal_init_inferior;
599 hpux_thread_ops.to_terminal_inferior = terminal_inferior;
600 hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
601 hpux_thread_ops.to_terminal_ours = terminal_ours;
602 hpux_thread_ops.to_terminal_info = child_terminal_info;
603 hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
604 hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
605 hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
606 hpux_thread_ops.to_can_run = hpux_thread_can_run;
607 hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
608 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
609 hpux_thread_ops.to_stop = hpux_thread_stop;
610 hpux_thread_ops.to_stratum = process_stratum;
611 hpux_thread_ops.to_has_all_memory = 1;
612 hpux_thread_ops.to_has_memory = 1;
613 hpux_thread_ops.to_has_stack = 1;
614 hpux_thread_ops.to_has_registers = 1;
615 hpux_thread_ops.to_has_execution = 1;
616 hpux_thread_ops.to_magic = OPS_MAGIC;
619 void
620 _initialize_hpux_thread (void)
622 init_hpux_thread_ops ();
623 add_target (&hpux_thread_ops);
625 child_suppress_run = 1;
626 /* Hook into new_objfile notification. */
627 target_new_objfile_chain = target_new_objfile_hook;
628 target_new_objfile_hook = hpux_thread_new_objfile;