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