*** empty log message ***
[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
4c38e0a4 4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2004, 2007, 2008, 2009, 2010
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
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
8a3fe4f8 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
c906108c 134static void
fba45db2 135hpux_thread_open (char *arg, int from_tty)
c906108c 136{
1df84f13 137 deprecated_child_ops.to_open (arg, from_tty);
c906108c
SS
138}
139
140/* Attach to process PID, then initialize for debugging it
141 and wait for the trace-trap that results from attaching. */
142
143static void
136d6dae 144hpux_thread_attach (struct target_ops *ops, char *args, int from_tty)
c906108c 145{
136d6dae 146 deprecated_child_ops.to_attach (&deprecated_child_ops, args, from_tty);
c906108c
SS
147
148 /* XXX - might want to iterate over all the threads and register them. */
149}
150
151/* Take a program previously attached to and detaches it.
152 The program resumes execution and will no longer stop
153 on signals, etc. We'd better not have left any breakpoints
154 in the program or it'll die when it hits one. For this
155 to work, it may be necessary for the process to have been
156 previously attached. It *might* work if the program was
157 started via the normal ptrace (PTRACE_TRACEME). */
158
159static void
136d6dae 160hpux_thread_detach (struct target_ops *ops, char *args, int from_tty)
c906108c 161{
136d6dae 162 deprecated_child_ops.to_detach (&deprecated_child_ops, args, from_tty);
c906108c
SS
163}
164
165/* Resume execution of process PID. If STEP is nozero, then
166 just single step it. If SIGNAL is nonzero, restart it with that
167 signal activated. We may have to convert pid from a thread-id to an LWP id
168 for procfs. */
169
170static void
28439f5e
PA
171hpux_thread_resume (struct target_ops *ops,
172 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 180
28439f5e 181 deprecated_child_ops.to_resume (&deprecated_child_ops, ptid, step, signo);
c906108c
SS
182
183 cached_thread = 0;
c906108c
SS
184
185 do_cleanups (old_chain);
186}
187
188/* Wait for any threads to stop. We may have to convert PID from a thread id
189 to a LWP id, and vice versa on the way out. */
190
39f77062 191static ptid_t
117de6a9 192hpux_thread_wait (struct target_ops *ops,
47608cb1 193 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
c906108c 194{
39f77062 195 ptid_t rtnval;
c906108c
SS
196 struct cleanup *old_chain;
197
39f77062 198 old_chain = save_inferior_ptid ();
c906108c 199
39f77062 200 inferior_ptid = main_ptid;
c906108c 201
39f77062
KB
202 if (!ptid_equal (ptid, minus_one_ptid))
203 ptid = main_ptid;
c906108c 204
117de6a9 205 rtnval = deprecated_child_ops.to_wait (&deprecated_child_ops,
47608cb1 206 ptid, ourstatus, options);
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
28439f5e
PA
242hpux_thread_fetch_registers (struct target_ops *ops,
243 struct regcache *regcache, int regno)
c906108c 244{
8d90747a 245 struct gdbarch *gdbarch = get_regcache_arch (regcache);
e17a4113 246 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
c906108c
SS
247 cma__t_int_tcb tcb, *tcb_ptr;
248 struct cleanup *old_chain;
249 int i;
250 int first_regno, last_regno;
251
f7926acf 252 tcb_ptr = find_tcb (inferior_ptid);
c906108c 253
39f77062 254 old_chain = save_inferior_ptid ();
c906108c 255
39f77062 256 inferior_ptid = main_ptid;
c906108c
SS
257
258 if (tcb_ptr->state == cma__c_state_running)
259 {
28439f5e
PA
260 deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
261 regcache, regno);
c906108c
SS
262
263 do_cleanups (old_chain);
264
265 return;
266 }
267
268 if (regno == -1)
269 {
270 first_regno = 0;
8d90747a 271 last_regno = gdbarch_num_regs (gdbarch) - 1;
c906108c
SS
272 }
273 else
274 {
275 first_regno = regno;
276 last_regno = regno;
277 }
278
279 for (regno = first_regno; regno <= last_regno; regno++)
280 {
281 if (regmap[regno] == -1)
28439f5e
PA
282 deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
283 regcache, regno);
c906108c
SS
284 else
285 {
123a958e 286 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
287 CORE_ADDR sp;
288
c5aa993b 289 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c 290
3f6306ec 291 if (regno == HPPA_FLAGS_REGNUM)
c906108c 292 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
8d90747a 293 memset (buf, '\000', register_size (gdbarch, regno));
3f6306ec 294 else if (regno == HPPA_SP_REGNUM)
e17a4113 295 store_unsigned_integer (buf, sizeof sp, byte_order, sp);
3f6306ec 296 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
8d90747a 297 read_memory (sp - 20, buf, register_size (gdbarch, regno));
c906108c 298 else
8d90747a
UW
299 read_memory (sp + regmap[regno], buf,
300 register_size (gdbarch, regno));
c906108c 301
56be3814 302 regcache_raw_supply (regcache, regno, buf);
c906108c
SS
303 }
304 }
305
306 do_cleanups (old_chain);
307}
308
309static void
28439f5e
PA
310hpux_thread_store_registers (struct target_ops *ops,
311 struct regcache *regcache, int regno)
c906108c 312{
8d90747a 313 struct gdbarch *gdbarch = get_regcache_arch (regcache);
c906108c
SS
314 cma__t_int_tcb tcb, *tcb_ptr;
315 struct cleanup *old_chain;
316 int i;
317 int first_regno, last_regno;
318
f7926acf 319 tcb_ptr = find_tcb (inferior_ptid);
c906108c 320
39f77062 321 old_chain = save_inferior_ptid ();
c906108c 322
39f77062 323 inferior_ptid = main_ptid;
c906108c
SS
324
325 if (tcb_ptr->state == cma__c_state_running)
326 {
28439f5e
PA
327 deprecated_child_ops.to_store_registers (&deprecated_child_ops,
328 regcache, regno);
c906108c
SS
329
330 do_cleanups (old_chain);
331
332 return;
333 }
334
335 if (regno == -1)
336 {
337 first_regno = 0;
8d90747a 338 last_regno = gdbarch_num_regs (gdbarch) - 1;
c906108c
SS
339 }
340 else
341 {
342 first_regno = regno;
343 last_regno = regno;
344 }
345
346 for (regno = first_regno; regno <= last_regno; regno++)
347 {
348 if (regmap[regno] == -1)
56be3814 349 deprecated_child_ops.to_store_registers (regcache, regno);
c906108c
SS
350 else
351 {
123a958e 352 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
353 CORE_ADDR sp;
354
c5aa993b 355 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c 356
3f6306ec 357 if (regno == HPPA_FLAGS_REGNUM)
28439f5e
PA
358 {
359 /* Let lower layer handle this... */
360 deprecated_child_ops.to_store_registers
361 (&deprecated_child_ops, regcache, regno);
362 }
3f6306ec 363 else if (regno == HPPA_SP_REGNUM)
c906108c 364 {
56be3814 365 regcache_raw_collect (regcache, regno, buf);
3f6306ec 366 write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
8d90747a 367 register_size (gdbarch, regno));
3f6306ec
DA
368 tcb_ptr->static_ctx.sp
369 = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
370 }
371 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
372 {
56be3814 373 regcache_raw_collect (regcache, regno, buf);
3f6306ec 374 write_memory (sp - 20, buf,
8d90747a 375 register_size (gdbarch, regno));
c906108c 376 }
c906108c 377 else
3f6306ec 378 {
56be3814 379 regcache_raw_collect (regcache, regno, buf);
3f6306ec 380 write_memory (sp + regmap[regno], buf,
8d90747a 381 register_size (gdbarch, regno));
3f6306ec 382 }
c906108c
SS
383 }
384 }
385
386 do_cleanups (old_chain);
387}
388
389/* Get ready to modify the registers array. On machines which store
390 individual registers, this doesn't need to do anything. On machines
391 which store all the registers in one fell swoop, this makes sure
392 that registers contains all the registers from the program being
393 debugged. */
394
395static void
316f2060 396hpux_thread_prepare_to_store (struct regcache *regcache)
c906108c 397{
316f2060 398 deprecated_child_ops.to_prepare_to_store (regcache);
c906108c
SS
399}
400
401static int
165a58fe 402hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
971429b4
AC
403 int dowrite, struct mem_attrib *attribs,
404 struct target_ops *target)
c906108c
SS
405{
406 int retval;
407 struct cleanup *old_chain;
408
39f77062 409 old_chain = save_inferior_ptid ();
c906108c 410
39f77062 411 inferior_ptid = main_ptid;
c906108c 412
971429b4 413 retval =
c8e73a31 414 deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
c906108c
SS
415
416 do_cleanups (old_chain);
417
418 return retval;
419}
420
421/* Print status information about what we're accessing. */
422
423static void
fba45db2 424hpux_thread_files_info (struct target_ops *ignore)
c906108c 425{
1df84f13 426 deprecated_child_ops.to_files_info (ignore);
c906108c
SS
427}
428
429static void
7d85a9c0 430hpux_thread_kill_inferior (struct target_ops *ops)
c906108c 431{
7d85a9c0 432 deprecated_child_ops.to_kill (&deprecated_child_ops);
c906108c
SS
433}
434
435static void
39f77062 436hpux_thread_notice_signals (ptid_t ptid)
c906108c 437{
1df84f13 438 deprecated_child_ops.to_notice_signals (ptid);
c906108c
SS
439}
440
441/* Fork an inferior process, and start debugging it with /proc. */
442
443static void
136d6dae
VP
444hpux_thread_create_inferior (struct target_ops *ops, char *exec_file,
445 char *allargs, char **env, int from_tty)
c906108c 446{
136d6dae
VP
447 deprecated_child_ops.to_create_inferior (&deprecated_child_ops,
448 exec_file, allargs, env, from_tty);
c906108c
SS
449
450 if (hpux_thread_active)
451 {
39f77062 452 main_ptid = inferior_ptid;
c906108c
SS
453
454 push_target (&hpux_thread_ops);
455
39f77062 456 inferior_ptid = find_active_thread ();
c906108c 457
39f77062 458 add_thread (inferior_ptid);
c906108c
SS
459 }
460}
461
462/* This routine is called whenever a new symbol table is read in, or when all
463 symbol tables are removed. libthread_db can only be initialized when it
464 finds the right variables in libthread.so. Since it's a shared library,
465 those variables don't show up until the library gets mapped and the symbol
466 table is read in. */
467
06d3b283 468static void
fba45db2 469hpux_thread_new_objfile (struct objfile *objfile)
c906108c
SS
470{
471 struct minimal_symbol *ms;
472
473 if (!objfile)
474 {
475 hpux_thread_active = 0;
06d3b283 476 return;
c906108c
SS
477 }
478
479 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
480
481 if (!ms)
06d3b283 482 return;
c906108c
SS
483
484 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
485
486 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
487
488 if (!ms)
06d3b283 489 return;
c906108c
SS
490
491 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
492
493 hpux_thread_active = 1;
494}
495
496/* Clean up after the inferior dies. */
497
498static void
fba45db2 499hpux_thread_mourn_inferior (void)
c906108c 500{
136d6dae 501 deprecated_child_ops.to_mourn_inferior (&deprecated_child_ops);
c906108c
SS
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
28439f5e 513hpux_thread_alive (struct target_ops *ops, ptid_t ptid)
c906108c
SS
514{
515 return 1;
516}
517
518static void
f9c72d52 519hpux_thread_stop (ptid_t ptid)
c906108c 520{
f9c72d52 521 deprecated_child_ops.to_stop (ptid);
c906108c
SS
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;
c8e73a31 551 hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
c906108c
SS
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;
c35b1492
PA
569 hpux_thread_ops.to_has_all_memory = default_child_has_all_memory;
570 hpux_thread_ops.to_has_memory = default_child_has_memory;
571 hpux_thread_ops.to_has_stack = default_child_has_stack;
572 hpux_thread_ops.to_has_registers = default_child_has_registers;
573 hpux_thread_ops.to_has_execution = default_child_has_execution;
c906108c
SS
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;
d9788fe8 584 /* Hook into new_objfile notification. */
06d3b283 585 observer_attach_new_objfile (hpux_thread_new_objfile);
c906108c 586}
This page took 0.770041 seconds and 4 git commands to generate.