]> Git Repo - binutils.git/blob - gdb/hpux-thread.c
Adjust all targets to new target_stop interface.
[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
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 hpux_thread_resume (ptid_t ptid, int step,
69                                 enum target_signal signo);
70
71 static void init_hpux_thread_ops (void);
72
73 static struct target_ops hpux_thread_ops;
74 \f
75 static ptid_t find_active_thread (void);
76
77 static int cached_thread;
78 static cma__t_int_tcb cached_tcb;
79
80 static ptid_t
81 find_active_thread (void)
82 {
83   static cma__t_int_tcb tcb;
84   CORE_ADDR tcb_ptr;
85
86   read_memory ((CORE_ADDR) P_cma__g_current_thread,
87                (char *) &tcb_ptr,
88                sizeof tcb_ptr);
89
90   read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
91
92   return (ptid_build (PIDGET (main_ptid), 0,
93                       cma_thread_get_unique (&tcb.prolog.client_thread)));
94 }
95
96 static cma__t_int_tcb *find_tcb (ptid_t ptid);
97
98 static cma__t_int_tcb *
99 find_tcb (ptid_t ptid)
100 {
101   cma__t_known_object queue_header;
102   cma__t_queue *queue_ptr;
103   int thread = ptid_get_tid (ptid);
104
105   if (thread == cached_thread)
106     return &cached_tcb;
107
108   read_memory ((CORE_ADDR) P_cma__g_known_threads,
109                (char *) &queue_header,
110                sizeof queue_header);
111
112   for (queue_ptr = queue_header.queue.flink;
113        queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
114        queue_ptr = cached_tcb.threads.flink)
115     {
116       cma__t_int_tcb *tcb_ptr;
117
118       tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
119
120       read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
121
122       if (cached_tcb.header.type == cma__c_obj_tcb)
123         if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
124           {
125             cached_thread = thread;
126             return &cached_tcb;
127           }
128     }
129
130   error (_("Can't find TCB %d"), thread);
131   return NULL;
132 }
133 \f
134 /* Most target vector functions from here on actually just pass through to
135    inftarg.c, as they don't need to do anything specific for threads.  */
136
137 static void
138 hpux_thread_open (char *arg, int from_tty)
139 {
140   deprecated_child_ops.to_open (arg, from_tty);
141 }
142
143 /* Attach to process PID, then initialize for debugging it
144    and wait for the trace-trap that results from attaching.  */
145
146 static void
147 hpux_thread_attach (char *args, int from_tty)
148 {
149   deprecated_child_ops.to_attach (args, from_tty);
150
151   /* XXX - might want to iterate over all the threads and register them. */
152 }
153
154 /* Take a program previously attached to and detaches it.
155    The program resumes execution and will no longer stop
156    on signals, etc.  We'd better not have left any breakpoints
157    in the program or it'll die when it hits one.  For this
158    to work, it may be necessary for the process to have been
159    previously attached.  It *might* work if the program was
160    started via the normal ptrace (PTRACE_TRACEME).  */
161
162 static void
163 hpux_thread_detach (char *args, int from_tty)
164 {
165   deprecated_child_ops.to_detach (args, from_tty);
166 }
167
168 /* Resume execution of process PID.  If STEP is nozero, then
169    just single step it.  If SIGNAL is nonzero, restart it with that
170    signal activated.  We may have to convert pid from a thread-id to an LWP id
171    for procfs.  */
172
173 static void
174 hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
175 {
176   struct cleanup *old_chain;
177
178   old_chain = save_inferior_ptid ();
179
180   ptid = main_ptid;
181   inferior_ptid = main_ptid;
182
183   deprecated_child_ops.to_resume (ptid, step, signo);
184
185   cached_thread = 0;
186
187   do_cleanups (old_chain);
188 }
189
190 /* Wait for any threads to stop.  We may have to convert PID from a thread id
191    to a LWP id, and vice versa on the way out.  */
192
193 static ptid_t
194 hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
195 {
196   ptid_t rtnval;
197   struct cleanup *old_chain;
198
199   old_chain = save_inferior_ptid ();
200
201   inferior_ptid = main_ptid;
202
203   if (!ptid_equal (ptid, minus_one_ptid))
204     ptid = main_ptid;
205
206   rtnval = deprecated_child_ops.to_wait (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 regcache *regcache, int regno)
243 {
244   struct gdbarch *gdbarch = get_regcache_arch (regcache);
245   cma__t_int_tcb tcb, *tcb_ptr;
246   struct cleanup *old_chain;
247   int i;
248   int first_regno, last_regno;
249
250   tcb_ptr = find_tcb (inferior_ptid);
251
252   old_chain = save_inferior_ptid ();
253
254   inferior_ptid = main_ptid;
255
256   if (tcb_ptr->state == cma__c_state_running)
257     {
258       deprecated_child_ops.to_fetch_registers (regcache, regno);
259
260       do_cleanups (old_chain);
261
262       return;
263     }
264
265   if (regno == -1)
266     {
267       first_regno = 0;
268       last_regno = gdbarch_num_regs (gdbarch) - 1;
269     }
270   else
271     {
272       first_regno = regno;
273       last_regno = regno;
274     }
275
276   for (regno = first_regno; regno <= last_regno; regno++)
277     {
278       if (regmap[regno] == -1)
279         deprecated_child_ops.to_fetch_registers (regcache, regno);
280       else
281         {
282           unsigned char buf[MAX_REGISTER_SIZE];
283           CORE_ADDR sp;
284
285           sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
286
287           if (regno == HPPA_FLAGS_REGNUM)
288             /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
289             memset (buf, '\000', register_size (gdbarch, regno));
290           else if (regno == HPPA_SP_REGNUM)
291             store_unsigned_integer (buf, sizeof sp, sp);
292           else if (regno == HPPA_PCOQ_HEAD_REGNUM)
293             read_memory (sp - 20, buf, register_size (gdbarch, regno));
294           else
295             read_memory (sp + regmap[regno], buf,
296                          register_size (gdbarch, regno));
297
298           regcache_raw_supply (regcache, regno, buf);
299         }
300     }
301
302   do_cleanups (old_chain);
303 }
304
305 static void
306 hpux_thread_store_registers (struct regcache *regcache, int regno)
307 {
308   struct gdbarch *gdbarch = get_regcache_arch (regcache);
309   cma__t_int_tcb tcb, *tcb_ptr;
310   struct cleanup *old_chain;
311   int i;
312   int first_regno, last_regno;
313
314   tcb_ptr = find_tcb (inferior_ptid);
315
316   old_chain = save_inferior_ptid ();
317
318   inferior_ptid = main_ptid;
319
320   if (tcb_ptr->state == cma__c_state_running)
321     {
322       deprecated_child_ops.to_store_registers (regcache, regno);
323
324       do_cleanups (old_chain);
325
326       return;
327     }
328
329   if (regno == -1)
330     {
331       first_regno = 0;
332       last_regno = gdbarch_num_regs (gdbarch) - 1;
333     }
334   else
335     {
336       first_regno = regno;
337       last_regno = regno;
338     }
339
340   for (regno = first_regno; regno <= last_regno; regno++)
341     {
342       if (regmap[regno] == -1)
343         deprecated_child_ops.to_store_registers (regcache, regno);
344       else
345         {
346           unsigned char buf[MAX_REGISTER_SIZE];
347           CORE_ADDR sp;
348
349           sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
350
351           if (regno == HPPA_FLAGS_REGNUM)
352             deprecated_child_ops.to_store_registers (regcache, regno);  /* Let lower layer handle this... */
353           else if (regno == HPPA_SP_REGNUM)
354             {
355               regcache_raw_collect (regcache, regno, buf);
356               write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
357                             register_size (gdbarch, regno));
358               tcb_ptr->static_ctx.sp
359                 = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
360             }
361           else if (regno == HPPA_PCOQ_HEAD_REGNUM)
362             {
363               regcache_raw_collect (regcache, regno, buf);
364               write_memory (sp - 20, buf,
365                             register_size (gdbarch, regno));
366             }
367           else
368             {
369               regcache_raw_collect (regcache, regno, buf);
370               write_memory (sp + regmap[regno], buf,
371                             register_size (gdbarch, regno));
372             }
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
386 hpux_thread_prepare_to_store (struct regcache *regcache)
387 {
388   deprecated_child_ops.to_prepare_to_store (regcache);
389 }
390
391 static int
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     deprecated_child_ops.deprecated_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
414 hpux_thread_files_info (struct target_ops *ignore)
415 {
416   deprecated_child_ops.to_files_info (ignore);
417 }
418
419 static void
420 hpux_thread_kill_inferior (void)
421 {
422   deprecated_child_ops.to_kill ();
423 }
424
425 static void
426 hpux_thread_notice_signals (ptid_t ptid)
427 {
428   deprecated_child_ops.to_notice_signals (ptid);
429 }
430
431 /* Fork an inferior process, and start debugging it with /proc.  */
432
433 static void
434 hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
435                              int from_tty)
436 {
437   deprecated_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 static void
458 hpux_thread_new_objfile (struct objfile *objfile)
459 {
460   struct minimal_symbol *ms;
461
462   if (!objfile)
463     {
464       hpux_thread_active = 0;
465       return;
466     }
467
468   ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
469
470   if (!ms)
471     return;
472
473   P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
474
475   ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
476
477   if (!ms)
478     return;
479
480   P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
481
482   hpux_thread_active = 1;
483 }
484
485 /* Clean up after the inferior dies.  */
486
487 static void
488 hpux_thread_mourn_inferior (void)
489 {
490   deprecated_child_ops.to_mourn_inferior ();
491 }
492
493 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
494
495 static int
496 hpux_thread_can_run (void)
497 {
498   return child_suppress_run;
499 }
500
501 static int
502 hpux_thread_alive (ptid_t ptid)
503 {
504   return 1;
505 }
506
507 static void
508 hpux_thread_stop (ptid_t ptid)
509 {
510   deprecated_child_ops.to_stop (ptid);
511 }
512 \f
513 /* Convert a pid to printable form. */
514
515 char *
516 hpux_pid_to_str (ptid_t ptid)
517 {
518   static char buf[100];
519   int pid = PIDGET (ptid);
520
521   sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
522
523   return buf;
524 }
525 \f
526 static void
527 init_hpux_thread_ops (void)
528 {
529   hpux_thread_ops.to_shortname = "hpux-threads";
530   hpux_thread_ops.to_longname = "HPUX threads and pthread.";
531   hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
532   hpux_thread_ops.to_open = hpux_thread_open;
533   hpux_thread_ops.to_attach = hpux_thread_attach;
534   hpux_thread_ops.to_detach = hpux_thread_detach;
535   hpux_thread_ops.to_resume = hpux_thread_resume;
536   hpux_thread_ops.to_wait = hpux_thread_wait;
537   hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
538   hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
539   hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
540   hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
541   hpux_thread_ops.to_files_info = hpux_thread_files_info;
542   hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
543   hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
544   hpux_thread_ops.to_terminal_init = terminal_init_inferior;
545   hpux_thread_ops.to_terminal_inferior = terminal_inferior;
546   hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
547   hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
548   hpux_thread_ops.to_terminal_ours = terminal_ours;
549   hpux_thread_ops.to_terminal_info = child_terminal_info;
550   hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
551   hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
552   hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
553   hpux_thread_ops.to_can_run = hpux_thread_can_run;
554   hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
555   hpux_thread_ops.to_thread_alive = hpux_thread_alive;
556   hpux_thread_ops.to_stop = hpux_thread_stop;
557   hpux_thread_ops.to_stratum = process_stratum;
558   hpux_thread_ops.to_has_all_memory = 1;
559   hpux_thread_ops.to_has_memory = 1;
560   hpux_thread_ops.to_has_stack = 1;
561   hpux_thread_ops.to_has_registers = 1;
562   hpux_thread_ops.to_has_execution = 1;
563   hpux_thread_ops.to_magic = OPS_MAGIC;
564 }
565
566 void
567 _initialize_hpux_thread (void)
568 {
569   init_hpux_thread_ops ();
570   add_target (&hpux_thread_ops);
571
572   child_suppress_run = 1;
573   /* Hook into new_objfile notification.  */
574   observer_attach_new_objfile (hpux_thread_new_objfile);
575 }
This page took 0.055446 seconds and 4 git commands to generate.