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