2004-09-29 Andrew Cagney <cagney@gnu.org>
[binutils-gdb.git] / gdb / hpux-thread.c
1 /* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
2 Copyright 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* This module implements a sort of half target that sits between the
22 machine-independent parts of GDB and the ptrace interface (infptrace.c) to
23 provide access to the HPUX user-mode thread implementation.
24
25 HPUX threads are true user-mode threads, which are invoked via the cma_*
26 and pthread_* (DCE and Posix respectivly) interfaces. These are mostly
27 implemented in user-space, with all thread context kept in various
28 structures that live in the user's heap. For the most part, the kernel has
29 no knowlege of these threads.
30
31 */
32
33 #include "defs.h"
34
35 #define _CMA_NOWRAPPERS_
36
37 #include <cma_tcb_defs.h>
38 #include <cma_deb_core.h>
39 #include "gdbthread.h"
40 #include "target.h"
41 #include "inferior.h"
42 #include "regcache.h"
43 #include <fcntl.h>
44 #include "gdb_stat.h"
45 #include "gdbcore.h"
46
47 extern int child_suppress_run;
48
49 extern void _initialize_hpux_thread (void);
50
51 struct string_map
52 {
53 int num;
54 char *str;
55 };
56
57 static int hpux_thread_active = 0;
58
59 static ptid_t main_ptid; /* Real process ID */
60
61 static CORE_ADDR P_cma__g_known_threads;
62 static CORE_ADDR P_cma__g_current_thread;
63
64 static void hpux_thread_resume (ptid_t ptid, int step,
65 enum target_signal signo);
66
67 static void init_hpux_thread_ops (void);
68
69 static struct target_ops hpux_thread_ops;
70 \f
71 static ptid_t find_active_thread (void);
72
73 static int cached_thread;
74 static cma__t_int_tcb cached_tcb;
75
76 static ptid_t
77 find_active_thread (void)
78 {
79 static cma__t_int_tcb tcb;
80 CORE_ADDR tcb_ptr;
81
82 read_memory ((CORE_ADDR) P_cma__g_current_thread,
83 (char *) &tcb_ptr,
84 sizeof tcb_ptr);
85
86 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
87
88 return (ptid_build (PIDGET (main_ptid), 0,
89 cma_thread_get_unique (&tcb.prolog.client_thread)));
90 }
91
92 static cma__t_int_tcb *find_tcb (ptid_t ptid);
93
94 static cma__t_int_tcb *
95 find_tcb (ptid_t ptid)
96 {
97 cma__t_known_object queue_header;
98 cma__t_queue *queue_ptr;
99 int thread = ptid_get_tid (ptid);
100
101 if (thread == cached_thread)
102 return &cached_tcb;
103
104 read_memory ((CORE_ADDR) P_cma__g_known_threads,
105 (char *) &queue_header,
106 sizeof queue_header);
107
108 for (queue_ptr = queue_header.queue.flink;
109 queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
110 queue_ptr = cached_tcb.threads.flink)
111 {
112 cma__t_int_tcb *tcb_ptr;
113
114 tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
115
116 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
117
118 if (cached_tcb.header.type == cma__c_obj_tcb)
119 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
120 {
121 cached_thread = thread;
122 return &cached_tcb;
123 }
124 }
125
126 error ("Can't find TCB %d", thread);
127 return NULL;
128 }
129 \f
130 /* Most target vector functions from here on actually just pass through to
131 inftarg.c, as they don't need to do anything specific for threads. */
132
133 static void
134 hpux_thread_open (char *arg, int from_tty)
135 {
136 child_ops.to_open (arg, from_tty);
137 }
138
139 /* Attach to process PID, then initialize for debugging it
140 and wait for the trace-trap that results from attaching. */
141
142 static void
143 hpux_thread_attach (char *args, int from_tty)
144 {
145 child_ops.to_attach (args, from_tty);
146
147 /* XXX - might want to iterate over all the threads and register them. */
148 }
149
150 /* Take a program previously attached to and detaches it.
151 The program resumes execution and will no longer stop
152 on signals, etc. We'd better not have left any breakpoints
153 in the program or it'll die when it hits one. For this
154 to work, it may be necessary for the process to have been
155 previously attached. It *might* work if the program was
156 started via the normal ptrace (PTRACE_TRACEME). */
157
158 static void
159 hpux_thread_detach (char *args, int from_tty)
160 {
161 child_ops.to_detach (args, from_tty);
162 }
163
164 /* Resume execution of process PID. If STEP is nozero, then
165 just single step it. If SIGNAL is nonzero, restart it with that
166 signal activated. We may have to convert pid from a thread-id to an LWP id
167 for procfs. */
168
169 static void
170 hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
171 {
172 struct cleanup *old_chain;
173
174 old_chain = save_inferior_ptid ();
175
176 ptid = main_ptid;
177 inferior_ptid = main_ptid;
178
179 #if 0
180 if (pid != -1)
181 {
182 pid = thread_to_lwp (pid, -2);
183 if (pid == -2) /* Inactive thread */
184 error ("This version of Solaris can't start inactive threads.");
185 }
186 #endif
187
188 child_ops.to_resume (ptid, step, signo);
189
190 cached_thread = 0;
191
192 do_cleanups (old_chain);
193 }
194
195 /* Wait for any threads to stop. We may have to convert PID from a thread id
196 to a LWP id, and vice versa on the way out. */
197
198 static ptid_t
199 hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
200 {
201 ptid_t rtnval;
202 struct cleanup *old_chain;
203
204 old_chain = save_inferior_ptid ();
205
206 inferior_ptid = main_ptid;
207
208 if (!ptid_equal (ptid, minus_one_ptid))
209 ptid = main_ptid;
210
211 rtnval = child_ops.to_wait (ptid, ourstatus);
212
213 rtnval = find_active_thread ();
214
215 do_cleanups (old_chain);
216
217 return rtnval;
218 }
219
220 static char regmap[NUM_REGS] =
221 {
222 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
223 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
224 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
225
226 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
227 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
228
229 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
230 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
231
232 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
233 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
234
235 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
236 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
237 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
238 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
239 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
240 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
241 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
242 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
243 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
244 };
245
246 static void
247 hpux_thread_fetch_registers (int regno)
248 {
249 cma__t_int_tcb tcb, *tcb_ptr;
250 struct cleanup *old_chain;
251 int i;
252 int first_regno, last_regno;
253
254 tcb_ptr = find_tcb (inferior_ptid);
255
256 old_chain = save_inferior_ptid ();
257
258 inferior_ptid = main_ptid;
259
260 if (tcb_ptr->state == cma__c_state_running)
261 {
262 child_ops.to_fetch_registers (regno);
263
264 do_cleanups (old_chain);
265
266 return;
267 }
268
269 if (regno == -1)
270 {
271 first_regno = 0;
272 last_regno = NUM_REGS - 1;
273 }
274 else
275 {
276 first_regno = regno;
277 last_regno = regno;
278 }
279
280 for (regno = first_regno; regno <= last_regno; regno++)
281 {
282 if (regmap[regno] == -1)
283 child_ops.to_fetch_registers (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 == FLAGS_REGNUM)
292 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
293 memset (buf, '\000', register_size (current_gdbarch, regno));
294 else if (regno == SP_REGNUM)
295 store_unsigned_integer (buf, sizeof sp, sp);
296 else if (regno == PC_REGNUM)
297 read_memory (sp - 20, buf, register_size (current_gdbarch, regno));
298 else
299 read_memory (sp + regmap[regno], buf, register_size (current_gdbarch, regno));
300
301 regcache_raw_supply (current_regcache, regno, buf);
302 }
303 }
304
305 do_cleanups (old_chain);
306 }
307
308 static void
309 hpux_thread_store_registers (int regno)
310 {
311 cma__t_int_tcb tcb, *tcb_ptr;
312 struct cleanup *old_chain;
313 int i;
314 int first_regno, last_regno;
315
316 tcb_ptr = find_tcb (inferior_ptid);
317
318 old_chain = save_inferior_ptid ();
319
320 inferior_ptid = main_ptid;
321
322 if (tcb_ptr->state == cma__c_state_running)
323 {
324 child_ops.to_store_registers (regno);
325
326 do_cleanups (old_chain);
327
328 return;
329 }
330
331 if (regno == -1)
332 {
333 first_regno = 0;
334 last_regno = NUM_REGS - 1;
335 }
336 else
337 {
338 first_regno = regno;
339 last_regno = regno;
340 }
341
342 for (regno = first_regno; regno <= last_regno; regno++)
343 {
344 if (regmap[regno] == -1)
345 child_ops.to_store_registers (regno);
346 else
347 {
348 unsigned char buf[MAX_REGISTER_SIZE];
349 CORE_ADDR sp;
350
351 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
352
353 if (regno == FLAGS_REGNUM)
354 child_ops.to_store_registers (regno); /* Let lower layer handle this... */
355 else if (regno == SP_REGNUM)
356 {
357 write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
358 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
359 register_size (current_gdbarch, regno));
360 tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
361 (extract_unsigned_integer (&deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
362 register_size (current_gdbarch, regno)) + 160);
363 }
364 else if (regno == PC_REGNUM)
365 write_memory (sp - 20,
366 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
367 register_size (current_gdbarch, regno));
368 else
369 write_memory (sp + regmap[regno],
370 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
371 register_size (current_gdbarch, regno));
372 }
373 }
374
375 do_cleanups (old_chain);
376 }
377
378 /* Get ready to modify the registers array. On machines which store
379 individual registers, this doesn't need to do anything. On machines
380 which store all the registers in one fell swoop, this makes sure
381 that registers contains all the registers from the program being
382 debugged. */
383
384 static void
385 hpux_thread_prepare_to_store (void)
386 {
387 child_ops.to_prepare_to_store ();
388 }
389
390 static int
391 hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
392 int dowrite, struct mem_attrib *attribs,
393 struct target_ops *target)
394 {
395 int retval;
396 struct cleanup *old_chain;
397
398 old_chain = save_inferior_ptid ();
399
400 inferior_ptid = main_ptid;
401
402 retval =
403 child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
404
405 do_cleanups (old_chain);
406
407 return retval;
408 }
409
410 /* Print status information about what we're accessing. */
411
412 static void
413 hpux_thread_files_info (struct target_ops *ignore)
414 {
415 child_ops.to_files_info (ignore);
416 }
417
418 static void
419 hpux_thread_kill_inferior (void)
420 {
421 child_ops.to_kill ();
422 }
423
424 static void
425 hpux_thread_notice_signals (ptid_t ptid)
426 {
427 child_ops.to_notice_signals (ptid);
428 }
429
430 /* Fork an inferior process, and start debugging it with /proc. */
431
432 static void
433 hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
434 int from_tty)
435 {
436 child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
437
438 if (hpux_thread_active)
439 {
440 main_ptid = inferior_ptid;
441
442 push_target (&hpux_thread_ops);
443
444 inferior_ptid = find_active_thread ();
445
446 add_thread (inferior_ptid);
447 }
448 }
449
450 /* This routine is called whenever a new symbol table is read in, or when all
451 symbol tables are removed. libthread_db can only be initialized when it
452 finds the right variables in libthread.so. Since it's a shared library,
453 those variables don't show up until the library gets mapped and the symbol
454 table is read in. */
455
456 /* This new_objfile event is now managed by a chained function pointer.
457 * It is the callee's responsability to call the next client on the chain.
458 */
459
460 /* Saved pointer to previous owner of the new_objfile event. */
461 static void (*target_new_objfile_chain) (struct objfile *);
462
463 void
464 hpux_thread_new_objfile (struct objfile *objfile)
465 {
466 struct minimal_symbol *ms;
467
468 if (!objfile)
469 {
470 hpux_thread_active = 0;
471 goto quit;
472 }
473
474 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
475
476 if (!ms)
477 goto quit;
478
479 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
480
481 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
482
483 if (!ms)
484 goto quit;
485
486 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
487
488 hpux_thread_active = 1;
489 quit:
490 /* Call predecessor on chain, if any. */
491 if (target_new_objfile_chain)
492 target_new_objfile_chain (objfile);
493 }
494
495 /* Clean up after the inferior dies. */
496
497 static void
498 hpux_thread_mourn_inferior (void)
499 {
500 child_ops.to_mourn_inferior ();
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 (ptid_t ptid)
513 {
514 return 1;
515 }
516
517 static void
518 hpux_thread_stop (void)
519 {
520 child_ops.to_stop ();
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.to_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 target_new_objfile_chain = deprecated_target_new_objfile_hook;
585 deprecated_target_new_objfile_hook = hpux_thread_new_objfile;
586 }