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