Fix typo.
[deliverable/binutils-gdb.git] / gdb / hpux-thread.c
CommitLineData
c906108c
SS
1/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
2 Copyright 1996, 1999 Free Software Foundation, Inc.
3
c5aa993b 4 This file is part of GDB.
c906108c 5
c5aa993b
JM
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.
c906108c 10
c5aa993b
JM
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.
c906108c 15
c5aa993b
JM
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. */
c906108c
SS
20
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.
24
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.
30
c5aa993b 31 */
c906108c
SS
32
33#include "defs.h"
34
35#define _CMA_NOWRAPPERS_
36
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 <fcntl.h>
c906108c
SS
43#include <sys/stat.h>
44#include "gdbcore.h"
45
46extern int child_suppress_run;
c5aa993b 47extern struct target_ops child_ops; /* target vector for inftarg.c */
c906108c 48
a14ed312 49extern void _initialize_hpux_thread (void);
c906108c
SS
50
51struct string_map
c5aa993b
JM
52 {
53 int num;
54 char *str;
55 };
c906108c
SS
56
57static int hpux_thread_active = 0;
58
59static int main_pid; /* Real process ID */
60
61static CORE_ADDR P_cma__g_known_threads;
62static CORE_ADDR P_cma__g_current_thread;
63
a14ed312 64static struct cleanup *save_inferior_pid (void);
c906108c 65
a14ed312 66static void restore_inferior_pid (int pid);
c906108c 67
a14ed312 68static void hpux_thread_resume (int pid, int step, enum target_signal signo);
c906108c 69
a14ed312 70static void init_hpux_thread_ops (void);
c906108c
SS
71
72static struct target_ops hpux_thread_ops;
73\f
74/*
75
c5aa993b 76 LOCAL FUNCTION
c906108c 77
c5aa993b
JM
78 save_inferior_pid - Save inferior_pid on the cleanup list
79 restore_inferior_pid - Restore inferior_pid from the cleanup list
c906108c 80
c5aa993b 81 SYNOPSIS
c906108c 82
c5aa993b
JM
83 struct cleanup *save_inferior_pid ()
84 void restore_inferior_pid (int pid)
c906108c 85
c5aa993b 86 DESCRIPTION
c906108c 87
c5aa993b
JM
88 These two functions act in unison to restore inferior_pid in
89 case of an error.
c906108c 90
c5aa993b 91 NOTES
c906108c 92
c5aa993b
JM
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.
c906108c
SS
98
99 */
100
101
102static struct cleanup *
103save_inferior_pid ()
104{
105 return make_cleanup (restore_inferior_pid, inferior_pid);
106}
107
108static void
109restore_inferior_pid (pid)
110 int pid;
111{
112 inferior_pid = pid;
113}
114\f
a14ed312 115static int find_active_thread (void);
c906108c
SS
116
117static int cached_thread;
118static int cached_active_thread;
119static cma__t_int_tcb cached_tcb;
120
121static int
122find_active_thread ()
123{
124 static cma__t_int_tcb tcb;
125 CORE_ADDR tcb_ptr;
126
127 if (cached_active_thread != 0)
128 return cached_active_thread;
129
c5aa993b
JM
130 read_memory ((CORE_ADDR) P_cma__g_current_thread,
131 (char *) &tcb_ptr,
c906108c
SS
132 sizeof tcb_ptr);
133
c5aa993b 134 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
c906108c
SS
135
136 return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid;
137}
138
a14ed312 139static cma__t_int_tcb *find_tcb (int thread);
c906108c
SS
140
141static cma__t_int_tcb *
142find_tcb (thread)
143 int thread;
144{
145 cma__t_known_object queue_header;
146 cma__t_queue *queue_ptr;
147
148 if (thread == cached_thread)
149 return &cached_tcb;
150
c5aa993b
JM
151 read_memory ((CORE_ADDR) P_cma__g_known_threads,
152 (char *) &queue_header,
c906108c
SS
153 sizeof queue_header);
154
155 for (queue_ptr = queue_header.queue.flink;
c5aa993b 156 queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
c906108c
SS
157 queue_ptr = cached_tcb.threads.flink)
158 {
159 cma__t_int_tcb *tcb_ptr;
160
161 tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
162
c5aa993b 163 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
c906108c
SS
164
165 if (cached_tcb.header.type == cma__c_obj_tcb)
166 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
167 {
168 cached_thread = thread;
169 return &cached_tcb;
170 }
171 }
172
173 error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
174 return NULL;
175}
176\f
177/* Most target vector functions from here on actually just pass through to
178 inftarg.c, as they don't need to do anything specific for threads. */
179
180/* ARGSUSED */
181static void
182hpux_thread_open (arg, from_tty)
183 char *arg;
184 int from_tty;
185{
186 child_ops.to_open (arg, from_tty);
187}
188
189/* Attach to process PID, then initialize for debugging it
190 and wait for the trace-trap that results from attaching. */
191
192static void
193hpux_thread_attach (args, from_tty)
194 char *args;
195 int from_tty;
196{
197 child_ops.to_attach (args, from_tty);
198
199 /* XXX - might want to iterate over all the threads and register them. */
200}
201
202/* Take a program previously attached to and detaches it.
203 The program resumes execution and will no longer stop
204 on signals, etc. We'd better not have left any breakpoints
205 in the program or it'll die when it hits one. For this
206 to work, it may be necessary for the process to have been
207 previously attached. It *might* work if the program was
208 started via the normal ptrace (PTRACE_TRACEME). */
209
210static void
211hpux_thread_detach (args, from_tty)
212 char *args;
213 int from_tty;
214{
215 child_ops.to_detach (args, from_tty);
216}
217
218/* Resume execution of process PID. If STEP is nozero, then
219 just single step it. If SIGNAL is nonzero, restart it with that
220 signal activated. We may have to convert pid from a thread-id to an LWP id
221 for procfs. */
222
223static void
224hpux_thread_resume (pid, step, signo)
225 int pid;
226 int step;
227 enum target_signal signo;
228{
229 struct cleanup *old_chain;
230
231 old_chain = save_inferior_pid ();
232
233 pid = inferior_pid = main_pid;
234
235#if 0
236 if (pid != -1)
237 {
238 pid = thread_to_lwp (pid, -2);
239 if (pid == -2) /* Inactive thread */
240 error ("This version of Solaris can't start inactive threads.");
241 }
242#endif
243
244 child_ops.to_resume (pid, step, signo);
245
246 cached_thread = 0;
247 cached_active_thread = 0;
248
249 do_cleanups (old_chain);
250}
251
252/* Wait for any threads to stop. We may have to convert PID from a thread id
253 to a LWP id, and vice versa on the way out. */
254
255static int
256hpux_thread_wait (pid, ourstatus)
257 int pid;
258 struct target_waitstatus *ourstatus;
259{
260 int rtnval;
261 struct cleanup *old_chain;
262
263 old_chain = save_inferior_pid ();
264
265 inferior_pid = main_pid;
266
267 if (pid != -1)
268 pid = main_pid;
269
270 rtnval = child_ops.to_wait (pid, ourstatus);
271
272 rtnval = find_active_thread ();
273
274 do_cleanups (old_chain);
275
276 return rtnval;
277}
278
279static char regmap[NUM_REGS] =
280{
c5aa993b
JM
281 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
282 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
283 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
c906108c
SS
284
285 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
286 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
287
288 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
289 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
290
291 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
292 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
293
294 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
c5aa993b
JM
295 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
296 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
297 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
298 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
299 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
300 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
301 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
302 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
c906108c
SS
303};
304
305static void
306hpux_thread_fetch_registers (regno)
307 int regno;
308{
309 cma__t_int_tcb tcb, *tcb_ptr;
310 struct cleanup *old_chain;
311 int i;
312 int first_regno, last_regno;
313
314 tcb_ptr = find_tcb (inferior_pid);
315
316 old_chain = save_inferior_pid ();
317
318 inferior_pid = main_pid;
319
320 if (tcb_ptr->state == cma__c_state_running)
321 {
322 child_ops.to_fetch_registers (regno);
323
324 do_cleanups (old_chain);
325
326 return;
327 }
328
329 if (regno == -1)
330 {
331 first_regno = 0;
332 last_regno = NUM_REGS - 1;
333 }
334 else
335 {
336 first_regno = regno;
337 last_regno = regno;
338 }
339
340 for (regno = first_regno; regno <= last_regno; regno++)
341 {
342 if (regmap[regno] == -1)
343 child_ops.to_fetch_registers (regno);
344 else
345 {
346 unsigned char buf[MAX_REGISTER_RAW_SIZE];
347 CORE_ADDR sp;
348
c5aa993b 349 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
350
351 if (regno == FLAGS_REGNUM)
352 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
353 memset (buf, '\000', REGISTER_RAW_SIZE (regno));
354 else if (regno == SP_REGNUM)
355 store_address (buf, sizeof sp, sp);
356 else if (regno == PC_REGNUM)
357 read_memory (sp - 20, buf, REGISTER_RAW_SIZE (regno));
358 else
359 read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
360
361 supply_register (regno, buf);
362 }
363 }
364
365 do_cleanups (old_chain);
366}
367
368static void
369hpux_thread_store_registers (regno)
370 int regno;
371{
372 cma__t_int_tcb tcb, *tcb_ptr;
373 struct cleanup *old_chain;
374 int i;
375 int first_regno, last_regno;
376
377 tcb_ptr = find_tcb (inferior_pid);
378
379 old_chain = save_inferior_pid ();
380
381 inferior_pid = main_pid;
382
383 if (tcb_ptr->state == cma__c_state_running)
384 {
385 child_ops.to_store_registers (regno);
386
387 do_cleanups (old_chain);
388
389 return;
390 }
391
392 if (regno == -1)
393 {
394 first_regno = 0;
395 last_regno = NUM_REGS - 1;
396 }
397 else
398 {
399 first_regno = regno;
400 last_regno = regno;
401 }
402
403 for (regno = first_regno; regno <= last_regno; regno++)
404 {
405 if (regmap[regno] == -1)
406 child_ops.to_store_registers (regno);
407 else
408 {
409 unsigned char buf[MAX_REGISTER_RAW_SIZE];
410 CORE_ADDR sp;
411
c5aa993b 412 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
413
414 if (regno == FLAGS_REGNUM)
c5aa993b 415 child_ops.to_store_registers (regno); /* Let lower layer handle this... */
c906108c
SS
416 else if (regno == SP_REGNUM)
417 {
c5aa993b 418 write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
c906108c
SS
419 registers + REGISTER_BYTE (regno),
420 REGISTER_RAW_SIZE (regno));
421 tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
422 (extract_address (registers + REGISTER_BYTE (regno), REGISTER_RAW_SIZE (regno)) + 160);
423 }
424 else if (regno == PC_REGNUM)
425 write_memory (sp - 20,
426 registers + REGISTER_BYTE (regno),
427 REGISTER_RAW_SIZE (regno));
428 else
429 write_memory (sp + regmap[regno],
430 registers + REGISTER_BYTE (regno),
431 REGISTER_RAW_SIZE (regno));
432 }
433 }
434
435 do_cleanups (old_chain);
436}
437
438/* Get ready to modify the registers array. On machines which store
439 individual registers, this doesn't need to do anything. On machines
440 which store all the registers in one fell swoop, this makes sure
441 that registers contains all the registers from the program being
442 debugged. */
443
444static void
445hpux_thread_prepare_to_store ()
446{
447 child_ops.to_prepare_to_store ();
448}
449
450static int
451hpux_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
452 CORE_ADDR memaddr;
453 char *myaddr;
454 int len;
455 int dowrite;
c5aa993b 456 struct target_ops *target; /* ignored */
c906108c
SS
457{
458 int retval;
459 struct cleanup *old_chain;
460
461 old_chain = save_inferior_pid ();
462
463 inferior_pid = main_pid;
464
465 retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
466
467 do_cleanups (old_chain);
468
469 return retval;
470}
471
472/* Print status information about what we're accessing. */
473
474static void
475hpux_thread_files_info (ignore)
476 struct target_ops *ignore;
477{
478 child_ops.to_files_info (ignore);
479}
480
481static void
482hpux_thread_kill_inferior ()
483{
484 child_ops.to_kill ();
485}
486
487static void
488hpux_thread_notice_signals (pid)
489 int pid;
490{
491 child_ops.to_notice_signals (pid);
492}
493
494/* Fork an inferior process, and start debugging it with /proc. */
495
496static void
497hpux_thread_create_inferior (exec_file, allargs, env)
498 char *exec_file;
499 char *allargs;
500 char **env;
501{
502 child_ops.to_create_inferior (exec_file, allargs, env);
503
504 if (hpux_thread_active)
505 {
506 main_pid = inferior_pid;
507
508 push_target (&hpux_thread_ops);
509
510 inferior_pid = find_active_thread ();
511
512 add_thread (inferior_pid);
513 }
514}
515
516/* This routine is called whenever a new symbol table is read in, or when all
517 symbol tables are removed. libthread_db can only be initialized when it
518 finds the right variables in libthread.so. Since it's a shared library,
519 those variables don't show up until the library gets mapped and the symbol
520 table is read in. */
521
11cf8741
JM
522/* This new_objfile event is now managed by a chained function pointer.
523 * It is the callee's responsability to call the next client on the chain.
524 */
525
526/* Saved pointer to previous owner of the new_objfile event. */
507f3c78 527static void (*target_new_objfile_chain) (struct objfile *);
11cf8741 528
c906108c
SS
529void
530hpux_thread_new_objfile (objfile)
531 struct objfile *objfile;
532{
533 struct minimal_symbol *ms;
534
535 if (!objfile)
536 {
537 hpux_thread_active = 0;
11cf8741 538 goto quit;
c906108c
SS
539 }
540
541 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
542
543 if (!ms)
11cf8741 544 goto quit;
c906108c
SS
545
546 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
547
548 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
549
550 if (!ms)
11cf8741 551 goto quit;
c906108c
SS
552
553 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
554
555 hpux_thread_active = 1;
11cf8741
JM
556quit:
557 /* Call predecessor on chain, if any. */
558 if (target_new_objfile_chain)
559 target_new_objfile_chain (objfile);
c906108c
SS
560}
561
562/* Clean up after the inferior dies. */
563
564static void
565hpux_thread_mourn_inferior ()
566{
567 child_ops.to_mourn_inferior ();
568}
569
570/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
571
572static int
573hpux_thread_can_run ()
574{
575 return child_suppress_run;
576}
577
578static int
579hpux_thread_alive (pid)
580 int pid;
581{
582 return 1;
583}
584
585static void
586hpux_thread_stop ()
587{
588 child_ops.to_stop ();
589}
590\f
591/* Convert a pid to printable form. */
592
593char *
594hpux_pid_to_str (pid)
595 int pid;
596{
597 static char buf[100];
598
599 sprintf (buf, "Thread %d", pid >> 16);
600
601 return buf;
602}
603\f
604static void
605init_hpux_thread_ops ()
606{
607 hpux_thread_ops.to_shortname = "hpux-threads";
608 hpux_thread_ops.to_longname = "HPUX threads and pthread.";
609 hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
610 hpux_thread_ops.to_open = hpux_thread_open;
611 hpux_thread_ops.to_attach = hpux_thread_attach;
612 hpux_thread_ops.to_detach = hpux_thread_detach;
613 hpux_thread_ops.to_resume = hpux_thread_resume;
614 hpux_thread_ops.to_wait = hpux_thread_wait;
615 hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
616 hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
617 hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
618 hpux_thread_ops.to_xfer_memory = hpux_thread_xfer_memory;
619 hpux_thread_ops.to_files_info = hpux_thread_files_info;
620 hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
621 hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
622 hpux_thread_ops.to_terminal_init = terminal_init_inferior;
623 hpux_thread_ops.to_terminal_inferior = terminal_inferior;
624 hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
625 hpux_thread_ops.to_terminal_ours = terminal_ours;
626 hpux_thread_ops.to_terminal_info = child_terminal_info;
627 hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
628 hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
629 hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
630 hpux_thread_ops.to_can_run = hpux_thread_can_run;
631 hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
b83266a0 632 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
c906108c
SS
633 hpux_thread_ops.to_stop = hpux_thread_stop;
634 hpux_thread_ops.to_stratum = process_stratum;
635 hpux_thread_ops.to_has_all_memory = 1;
636 hpux_thread_ops.to_has_memory = 1;
637 hpux_thread_ops.to_has_stack = 1;
638 hpux_thread_ops.to_has_registers = 1;
639 hpux_thread_ops.to_has_execution = 1;
640 hpux_thread_ops.to_magic = OPS_MAGIC;
641}
642
643void
644_initialize_hpux_thread ()
645{
646 init_hpux_thread_ops ();
647 add_target (&hpux_thread_ops);
648
649 child_suppress_run = 1;
11cf8741
JM
650 /* Hook into new_objfile notification. */
651 target_new_objfile_chain = target_new_objfile_hook;
652 target_new_objfile_hook = hpux_thread_new_objfile;
c906108c 653}
This page took 0.107481 seconds and 4 git commands to generate.