gas/testsuite/
[external/binutils.git] / gdb / hpux-thread.c
1 /* Low level interface for debugging HPUX/DCE threads for GDB, the GNU
2    debugger.
3
4    Copyright (C) 1996, 1998, 1999, 2000, 2001, 2004, 2007, 2008, 2009
5    Free Software 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 3 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, see <http://www.gnu.org/licenses/>.  */
21
22 /* This module implements a sort of half target that sits between the
23    machine-independent parts of GDB and the ptrace interface (infptrace.c) to
24    provide access to the HPUX user-mode thread implementation.
25
26    HPUX threads are true user-mode threads, which are invoked via the cma_*
27    and pthread_* (DCE and Posix respectivly) interfaces.  These are mostly
28    implemented in user-space, with all thread context kept in various
29    structures that live in the user's heap.  For the most part, the kernel has
30    no knowlege of these threads.
31
32  */
33
34 #include "defs.h"
35
36 #define _CMA_NOWRAPPERS_
37
38 #include <cma_tcb_defs.h>
39 #include <cma_deb_core.h>
40 #include "gdbthread.h"
41 #include "target.h"
42 #include "inferior.h"
43 #include "regcache.h"
44 #include <fcntl.h>
45 #include <string.h>
46 #include "gdb_stat.h"
47 #include "gdbcore.h"
48 #include "hppa-tdep.h"
49 #include "observer.h"
50
51 extern int child_suppress_run;
52
53 extern void _initialize_hpux_thread (void);
54
55 struct string_map
56   {
57     int num;
58     char *str;
59   };
60
61 static int hpux_thread_active = 0;
62
63 static ptid_t main_ptid;                /* Real process ID */
64
65 static CORE_ADDR P_cma__g_known_threads;
66 static CORE_ADDR P_cma__g_current_thread;
67
68 static void init_hpux_thread_ops (void);
69
70 static struct target_ops hpux_thread_ops;
71 \f
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
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 *
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 \f
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
135 hpux_thread_open (char *arg, int from_tty)
136 {
137   deprecated_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
144 hpux_thread_attach (struct target_ops *ops, char *args, int from_tty)
145 {
146   deprecated_child_ops.to_attach (&deprecated_child_ops, 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
160 hpux_thread_detach (struct target_ops *ops, char *args, int from_tty)
161 {
162   deprecated_child_ops.to_detach (&deprecated_child_ops, 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
171 hpux_thread_resume (struct target_ops *ops,
172                     ptid_t ptid, int step, enum target_signal signo)
173 {
174   struct cleanup *old_chain;
175
176   old_chain = save_inferior_ptid ();
177
178   ptid = main_ptid;
179   inferior_ptid = main_ptid;
180
181   deprecated_child_ops.to_resume (&deprecated_child_ops, ptid, step, signo);
182
183   cached_thread = 0;
184
185   do_cleanups (old_chain);
186 }
187
188 /* Wait for any threads to stop.  We may have to convert PID from a thread id
189    to a LWP id, and vice versa on the way out.  */
190
191 static ptid_t
192 hpux_thread_wait (struct target_ops *ops,
193                   ptid_t ptid, struct target_waitstatus *ourstatus)
194 {
195   ptid_t rtnval;
196   struct cleanup *old_chain;
197
198   old_chain = save_inferior_ptid ();
199
200   inferior_ptid = main_ptid;
201
202   if (!ptid_equal (ptid, minus_one_ptid))
203     ptid = main_ptid;
204
205   rtnval = deprecated_child_ops.to_wait (&deprecated_child_ops,
206                                          ptid, ourstatus);
207
208   rtnval = find_active_thread ();
209
210   do_cleanups (old_chain);
211
212   return rtnval;
213 }
214
215 static char regmap[] =
216 {
217   -2, -1, -1, 0, 4, 8, 12, 16, 20, 24,  /* flags, r1 -> r9 */
218   28, 32, 36, 40, 44, 48, 52, 56, 60, -1,       /* r10 -> r19 */
219   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,       /* r20 -> r29 */
220
221   /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
222   -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
223
224   /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
225   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226
227   /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
228   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
229
230   -1, -1, -1, -1,               /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
231   144, -1, -1, -1, -1, -1, -1, -1,      /* fpsr, fpe1 -> fpe7 */
232   -1, -1, -1, -1, -1, -1, -1, -1,       /* fr4 -> fr7 */
233   -1, -1, -1, -1, -1, -1, -1, -1,       /* fr8 -> fr11 */
234   136, -1, 128, -1, 120, -1, 112, -1,   /* fr12 -> fr15 */
235   104, -1, 96, -1, 88, -1, 80, -1,      /* fr16 -> fr19 */
236   72, -1, 64, -1, -1, -1, -1, -1,       /* fr20 -> fr23 */
237   -1, -1, -1, -1, -1, -1, -1, -1,       /* fr24 -> fr27 */
238   -1, -1, -1, -1, -1, -1, -1, -1,       /* fr28 -> fr31 */
239 };
240
241 static void
242 hpux_thread_fetch_registers (struct target_ops *ops,
243                              struct regcache *regcache, int regno)
244 {
245   struct gdbarch *gdbarch = get_regcache_arch (regcache);
246   cma__t_int_tcb tcb, *tcb_ptr;
247   struct cleanup *old_chain;
248   int i;
249   int first_regno, last_regno;
250
251   tcb_ptr = find_tcb (inferior_ptid);
252
253   old_chain = save_inferior_ptid ();
254
255   inferior_ptid = main_ptid;
256
257   if (tcb_ptr->state == cma__c_state_running)
258     {
259       deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
260                                                regcache, regno);
261
262       do_cleanups (old_chain);
263
264       return;
265     }
266
267   if (regno == -1)
268     {
269       first_regno = 0;
270       last_regno = gdbarch_num_regs (gdbarch) - 1;
271     }
272   else
273     {
274       first_regno = regno;
275       last_regno = regno;
276     }
277
278   for (regno = first_regno; regno <= last_regno; regno++)
279     {
280       if (regmap[regno] == -1)
281         deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
282                                                  regcache, regno);
283       else
284         {
285           unsigned char buf[MAX_REGISTER_SIZE];
286           CORE_ADDR sp;
287
288           sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
289
290           if (regno == HPPA_FLAGS_REGNUM)
291             /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
292             memset (buf, '\000', register_size (gdbarch, regno));
293           else if (regno == HPPA_SP_REGNUM)
294             store_unsigned_integer (buf, sizeof sp, sp);
295           else if (regno == HPPA_PCOQ_HEAD_REGNUM)
296             read_memory (sp - 20, buf, register_size (gdbarch, regno));
297           else
298             read_memory (sp + regmap[regno], buf,
299                          register_size (gdbarch, regno));
300
301           regcache_raw_supply (regcache, regno, buf);
302         }
303     }
304
305   do_cleanups (old_chain);
306 }
307
308 static void
309 hpux_thread_store_registers (struct target_ops *ops,
310                              struct regcache *regcache, int regno)
311 {
312   struct gdbarch *gdbarch = get_regcache_arch (regcache);
313   cma__t_int_tcb tcb, *tcb_ptr;
314   struct cleanup *old_chain;
315   int i;
316   int first_regno, last_regno;
317
318   tcb_ptr = find_tcb (inferior_ptid);
319
320   old_chain = save_inferior_ptid ();
321
322   inferior_ptid = main_ptid;
323
324   if (tcb_ptr->state == cma__c_state_running)
325     {
326       deprecated_child_ops.to_store_registers (&deprecated_child_ops,
327                                                regcache, regno);
328
329       do_cleanups (old_chain);
330
331       return;
332     }
333
334   if (regno == -1)
335     {
336       first_regno = 0;
337       last_regno = gdbarch_num_regs (gdbarch) - 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 (regcache, 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 == HPPA_FLAGS_REGNUM)
357             {
358               /* Let lower layer handle this... */
359               deprecated_child_ops.to_store_registers
360                 (&deprecated_child_ops, regcache, regno);
361             }
362           else if (regno == HPPA_SP_REGNUM)
363             {
364               regcache_raw_collect (regcache, regno, buf);
365               write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
366                             register_size (gdbarch, regno));
367               tcb_ptr->static_ctx.sp
368                 = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
369             }
370           else if (regno == HPPA_PCOQ_HEAD_REGNUM)
371             {
372               regcache_raw_collect (regcache, regno, buf);
373               write_memory (sp - 20, buf,
374                             register_size (gdbarch, regno));
375             }
376           else
377             {
378               regcache_raw_collect (regcache, regno, buf);
379               write_memory (sp + regmap[regno], buf,
380                             register_size (gdbarch, regno));
381             }
382         }
383     }
384
385   do_cleanups (old_chain);
386 }
387
388 /* Get ready to modify the registers array.  On machines which store
389    individual registers, this doesn't need to do anything.  On machines
390    which store all the registers in one fell swoop, this makes sure
391    that registers contains all the registers from the program being
392    debugged.  */
393
394 static void
395 hpux_thread_prepare_to_store (struct regcache *regcache)
396 {
397   deprecated_child_ops.to_prepare_to_store (regcache);
398 }
399
400 static int
401 hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
402                          int dowrite, struct mem_attrib *attribs,
403                          struct target_ops *target)
404 {
405   int retval;
406   struct cleanup *old_chain;
407
408   old_chain = save_inferior_ptid ();
409
410   inferior_ptid = main_ptid;
411
412   retval = 
413     deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
414
415   do_cleanups (old_chain);
416
417   return retval;
418 }
419
420 /* Print status information about what we're accessing.  */
421
422 static void
423 hpux_thread_files_info (struct target_ops *ignore)
424 {
425   deprecated_child_ops.to_files_info (ignore);
426 }
427
428 static void
429 hpux_thread_kill_inferior (struct target_ops *ops)
430 {
431   deprecated_child_ops.to_kill (&deprecated_child_ops);
432 }
433
434 static void
435 hpux_thread_notice_signals (ptid_t ptid)
436 {
437   deprecated_child_ops.to_notice_signals (ptid);
438 }
439
440 /* Fork an inferior process, and start debugging it with /proc.  */
441
442 static void
443 hpux_thread_create_inferior (struct target_ops *ops, char *exec_file,
444                              char *allargs, char **env, int from_tty)
445 {
446   deprecated_child_ops.to_create_inferior (&deprecated_child_ops, 
447                                            exec_file, allargs, env, from_tty);
448
449   if (hpux_thread_active)
450     {
451       main_ptid = inferior_ptid;
452
453       push_target (&hpux_thread_ops);
454
455       inferior_ptid = find_active_thread ();
456
457       add_thread (inferior_ptid);
458     }
459 }
460
461 /* This routine is called whenever a new symbol table is read in, or when all
462    symbol tables are removed.  libthread_db can only be initialized when it
463    finds the right variables in libthread.so.  Since it's a shared library,
464    those variables don't show up until the library gets mapped and the symbol
465    table is read in.  */
466
467 static void
468 hpux_thread_new_objfile (struct objfile *objfile)
469 {
470   struct minimal_symbol *ms;
471
472   if (!objfile)
473     {
474       hpux_thread_active = 0;
475       return;
476     }
477
478   ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
479
480   if (!ms)
481     return;
482
483   P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
484
485   ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
486
487   if (!ms)
488     return;
489
490   P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
491
492   hpux_thread_active = 1;
493 }
494
495 /* Clean up after the inferior dies.  */
496
497 static void
498 hpux_thread_mourn_inferior (void)
499 {
500   deprecated_child_ops.to_mourn_inferior (&deprecated_child_ops);
501 }
502
503 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
504
505 static int
506 hpux_thread_can_run (void)
507 {
508   return child_suppress_run;
509 }
510
511 static int
512 hpux_thread_alive (struct target_ops *ops, ptid_t ptid)
513 {
514   return 1;
515 }
516
517 static void
518 hpux_thread_stop (ptid_t ptid)
519 {
520   deprecated_child_ops.to_stop (ptid);
521 }
522 \f
523 /* Convert a pid to printable form. */
524
525 char *
526 hpux_pid_to_str (ptid_t ptid)
527 {
528   static char buf[100];
529   int pid = PIDGET (ptid);
530
531   sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
532
533   return buf;
534 }
535 \f
536 static void
537 init_hpux_thread_ops (void)
538 {
539   hpux_thread_ops.to_shortname = "hpux-threads";
540   hpux_thread_ops.to_longname = "HPUX threads and pthread.";
541   hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
542   hpux_thread_ops.to_open = hpux_thread_open;
543   hpux_thread_ops.to_attach = hpux_thread_attach;
544   hpux_thread_ops.to_detach = hpux_thread_detach;
545   hpux_thread_ops.to_resume = hpux_thread_resume;
546   hpux_thread_ops.to_wait = hpux_thread_wait;
547   hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
548   hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
549   hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
550   hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
551   hpux_thread_ops.to_files_info = hpux_thread_files_info;
552   hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
553   hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
554   hpux_thread_ops.to_terminal_init = terminal_init_inferior;
555   hpux_thread_ops.to_terminal_inferior = terminal_inferior;
556   hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
557   hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
558   hpux_thread_ops.to_terminal_ours = terminal_ours;
559   hpux_thread_ops.to_terminal_info = child_terminal_info;
560   hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
561   hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
562   hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
563   hpux_thread_ops.to_can_run = hpux_thread_can_run;
564   hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
565   hpux_thread_ops.to_thread_alive = hpux_thread_alive;
566   hpux_thread_ops.to_stop = hpux_thread_stop;
567   hpux_thread_ops.to_stratum = process_stratum;
568   hpux_thread_ops.to_has_all_memory = 1;
569   hpux_thread_ops.to_has_memory = 1;
570   hpux_thread_ops.to_has_stack = 1;
571   hpux_thread_ops.to_has_registers = 1;
572   hpux_thread_ops.to_has_execution = 1;
573   hpux_thread_ops.to_magic = OPS_MAGIC;
574 }
575
576 void
577 _initialize_hpux_thread (void)
578 {
579   init_hpux_thread_ops ();
580   add_target (&hpux_thread_ops);
581
582   child_suppress_run = 1;
583   /* Hook into new_objfile notification.  */
584   observer_attach_new_objfile (hpux_thread_new_objfile);
585 }