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