2009-12-15 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.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, int options)
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, options);
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 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
247 cma__t_int_tcb tcb, *tcb_ptr;
248 struct cleanup *old_chain;
249 int i;
250 int first_regno, last_regno;
251
252 tcb_ptr = find_tcb (inferior_ptid);
253
254 old_chain = save_inferior_ptid ();
255
256 inferior_ptid = main_ptid;
257
258 if (tcb_ptr->state == cma__c_state_running)
259 {
260 deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
261 regcache, regno);
262
263 do_cleanups (old_chain);
264
265 return;
266 }
267
268 if (regno == -1)
269 {
270 first_regno = 0;
271 last_regno = gdbarch_num_regs (gdbarch) - 1;
272 }
273 else
274 {
275 first_regno = regno;
276 last_regno = regno;
277 }
278
279 for (regno = first_regno; regno <= last_regno; regno++)
280 {
281 if (regmap[regno] == -1)
282 deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
283 regcache, regno);
284 else
285 {
286 unsigned char buf[MAX_REGISTER_SIZE];
287 CORE_ADDR sp;
288
289 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
290
291 if (regno == HPPA_FLAGS_REGNUM)
292 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
293 memset (buf, '\000', register_size (gdbarch, regno));
294 else if (regno == HPPA_SP_REGNUM)
295 store_unsigned_integer (buf, sizeof sp, byte_order, sp);
296 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
297 read_memory (sp - 20, buf, register_size (gdbarch, regno));
298 else
299 read_memory (sp + regmap[regno], buf,
300 register_size (gdbarch, regno));
301
302 regcache_raw_supply (regcache, regno, buf);
303 }
304 }
305
306 do_cleanups (old_chain);
307 }
308
309 static void
310 hpux_thread_store_registers (struct target_ops *ops,
311 struct regcache *regcache, int regno)
312 {
313 struct gdbarch *gdbarch = get_regcache_arch (regcache);
314 cma__t_int_tcb tcb, *tcb_ptr;
315 struct cleanup *old_chain;
316 int i;
317 int first_regno, last_regno;
318
319 tcb_ptr = find_tcb (inferior_ptid);
320
321 old_chain = save_inferior_ptid ();
322
323 inferior_ptid = main_ptid;
324
325 if (tcb_ptr->state == cma__c_state_running)
326 {
327 deprecated_child_ops.to_store_registers (&deprecated_child_ops,
328 regcache, regno);
329
330 do_cleanups (old_chain);
331
332 return;
333 }
334
335 if (regno == -1)
336 {
337 first_regno = 0;
338 last_regno = gdbarch_num_regs (gdbarch) - 1;
339 }
340 else
341 {
342 first_regno = regno;
343 last_regno = regno;
344 }
345
346 for (regno = first_regno; regno <= last_regno; regno++)
347 {
348 if (regmap[regno] == -1)
349 deprecated_child_ops.to_store_registers (regcache, regno);
350 else
351 {
352 unsigned char buf[MAX_REGISTER_SIZE];
353 CORE_ADDR sp;
354
355 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
356
357 if (regno == HPPA_FLAGS_REGNUM)
358 {
359 /* Let lower layer handle this... */
360 deprecated_child_ops.to_store_registers
361 (&deprecated_child_ops, regcache, regno);
362 }
363 else if (regno == HPPA_SP_REGNUM)
364 {
365 regcache_raw_collect (regcache, regno, buf);
366 write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
367 register_size (gdbarch, regno));
368 tcb_ptr->static_ctx.sp
369 = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
370 }
371 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
372 {
373 regcache_raw_collect (regcache, regno, buf);
374 write_memory (sp - 20, buf,
375 register_size (gdbarch, regno));
376 }
377 else
378 {
379 regcache_raw_collect (regcache, regno, buf);
380 write_memory (sp + regmap[regno], buf,
381 register_size (gdbarch, regno));
382 }
383 }
384 }
385
386 do_cleanups (old_chain);
387 }
388
389 /* Get ready to modify the registers array. On machines which store
390 individual registers, this doesn't need to do anything. On machines
391 which store all the registers in one fell swoop, this makes sure
392 that registers contains all the registers from the program being
393 debugged. */
394
395 static void
396 hpux_thread_prepare_to_store (struct regcache *regcache)
397 {
398 deprecated_child_ops.to_prepare_to_store (regcache);
399 }
400
401 static int
402 hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
403 int dowrite, struct mem_attrib *attribs,
404 struct target_ops *target)
405 {
406 int retval;
407 struct cleanup *old_chain;
408
409 old_chain = save_inferior_ptid ();
410
411 inferior_ptid = main_ptid;
412
413 retval =
414 deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
415
416 do_cleanups (old_chain);
417
418 return retval;
419 }
420
421 /* Print status information about what we're accessing. */
422
423 static void
424 hpux_thread_files_info (struct target_ops *ignore)
425 {
426 deprecated_child_ops.to_files_info (ignore);
427 }
428
429 static void
430 hpux_thread_kill_inferior (struct target_ops *ops)
431 {
432 deprecated_child_ops.to_kill (&deprecated_child_ops);
433 }
434
435 static void
436 hpux_thread_notice_signals (ptid_t ptid)
437 {
438 deprecated_child_ops.to_notice_signals (ptid);
439 }
440
441 /* Fork an inferior process, and start debugging it with /proc. */
442
443 static void
444 hpux_thread_create_inferior (struct target_ops *ops, char *exec_file,
445 char *allargs, char **env, int from_tty)
446 {
447 deprecated_child_ops.to_create_inferior (&deprecated_child_ops,
448 exec_file, allargs, env, from_tty);
449
450 if (hpux_thread_active)
451 {
452 main_ptid = inferior_ptid;
453
454 push_target (&hpux_thread_ops);
455
456 inferior_ptid = find_active_thread ();
457
458 add_thread (inferior_ptid);
459 }
460 }
461
462 /* This routine is called whenever a new symbol table is read in, or when all
463 symbol tables are removed. libthread_db can only be initialized when it
464 finds the right variables in libthread.so. Since it's a shared library,
465 those variables don't show up until the library gets mapped and the symbol
466 table is read in. */
467
468 static void
469 hpux_thread_new_objfile (struct objfile *objfile)
470 {
471 struct minimal_symbol *ms;
472
473 if (!objfile)
474 {
475 hpux_thread_active = 0;
476 return;
477 }
478
479 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
480
481 if (!ms)
482 return;
483
484 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
485
486 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
487
488 if (!ms)
489 return;
490
491 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
492
493 hpux_thread_active = 1;
494 }
495
496 /* Clean up after the inferior dies. */
497
498 static void
499 hpux_thread_mourn_inferior (void)
500 {
501 deprecated_child_ops.to_mourn_inferior (&deprecated_child_ops);
502 }
503
504 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
505
506 static int
507 hpux_thread_can_run (void)
508 {
509 return child_suppress_run;
510 }
511
512 static int
513 hpux_thread_alive (struct target_ops *ops, ptid_t ptid)
514 {
515 return 1;
516 }
517
518 static void
519 hpux_thread_stop (ptid_t ptid)
520 {
521 deprecated_child_ops.to_stop (ptid);
522 }
523 \f
524 /* Convert a pid to printable form. */
525
526 char *
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 \f
537 static 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.deprecated_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 = default_child_has_all_memory;
570 hpux_thread_ops.to_has_memory = default_child_has_memory;
571 hpux_thread_ops.to_has_stack = default_child_has_stack;
572 hpux_thread_ops.to_has_registers = default_child_has_registers;
573 hpux_thread_ops.to_has_execution = default_child_has_execution;
574 hpux_thread_ops.to_magic = OPS_MAGIC;
575 }
576
577 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 observer_attach_new_objfile (hpux_thread_new_objfile);
586 }
This page took 0.050177 seconds and 4 git commands to generate.