Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / gdb / gdb / hpux-thread.c
1 /* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
2    Copyright 1996, 1999 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
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.
10
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.
15
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.  */
19
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.
23
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.
29
30    */
31
32 #include "defs.h"
33
34 #define _CMA_NOWRAPPERS_
35
36 #include <cma_tcb_defs.h>
37 #include <cma_deb_core.h>
38 #include "gdbthread.h"
39 #include "target.h"
40 #include "inferior.h"
41 #include <fcntl.h>
42 #include <unistd.h>
43 #include <sys/stat.h>
44 #include "gdbcore.h"
45
46 extern int child_suppress_run;
47 extern struct target_ops child_ops; /* target vector for inftarg.c */
48
49 extern void _initialize_hpux_thread PARAMS ((void));
50
51 struct string_map
52 {
53   int num;
54   char *str;
55 };
56
57 static int hpux_thread_active = 0;
58
59 static int main_pid;            /* Real process ID */
60
61 static CORE_ADDR P_cma__g_known_threads;
62 static CORE_ADDR P_cma__g_current_thread;
63
64 static struct cleanup * save_inferior_pid PARAMS ((void));
65
66 static void restore_inferior_pid PARAMS ((int pid));
67
68 static void hpux_thread_resume PARAMS ((int pid, int step,
69                                         enum target_signal signo));
70
71 static void init_hpux_thread_ops PARAMS ((void));
72
73 static struct target_ops hpux_thread_ops;
74 \f
75 /*
76
77 LOCAL FUNCTION
78
79         save_inferior_pid - Save inferior_pid on the cleanup list
80         restore_inferior_pid - Restore inferior_pid from the cleanup list
81
82 SYNOPSIS
83
84         struct cleanup *save_inferior_pid ()
85         void restore_inferior_pid (int pid)
86
87 DESCRIPTION
88
89         These two functions act in unison to restore inferior_pid in
90         case of an error.
91
92 NOTES
93
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.
99
100  */
101
102
103 static struct cleanup *
104 save_inferior_pid ()
105 {
106   return make_cleanup (restore_inferior_pid, inferior_pid);
107 }
108
109 static void
110 restore_inferior_pid (pid)
111      int pid;
112 {
113   inferior_pid = pid;
114 }
115 \f
116 static int find_active_thread PARAMS ((void));
117
118 static int cached_thread;
119 static int cached_active_thread;
120 static cma__t_int_tcb cached_tcb;
121
122 static int
123 find_active_thread ()
124 {
125   static cma__t_int_tcb tcb;
126   CORE_ADDR tcb_ptr;
127
128   if (cached_active_thread != 0)
129     return cached_active_thread;
130
131   read_memory ((CORE_ADDR)P_cma__g_current_thread,
132                (char *)&tcb_ptr,
133                sizeof tcb_ptr);
134
135   read_memory (tcb_ptr, (char *)&tcb, sizeof tcb);
136
137   return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid;
138 }
139
140 static cma__t_int_tcb * find_tcb PARAMS ((int thread));
141
142 static cma__t_int_tcb *
143 find_tcb (thread)
144      int thread;
145 {
146   cma__t_known_object queue_header;
147   cma__t_queue *queue_ptr;
148
149   if (thread == cached_thread)
150     return &cached_tcb;
151
152   read_memory ((CORE_ADDR)P_cma__g_known_threads,
153                (char *)&queue_header,
154                sizeof queue_header);
155
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)
159     {
160       cma__t_int_tcb *tcb_ptr;
161
162       tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
163
164       read_memory ((CORE_ADDR)tcb_ptr, (char *)&cached_tcb, sizeof cached_tcb);
165
166       if (cached_tcb.header.type == cma__c_obj_tcb)
167         if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
168           {
169             cached_thread = thread;
170             return &cached_tcb;
171           }
172     }
173
174   error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
175   return NULL;
176 }
177 \f
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.  */
180
181 /* ARGSUSED */
182 static void
183 hpux_thread_open (arg, from_tty)
184      char *arg;
185      int from_tty;
186 {
187   child_ops.to_open (arg, from_tty);
188 }
189
190 /* Attach to process PID, then initialize for debugging it
191    and wait for the trace-trap that results from attaching.  */
192
193 static void
194 hpux_thread_attach (args, from_tty)
195      char *args;
196      int from_tty;
197 {
198   child_ops.to_attach (args, from_tty);
199
200   /* XXX - might want to iterate over all the threads and register them. */
201 }
202
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).  */
210
211 static void
212 hpux_thread_detach (args, from_tty)
213      char *args;
214      int from_tty;
215 {
216   child_ops.to_detach (args, from_tty);
217 }
218
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
222    for procfs.  */
223
224 static void
225 hpux_thread_resume (pid, step, signo)
226      int pid;
227      int step;
228      enum target_signal signo;
229 {
230   struct cleanup *old_chain;
231
232   old_chain = save_inferior_pid ();
233
234   pid = inferior_pid = main_pid;
235
236 #if 0
237   if (pid != -1)
238     {
239       pid = thread_to_lwp (pid, -2);
240       if (pid == -2)            /* Inactive thread */
241         error ("This version of Solaris can't start inactive threads.");
242     }
243 #endif
244
245   child_ops.to_resume (pid, step, signo);
246
247   cached_thread = 0;
248   cached_active_thread = 0;
249
250   do_cleanups (old_chain);
251 }
252
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.  */
255
256 static int
257 hpux_thread_wait (pid, ourstatus)
258      int pid;
259      struct target_waitstatus *ourstatus;
260 {
261   int rtnval;
262   struct cleanup *old_chain;
263
264   old_chain = save_inferior_pid ();
265
266   inferior_pid = main_pid;
267
268   if (pid != -1)
269     pid = main_pid;
270
271   rtnval = child_ops.to_wait (pid, ourstatus);
272
273   rtnval = find_active_thread ();
274
275   do_cleanups (old_chain);
276
277   return rtnval;
278 }
279
280 static char regmap[NUM_REGS] =
281 {
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 */
285
286   /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
287   -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
288
289   /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
290   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
291
292   /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
293   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
294
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 */
304 };
305
306 static void
307 hpux_thread_fetch_registers (regno)
308      int regno;
309 {
310   cma__t_int_tcb tcb, *tcb_ptr;
311   struct cleanup *old_chain;
312   int i;
313   int first_regno, last_regno;
314
315   tcb_ptr = find_tcb (inferior_pid);
316
317   old_chain = save_inferior_pid ();
318
319   inferior_pid = main_pid;
320
321   if (tcb_ptr->state == cma__c_state_running)
322     {
323       child_ops.to_fetch_registers (regno);
324
325       do_cleanups (old_chain);
326
327       return;
328     }
329
330   if (regno == -1)
331     {
332       first_regno = 0;
333       last_regno = NUM_REGS - 1;
334     }
335   else
336     {
337       first_regno = regno;
338       last_regno = regno;
339     }
340
341   for (regno = first_regno; regno <= last_regno; regno++)
342     {
343       if (regmap[regno] == -1)
344         child_ops.to_fetch_registers (regno);
345       else
346         {
347           unsigned char buf[MAX_REGISTER_RAW_SIZE];
348           CORE_ADDR sp;
349
350           sp = (CORE_ADDR)tcb_ptr->static_ctx.sp - 160;
351
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));
359           else
360             read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
361
362           supply_register (regno, buf);
363         }
364     }
365
366   do_cleanups (old_chain);
367 }
368
369 static void
370 hpux_thread_store_registers (regno)
371      int regno;
372 {
373   cma__t_int_tcb tcb, *tcb_ptr;
374   struct cleanup *old_chain;
375   int i;
376   int first_regno, last_regno;
377
378   tcb_ptr = find_tcb (inferior_pid);
379
380   old_chain = save_inferior_pid ();
381
382   inferior_pid = main_pid;
383
384   if (tcb_ptr->state == cma__c_state_running)
385     {
386       child_ops.to_store_registers (regno);
387
388       do_cleanups (old_chain);
389
390       return;
391     }
392
393   if (regno == -1)
394     {
395       first_regno = 0;
396       last_regno = NUM_REGS - 1;
397     }
398   else
399     {
400       first_regno = regno;
401       last_regno = regno;
402     }
403
404   for (regno = first_regno; regno <= last_regno; regno++)
405     {
406       if (regmap[regno] == -1)
407         child_ops.to_store_registers (regno);
408       else
409         {
410           unsigned char buf[MAX_REGISTER_RAW_SIZE];
411           CORE_ADDR sp;
412
413           sp = (CORE_ADDR)tcb_ptr->static_ctx.sp - 160;
414
415           if (regno == FLAGS_REGNUM)
416             child_ops.to_store_registers (regno); /* Let lower layer handle this... */
417           else if (regno == SP_REGNUM)
418             {
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);
424             }
425           else if (regno == PC_REGNUM)
426             write_memory (sp - 20,
427                           registers + REGISTER_BYTE (regno),
428                           REGISTER_RAW_SIZE (regno));
429           else
430             write_memory (sp + regmap[regno],
431                           registers + REGISTER_BYTE (regno),
432                           REGISTER_RAW_SIZE (regno));
433         }
434     }
435
436   do_cleanups (old_chain);
437 }
438
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
443    debugged.  */
444
445 static void
446 hpux_thread_prepare_to_store ()
447 {
448   child_ops.to_prepare_to_store ();
449 }
450
451 static int
452 hpux_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
453      CORE_ADDR memaddr;
454      char *myaddr;
455      int len;
456      int dowrite;
457      struct target_ops *target; /* ignored */
458 {
459   int retval;
460   struct cleanup *old_chain;
461
462   old_chain = save_inferior_pid ();
463
464   inferior_pid = main_pid;
465
466   retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
467
468   do_cleanups (old_chain);
469
470   return retval;
471 }
472
473 /* Print status information about what we're accessing.  */
474
475 static void
476 hpux_thread_files_info (ignore)
477      struct target_ops *ignore;
478 {
479   child_ops.to_files_info (ignore);
480 }
481
482 static void
483 hpux_thread_kill_inferior ()
484 {
485   child_ops.to_kill ();
486 }
487
488 static void
489 hpux_thread_notice_signals (pid)
490      int pid;
491 {
492   child_ops.to_notice_signals (pid);
493 }
494
495 /* Fork an inferior process, and start debugging it with /proc.  */
496
497 static void
498 hpux_thread_create_inferior (exec_file, allargs, env)
499      char *exec_file;
500      char *allargs;
501      char **env;
502 {
503   child_ops.to_create_inferior (exec_file, allargs, env);
504
505   if (hpux_thread_active)
506     {
507       main_pid = inferior_pid;
508
509       push_target (&hpux_thread_ops);
510
511       inferior_pid = find_active_thread ();
512
513       add_thread (inferior_pid);
514     }
515 }
516
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
521    table is read in.  */
522
523 void
524 hpux_thread_new_objfile (objfile)
525      struct objfile *objfile;
526 {
527   struct minimal_symbol *ms;
528
529   if (!objfile)
530     {
531       hpux_thread_active = 0;
532
533       return;
534     }
535
536   ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
537
538   if (!ms)
539     return;
540
541   P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
542
543   ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
544
545   if (!ms)
546     return;
547
548   P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
549
550   hpux_thread_active = 1;
551 }
552
553 /* Clean up after the inferior dies.  */
554
555 static void
556 hpux_thread_mourn_inferior ()
557 {
558   child_ops.to_mourn_inferior ();
559 }
560
561 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
562
563 static int
564 hpux_thread_can_run ()
565 {
566   return child_suppress_run;
567 }
568
569 static int
570 hpux_thread_alive (pid)
571      int pid;
572 {
573   return 1;
574 }
575
576 static void
577 hpux_thread_stop ()
578 {
579   child_ops.to_stop ();
580 }
581 \f
582 /* Convert a pid to printable form. */
583
584 char *
585 hpux_pid_to_str (pid)
586      int pid;
587 {
588   static char buf[100];
589
590   sprintf (buf, "Thread %d", pid >> 16);
591
592   return buf;
593 }
594 \f
595 static void
596 init_hpux_thread_ops ()
597 {
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;
632 }
633
634 void
635 _initialize_hpux_thread ()
636 {
637   init_hpux_thread_ops ();
638   add_target (&hpux_thread_ops);
639
640   child_suppress_run = 1;
641 }