* mips-tdep.c (mips_type_needs_double_align): New function.
[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>
c906108c
SS
44#include <sys/stat.h>
45#include "gdbcore.h"
46
47extern int child_suppress_run;
c5aa993b 48extern struct target_ops child_ops; /* target vector for inftarg.c */
c906108c 49
a14ed312 50extern void _initialize_hpux_thread (void);
c906108c
SS
51
52struct string_map
c5aa993b
JM
53 {
54 int num;
55 char *str;
56 };
c906108c
SS
57
58static int hpux_thread_active = 0;
59
39f77062 60static ptid_t main_ptid; /* Real process ID */
c906108c
SS
61
62static CORE_ADDR P_cma__g_known_threads;
63static CORE_ADDR P_cma__g_current_thread;
64
39f77062
KB
65static void hpux_thread_resume (ptid_t ptid, int step,
66 enum target_signal signo);
c906108c 67
a14ed312 68static void init_hpux_thread_ops (void);
c906108c
SS
69
70static struct target_ops hpux_thread_ops;
71\f
a14ed312 72static int find_active_thread (void);
c906108c
SS
73
74static int cached_thread;
75static int cached_active_thread;
76static cma__t_int_tcb cached_tcb;
77
78static int
fba45db2 79find_active_thread (void)
c906108c
SS
80{
81 static cma__t_int_tcb tcb;
82 CORE_ADDR tcb_ptr;
83
84 if (cached_active_thread != 0)
85 return cached_active_thread;
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
39f77062
KB
93 return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16)
94 | PIDGET (main_ptid);
c906108c
SS
95}
96
a14ed312 97static cma__t_int_tcb *find_tcb (int thread);
c906108c
SS
98
99static cma__t_int_tcb *
fba45db2 100find_tcb (int thread)
c906108c
SS
101{
102 cma__t_known_object queue_header;
103 cma__t_queue *queue_ptr;
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)
123 if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
124 {
125 cached_thread = thread;
126 return &cached_tcb;
127 }
128 }
129
130 error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
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
137/* ARGSUSED */
138static void
fba45db2 139hpux_thread_open (char *arg, int from_tty)
c906108c
SS
140{
141 child_ops.to_open (arg, from_tty);
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
SS
149{
150 child_ops.to_attach (args, from_tty);
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
SS
165{
166 child_ops.to_detach (args, from_tty);
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 */
189 error ("This version of Solaris can't start inactive threads.");
190 }
191#endif
192
39f77062 193 child_ops.to_resume (ptid, step, signo);
c906108c
SS
194
195 cached_thread = 0;
196 cached_active_thread = 0;
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
39f77062 217 rtnval = 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
226static char regmap[NUM_REGS] =
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
fba45db2 253hpux_thread_fetch_registers (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
39f77062 260 tcb_ptr = find_tcb (PIDGET (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 {
268 child_ops.to_fetch_registers (regno);
269
270 do_cleanups (old_chain);
271
272 return;
273 }
274
275 if (regno == -1)
276 {
277 first_regno = 0;
278 last_regno = NUM_REGS - 1;
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)
289 child_ops.to_fetch_registers (regno);
290 else
291 {
292 unsigned char buf[MAX_REGISTER_RAW_SIZE];
293 CORE_ADDR sp;
294
c5aa993b 295 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
296
297 if (regno == FLAGS_REGNUM)
298 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
299 memset (buf, '\000', REGISTER_RAW_SIZE (regno));
300 else if (regno == SP_REGNUM)
301 store_address (buf, sizeof sp, sp);
302 else if (regno == PC_REGNUM)
303 read_memory (sp - 20, buf, REGISTER_RAW_SIZE (regno));
304 else
305 read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
306
307 supply_register (regno, buf);
308 }
309 }
310
311 do_cleanups (old_chain);
312}
313
314static void
fba45db2 315hpux_thread_store_registers (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
39f77062 322 tcb_ptr = find_tcb (PIDGET (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 {
330 child_ops.to_store_registers (regno);
331
332 do_cleanups (old_chain);
333
334 return;
335 }
336
337 if (regno == -1)
338 {
339 first_regno = 0;
340 last_regno = NUM_REGS - 1;
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)
351 child_ops.to_store_registers (regno);
352 else
353 {
354 unsigned char buf[MAX_REGISTER_RAW_SIZE];
355 CORE_ADDR sp;
356
c5aa993b 357 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c
SS
358
359 if (regno == FLAGS_REGNUM)
c5aa993b 360 child_ops.to_store_registers (regno); /* Let lower layer handle this... */
c906108c
SS
361 else if (regno == SP_REGNUM)
362 {
c5aa993b 363 write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
c906108c
SS
364 registers + REGISTER_BYTE (regno),
365 REGISTER_RAW_SIZE (regno));
366 tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
367 (extract_address (registers + REGISTER_BYTE (regno), REGISTER_RAW_SIZE (regno)) + 160);
368 }
369 else if (regno == PC_REGNUM)
370 write_memory (sp - 20,
371 registers + REGISTER_BYTE (regno),
372 REGISTER_RAW_SIZE (regno));
373 else
374 write_memory (sp + regmap[regno],
375 registers + REGISTER_BYTE (regno),
376 REGISTER_RAW_SIZE (regno));
377 }
378 }
379
380 do_cleanups (old_chain);
381}
382
383/* Get ready to modify the registers array. On machines which store
384 individual registers, this doesn't need to do anything. On machines
385 which store all the registers in one fell swoop, this makes sure
386 that registers contains all the registers from the program being
387 debugged. */
388
389static void
fba45db2 390hpux_thread_prepare_to_store (void)
c906108c
SS
391{
392 child_ops.to_prepare_to_store ();
393}
394
395static int
165a58fe 396hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
971429b4
AC
397 int dowrite, struct mem_attrib *attribs,
398 struct target_ops *target)
c906108c
SS
399{
400 int retval;
401 struct cleanup *old_chain;
402
39f77062 403 old_chain = save_inferior_ptid ();
c906108c 404
39f77062 405 inferior_ptid = main_ptid;
c906108c 406
971429b4
AC
407 retval =
408 child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
c906108c
SS
409
410 do_cleanups (old_chain);
411
412 return retval;
413}
414
415/* Print status information about what we're accessing. */
416
417static void
fba45db2 418hpux_thread_files_info (struct target_ops *ignore)
c906108c
SS
419{
420 child_ops.to_files_info (ignore);
421}
422
423static void
fba45db2 424hpux_thread_kill_inferior (void)
c906108c
SS
425{
426 child_ops.to_kill ();
427}
428
429static void
39f77062 430hpux_thread_notice_signals (ptid_t ptid)
c906108c 431{
39f77062 432 child_ops.to_notice_signals (ptid);
c906108c
SS
433}
434
435/* Fork an inferior process, and start debugging it with /proc. */
436
437static void
fba45db2 438hpux_thread_create_inferior (char *exec_file, char *allargs, char **env)
c906108c
SS
439{
440 child_ops.to_create_inferior (exec_file, allargs, env);
441
442 if (hpux_thread_active)
443 {
39f77062 444 main_ptid = inferior_ptid;
c906108c
SS
445
446 push_target (&hpux_thread_ops);
447
39f77062 448 inferior_ptid = find_active_thread ();
c906108c 449
39f77062 450 add_thread (inferior_ptid);
c906108c
SS
451 }
452}
453
454/* This routine is called whenever a new symbol table is read in, or when all
455 symbol tables are removed. libthread_db can only be initialized when it
456 finds the right variables in libthread.so. Since it's a shared library,
457 those variables don't show up until the library gets mapped and the symbol
458 table is read in. */
459
11cf8741
JM
460/* This new_objfile event is now managed by a chained function pointer.
461 * It is the callee's responsability to call the next client on the chain.
462 */
463
464/* Saved pointer to previous owner of the new_objfile event. */
507f3c78 465static void (*target_new_objfile_chain) (struct objfile *);
11cf8741 466
c906108c 467void
fba45db2 468hpux_thread_new_objfile (struct objfile *objfile)
c906108c
SS
469{
470 struct minimal_symbol *ms;
471
472 if (!objfile)
473 {
474 hpux_thread_active = 0;
11cf8741 475 goto quit;
c906108c
SS
476 }
477
478 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
479
480 if (!ms)
11cf8741 481 goto quit;
c906108c
SS
482
483 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
484
485 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
486
487 if (!ms)
11cf8741 488 goto quit;
c906108c
SS
489
490 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
491
492 hpux_thread_active = 1;
11cf8741
JM
493quit:
494 /* Call predecessor on chain, if any. */
495 if (target_new_objfile_chain)
496 target_new_objfile_chain (objfile);
c906108c
SS
497}
498
499/* Clean up after the inferior dies. */
500
501static void
fba45db2 502hpux_thread_mourn_inferior (void)
c906108c
SS
503{
504 child_ops.to_mourn_inferior ();
505}
506
507/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
508
509static int
fba45db2 510hpux_thread_can_run (void)
c906108c
SS
511{
512 return child_suppress_run;
513}
514
515static int
39f77062 516hpux_thread_alive (ptid_t ptid)
c906108c
SS
517{
518 return 1;
519}
520
521static void
fba45db2 522hpux_thread_stop (void)
c906108c
SS
523{
524 child_ops.to_stop ();
525}
526\f
527/* Convert a pid to printable form. */
528
529char *
39f77062 530hpux_pid_to_str (ptid_t ptid)
c906108c
SS
531{
532 static char buf[100];
39f77062 533 int pid = PIDGET (ptid);
c906108c
SS
534
535 sprintf (buf, "Thread %d", pid >> 16);
536
537 return buf;
538}
539\f
540static void
fba45db2 541init_hpux_thread_ops (void)
c906108c
SS
542{
543 hpux_thread_ops.to_shortname = "hpux-threads";
544 hpux_thread_ops.to_longname = "HPUX threads and pthread.";
545 hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
546 hpux_thread_ops.to_open = hpux_thread_open;
547 hpux_thread_ops.to_attach = hpux_thread_attach;
548 hpux_thread_ops.to_detach = hpux_thread_detach;
549 hpux_thread_ops.to_resume = hpux_thread_resume;
550 hpux_thread_ops.to_wait = hpux_thread_wait;
551 hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
552 hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
553 hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
554 hpux_thread_ops.to_xfer_memory = hpux_thread_xfer_memory;
555 hpux_thread_ops.to_files_info = hpux_thread_files_info;
556 hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
557 hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
558 hpux_thread_ops.to_terminal_init = terminal_init_inferior;
559 hpux_thread_ops.to_terminal_inferior = terminal_inferior;
560 hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
561 hpux_thread_ops.to_terminal_ours = terminal_ours;
562 hpux_thread_ops.to_terminal_info = child_terminal_info;
563 hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
564 hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
565 hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
566 hpux_thread_ops.to_can_run = hpux_thread_can_run;
567 hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
b83266a0 568 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
c906108c
SS
569 hpux_thread_ops.to_stop = hpux_thread_stop;
570 hpux_thread_ops.to_stratum = process_stratum;
571 hpux_thread_ops.to_has_all_memory = 1;
572 hpux_thread_ops.to_has_memory = 1;
573 hpux_thread_ops.to_has_stack = 1;
574 hpux_thread_ops.to_has_registers = 1;
575 hpux_thread_ops.to_has_execution = 1;
576 hpux_thread_ops.to_magic = OPS_MAGIC;
577}
578
579void
fba45db2 580_initialize_hpux_thread (void)
c906108c
SS
581{
582 init_hpux_thread_ops ();
583 add_target (&hpux_thread_ops);
584
585 child_suppress_run = 1;
11cf8741
JM
586 /* Hook into new_objfile notification. */
587 target_new_objfile_chain = target_new_objfile_hook;
588 target_new_objfile_hook = hpux_thread_new_objfile;
c906108c 589}
This page took 0.125763 seconds and 4 git commands to generate.