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