xref: /openbsd/gnu/usr.bin/binutils/gdb/hpux-thread.c (revision 63addd46)
1 /* Low level interface for debugging HPUX/DCE threads for GDB, the GNU
2    debugger.
3 
4    Copyright 1996, 1998, 1999, 2000, 2001, 2004 Free Software
5    Foundation, Inc.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330,
22    Boston, MA 02111-1307, USA.  */
23 
24 /* This module implements a sort of half target that sits between the
25    machine-independent parts of GDB and the ptrace interface (infptrace.c) to
26    provide access to the HPUX user-mode thread implementation.
27 
28    HPUX threads are true user-mode threads, which are invoked via the cma_*
29    and pthread_* (DCE and Posix respectivly) interfaces.  These are mostly
30    implemented in user-space, with all thread context kept in various
31    structures that live in the user's heap.  For the most part, the kernel has
32    no knowlege of these threads.
33 
34  */
35 
36 #include "defs.h"
37 
38 #define _CMA_NOWRAPPERS_
39 
40 #include <cma_tcb_defs.h>
41 #include <cma_deb_core.h>
42 #include "gdbthread.h"
43 #include "target.h"
44 #include "inferior.h"
45 #include "regcache.h"
46 #include <fcntl.h>
47 #include "gdb_stat.h"
48 #include "gdbcore.h"
49 
50 extern int child_suppress_run;
51 
52 extern void _initialize_hpux_thread (void);
53 
54 struct string_map
55   {
56     int num;
57     char *str;
58   };
59 
60 static int hpux_thread_active = 0;
61 
62 static ptid_t main_ptid;		/* Real process ID */
63 
64 static CORE_ADDR P_cma__g_known_threads;
65 static CORE_ADDR P_cma__g_current_thread;
66 
67 static void hpux_thread_resume (ptid_t ptid, int step,
68                                 enum target_signal signo);
69 
70 static void init_hpux_thread_ops (void);
71 
72 static struct target_ops hpux_thread_ops;
73 
74 static ptid_t find_active_thread (void);
75 
76 static int cached_thread;
77 static cma__t_int_tcb cached_tcb;
78 
79 static ptid_t
find_active_thread(void)80 find_active_thread (void)
81 {
82   static cma__t_int_tcb tcb;
83   CORE_ADDR tcb_ptr;
84 
85   read_memory ((CORE_ADDR) P_cma__g_current_thread,
86 	       (char *) &tcb_ptr,
87 	       sizeof tcb_ptr);
88 
89   read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
90 
91   return (ptid_build (PIDGET (main_ptid), 0,
92                       cma_thread_get_unique (&tcb.prolog.client_thread)));
93 }
94 
95 static cma__t_int_tcb *find_tcb (ptid_t ptid);
96 
97 static cma__t_int_tcb *
find_tcb(ptid_t ptid)98 find_tcb (ptid_t ptid)
99 {
100   cma__t_known_object queue_header;
101   cma__t_queue *queue_ptr;
102   int thread = ptid_get_tid (ptid);
103 
104   if (thread == cached_thread)
105     return &cached_tcb;
106 
107   read_memory ((CORE_ADDR) P_cma__g_known_threads,
108 	       (char *) &queue_header,
109 	       sizeof queue_header);
110 
111   for (queue_ptr = queue_header.queue.flink;
112        queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
113        queue_ptr = cached_tcb.threads.flink)
114     {
115       cma__t_int_tcb *tcb_ptr;
116 
117       tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
118 
119       read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
120 
121       if (cached_tcb.header.type == cma__c_obj_tcb)
122 	if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
123 	  {
124 	    cached_thread = thread;
125 	    return &cached_tcb;
126 	  }
127     }
128 
129   error ("Can't find TCB %d", thread);
130   return NULL;
131 }
132 
133 /* Most target vector functions from here on actually just pass through to
134    inftarg.c, as they don't need to do anything specific for threads.  */
135 
136 static void
hpux_thread_open(char * arg,int from_tty)137 hpux_thread_open (char *arg, int from_tty)
138 {
139   deprecated_child_ops.to_open (arg, from_tty);
140 }
141 
142 /* Attach to process PID, then initialize for debugging it
143    and wait for the trace-trap that results from attaching.  */
144 
145 static void
hpux_thread_attach(char * args,int from_tty)146 hpux_thread_attach (char *args, int from_tty)
147 {
148   deprecated_child_ops.to_attach (args, from_tty);
149 
150   /* XXX - might want to iterate over all the threads and register them. */
151 }
152 
153 /* Take a program previously attached to and detaches it.
154    The program resumes execution and will no longer stop
155    on signals, etc.  We'd better not have left any breakpoints
156    in the program or it'll die when it hits one.  For this
157    to work, it may be necessary for the process to have been
158    previously attached.  It *might* work if the program was
159    started via the normal ptrace (PTRACE_TRACEME).  */
160 
161 static void
hpux_thread_detach(char * args,int from_tty)162 hpux_thread_detach (char *args, int from_tty)
163 {
164   deprecated_child_ops.to_detach (args, from_tty);
165 }
166 
167 /* Resume execution of process PID.  If STEP is nozero, then
168    just single step it.  If SIGNAL is nonzero, restart it with that
169    signal activated.  We may have to convert pid from a thread-id to an LWP id
170    for procfs.  */
171 
172 static void
hpux_thread_resume(ptid_t ptid,int step,enum target_signal signo)173 hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
174 {
175   struct cleanup *old_chain;
176 
177   old_chain = save_inferior_ptid ();
178 
179   ptid = main_ptid;
180   inferior_ptid = main_ptid;
181 
182 #if 0
183   if (pid != -1)
184     {
185       pid = thread_to_lwp (pid, -2);
186       if (pid == -2)		/* Inactive thread */
187 	error ("This version of Solaris can't start inactive threads.");
188     }
189 #endif
190 
191   deprecated_child_ops.to_resume (ptid, step, signo);
192 
193   cached_thread = 0;
194 
195   do_cleanups (old_chain);
196 }
197 
198 /* Wait for any threads to stop.  We may have to convert PID from a thread id
199    to a LWP id, and vice versa on the way out.  */
200 
201 static ptid_t
hpux_thread_wait(ptid_t ptid,struct target_waitstatus * ourstatus)202 hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
203 {
204   ptid_t rtnval;
205   struct cleanup *old_chain;
206 
207   old_chain = save_inferior_ptid ();
208 
209   inferior_ptid = main_ptid;
210 
211   if (!ptid_equal (ptid, minus_one_ptid))
212     ptid = main_ptid;
213 
214   rtnval = deprecated_child_ops.to_wait (ptid, ourstatus);
215 
216   rtnval = find_active_thread ();
217 
218   do_cleanups (old_chain);
219 
220   return rtnval;
221 }
222 
223 static char regmap[NUM_REGS] =
224 {
225   -2, -1, -1, 0, 4, 8, 12, 16, 20, 24,	/* flags, r1 -> r9 */
226   28, 32, 36, 40, 44, 48, 52, 56, 60, -1,	/* r10 -> r19 */
227   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/* r20 -> r29 */
228 
229   /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
230   -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
231 
232   /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
233   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
234 
235   /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
236   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
237 
238   -1, -1, -1, -1,		/* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
239   144, -1, -1, -1, -1, -1, -1, -1,	/* fpsr, fpe1 -> fpe7 */
240   -1, -1, -1, -1, -1, -1, -1, -1,	/* fr4 -> fr7 */
241   -1, -1, -1, -1, -1, -1, -1, -1,	/* fr8 -> fr11 */
242   136, -1, 128, -1, 120, -1, 112, -1,	/* fr12 -> fr15 */
243   104, -1, 96, -1, 88, -1, 80, -1,	/* fr16 -> fr19 */
244   72, -1, 64, -1, -1, -1, -1, -1,	/* fr20 -> fr23 */
245   -1, -1, -1, -1, -1, -1, -1, -1,	/* fr24 -> fr27 */
246   -1, -1, -1, -1, -1, -1, -1, -1,	/* fr28 -> fr31 */
247 };
248 
249 static void
hpux_thread_fetch_registers(int regno)250 hpux_thread_fetch_registers (int regno)
251 {
252   cma__t_int_tcb tcb, *tcb_ptr;
253   struct cleanup *old_chain;
254   int i;
255   int first_regno, last_regno;
256 
257   tcb_ptr = find_tcb (inferior_ptid);
258 
259   old_chain = save_inferior_ptid ();
260 
261   inferior_ptid = main_ptid;
262 
263   if (tcb_ptr->state == cma__c_state_running)
264     {
265       deprecated_child_ops.to_fetch_registers (regno);
266 
267       do_cleanups (old_chain);
268 
269       return;
270     }
271 
272   if (regno == -1)
273     {
274       first_regno = 0;
275       last_regno = NUM_REGS - 1;
276     }
277   else
278     {
279       first_regno = regno;
280       last_regno = regno;
281     }
282 
283   for (regno = first_regno; regno <= last_regno; regno++)
284     {
285       if (regmap[regno] == -1)
286 	deprecated_child_ops.to_fetch_registers (regno);
287       else
288 	{
289 	  unsigned char buf[MAX_REGISTER_SIZE];
290 	  CORE_ADDR sp;
291 
292 	  sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
293 
294 	  if (regno == FLAGS_REGNUM)
295 	    /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
296 	    memset (buf, '\000', register_size (current_gdbarch, regno));
297 	  else if (regno == SP_REGNUM)
298 	    store_unsigned_integer (buf, sizeof sp, sp);
299 	  else if (regno == PC_REGNUM)
300 	    read_memory (sp - 20, buf, register_size (current_gdbarch, regno));
301 	  else
302 	    read_memory (sp + regmap[regno], buf, register_size (current_gdbarch, regno));
303 
304 	  regcache_raw_supply (current_regcache, regno, buf);
305 	}
306     }
307 
308   do_cleanups (old_chain);
309 }
310 
311 static void
hpux_thread_store_registers(int regno)312 hpux_thread_store_registers (int regno)
313 {
314   cma__t_int_tcb tcb, *tcb_ptr;
315   struct cleanup *old_chain;
316   int i;
317   int first_regno, last_regno;
318 
319   tcb_ptr = find_tcb (inferior_ptid);
320 
321   old_chain = save_inferior_ptid ();
322 
323   inferior_ptid = main_ptid;
324 
325   if (tcb_ptr->state == cma__c_state_running)
326     {
327       deprecated_child_ops.to_store_registers (regno);
328 
329       do_cleanups (old_chain);
330 
331       return;
332     }
333 
334   if (regno == -1)
335     {
336       first_regno = 0;
337       last_regno = NUM_REGS - 1;
338     }
339   else
340     {
341       first_regno = regno;
342       last_regno = regno;
343     }
344 
345   for (regno = first_regno; regno <= last_regno; regno++)
346     {
347       if (regmap[regno] == -1)
348 	deprecated_child_ops.to_store_registers (regno);
349       else
350 	{
351 	  unsigned char buf[MAX_REGISTER_SIZE];
352 	  CORE_ADDR sp;
353 
354 	  sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
355 
356 	  if (regno == FLAGS_REGNUM)
357 	    deprecated_child_ops.to_store_registers (regno);	/* Let lower layer handle this... */
358 	  else if (regno == SP_REGNUM)
359 	    {
360 	      write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
361 			    &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
362 			    register_size (current_gdbarch, regno));
363 	      tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
364 		(extract_unsigned_integer (&deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
365 					   register_size (current_gdbarch, regno)) + 160);
366 	    }
367 	  else if (regno == PC_REGNUM)
368 	    write_memory (sp - 20,
369 			  &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
370 			  register_size (current_gdbarch, regno));
371 	  else
372 	    write_memory (sp + regmap[regno],
373 			  &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
374 			  register_size (current_gdbarch, regno));
375 	}
376     }
377 
378   do_cleanups (old_chain);
379 }
380 
381 /* Get ready to modify the registers array.  On machines which store
382    individual registers, this doesn't need to do anything.  On machines
383    which store all the registers in one fell swoop, this makes sure
384    that registers contains all the registers from the program being
385    debugged.  */
386 
387 static void
hpux_thread_prepare_to_store(void)388 hpux_thread_prepare_to_store (void)
389 {
390   deprecated_child_ops.to_prepare_to_store ();
391 }
392 
393 static int
hpux_thread_xfer_memory(CORE_ADDR memaddr,char * myaddr,int len,int dowrite,struct mem_attrib * attribs,struct target_ops * target)394 hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
395 			 int dowrite, struct mem_attrib *attribs,
396 			 struct target_ops *target)
397 {
398   int retval;
399   struct cleanup *old_chain;
400 
401   old_chain = save_inferior_ptid ();
402 
403   inferior_ptid = main_ptid;
404 
405   retval =
406     deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
407 
408   do_cleanups (old_chain);
409 
410   return retval;
411 }
412 
413 /* Print status information about what we're accessing.  */
414 
415 static void
hpux_thread_files_info(struct target_ops * ignore)416 hpux_thread_files_info (struct target_ops *ignore)
417 {
418   deprecated_child_ops.to_files_info (ignore);
419 }
420 
421 static void
hpux_thread_kill_inferior(void)422 hpux_thread_kill_inferior (void)
423 {
424   deprecated_child_ops.to_kill ();
425 }
426 
427 static void
hpux_thread_notice_signals(ptid_t ptid)428 hpux_thread_notice_signals (ptid_t ptid)
429 {
430   deprecated_child_ops.to_notice_signals (ptid);
431 }
432 
433 /* Fork an inferior process, and start debugging it with /proc.  */
434 
435 static void
hpux_thread_create_inferior(char * exec_file,char * allargs,char ** env,int from_tty)436 hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
437 			     int from_tty)
438 {
439   deprecated_child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
440 
441   if (hpux_thread_active)
442     {
443       main_ptid = inferior_ptid;
444 
445       push_target (&hpux_thread_ops);
446 
447       inferior_ptid = find_active_thread ();
448 
449       add_thread (inferior_ptid);
450     }
451 }
452 
453 /* This routine is called whenever a new symbol table is read in, or when all
454    symbol tables are removed.  libthread_db can only be initialized when it
455    finds the right variables in libthread.so.  Since it's a shared library,
456    those variables don't show up until the library gets mapped and the symbol
457    table is read in.  */
458 
459 /* This new_objfile event is now managed by a chained function pointer.
460  * It is the callee's responsability to call the next client on the chain.
461  */
462 
463 /* Saved pointer to previous owner of the new_objfile event. */
464 static void (*target_new_objfile_chain) (struct objfile *);
465 
466 void
hpux_thread_new_objfile(struct objfile * objfile)467 hpux_thread_new_objfile (struct objfile *objfile)
468 {
469   struct minimal_symbol *ms;
470 
471   if (!objfile)
472     {
473       hpux_thread_active = 0;
474       goto quit;
475     }
476 
477   ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
478 
479   if (!ms)
480     goto quit;
481 
482   P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
483 
484   ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
485 
486   if (!ms)
487     goto quit;
488 
489   P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
490 
491   hpux_thread_active = 1;
492 quit:
493   /* Call predecessor on chain, if any. */
494   if (target_new_objfile_chain)
495     target_new_objfile_chain (objfile);
496 }
497 
498 /* Clean up after the inferior dies.  */
499 
500 static void
hpux_thread_mourn_inferior(void)501 hpux_thread_mourn_inferior (void)
502 {
503   deprecated_child_ops.to_mourn_inferior ();
504 }
505 
506 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
507 
508 static int
hpux_thread_can_run(void)509 hpux_thread_can_run (void)
510 {
511   return child_suppress_run;
512 }
513 
514 static int
hpux_thread_alive(ptid_t ptid)515 hpux_thread_alive (ptid_t ptid)
516 {
517   return 1;
518 }
519 
520 static void
hpux_thread_stop(void)521 hpux_thread_stop (void)
522 {
523   deprecated_child_ops.to_stop ();
524 }
525 
526 /* Convert a pid to printable form. */
527 
528 char *
hpux_pid_to_str(ptid_t ptid)529 hpux_pid_to_str (ptid_t ptid)
530 {
531   static char buf[100];
532   int pid = PIDGET (ptid);
533 
534   sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
535 
536   return buf;
537 }
538 
539 static void
init_hpux_thread_ops(void)540 init_hpux_thread_ops (void)
541 {
542   hpux_thread_ops.to_shortname = "hpux-threads";
543   hpux_thread_ops.to_longname = "HPUX threads and pthread.";
544   hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
545   hpux_thread_ops.to_open = hpux_thread_open;
546   hpux_thread_ops.to_attach = hpux_thread_attach;
547   hpux_thread_ops.to_detach = hpux_thread_detach;
548   hpux_thread_ops.to_resume = hpux_thread_resume;
549   hpux_thread_ops.to_wait = hpux_thread_wait;
550   hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
551   hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
552   hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
553   hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
554   hpux_thread_ops.to_files_info = hpux_thread_files_info;
555   hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
556   hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
557   hpux_thread_ops.to_terminal_init = terminal_init_inferior;
558   hpux_thread_ops.to_terminal_inferior = terminal_inferior;
559   hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
560   hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
561   hpux_thread_ops.to_terminal_ours = terminal_ours;
562   hpux_thread_ops.to_terminal_info = child_terminal_info;
563   hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
564   hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
565   hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
566   hpux_thread_ops.to_can_run = hpux_thread_can_run;
567   hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
568   hpux_thread_ops.to_thread_alive = hpux_thread_alive;
569   hpux_thread_ops.to_stop = hpux_thread_stop;
570   hpux_thread_ops.to_stratum = process_stratum;
571   hpux_thread_ops.to_has_all_memory = 1;
572   hpux_thread_ops.to_has_memory = 1;
573   hpux_thread_ops.to_has_stack = 1;
574   hpux_thread_ops.to_has_registers = 1;
575   hpux_thread_ops.to_has_execution = 1;
576   hpux_thread_ops.to_magic = OPS_MAGIC;
577 }
578 
579 void
_initialize_hpux_thread(void)580 _initialize_hpux_thread (void)
581 {
582   init_hpux_thread_ops ();
583   add_target (&hpux_thread_ops);
584 
585   child_suppress_run = 1;
586   /* Hook into new_objfile notification. */
587   target_new_objfile_chain = deprecated_target_new_objfile_hook;
588   deprecated_target_new_objfile_hook  = hpux_thread_new_objfile;
589 }
590