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