2008-10-29 Stefan Schulze Frielinghaus <xxschulz@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
9b254dd1 4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2004, 2007, 2008
6aba47ca 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 182
1df84f13 183 deprecated_child_ops.to_resume (ptid, step, signo);
c906108c
SS
184
185 cached_thread = 0;
c906108c
SS
186
187 do_cleanups (old_chain);
188}
189
190/* Wait for any threads to stop. We may have to convert PID from a thread id
191 to a LWP id, and vice versa on the way out. */
192
39f77062
KB
193static ptid_t
194hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c 195{
39f77062 196 ptid_t rtnval;
c906108c
SS
197 struct cleanup *old_chain;
198
39f77062 199 old_chain = save_inferior_ptid ();
c906108c 200
39f77062 201 inferior_ptid = main_ptid;
c906108c 202
39f77062
KB
203 if (!ptid_equal (ptid, minus_one_ptid))
204 ptid = main_ptid;
c906108c 205
1df84f13 206 rtnval = deprecated_child_ops.to_wait (ptid, ourstatus);
c906108c
SS
207
208 rtnval = find_active_thread ();
209
210 do_cleanups (old_chain);
211
212 return rtnval;
213}
214
3f6306ec 215static char regmap[] =
c906108c 216{
c5aa993b
JM
217 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
218 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
219 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
c906108c
SS
220
221 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
222 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
223
224 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
225 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226
227 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
228 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
229
230 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
c5aa993b
JM
231 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
232 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
233 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
234 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
235 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
236 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
237 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
238 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
c906108c
SS
239};
240
241static void
56be3814 242hpux_thread_fetch_registers (struct regcache *regcache, int regno)
c906108c 243{
8d90747a 244 struct gdbarch *gdbarch = get_regcache_arch (regcache);
c906108c
SS
245 cma__t_int_tcb tcb, *tcb_ptr;
246 struct cleanup *old_chain;
247 int i;
248 int first_regno, last_regno;
249
f7926acf 250 tcb_ptr = find_tcb (inferior_ptid);
c906108c 251
39f77062 252 old_chain = save_inferior_ptid ();
c906108c 253
39f77062 254 inferior_ptid = main_ptid;
c906108c
SS
255
256 if (tcb_ptr->state == cma__c_state_running)
257 {
56be3814 258 deprecated_child_ops.to_fetch_registers (regcache, regno);
c906108c
SS
259
260 do_cleanups (old_chain);
261
262 return;
263 }
264
265 if (regno == -1)
266 {
267 first_regno = 0;
8d90747a 268 last_regno = gdbarch_num_regs (gdbarch) - 1;
c906108c
SS
269 }
270 else
271 {
272 first_regno = regno;
273 last_regno = regno;
274 }
275
276 for (regno = first_regno; regno <= last_regno; regno++)
277 {
278 if (regmap[regno] == -1)
56be3814 279 deprecated_child_ops.to_fetch_registers (regcache, regno);
c906108c
SS
280 else
281 {
123a958e 282 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
283 CORE_ADDR sp;
284
c5aa993b 285 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c 286
3f6306ec 287 if (regno == HPPA_FLAGS_REGNUM)
c906108c 288 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
8d90747a 289 memset (buf, '\000', register_size (gdbarch, regno));
3f6306ec 290 else if (regno == HPPA_SP_REGNUM)
fbd9dcd3 291 store_unsigned_integer (buf, sizeof sp, sp);
3f6306ec 292 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
8d90747a 293 read_memory (sp - 20, buf, register_size (gdbarch, regno));
c906108c 294 else
8d90747a
UW
295 read_memory (sp + regmap[regno], buf,
296 register_size (gdbarch, regno));
c906108c 297
56be3814 298 regcache_raw_supply (regcache, regno, buf);
c906108c
SS
299 }
300 }
301
302 do_cleanups (old_chain);
303}
304
305static void
56be3814 306hpux_thread_store_registers (struct regcache *regcache, int regno)
c906108c 307{
8d90747a 308 struct gdbarch *gdbarch = get_regcache_arch (regcache);
c906108c
SS
309 cma__t_int_tcb tcb, *tcb_ptr;
310 struct cleanup *old_chain;
311 int i;
312 int first_regno, last_regno;
313
f7926acf 314 tcb_ptr = find_tcb (inferior_ptid);
c906108c 315
39f77062 316 old_chain = save_inferior_ptid ();
c906108c 317
39f77062 318 inferior_ptid = main_ptid;
c906108c
SS
319
320 if (tcb_ptr->state == cma__c_state_running)
321 {
56be3814 322 deprecated_child_ops.to_store_registers (regcache, regno);
c906108c
SS
323
324 do_cleanups (old_chain);
325
326 return;
327 }
328
329 if (regno == -1)
330 {
331 first_regno = 0;
8d90747a 332 last_regno = gdbarch_num_regs (gdbarch) - 1;
c906108c
SS
333 }
334 else
335 {
336 first_regno = regno;
337 last_regno = regno;
338 }
339
340 for (regno = first_regno; regno <= last_regno; regno++)
341 {
342 if (regmap[regno] == -1)
56be3814 343 deprecated_child_ops.to_store_registers (regcache, regno);
c906108c
SS
344 else
345 {
123a958e 346 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
347 CORE_ADDR sp;
348
c5aa993b 349 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c 350
3f6306ec 351 if (regno == HPPA_FLAGS_REGNUM)
56be3814 352 deprecated_child_ops.to_store_registers (regcache, regno); /* Let lower layer handle this... */
3f6306ec 353 else if (regno == HPPA_SP_REGNUM)
c906108c 354 {
56be3814 355 regcache_raw_collect (regcache, regno, buf);
3f6306ec 356 write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
8d90747a 357 register_size (gdbarch, regno));
3f6306ec
DA
358 tcb_ptr->static_ctx.sp
359 = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
360 }
361 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
362 {
56be3814 363 regcache_raw_collect (regcache, regno, buf);
3f6306ec 364 write_memory (sp - 20, buf,
8d90747a 365 register_size (gdbarch, regno));
c906108c 366 }
c906108c 367 else
3f6306ec 368 {
56be3814 369 regcache_raw_collect (regcache, regno, buf);
3f6306ec 370 write_memory (sp + regmap[regno], buf,
8d90747a 371 register_size (gdbarch, regno));
3f6306ec 372 }
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
316f2060 386hpux_thread_prepare_to_store (struct regcache *regcache)
c906108c 387{
316f2060 388 deprecated_child_ops.to_prepare_to_store (regcache);
c906108c
SS
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 403 retval =
c8e73a31 404 deprecated_child_ops.deprecated_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 415{
1df84f13 416 deprecated_child_ops.to_files_info (ignore);
c906108c
SS
417}
418
419static void
fba45db2 420hpux_thread_kill_inferior (void)
c906108c 421{
1df84f13 422 deprecated_child_ops.to_kill ();
c906108c
SS
423}
424
425static void
39f77062 426hpux_thread_notice_signals (ptid_t ptid)
c906108c 427{
1df84f13 428 deprecated_child_ops.to_notice_signals (ptid);
c906108c
SS
429}
430
431/* Fork an inferior process, and start debugging it with /proc. */
432
433static void
c27cda74
AC
434hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
435 int from_tty)
c906108c 436{
1df84f13 437 deprecated_child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
c906108c
SS
438
439 if (hpux_thread_active)
440 {
39f77062 441 main_ptid = inferior_ptid;
c906108c
SS
442
443 push_target (&hpux_thread_ops);
444
39f77062 445 inferior_ptid = find_active_thread ();
c906108c 446
39f77062 447 add_thread (inferior_ptid);
c906108c
SS
448 }
449}
450
451/* This routine is called whenever a new symbol table is read in, or when all
452 symbol tables are removed. libthread_db can only be initialized when it
453 finds the right variables in libthread.so. Since it's a shared library,
454 those variables don't show up until the library gets mapped and the symbol
455 table is read in. */
456
06d3b283 457static void
fba45db2 458hpux_thread_new_objfile (struct objfile *objfile)
c906108c
SS
459{
460 struct minimal_symbol *ms;
461
462 if (!objfile)
463 {
464 hpux_thread_active = 0;
06d3b283 465 return;
c906108c
SS
466 }
467
468 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
469
470 if (!ms)
06d3b283 471 return;
c906108c
SS
472
473 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
474
475 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
476
477 if (!ms)
06d3b283 478 return;
c906108c
SS
479
480 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
481
482 hpux_thread_active = 1;
483}
484
485/* Clean up after the inferior dies. */
486
487static void
fba45db2 488hpux_thread_mourn_inferior (void)
c906108c 489{
1df84f13 490 deprecated_child_ops.to_mourn_inferior ();
c906108c
SS
491}
492
493/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
494
495static int
fba45db2 496hpux_thread_can_run (void)
c906108c
SS
497{
498 return child_suppress_run;
499}
500
501static int
39f77062 502hpux_thread_alive (ptid_t ptid)
c906108c
SS
503{
504 return 1;
505}
506
507static void
f9c72d52 508hpux_thread_stop (ptid_t ptid)
c906108c 509{
f9c72d52 510 deprecated_child_ops.to_stop (ptid);
c906108c
SS
511}
512\f
513/* Convert a pid to printable form. */
514
515char *
39f77062 516hpux_pid_to_str (ptid_t ptid)
c906108c
SS
517{
518 static char buf[100];
39f77062 519 int pid = PIDGET (ptid);
c906108c 520
f7926acf 521 sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
c906108c
SS
522
523 return buf;
524}
525\f
526static void
fba45db2 527init_hpux_thread_ops (void)
c906108c
SS
528{
529 hpux_thread_ops.to_shortname = "hpux-threads";
530 hpux_thread_ops.to_longname = "HPUX threads and pthread.";
531 hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
532 hpux_thread_ops.to_open = hpux_thread_open;
533 hpux_thread_ops.to_attach = hpux_thread_attach;
534 hpux_thread_ops.to_detach = hpux_thread_detach;
535 hpux_thread_ops.to_resume = hpux_thread_resume;
536 hpux_thread_ops.to_wait = hpux_thread_wait;
537 hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
538 hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
539 hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
c8e73a31 540 hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
c906108c
SS
541 hpux_thread_ops.to_files_info = hpux_thread_files_info;
542 hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
543 hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
544 hpux_thread_ops.to_terminal_init = terminal_init_inferior;
545 hpux_thread_ops.to_terminal_inferior = terminal_inferior;
546 hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
a790ad35 547 hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
c906108c
SS
548 hpux_thread_ops.to_terminal_ours = terminal_ours;
549 hpux_thread_ops.to_terminal_info = child_terminal_info;
550 hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
551 hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
552 hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
553 hpux_thread_ops.to_can_run = hpux_thread_can_run;
554 hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
b83266a0 555 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
c906108c
SS
556 hpux_thread_ops.to_stop = hpux_thread_stop;
557 hpux_thread_ops.to_stratum = process_stratum;
558 hpux_thread_ops.to_has_all_memory = 1;
559 hpux_thread_ops.to_has_memory = 1;
560 hpux_thread_ops.to_has_stack = 1;
561 hpux_thread_ops.to_has_registers = 1;
562 hpux_thread_ops.to_has_execution = 1;
563 hpux_thread_ops.to_magic = OPS_MAGIC;
564}
565
566void
fba45db2 567_initialize_hpux_thread (void)
c906108c
SS
568{
569 init_hpux_thread_ops ();
570 add_target (&hpux_thread_ops);
571
572 child_suppress_run = 1;
d9788fe8 573 /* Hook into new_objfile notification. */
06d3b283 574 observer_attach_new_objfile (hpux_thread_new_objfile);
c906108c 575}
This page took 0.688855 seconds and 4 git commands to generate.