2007-05-31 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / hpux-thread.c
CommitLineData
1df84f13
AC
1/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU
2 debugger.
3
6aba47ca
DJ
4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2004, 2007
5 Free Software Foundation, Inc.
c906108c 6
c5aa993b 7 This file is part of GDB.
c906108c 8
c5aa993b
JM
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 2 of the License, or
12 (at your option) any later version.
c906108c 13
c5aa993b
JM
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.
c906108c 18
c5aa993b
JM
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
197e01b6
EZ
21 Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
c906108c
SS
23
24/* This module implements a sort of half target that sits between the
25 machine-independent parts of GDB and the ptrace interface (infptrace.c) to
26 provide access to the HPUX user-mode thread implementation.
27
28 HPUX threads are true user-mode threads, which are invoked via the cma_*
29 and pthread_* (DCE and Posix respectivly) interfaces. These are mostly
30 implemented in user-space, with all thread context kept in various
31 structures that live in the user's heap. For the most part, the kernel has
32 no knowlege of these threads.
33
c5aa993b 34 */
c906108c
SS
35
36#include "defs.h"
37
38#define _CMA_NOWRAPPERS_
39
40#include <cma_tcb_defs.h>
41#include <cma_deb_core.h>
42#include "gdbthread.h"
43#include "target.h"
44#include "inferior.h"
4e052eda 45#include "regcache.h"
c906108c 46#include <fcntl.h>
3f6306ec 47#include <string.h>
b8a92b82 48#include "gdb_stat.h"
c906108c 49#include "gdbcore.h"
3f6306ec 50#include "hppa-tdep.h"
06d3b283 51#include "observer.h"
c906108c
SS
52
53extern int child_suppress_run;
c906108c 54
a14ed312 55extern void _initialize_hpux_thread (void);
c906108c
SS
56
57struct string_map
c5aa993b
JM
58 {
59 int num;
60 char *str;
61 };
c906108c
SS
62
63static int hpux_thread_active = 0;
64
39f77062 65static ptid_t main_ptid; /* Real process ID */
c906108c
SS
66
67static CORE_ADDR P_cma__g_known_threads;
68static CORE_ADDR P_cma__g_current_thread;
69
39f77062
KB
70static void hpux_thread_resume (ptid_t ptid, int step,
71 enum target_signal signo);
c906108c 72
a14ed312 73static void init_hpux_thread_ops (void);
c906108c
SS
74
75static struct target_ops hpux_thread_ops;
76\f
f7926acf 77static ptid_t find_active_thread (void);
c906108c
SS
78
79static int cached_thread;
c906108c
SS
80static cma__t_int_tcb cached_tcb;
81
f7926acf 82static ptid_t
fba45db2 83find_active_thread (void)
c906108c
SS
84{
85 static cma__t_int_tcb tcb;
86 CORE_ADDR tcb_ptr;
87
c5aa993b
JM
88 read_memory ((CORE_ADDR) P_cma__g_current_thread,
89 (char *) &tcb_ptr,
c906108c
SS
90 sizeof tcb_ptr);
91
c5aa993b 92 read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
c906108c 93
f7926acf
JB
94 return (ptid_build (PIDGET (main_ptid), 0,
95 cma_thread_get_unique (&tcb.prolog.client_thread)));
c906108c
SS
96}
97
f7926acf 98static cma__t_int_tcb *find_tcb (ptid_t ptid);
c906108c
SS
99
100static cma__t_int_tcb *
f7926acf 101find_tcb (ptid_t ptid)
c906108c
SS
102{
103 cma__t_known_object queue_header;
104 cma__t_queue *queue_ptr;
f7926acf 105 int thread = ptid_get_tid (ptid);
c906108c
SS
106
107 if (thread == cached_thread)
108 return &cached_tcb;
109
c5aa993b
JM
110 read_memory ((CORE_ADDR) P_cma__g_known_threads,
111 (char *) &queue_header,
c906108c
SS
112 sizeof queue_header);
113
114 for (queue_ptr = queue_header.queue.flink;
c5aa993b 115 queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
c906108c
SS
116 queue_ptr = cached_tcb.threads.flink)
117 {
118 cma__t_int_tcb *tcb_ptr;
119
120 tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
121
c5aa993b 122 read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
c906108c
SS
123
124 if (cached_tcb.header.type == cma__c_obj_tcb)
f7926acf 125 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
c906108c
SS
126 {
127 cached_thread = thread;
128 return &cached_tcb;
129 }
130 }
131
8a3fe4f8 132 error (_("Can't find TCB %d"), thread);
c906108c
SS
133 return NULL;
134}
135\f
136/* Most target vector functions from here on actually just pass through to
137 inftarg.c, as they don't need to do anything specific for threads. */
138
c906108c 139static void
fba45db2 140hpux_thread_open (char *arg, int from_tty)
c906108c 141{
1df84f13 142 deprecated_child_ops.to_open (arg, from_tty);
c906108c
SS
143}
144
145/* Attach to process PID, then initialize for debugging it
146 and wait for the trace-trap that results from attaching. */
147
148static void
fba45db2 149hpux_thread_attach (char *args, int from_tty)
c906108c 150{
1df84f13 151 deprecated_child_ops.to_attach (args, from_tty);
c906108c
SS
152
153 /* XXX - might want to iterate over all the threads and register them. */
154}
155
156/* Take a program previously attached to and detaches it.
157 The program resumes execution and will no longer stop
158 on signals, etc. We'd better not have left any breakpoints
159 in the program or it'll die when it hits one. For this
160 to work, it may be necessary for the process to have been
161 previously attached. It *might* work if the program was
162 started via the normal ptrace (PTRACE_TRACEME). */
163
164static void
fba45db2 165hpux_thread_detach (char *args, int from_tty)
c906108c 166{
1df84f13 167 deprecated_child_ops.to_detach (args, from_tty);
c906108c
SS
168}
169
170/* Resume execution of process PID. If STEP is nozero, then
171 just single step it. If SIGNAL is nonzero, restart it with that
172 signal activated. We may have to convert pid from a thread-id to an LWP id
173 for procfs. */
174
175static void
39f77062 176hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
c906108c
SS
177{
178 struct cleanup *old_chain;
179
39f77062 180 old_chain = save_inferior_ptid ();
c906108c 181
39f77062
KB
182 ptid = main_ptid;
183 inferior_ptid = main_ptid;
c906108c
SS
184
185#if 0
186 if (pid != -1)
187 {
188 pid = thread_to_lwp (pid, -2);
189 if (pid == -2) /* Inactive thread */
8a3fe4f8 190 error (_("This version of Solaris can't start inactive threads."));
c906108c
SS
191 }
192#endif
193
1df84f13 194 deprecated_child_ops.to_resume (ptid, step, signo);
c906108c
SS
195
196 cached_thread = 0;
c906108c
SS
197
198 do_cleanups (old_chain);
199}
200
201/* Wait for any threads to stop. We may have to convert PID from a thread id
202 to a LWP id, and vice versa on the way out. */
203
39f77062
KB
204static ptid_t
205hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c 206{
39f77062 207 ptid_t rtnval;
c906108c
SS
208 struct cleanup *old_chain;
209
39f77062 210 old_chain = save_inferior_ptid ();
c906108c 211
39f77062 212 inferior_ptid = main_ptid;
c906108c 213
39f77062
KB
214 if (!ptid_equal (ptid, minus_one_ptid))
215 ptid = main_ptid;
c906108c 216
1df84f13 217 rtnval = deprecated_child_ops.to_wait (ptid, ourstatus);
c906108c
SS
218
219 rtnval = find_active_thread ();
220
221 do_cleanups (old_chain);
222
223 return rtnval;
224}
225
3f6306ec 226static char regmap[] =
c906108c 227{
c5aa993b
JM
228 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
229 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
230 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
c906108c
SS
231
232 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
233 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
234
235 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
236 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
237
238 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
239 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
240
241 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
c5aa993b
JM
242 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
243 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
244 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
245 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
246 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
247 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
248 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
249 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
c906108c
SS
250};
251
252static void
56be3814 253hpux_thread_fetch_registers (struct regcache *regcache, int regno)
c906108c
SS
254{
255 cma__t_int_tcb tcb, *tcb_ptr;
256 struct cleanup *old_chain;
257 int i;
258 int first_regno, last_regno;
259
f7926acf 260 tcb_ptr = find_tcb (inferior_ptid);
c906108c 261
39f77062 262 old_chain = save_inferior_ptid ();
c906108c 263
39f77062 264 inferior_ptid = main_ptid;
c906108c
SS
265
266 if (tcb_ptr->state == cma__c_state_running)
267 {
56be3814 268 deprecated_child_ops.to_fetch_registers (regcache, regno);
c906108c
SS
269
270 do_cleanups (old_chain);
271
272 return;
273 }
274
275 if (regno == -1)
276 {
277 first_regno = 0;
f57d151a 278 last_regno = gdbarch_num_regs (current_gdbarch) - 1;
c906108c
SS
279 }
280 else
281 {
282 first_regno = regno;
283 last_regno = regno;
284 }
285
286 for (regno = first_regno; regno <= last_regno; regno++)
287 {
288 if (regmap[regno] == -1)
56be3814 289 deprecated_child_ops.to_fetch_registers (regcache, regno);
c906108c
SS
290 else
291 {
123a958e 292 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
293 CORE_ADDR sp;
294
c5aa993b 295 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c 296
3f6306ec 297 if (regno == HPPA_FLAGS_REGNUM)
c906108c 298 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
3acba339 299 memset (buf, '\000', register_size (current_gdbarch, regno));
3f6306ec 300 else if (regno == HPPA_SP_REGNUM)
fbd9dcd3 301 store_unsigned_integer (buf, sizeof sp, sp);
3f6306ec 302 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
3acba339 303 read_memory (sp - 20, buf, register_size (current_gdbarch, regno));
c906108c 304 else
3acba339 305 read_memory (sp + regmap[regno], buf, register_size (current_gdbarch, regno));
c906108c 306
56be3814 307 regcache_raw_supply (regcache, regno, buf);
c906108c
SS
308 }
309 }
310
311 do_cleanups (old_chain);
312}
313
314static void
56be3814 315hpux_thread_store_registers (struct regcache *regcache, int regno)
c906108c
SS
316{
317 cma__t_int_tcb tcb, *tcb_ptr;
318 struct cleanup *old_chain;
319 int i;
320 int first_regno, last_regno;
321
f7926acf 322 tcb_ptr = find_tcb (inferior_ptid);
c906108c 323
39f77062 324 old_chain = save_inferior_ptid ();
c906108c 325
39f77062 326 inferior_ptid = main_ptid;
c906108c
SS
327
328 if (tcb_ptr->state == cma__c_state_running)
329 {
56be3814 330 deprecated_child_ops.to_store_registers (regcache, regno);
c906108c
SS
331
332 do_cleanups (old_chain);
333
334 return;
335 }
336
337 if (regno == -1)
338 {
339 first_regno = 0;
f57d151a 340 last_regno = gdbarch_num_regs (current_gdbarch) - 1;
c906108c
SS
341 }
342 else
343 {
344 first_regno = regno;
345 last_regno = regno;
346 }
347
348 for (regno = first_regno; regno <= last_regno; regno++)
349 {
350 if (regmap[regno] == -1)
56be3814 351 deprecated_child_ops.to_store_registers (regcache, regno);
c906108c
SS
352 else
353 {
123a958e 354 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
355 CORE_ADDR sp;
356
c5aa993b 357 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c 358
3f6306ec 359 if (regno == HPPA_FLAGS_REGNUM)
56be3814 360 deprecated_child_ops.to_store_registers (regcache, regno); /* Let lower layer handle this... */
3f6306ec 361 else if (regno == HPPA_SP_REGNUM)
c906108c 362 {
56be3814 363 regcache_raw_collect (regcache, regno, buf);
3f6306ec
DA
364 write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
365 register_size (current_gdbarch, regno));
366 tcb_ptr->static_ctx.sp
367 = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
368 }
369 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
370 {
56be3814 371 regcache_raw_collect (regcache, regno, buf);
3f6306ec 372 write_memory (sp - 20, buf,
3acba339 373 register_size (current_gdbarch, regno));
c906108c 374 }
c906108c 375 else
3f6306ec 376 {
56be3814 377 regcache_raw_collect (regcache, regno, buf);
3f6306ec
DA
378 write_memory (sp + regmap[regno], buf,
379 register_size (current_gdbarch, regno));
380 }
c906108c
SS
381 }
382 }
383
384 do_cleanups (old_chain);
385}
386
387/* Get ready to modify the registers array. On machines which store
388 individual registers, this doesn't need to do anything. On machines
389 which store all the registers in one fell swoop, this makes sure
390 that registers contains all the registers from the program being
391 debugged. */
392
393static void
316f2060 394hpux_thread_prepare_to_store (struct regcache *regcache)
c906108c 395{
316f2060 396 deprecated_child_ops.to_prepare_to_store (regcache);
c906108c
SS
397}
398
399static int
165a58fe 400hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
971429b4
AC
401 int dowrite, struct mem_attrib *attribs,
402 struct target_ops *target)
c906108c
SS
403{
404 int retval;
405 struct cleanup *old_chain;
406
39f77062 407 old_chain = save_inferior_ptid ();
c906108c 408
39f77062 409 inferior_ptid = main_ptid;
c906108c 410
971429b4 411 retval =
c8e73a31 412 deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
c906108c
SS
413
414 do_cleanups (old_chain);
415
416 return retval;
417}
418
419/* Print status information about what we're accessing. */
420
421static void
fba45db2 422hpux_thread_files_info (struct target_ops *ignore)
c906108c 423{
1df84f13 424 deprecated_child_ops.to_files_info (ignore);
c906108c
SS
425}
426
427static void
fba45db2 428hpux_thread_kill_inferior (void)
c906108c 429{
1df84f13 430 deprecated_child_ops.to_kill ();
c906108c
SS
431}
432
433static void
39f77062 434hpux_thread_notice_signals (ptid_t ptid)
c906108c 435{
1df84f13 436 deprecated_child_ops.to_notice_signals (ptid);
c906108c
SS
437}
438
439/* Fork an inferior process, and start debugging it with /proc. */
440
441static void
c27cda74
AC
442hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
443 int from_tty)
c906108c 444{
1df84f13 445 deprecated_child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
c906108c
SS
446
447 if (hpux_thread_active)
448 {
39f77062 449 main_ptid = inferior_ptid;
c906108c
SS
450
451 push_target (&hpux_thread_ops);
452
39f77062 453 inferior_ptid = find_active_thread ();
c906108c 454
39f77062 455 add_thread (inferior_ptid);
c906108c
SS
456 }
457}
458
459/* This routine is called whenever a new symbol table is read in, or when all
460 symbol tables are removed. libthread_db can only be initialized when it
461 finds the right variables in libthread.so. Since it's a shared library,
462 those variables don't show up until the library gets mapped and the symbol
463 table is read in. */
464
06d3b283 465static void
fba45db2 466hpux_thread_new_objfile (struct objfile *objfile)
c906108c
SS
467{
468 struct minimal_symbol *ms;
469
470 if (!objfile)
471 {
472 hpux_thread_active = 0;
06d3b283 473 return;
c906108c
SS
474 }
475
476 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
477
478 if (!ms)
06d3b283 479 return;
c906108c
SS
480
481 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
482
483 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
484
485 if (!ms)
06d3b283 486 return;
c906108c
SS
487
488 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
489
490 hpux_thread_active = 1;
491}
492
493/* Clean up after the inferior dies. */
494
495static void
fba45db2 496hpux_thread_mourn_inferior (void)
c906108c 497{
1df84f13 498 deprecated_child_ops.to_mourn_inferior ();
c906108c
SS
499}
500
501/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
502
503static int
fba45db2 504hpux_thread_can_run (void)
c906108c
SS
505{
506 return child_suppress_run;
507}
508
509static int
39f77062 510hpux_thread_alive (ptid_t ptid)
c906108c
SS
511{
512 return 1;
513}
514
515static void
fba45db2 516hpux_thread_stop (void)
c906108c 517{
1df84f13 518 deprecated_child_ops.to_stop ();
c906108c
SS
519}
520\f
521/* Convert a pid to printable form. */
522
523char *
39f77062 524hpux_pid_to_str (ptid_t ptid)
c906108c
SS
525{
526 static char buf[100];
39f77062 527 int pid = PIDGET (ptid);
c906108c 528
f7926acf 529 sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
c906108c
SS
530
531 return buf;
532}
533\f
534static void
fba45db2 535init_hpux_thread_ops (void)
c906108c
SS
536{
537 hpux_thread_ops.to_shortname = "hpux-threads";
538 hpux_thread_ops.to_longname = "HPUX threads and pthread.";
539 hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
540 hpux_thread_ops.to_open = hpux_thread_open;
541 hpux_thread_ops.to_attach = hpux_thread_attach;
542 hpux_thread_ops.to_detach = hpux_thread_detach;
543 hpux_thread_ops.to_resume = hpux_thread_resume;
544 hpux_thread_ops.to_wait = hpux_thread_wait;
545 hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
546 hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
547 hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
c8e73a31 548 hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
c906108c
SS
549 hpux_thread_ops.to_files_info = hpux_thread_files_info;
550 hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
551 hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
552 hpux_thread_ops.to_terminal_init = terminal_init_inferior;
553 hpux_thread_ops.to_terminal_inferior = terminal_inferior;
554 hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
a790ad35 555 hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
c906108c
SS
556 hpux_thread_ops.to_terminal_ours = terminal_ours;
557 hpux_thread_ops.to_terminal_info = child_terminal_info;
558 hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
559 hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
560 hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
561 hpux_thread_ops.to_can_run = hpux_thread_can_run;
562 hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
b83266a0 563 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
c906108c
SS
564 hpux_thread_ops.to_stop = hpux_thread_stop;
565 hpux_thread_ops.to_stratum = process_stratum;
566 hpux_thread_ops.to_has_all_memory = 1;
567 hpux_thread_ops.to_has_memory = 1;
568 hpux_thread_ops.to_has_stack = 1;
569 hpux_thread_ops.to_has_registers = 1;
570 hpux_thread_ops.to_has_execution = 1;
571 hpux_thread_ops.to_magic = OPS_MAGIC;
572}
573
574void
fba45db2 575_initialize_hpux_thread (void)
c906108c
SS
576{
577 init_hpux_thread_ops ();
578 add_target (&hpux_thread_ops);
579
580 child_suppress_run = 1;
d9788fe8 581 /* Hook into new_objfile notification. */
06d3b283 582 observer_attach_new_objfile (hpux_thread_new_objfile);
c906108c 583}
This page took 0.551458 seconds and 4 git commands to generate.