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