2004-04-21 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / hpux-thread.c
CommitLineData
c906108c 1/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
b6ba6518 2 Copyright 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
c906108c 3
c5aa993b 4 This file is part of GDB.
c906108c 5
c5aa993b
JM
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.
c906108c 10
c5aa993b
JM
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.
c906108c 15
c5aa993b
JM
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. */
c906108c
SS
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
c5aa993b 31 */
c906108c
SS
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"
4e052eda 42#include "regcache.h"
c906108c 43#include <fcntl.h>
b8a92b82 44#include "gdb_stat.h"
c906108c
SS
45#include "gdbcore.h"
46
47extern int child_suppress_run;
c5aa993b 48extern struct target_ops child_ops; /* target vector for inftarg.c */
c906108c 49
a14ed312 50extern void _initialize_hpux_thread (void);
c906108c
SS
51
52struct string_map
c5aa993b
JM
53 {
54 int num;
55 char *str;
56 };
c906108c
SS
57
58static int hpux_thread_active = 0;
59
39f77062 60static ptid_t main_ptid; /* Real process ID */
c906108c
SS
61
62static CORE_ADDR P_cma__g_known_threads;
63static CORE_ADDR P_cma__g_current_thread;
64
39f77062
KB
65static void hpux_thread_resume (ptid_t ptid, int step,
66 enum target_signal signo);
c906108c 67
a14ed312 68static void init_hpux_thread_ops (void);
c906108c
SS
69
70static struct target_ops hpux_thread_ops;
71\f
f7926acf 72static ptid_t find_active_thread (void);
c906108c
SS
73
74static int cached_thread;
c906108c
SS
75static cma__t_int_tcb cached_tcb;
76
f7926acf 77static ptid_t
fba45db2 78find_active_thread (void)
c906108c
SS
79{
80 static cma__t_int_tcb tcb;
81 CORE_ADDR tcb_ptr;
82
c5aa993b
JM
83 read_memory ((CORE_ADDR) P_cma__g_current_thread,
84 (char *) &tcb_ptr,
c906108c
SS
85 sizeof tcb_ptr);
86
c5aa993b 87 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
c906108c 88
f7926acf
JB
89 return (ptid_build (PIDGET (main_ptid), 0,
90 cma_thread_get_unique (&tcb.prolog.client_thread)));
c906108c
SS
91}
92
f7926acf 93static cma__t_int_tcb *find_tcb (ptid_t ptid);
c906108c
SS
94
95static cma__t_int_tcb *
f7926acf 96find_tcb (ptid_t ptid)
c906108c
SS
97{
98 cma__t_known_object queue_header;
99 cma__t_queue *queue_ptr;
f7926acf 100 int thread = ptid_get_tid (ptid);
c906108c
SS
101
102 if (thread == cached_thread)
103 return &cached_tcb;
104
c5aa993b
JM
105 read_memory ((CORE_ADDR) P_cma__g_known_threads,
106 (char *) &queue_header,
c906108c
SS
107 sizeof queue_header);
108
109 for (queue_ptr = queue_header.queue.flink;
c5aa993b 110 queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
c906108c
SS
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
c5aa993b 117 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
c906108c
SS
118
119 if (cached_tcb.header.type == cma__c_obj_tcb)
f7926acf 120 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
c906108c
SS
121 {
122 cached_thread = thread;
123 return &cached_tcb;
124 }
125 }
126
f7926acf 127 error ("Can't find TCB %d", thread);
c906108c
SS
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
c906108c 134static void
fba45db2 135hpux_thread_open (char *arg, int from_tty)
c906108c
SS
136{
137 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
143static void
fba45db2 144hpux_thread_attach (char *args, int from_tty)
c906108c
SS
145{
146 child_ops.to_attach (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
159static void
fba45db2 160hpux_thread_detach (char *args, int from_tty)
c906108c
SS
161{
162 child_ops.to_detach (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
170static void
39f77062 171hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
c906108c
SS
172{
173 struct cleanup *old_chain;
174
39f77062 175 old_chain = save_inferior_ptid ();
c906108c 176
39f77062
KB
177 ptid = main_ptid;
178 inferior_ptid = main_ptid;
c906108c
SS
179
180#if 0
181 if (pid != -1)
182 {
183 pid = thread_to_lwp (pid, -2);
184 if (pid == -2) /* Inactive thread */
185 error ("This version of Solaris can't start inactive threads.");
186 }
187#endif
188
39f77062 189 child_ops.to_resume (ptid, step, signo);
c906108c
SS
190
191 cached_thread = 0;
c906108c
SS
192
193 do_cleanups (old_chain);
194}
195
196/* Wait for any threads to stop. We may have to convert PID from a thread id
197 to a LWP id, and vice versa on the way out. */
198
39f77062
KB
199static ptid_t
200hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c 201{
39f77062 202 ptid_t rtnval;
c906108c
SS
203 struct cleanup *old_chain;
204
39f77062 205 old_chain = save_inferior_ptid ();
c906108c 206
39f77062 207 inferior_ptid = main_ptid;
c906108c 208
39f77062
KB
209 if (!ptid_equal (ptid, minus_one_ptid))
210 ptid = main_ptid;
c906108c 211
39f77062 212 rtnval = child_ops.to_wait (ptid, ourstatus);
c906108c
SS
213
214 rtnval = find_active_thread ();
215
216 do_cleanups (old_chain);
217
218 return rtnval;
219}
220
221static char regmap[NUM_REGS] =
222{
c5aa993b
JM
223 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
224 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
225 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
c906108c
SS
226
227 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
228 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
229
230 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
231 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
232
233 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
234 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
235
236 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
c5aa993b
JM
237 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
238 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
239 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
240 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
241 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
242 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
243 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
244 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
c906108c
SS
245};
246
247static void
fba45db2 248hpux_thread_fetch_registers (int regno)
c906108c
SS
249{
250 cma__t_int_tcb tcb, *tcb_ptr;
251 struct cleanup *old_chain;
252 int i;
253 int first_regno, last_regno;
254
f7926acf 255 tcb_ptr = find_tcb (inferior_ptid);
c906108c 256
39f77062 257 old_chain = save_inferior_ptid ();
c906108c 258
39f77062 259 inferior_ptid = main_ptid;
c906108c
SS
260
261 if (tcb_ptr->state == cma__c_state_running)
262 {
263 child_ops.to_fetch_registers (regno);
264
265 do_cleanups (old_chain);
266
267 return;
268 }
269
270 if (regno == -1)
271 {
272 first_regno = 0;
273 last_regno = NUM_REGS - 1;
274 }
275 else
276 {
277 first_regno = regno;
278 last_regno = regno;
279 }
280
281 for (regno = first_regno; regno <= last_regno; regno++)
282 {
283 if (regmap[regno] == -1)
284 child_ops.to_fetch_registers (regno);
285 else
286 {
123a958e 287 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
288 CORE_ADDR sp;
289
c5aa993b 290 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
291
292 if (regno == FLAGS_REGNUM)
293 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
12c266ea 294 memset (buf, '\000', DEPRECATED_REGISTER_RAW_SIZE (regno));
c906108c 295 else if (regno == SP_REGNUM)
fbd9dcd3 296 store_unsigned_integer (buf, sizeof sp, sp);
c906108c 297 else if (regno == PC_REGNUM)
12c266ea 298 read_memory (sp - 20, buf, DEPRECATED_REGISTER_RAW_SIZE (regno));
c906108c 299 else
12c266ea 300 read_memory (sp + regmap[regno], buf, DEPRECATED_REGISTER_RAW_SIZE (regno));
c906108c
SS
301
302 supply_register (regno, buf);
303 }
304 }
305
306 do_cleanups (old_chain);
307}
308
309static void
fba45db2 310hpux_thread_store_registers (int regno)
c906108c
SS
311{
312 cma__t_int_tcb tcb, *tcb_ptr;
313 struct cleanup *old_chain;
314 int i;
315 int first_regno, last_regno;
316
f7926acf 317 tcb_ptr = find_tcb (inferior_ptid);
c906108c 318
39f77062 319 old_chain = save_inferior_ptid ();
c906108c 320
39f77062 321 inferior_ptid = main_ptid;
c906108c
SS
322
323 if (tcb_ptr->state == cma__c_state_running)
324 {
325 child_ops.to_store_registers (regno);
326
327 do_cleanups (old_chain);
328
329 return;
330 }
331
332 if (regno == -1)
333 {
334 first_regno = 0;
335 last_regno = NUM_REGS - 1;
336 }
337 else
338 {
339 first_regno = regno;
340 last_regno = regno;
341 }
342
343 for (regno = first_regno; regno <= last_regno; regno++)
344 {
345 if (regmap[regno] == -1)
346 child_ops.to_store_registers (regno);
347 else
348 {
123a958e 349 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
350 CORE_ADDR sp;
351
c5aa993b 352 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
353
354 if (regno == FLAGS_REGNUM)
c5aa993b 355 child_ops.to_store_registers (regno); /* Let lower layer handle this... */
c906108c
SS
356 else if (regno == SP_REGNUM)
357 {
c5aa993b 358 write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
62700349 359 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
12c266ea 360 DEPRECATED_REGISTER_RAW_SIZE (regno));
c906108c 361 tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
62700349 362 (extract_unsigned_integer (&deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
12c266ea 363 DEPRECATED_REGISTER_RAW_SIZE (regno)) + 160);
c906108c
SS
364 }
365 else if (regno == PC_REGNUM)
366 write_memory (sp - 20,
62700349 367 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
12c266ea 368 DEPRECATED_REGISTER_RAW_SIZE (regno));
c906108c
SS
369 else
370 write_memory (sp + regmap[regno],
62700349 371 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
12c266ea 372 DEPRECATED_REGISTER_RAW_SIZE (regno));
c906108c
SS
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
385static void
fba45db2 386hpux_thread_prepare_to_store (void)
c906108c
SS
387{
388 child_ops.to_prepare_to_store ();
389}
390
391static int
165a58fe 392hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
971429b4
AC
393 int dowrite, struct mem_attrib *attribs,
394 struct target_ops *target)
c906108c
SS
395{
396 int retval;
397 struct cleanup *old_chain;
398
39f77062 399 old_chain = save_inferior_ptid ();
c906108c 400
39f77062 401 inferior_ptid = main_ptid;
c906108c 402
971429b4
AC
403 retval =
404 child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
c906108c
SS
405
406 do_cleanups (old_chain);
407
408 return retval;
409}
410
411/* Print status information about what we're accessing. */
412
413static void
fba45db2 414hpux_thread_files_info (struct target_ops *ignore)
c906108c
SS
415{
416 child_ops.to_files_info (ignore);
417}
418
419static void
fba45db2 420hpux_thread_kill_inferior (void)
c906108c
SS
421{
422 child_ops.to_kill ();
423}
424
425static void
39f77062 426hpux_thread_notice_signals (ptid_t ptid)
c906108c 427{
39f77062 428 child_ops.to_notice_signals (ptid);
c906108c
SS
429}
430
431/* Fork an inferior process, and start debugging it with /proc. */
432
433static void
fba45db2 434hpux_thread_create_inferior (char *exec_file, char *allargs, char **env)
c906108c
SS
435{
436 child_ops.to_create_inferior (exec_file, allargs, env);
437
438 if (hpux_thread_active)
439 {
39f77062 440 main_ptid = inferior_ptid;
c906108c
SS
441
442 push_target (&hpux_thread_ops);
443
39f77062 444 inferior_ptid = find_active_thread ();
c906108c 445
39f77062 446 add_thread (inferior_ptid);
c906108c
SS
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
11cf8741
JM
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. */
507f3c78 461static void (*target_new_objfile_chain) (struct objfile *);
11cf8741 462
c906108c 463void
fba45db2 464hpux_thread_new_objfile (struct objfile *objfile)
c906108c
SS
465{
466 struct minimal_symbol *ms;
467
468 if (!objfile)
469 {
470 hpux_thread_active = 0;
11cf8741 471 goto quit;
c906108c
SS
472 }
473
474 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
475
476 if (!ms)
11cf8741 477 goto quit;
c906108c
SS
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)
11cf8741 484 goto quit;
c906108c
SS
485
486 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
487
488 hpux_thread_active = 1;
11cf8741
JM
489quit:
490 /* Call predecessor on chain, if any. */
491 if (target_new_objfile_chain)
492 target_new_objfile_chain (objfile);
c906108c
SS
493}
494
495/* Clean up after the inferior dies. */
496
497static void
fba45db2 498hpux_thread_mourn_inferior (void)
c906108c
SS
499{
500 child_ops.to_mourn_inferior ();
501}
502
503/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
504
505static int
fba45db2 506hpux_thread_can_run (void)
c906108c
SS
507{
508 return child_suppress_run;
509}
510
511static int
39f77062 512hpux_thread_alive (ptid_t ptid)
c906108c
SS
513{
514 return 1;
515}
516
517static void
fba45db2 518hpux_thread_stop (void)
c906108c
SS
519{
520 child_ops.to_stop ();
521}
522\f
523/* Convert a pid to printable form. */
524
525char *
39f77062 526hpux_pid_to_str (ptid_t ptid)
c906108c
SS
527{
528 static char buf[100];
39f77062 529 int pid = PIDGET (ptid);
c906108c 530
f7926acf 531 sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
c906108c
SS
532
533 return buf;
534}
535\f
536static void
fba45db2 537init_hpux_thread_ops (void)
c906108c
SS
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;
a790ad35 557 hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
c906108c
SS
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;
b83266a0 565 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
c906108c
SS
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
576void
fba45db2 577_initialize_hpux_thread (void)
c906108c
SS
578{
579 init_hpux_thread_ops ();
580 add_target (&hpux_thread_ops);
581
582 child_suppress_run = 1;
11cf8741 583 /* Hook into new_objfile notification. */
9a4105ab
AC
584 target_new_objfile_chain = deprecated_target_new_objfile_hook;
585 deprecated_target_new_objfile_hook = hpux_thread_new_objfile;
c906108c 586}
This page took 0.524558 seconds and 4 git commands to generate.