* m88kbsd-nat.c: Include "target.h" and "inf-ptrace.h".
[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;
c906108c 48
a14ed312 49extern void _initialize_hpux_thread (void);
c906108c
SS
50
51struct string_map
c5aa993b
JM
52 {
53 int num;
54 char *str;
55 };
c906108c
SS
56
57static int hpux_thread_active = 0;
58
39f77062 59static ptid_t main_ptid; /* Real process ID */
c906108c
SS
60
61static CORE_ADDR P_cma__g_known_threads;
62static CORE_ADDR P_cma__g_current_thread;
63
39f77062
KB
64static void hpux_thread_resume (ptid_t ptid, int step,
65 enum target_signal signo);
c906108c 66
a14ed312 67static void init_hpux_thread_ops (void);
c906108c
SS
68
69static struct target_ops hpux_thread_ops;
70\f
f7926acf 71static ptid_t find_active_thread (void);
c906108c
SS
72
73static int cached_thread;
c906108c
SS
74static cma__t_int_tcb cached_tcb;
75
f7926acf 76static ptid_t
fba45db2 77find_active_thread (void)
c906108c
SS
78{
79 static cma__t_int_tcb tcb;
80 CORE_ADDR tcb_ptr;
81
c5aa993b
JM
82 read_memory ((CORE_ADDR) P_cma__g_current_thread,
83 (char *) &tcb_ptr,
c906108c
SS
84 sizeof tcb_ptr);
85
c5aa993b 86 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
c906108c 87
f7926acf
JB
88 return (ptid_build (PIDGET (main_ptid), 0,
89 cma_thread_get_unique (&tcb.prolog.client_thread)));
c906108c
SS
90}
91
f7926acf 92static cma__t_int_tcb *find_tcb (ptid_t ptid);
c906108c
SS
93
94static cma__t_int_tcb *
f7926acf 95find_tcb (ptid_t ptid)
c906108c
SS
96{
97 cma__t_known_object queue_header;
98 cma__t_queue *queue_ptr;
f7926acf 99 int thread = ptid_get_tid (ptid);
c906108c
SS
100
101 if (thread == cached_thread)
102 return &cached_tcb;
103
c5aa993b
JM
104 read_memory ((CORE_ADDR) P_cma__g_known_threads,
105 (char *) &queue_header,
c906108c
SS
106 sizeof queue_header);
107
108 for (queue_ptr = queue_header.queue.flink;
c5aa993b 109 queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
c906108c
SS
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
c5aa993b 116 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
c906108c
SS
117
118 if (cached_tcb.header.type == cma__c_obj_tcb)
f7926acf 119 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
c906108c
SS
120 {
121 cached_thread = thread;
122 return &cached_tcb;
123 }
124 }
125
f7926acf 126 error ("Can't find TCB %d", thread);
c906108c
SS
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
c906108c 133static void
fba45db2 134hpux_thread_open (char *arg, int from_tty)
c906108c
SS
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
142static void
fba45db2 143hpux_thread_attach (char *args, int from_tty)
c906108c
SS
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
158static void
fba45db2 159hpux_thread_detach (char *args, int from_tty)
c906108c
SS
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
169static void
39f77062 170hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
c906108c
SS
171{
172 struct cleanup *old_chain;
173
39f77062 174 old_chain = save_inferior_ptid ();
c906108c 175
39f77062
KB
176 ptid = main_ptid;
177 inferior_ptid = main_ptid;
c906108c
SS
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
39f77062 188 child_ops.to_resume (ptid, step, signo);
c906108c
SS
189
190 cached_thread = 0;
c906108c
SS
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
39f77062
KB
198static ptid_t
199hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c 200{
39f77062 201 ptid_t rtnval;
c906108c
SS
202 struct cleanup *old_chain;
203
39f77062 204 old_chain = save_inferior_ptid ();
c906108c 205
39f77062 206 inferior_ptid = main_ptid;
c906108c 207
39f77062
KB
208 if (!ptid_equal (ptid, minus_one_ptid))
209 ptid = main_ptid;
c906108c 210
39f77062 211 rtnval = child_ops.to_wait (ptid, ourstatus);
c906108c
SS
212
213 rtnval = find_active_thread ();
214
215 do_cleanups (old_chain);
216
217 return rtnval;
218}
219
220static char regmap[NUM_REGS] =
221{
c5aa993b
JM
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 */
c906108c
SS
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 */
c5aa993b
JM
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 */
c906108c
SS
244};
245
246static void
fba45db2 247hpux_thread_fetch_registers (int regno)
c906108c
SS
248{
249 cma__t_int_tcb tcb, *tcb_ptr;
250 struct cleanup *old_chain;
251 int i;
252 int first_regno, last_regno;
253
f7926acf 254 tcb_ptr = find_tcb (inferior_ptid);
c906108c 255
39f77062 256 old_chain = save_inferior_ptid ();
c906108c 257
39f77062 258 inferior_ptid = main_ptid;
c906108c
SS
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 {
123a958e 286 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
287 CORE_ADDR sp;
288
c5aa993b 289 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
290
291 if (regno == FLAGS_REGNUM)
292 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
3acba339 293 memset (buf, '\000', register_size (current_gdbarch, regno));
c906108c 294 else if (regno == SP_REGNUM)
fbd9dcd3 295 store_unsigned_integer (buf, sizeof sp, sp);
c906108c 296 else if (regno == PC_REGNUM)
3acba339 297 read_memory (sp - 20, buf, register_size (current_gdbarch, regno));
c906108c 298 else
3acba339 299 read_memory (sp + regmap[regno], buf, register_size (current_gdbarch, regno));
c906108c 300
23a6d369 301 regcache_raw_supply (current_regcache, regno, buf);
c906108c
SS
302 }
303 }
304
305 do_cleanups (old_chain);
306}
307
308static void
fba45db2 309hpux_thread_store_registers (int regno)
c906108c
SS
310{
311 cma__t_int_tcb tcb, *tcb_ptr;
312 struct cleanup *old_chain;
313 int i;
314 int first_regno, last_regno;
315
f7926acf 316 tcb_ptr = find_tcb (inferior_ptid);
c906108c 317
39f77062 318 old_chain = save_inferior_ptid ();
c906108c 319
39f77062 320 inferior_ptid = main_ptid;
c906108c
SS
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 {
123a958e 348 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
349 CORE_ADDR sp;
350
c5aa993b 351 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
352
353 if (regno == FLAGS_REGNUM)
c5aa993b 354 child_ops.to_store_registers (regno); /* Let lower layer handle this... */
c906108c
SS
355 else if (regno == SP_REGNUM)
356 {
c5aa993b 357 write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
62700349 358 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
3acba339 359 register_size (current_gdbarch, regno));
c906108c 360 tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
62700349 361 (extract_unsigned_integer (&deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
3acba339 362 register_size (current_gdbarch, regno)) + 160);
c906108c
SS
363 }
364 else if (regno == PC_REGNUM)
365 write_memory (sp - 20,
62700349 366 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
3acba339 367 register_size (current_gdbarch, regno));
c906108c
SS
368 else
369 write_memory (sp + regmap[regno],
62700349 370 &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
3acba339 371 register_size (current_gdbarch, regno));
c906108c
SS
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
384static void
fba45db2 385hpux_thread_prepare_to_store (void)
c906108c
SS
386{
387 child_ops.to_prepare_to_store ();
388}
389
390static int
165a58fe 391hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
971429b4
AC
392 int dowrite, struct mem_attrib *attribs,
393 struct target_ops *target)
c906108c
SS
394{
395 int retval;
396 struct cleanup *old_chain;
397
39f77062 398 old_chain = save_inferior_ptid ();
c906108c 399
39f77062 400 inferior_ptid = main_ptid;
c906108c 401
971429b4
AC
402 retval =
403 child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
c906108c
SS
404
405 do_cleanups (old_chain);
406
407 return retval;
408}
409
410/* Print status information about what we're accessing. */
411
412static void
fba45db2 413hpux_thread_files_info (struct target_ops *ignore)
c906108c
SS
414{
415 child_ops.to_files_info (ignore);
416}
417
418static void
fba45db2 419hpux_thread_kill_inferior (void)
c906108c
SS
420{
421 child_ops.to_kill ();
422}
423
424static void
39f77062 425hpux_thread_notice_signals (ptid_t ptid)
c906108c 426{
39f77062 427 child_ops.to_notice_signals (ptid);
c906108c
SS
428}
429
430/* Fork an inferior process, and start debugging it with /proc. */
431
432static void
c27cda74
AC
433hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
434 int from_tty)
c906108c 435{
c27cda74 436 child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
c906108c
SS
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.400552 seconds and 4 git commands to generate.