2009-01-30 Julian Brown <julian@codesourcery.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 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 (struct target_ops *ops, char *args, int from_tty)
148 {
149 deprecated_child_ops.to_attach (&deprecated_child_ops, 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 (struct target_ops *ops, char *args, int from_tty)
164 {
165 deprecated_child_ops.to_detach (&deprecated_child_ops, 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 (struct target_ops *ops, char *exec_file,
435 char *allargs, char **env, int from_tty)
436 {
437 deprecated_child_ops.to_create_inferior (&deprecated_child_ops,
438 exec_file, allargs, env, from_tty);
439
440 if (hpux_thread_active)
441 {
442 main_ptid = inferior_ptid;
443
444 push_target (&hpux_thread_ops);
445
446 inferior_ptid = find_active_thread ();
447
448 add_thread (inferior_ptid);
449 }
450 }
451
452 /* This routine is called whenever a new symbol table is read in, or when all
453 symbol tables are removed. libthread_db can only be initialized when it
454 finds the right variables in libthread.so. Since it's a shared library,
455 those variables don't show up until the library gets mapped and the symbol
456 table is read in. */
457
458 static void
459 hpux_thread_new_objfile (struct objfile *objfile)
460 {
461 struct minimal_symbol *ms;
462
463 if (!objfile)
464 {
465 hpux_thread_active = 0;
466 return;
467 }
468
469 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
470
471 if (!ms)
472 return;
473
474 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
475
476 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
477
478 if (!ms)
479 return;
480
481 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
482
483 hpux_thread_active = 1;
484 }
485
486 /* Clean up after the inferior dies. */
487
488 static void
489 hpux_thread_mourn_inferior (void)
490 {
491 deprecated_child_ops.to_mourn_inferior (&deprecated_child_ops);
492 }
493
494 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
495
496 static int
497 hpux_thread_can_run (void)
498 {
499 return child_suppress_run;
500 }
501
502 static int
503 hpux_thread_alive (ptid_t ptid)
504 {
505 return 1;
506 }
507
508 static void
509 hpux_thread_stop (ptid_t ptid)
510 {
511 deprecated_child_ops.to_stop (ptid);
512 }
513 \f
514 /* Convert a pid to printable form. */
515
516 char *
517 hpux_pid_to_str (ptid_t ptid)
518 {
519 static char buf[100];
520 int pid = PIDGET (ptid);
521
522 sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
523
524 return buf;
525 }
526 \f
527 static void
528 init_hpux_thread_ops (void)
529 {
530 hpux_thread_ops.to_shortname = "hpux-threads";
531 hpux_thread_ops.to_longname = "HPUX threads and pthread.";
532 hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
533 hpux_thread_ops.to_open = hpux_thread_open;
534 hpux_thread_ops.to_attach = hpux_thread_attach;
535 hpux_thread_ops.to_detach = hpux_thread_detach;
536 hpux_thread_ops.to_resume = hpux_thread_resume;
537 hpux_thread_ops.to_wait = hpux_thread_wait;
538 hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
539 hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
540 hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
541 hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
542 hpux_thread_ops.to_files_info = hpux_thread_files_info;
543 hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
544 hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
545 hpux_thread_ops.to_terminal_init = terminal_init_inferior;
546 hpux_thread_ops.to_terminal_inferior = terminal_inferior;
547 hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
548 hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
549 hpux_thread_ops.to_terminal_ours = terminal_ours;
550 hpux_thread_ops.to_terminal_info = child_terminal_info;
551 hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
552 hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
553 hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
554 hpux_thread_ops.to_can_run = hpux_thread_can_run;
555 hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
556 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
557 hpux_thread_ops.to_stop = hpux_thread_stop;
558 hpux_thread_ops.to_stratum = process_stratum;
559 hpux_thread_ops.to_has_all_memory = 1;
560 hpux_thread_ops.to_has_memory = 1;
561 hpux_thread_ops.to_has_stack = 1;
562 hpux_thread_ops.to_has_registers = 1;
563 hpux_thread_ops.to_has_execution = 1;
564 hpux_thread_ops.to_magic = OPS_MAGIC;
565 }
566
567 void
568 _initialize_hpux_thread (void)
569 {
570 init_hpux_thread_ops ();
571 add_target (&hpux_thread_ops);
572
573 child_suppress_run = 1;
574 /* Hook into new_objfile notification. */
575 observer_attach_new_objfile (hpux_thread_new_objfile);
576 }
This page took 0.042268 seconds and 4 git commands to generate.