Fix up some formatting.
[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
0fb0cc75 4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2004, 2007, 2008, 2009
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
136d6dae 147hpux_thread_attach (struct target_ops *ops, char *args, int from_tty)
c906108c 148{
136d6dae 149 deprecated_child_ops.to_attach (&deprecated_child_ops, 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
136d6dae 163hpux_thread_detach (struct target_ops *ops, char *args, int from_tty)
c906108c 164{
136d6dae 165 deprecated_child_ops.to_detach (&deprecated_child_ops, 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 193static ptid_t
117de6a9
PA
194hpux_thread_wait (struct target_ops *ops,
195 ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c 196{
39f77062 197 ptid_t rtnval;
c906108c
SS
198 struct cleanup *old_chain;
199
39f77062 200 old_chain = save_inferior_ptid ();
c906108c 201
39f77062 202 inferior_ptid = main_ptid;
c906108c 203
39f77062
KB
204 if (!ptid_equal (ptid, minus_one_ptid))
205 ptid = main_ptid;
c906108c 206
117de6a9
PA
207 rtnval = deprecated_child_ops.to_wait (&deprecated_child_ops,
208 ptid, ourstatus);
c906108c
SS
209
210 rtnval = find_active_thread ();
211
212 do_cleanups (old_chain);
213
214 return rtnval;
215}
216
3f6306ec 217static char regmap[] =
c906108c 218{
c5aa993b
JM
219 -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
220 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
221 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
c906108c
SS
222
223 /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
224 -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
225
226 /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
227 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
228
229 /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
230 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
231
232 -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
c5aa993b
JM
233 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
234 -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
235 -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
236 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
237 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
238 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
239 -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
240 -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
c906108c
SS
241};
242
243static void
56be3814 244hpux_thread_fetch_registers (struct regcache *regcache, int regno)
c906108c 245{
8d90747a 246 struct gdbarch *gdbarch = get_regcache_arch (regcache);
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 {
56be3814 260 deprecated_child_ops.to_fetch_registers (regcache, regno);
c906108c
SS
261
262 do_cleanups (old_chain);
263
264 return;
265 }
266
267 if (regno == -1)
268 {
269 first_regno = 0;
8d90747a 270 last_regno = gdbarch_num_regs (gdbarch) - 1;
c906108c
SS
271 }
272 else
273 {
274 first_regno = regno;
275 last_regno = regno;
276 }
277
278 for (regno = first_regno; regno <= last_regno; regno++)
279 {
280 if (regmap[regno] == -1)
56be3814 281 deprecated_child_ops.to_fetch_registers (regcache, regno);
c906108c
SS
282 else
283 {
123a958e 284 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
285 CORE_ADDR sp;
286
c5aa993b 287 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c 288
3f6306ec 289 if (regno == HPPA_FLAGS_REGNUM)
c906108c 290 /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
8d90747a 291 memset (buf, '\000', register_size (gdbarch, regno));
3f6306ec 292 else if (regno == HPPA_SP_REGNUM)
fbd9dcd3 293 store_unsigned_integer (buf, sizeof sp, sp);
3f6306ec 294 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
8d90747a 295 read_memory (sp - 20, buf, register_size (gdbarch, regno));
c906108c 296 else
8d90747a
UW
297 read_memory (sp + regmap[regno], buf,
298 register_size (gdbarch, regno));
c906108c 299
56be3814 300 regcache_raw_supply (regcache, regno, buf);
c906108c
SS
301 }
302 }
303
304 do_cleanups (old_chain);
305}
306
307static void
56be3814 308hpux_thread_store_registers (struct regcache *regcache, int regno)
c906108c 309{
8d90747a 310 struct gdbarch *gdbarch = get_regcache_arch (regcache);
c906108c
SS
311 cma__t_int_tcb tcb, *tcb_ptr;
312 struct cleanup *old_chain;
313 int i;
314 int first_regno, last_regno;
315
f7926acf 316 tcb_ptr = find_tcb (inferior_ptid);
c906108c 317
39f77062 318 old_chain = save_inferior_ptid ();
c906108c 319
39f77062 320 inferior_ptid = main_ptid;
c906108c
SS
321
322 if (tcb_ptr->state == cma__c_state_running)
323 {
56be3814 324 deprecated_child_ops.to_store_registers (regcache, regno);
c906108c
SS
325
326 do_cleanups (old_chain);
327
328 return;
329 }
330
331 if (regno == -1)
332 {
333 first_regno = 0;
8d90747a 334 last_regno = gdbarch_num_regs (gdbarch) - 1;
c906108c
SS
335 }
336 else
337 {
338 first_regno = regno;
339 last_regno = regno;
340 }
341
342 for (regno = first_regno; regno <= last_regno; regno++)
343 {
344 if (regmap[regno] == -1)
56be3814 345 deprecated_child_ops.to_store_registers (regcache, regno);
c906108c
SS
346 else
347 {
123a958e 348 unsigned char buf[MAX_REGISTER_SIZE];
c906108c
SS
349 CORE_ADDR sp;
350
c5aa993b 351 sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
c906108c 352
3f6306ec 353 if (regno == HPPA_FLAGS_REGNUM)
56be3814 354 deprecated_child_ops.to_store_registers (regcache, regno); /* Let lower layer handle this... */
3f6306ec 355 else if (regno == HPPA_SP_REGNUM)
c906108c 356 {
56be3814 357 regcache_raw_collect (regcache, regno, buf);
3f6306ec 358 write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
8d90747a 359 register_size (gdbarch, regno));
3f6306ec
DA
360 tcb_ptr->static_ctx.sp
361 = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
362 }
363 else if (regno == HPPA_PCOQ_HEAD_REGNUM)
364 {
56be3814 365 regcache_raw_collect (regcache, regno, buf);
3f6306ec 366 write_memory (sp - 20, buf,
8d90747a 367 register_size (gdbarch, regno));
c906108c 368 }
c906108c 369 else
3f6306ec 370 {
56be3814 371 regcache_raw_collect (regcache, regno, buf);
3f6306ec 372 write_memory (sp + regmap[regno], buf,
8d90747a 373 register_size (gdbarch, regno));
3f6306ec 374 }
c906108c
SS
375 }
376 }
377
378 do_cleanups (old_chain);
379}
380
381/* Get ready to modify the registers array. On machines which store
382 individual registers, this doesn't need to do anything. On machines
383 which store all the registers in one fell swoop, this makes sure
384 that registers contains all the registers from the program being
385 debugged. */
386
387static void
316f2060 388hpux_thread_prepare_to_store (struct regcache *regcache)
c906108c 389{
316f2060 390 deprecated_child_ops.to_prepare_to_store (regcache);
c906108c
SS
391}
392
393static int
165a58fe 394hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
971429b4
AC
395 int dowrite, struct mem_attrib *attribs,
396 struct target_ops *target)
c906108c
SS
397{
398 int retval;
399 struct cleanup *old_chain;
400
39f77062 401 old_chain = save_inferior_ptid ();
c906108c 402
39f77062 403 inferior_ptid = main_ptid;
c906108c 404
971429b4 405 retval =
c8e73a31 406 deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
c906108c
SS
407
408 do_cleanups (old_chain);
409
410 return retval;
411}
412
413/* Print status information about what we're accessing. */
414
415static void
fba45db2 416hpux_thread_files_info (struct target_ops *ignore)
c906108c 417{
1df84f13 418 deprecated_child_ops.to_files_info (ignore);
c906108c
SS
419}
420
421static void
fba45db2 422hpux_thread_kill_inferior (void)
c906108c 423{
1df84f13 424 deprecated_child_ops.to_kill ();
c906108c
SS
425}
426
427static void
39f77062 428hpux_thread_notice_signals (ptid_t ptid)
c906108c 429{
1df84f13 430 deprecated_child_ops.to_notice_signals (ptid);
c906108c
SS
431}
432
433/* Fork an inferior process, and start debugging it with /proc. */
434
435static void
136d6dae
VP
436hpux_thread_create_inferior (struct target_ops *ops, char *exec_file,
437 char *allargs, char **env, int from_tty)
c906108c 438{
136d6dae
VP
439 deprecated_child_ops.to_create_inferior (&deprecated_child_ops,
440 exec_file, allargs, env, from_tty);
c906108c
SS
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
06d3b283 460static void
fba45db2 461hpux_thread_new_objfile (struct objfile *objfile)
c906108c
SS
462{
463 struct minimal_symbol *ms;
464
465 if (!objfile)
466 {
467 hpux_thread_active = 0;
06d3b283 468 return;
c906108c
SS
469 }
470
471 ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
472
473 if (!ms)
06d3b283 474 return;
c906108c
SS
475
476 P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
477
478 ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
479
480 if (!ms)
06d3b283 481 return;
c906108c
SS
482
483 P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
484
485 hpux_thread_active = 1;
486}
487
488/* Clean up after the inferior dies. */
489
490static void
fba45db2 491hpux_thread_mourn_inferior (void)
c906108c 492{
136d6dae 493 deprecated_child_ops.to_mourn_inferior (&deprecated_child_ops);
c906108c
SS
494}
495
496/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
497
498static int
fba45db2 499hpux_thread_can_run (void)
c906108c
SS
500{
501 return child_suppress_run;
502}
503
504static int
39f77062 505hpux_thread_alive (ptid_t ptid)
c906108c
SS
506{
507 return 1;
508}
509
510static void
f9c72d52 511hpux_thread_stop (ptid_t ptid)
c906108c 512{
f9c72d52 513 deprecated_child_ops.to_stop (ptid);
c906108c
SS
514}
515\f
516/* Convert a pid to printable form. */
517
518char *
39f77062 519hpux_pid_to_str (ptid_t ptid)
c906108c
SS
520{
521 static char buf[100];
39f77062 522 int pid = PIDGET (ptid);
c906108c 523
f7926acf 524 sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
c906108c
SS
525
526 return buf;
527}
528\f
529static void
fba45db2 530init_hpux_thread_ops (void)
c906108c
SS
531{
532 hpux_thread_ops.to_shortname = "hpux-threads";
533 hpux_thread_ops.to_longname = "HPUX threads and pthread.";
534 hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
535 hpux_thread_ops.to_open = hpux_thread_open;
536 hpux_thread_ops.to_attach = hpux_thread_attach;
537 hpux_thread_ops.to_detach = hpux_thread_detach;
538 hpux_thread_ops.to_resume = hpux_thread_resume;
539 hpux_thread_ops.to_wait = hpux_thread_wait;
540 hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
541 hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
542 hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
c8e73a31 543 hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
c906108c
SS
544 hpux_thread_ops.to_files_info = hpux_thread_files_info;
545 hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
546 hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
547 hpux_thread_ops.to_terminal_init = terminal_init_inferior;
548 hpux_thread_ops.to_terminal_inferior = terminal_inferior;
549 hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
a790ad35 550 hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
c906108c
SS
551 hpux_thread_ops.to_terminal_ours = terminal_ours;
552 hpux_thread_ops.to_terminal_info = child_terminal_info;
553 hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
554 hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
555 hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
556 hpux_thread_ops.to_can_run = hpux_thread_can_run;
557 hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
b83266a0 558 hpux_thread_ops.to_thread_alive = hpux_thread_alive;
c906108c
SS
559 hpux_thread_ops.to_stop = hpux_thread_stop;
560 hpux_thread_ops.to_stratum = process_stratum;
561 hpux_thread_ops.to_has_all_memory = 1;
562 hpux_thread_ops.to_has_memory = 1;
563 hpux_thread_ops.to_has_stack = 1;
564 hpux_thread_ops.to_has_registers = 1;
565 hpux_thread_ops.to_has_execution = 1;
566 hpux_thread_ops.to_magic = OPS_MAGIC;
567}
568
569void
fba45db2 570_initialize_hpux_thread (void)
c906108c
SS
571{
572 init_hpux_thread_ops ();
573 add_target (&hpux_thread_ops);
574
575 child_suppress_run = 1;
d9788fe8 576 /* Hook into new_objfile notification. */
06d3b283 577 observer_attach_new_objfile (hpux_thread_new_objfile);
c906108c 578}
This page took 0.653376 seconds and 4 git commands to generate.