1/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU
2   debugger.
3
4   Copyright (C) 1996, 1998, 1999, 2000, 2001, 2004, 2007
5   Free Software Foundation, Inc.
6
7   This file is part of GDB.
8
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
11   the Free Software Foundation; either version 3 of the License, or
12   (at your option) any later version.
13
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.
18
19   You should have received a copy of the GNU General Public License
20   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
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
32 */
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"
43#include "regcache.h"
44#include <fcntl.h>
45#include <string.h>
46#include "gdb_stat.h"
47#include "gdbcore.h"
48#include "hppa-tdep.h"
49#include "observer.h"
50
51extern int child_suppress_run;
52
53extern void _initialize_hpux_thread (void);
54
55struct string_map
56  {
57    int num;
58    char *str;
59  };
60
61static int hpux_thread_active = 0;
62
63static ptid_t main_ptid;		/* Real process ID */
64
65static CORE_ADDR P_cma__g_known_threads;
66static CORE_ADDR P_cma__g_current_thread;
67
68static void hpux_thread_resume (ptid_t ptid, int step,
69                                enum target_signal signo);
70
71static void init_hpux_thread_ops (void);
72
73static struct target_ops hpux_thread_ops;
74
75static ptid_t find_active_thread (void);
76
77static int cached_thread;
78static cma__t_int_tcb cached_tcb;
79
80static ptid_t
81find_active_thread (void)
82{
83  static cma__t_int_tcb tcb;
84  CORE_ADDR tcb_ptr;
85
86  read_memory ((CORE_ADDR) P_cma__g_current_thread,
87	       (char *) &tcb_ptr,
88	       sizeof tcb_ptr);
89
90  read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
91
92  return (ptid_build (PIDGET (main_ptid), 0,
93                      cma_thread_get_unique (&tcb.prolog.client_thread)));
94}
95
96static cma__t_int_tcb *find_tcb (ptid_t ptid);
97
98static cma__t_int_tcb *
99find_tcb (ptid_t ptid)
100{
101  cma__t_known_object queue_header;
102  cma__t_queue *queue_ptr;
103  int thread = ptid_get_tid (ptid);
104
105  if (thread == cached_thread)
106    return &cached_tcb;
107
108  read_memory ((CORE_ADDR) P_cma__g_known_threads,
109	       (char *) &queue_header,
110	       sizeof queue_header);
111
112  for (queue_ptr = queue_header.queue.flink;
113       queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
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
120      read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
121
122      if (cached_tcb.header.type == cma__c_obj_tcb)
123	if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
124	  {
125	    cached_thread = thread;
126	    return &cached_tcb;
127	  }
128    }
129
130  error (_("Can't find TCB %d"), thread);
131  return NULL;
132}
133
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
137static void
138hpux_thread_open (char *arg, int from_tty)
139{
140  deprecated_child_ops.to_open (arg, from_tty);
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
147hpux_thread_attach (char *args, int from_tty)
148{
149  deprecated_child_ops.to_attach (args, from_tty);
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
163hpux_thread_detach (char *args, int from_tty)
164{
165  deprecated_child_ops.to_detach (args, from_tty);
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
174hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
175{
176  struct cleanup *old_chain;
177
178  old_chain = save_inferior_ptid ();
179
180  ptid = main_ptid;
181  inferior_ptid = main_ptid;
182
183#if 0
184  if (pid != -1)
185    {
186      pid = thread_to_lwp (pid, -2);
187      if (pid == -2)		/* Inactive thread */
188	error (_("This version of Solaris can't start inactive threads."));
189    }
190#endif
191
192  deprecated_child_ops.to_resume (ptid, step, signo);
193
194  cached_thread = 0;
195
196  do_cleanups (old_chain);
197}
198
199/* Wait for any threads to stop.  We may have to convert PID from a thread id
200   to a LWP id, and vice versa on the way out.  */
201
202static ptid_t
203hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
204{
205  ptid_t rtnval;
206  struct cleanup *old_chain;
207
208  old_chain = save_inferior_ptid ();
209
210  inferior_ptid = main_ptid;
211
212  if (!ptid_equal (ptid, minus_one_ptid))
213    ptid = main_ptid;
214
215  rtnval = deprecated_child_ops.to_wait (ptid, ourstatus);
216
217  rtnval = find_active_thread ();
218
219  do_cleanups (old_chain);
220
221  return rtnval;
222}
223
224static char regmap[] =
225{
226  -2, -1, -1, 0, 4, 8, 12, 16, 20, 24,	/* flags, r1 -> r9 */
227  28, 32, 36, 40, 44, 48, 52, 56, 60, -1,	/* r10 -> r19 */
228  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/* r20 -> r29 */
229
230  /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
231  -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
232
233  /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
234  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
235
236  /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
237  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
238
239  -1, -1, -1, -1,		/* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
240  144, -1, -1, -1, -1, -1, -1, -1,	/* fpsr, fpe1 -> fpe7 */
241  -1, -1, -1, -1, -1, -1, -1, -1,	/* fr4 -> fr7 */
242  -1, -1, -1, -1, -1, -1, -1, -1,	/* fr8 -> fr11 */
243  136, -1, 128, -1, 120, -1, 112, -1,	/* fr12 -> fr15 */
244  104, -1, 96, -1, 88, -1, 80, -1,	/* fr16 -> fr19 */
245  72, -1, 64, -1, -1, -1, -1, -1,	/* fr20 -> fr23 */
246  -1, -1, -1, -1, -1, -1, -1, -1,	/* fr24 -> fr27 */
247  -1, -1, -1, -1, -1, -1, -1, -1,	/* fr28 -> fr31 */
248};
249
250static void
251hpux_thread_fetch_registers (struct regcache *regcache, int regno)
252{
253  cma__t_int_tcb tcb, *tcb_ptr;
254  struct cleanup *old_chain;
255  int i;
256  int first_regno, last_regno;
257
258  tcb_ptr = find_tcb (inferior_ptid);
259
260  old_chain = save_inferior_ptid ();
261
262  inferior_ptid = main_ptid;
263
264  if (tcb_ptr->state == cma__c_state_running)
265    {
266      deprecated_child_ops.to_fetch_registers (regcache, regno);
267
268      do_cleanups (old_chain);
269
270      return;
271    }
272
273  if (regno == -1)
274    {
275      first_regno = 0;
276      last_regno = gdbarch_num_regs (current_gdbarch) - 1;
277    }
278  else
279    {
280      first_regno = regno;
281      last_regno = regno;
282    }
283
284  for (regno = first_regno; regno <= last_regno; regno++)
285    {
286      if (regmap[regno] == -1)
287	deprecated_child_ops.to_fetch_registers (regcache, regno);
288      else
289	{
290	  unsigned char buf[MAX_REGISTER_SIZE];
291	  CORE_ADDR sp;
292
293	  sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
294
295	  if (regno == HPPA_FLAGS_REGNUM)
296	    /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
297	    memset (buf, '\000', register_size (current_gdbarch, regno));
298	  else if (regno == HPPA_SP_REGNUM)
299	    store_unsigned_integer (buf, sizeof sp, sp);
300	  else if (regno == HPPA_PCOQ_HEAD_REGNUM)
301	    read_memory (sp - 20, buf, register_size (current_gdbarch, regno));
302	  else
303	    read_memory (sp + regmap[regno], buf, register_size (current_gdbarch, regno));
304
305	  regcache_raw_supply (regcache, regno, buf);
306	}
307    }
308
309  do_cleanups (old_chain);
310}
311
312static void
313hpux_thread_store_registers (struct regcache *regcache, int regno)
314{
315  cma__t_int_tcb tcb, *tcb_ptr;
316  struct cleanup *old_chain;
317  int i;
318  int first_regno, last_regno;
319
320  tcb_ptr = find_tcb (inferior_ptid);
321
322  old_chain = save_inferior_ptid ();
323
324  inferior_ptid = main_ptid;
325
326  if (tcb_ptr->state == cma__c_state_running)
327    {
328      deprecated_child_ops.to_store_registers (regcache, regno);
329
330      do_cleanups (old_chain);
331
332      return;
333    }
334
335  if (regno == -1)
336    {
337      first_regno = 0;
338      last_regno = gdbarch_num_regs (current_gdbarch) - 1;
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)
349	deprecated_child_ops.to_store_registers (regcache, regno);
350      else
351	{
352	  unsigned char buf[MAX_REGISTER_SIZE];
353	  CORE_ADDR sp;
354
355	  sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
356
357	  if (regno == HPPA_FLAGS_REGNUM)
358	    deprecated_child_ops.to_store_registers (regcache, regno);	/* Let lower layer handle this... */
359	  else if (regno == HPPA_SP_REGNUM)
360	    {
361	      regcache_raw_collect (regcache, regno, buf);
362	      write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
363			    register_size (current_gdbarch, regno));
364	      tcb_ptr->static_ctx.sp
365		= (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
366	    }
367	  else if (regno == HPPA_PCOQ_HEAD_REGNUM)
368	    {
369	      regcache_raw_collect (regcache, regno, buf);
370	      write_memory (sp - 20, buf,
371			    register_size (current_gdbarch, regno));
372	    }
373	  else
374	    {
375	      regcache_raw_collect (regcache, regno, buf);
376	      write_memory (sp + regmap[regno], buf,
377			    register_size (current_gdbarch, regno));
378	    }
379	}
380    }
381
382  do_cleanups (old_chain);
383}
384
385/* Get ready to modify the registers array.  On machines which store
386   individual registers, this doesn't need to do anything.  On machines
387   which store all the registers in one fell swoop, this makes sure
388   that registers contains all the registers from the program being
389   debugged.  */
390
391static void
392hpux_thread_prepare_to_store (struct regcache *regcache)
393{
394  deprecated_child_ops.to_prepare_to_store (regcache);
395}
396
397static int
398hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
399			 int dowrite, struct mem_attrib *attribs,
400			 struct target_ops *target)
401{
402  int retval;
403  struct cleanup *old_chain;
404
405  old_chain = save_inferior_ptid ();
406
407  inferior_ptid = main_ptid;
408
409  retval =
410    deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
411
412  do_cleanups (old_chain);
413
414  return retval;
415}
416
417/* Print status information about what we're accessing.  */
418
419static void
420hpux_thread_files_info (struct target_ops *ignore)
421{
422  deprecated_child_ops.to_files_info (ignore);
423}
424
425static void
426hpux_thread_kill_inferior (void)
427{
428  deprecated_child_ops.to_kill ();
429}
430
431static void
432hpux_thread_notice_signals (ptid_t ptid)
433{
434  deprecated_child_ops.to_notice_signals (ptid);
435}
436
437/* Fork an inferior process, and start debugging it with /proc.  */
438
439static void
440hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
441			     int from_tty)
442{
443  deprecated_child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
444
445  if (hpux_thread_active)
446    {
447      main_ptid = inferior_ptid;
448
449      push_target (&hpux_thread_ops);
450
451      inferior_ptid = find_active_thread ();
452
453      add_thread (inferior_ptid);
454    }
455}
456
457/* This routine is called whenever a new symbol table is read in, or when all
458   symbol tables are removed.  libthread_db can only be initialized when it
459   finds the right variables in libthread.so.  Since it's a shared library,
460   those variables don't show up until the library gets mapped and the symbol
461   table is read in.  */
462
463static void
464hpux_thread_new_objfile (struct objfile *objfile)
465{
466  struct minimal_symbol *ms;
467
468  if (!objfile)
469    {
470      hpux_thread_active = 0;
471      return;
472    }
473
474  ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
475
476  if (!ms)
477    return;
478
479  P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
480
481  ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
482
483  if (!ms)
484    return;
485
486  P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
487
488  hpux_thread_active = 1;
489}
490
491/* Clean up after the inferior dies.  */
492
493static void
494hpux_thread_mourn_inferior (void)
495{
496  deprecated_child_ops.to_mourn_inferior ();
497}
498
499/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
500
501static int
502hpux_thread_can_run (void)
503{
504  return child_suppress_run;
505}
506
507static int
508hpux_thread_alive (ptid_t ptid)
509{
510  return 1;
511}
512
513static void
514hpux_thread_stop (void)
515{
516  deprecated_child_ops.to_stop ();
517}
518
519/* Convert a pid to printable form. */
520
521char *
522hpux_pid_to_str (ptid_t ptid)
523{
524  static char buf[100];
525  int pid = PIDGET (ptid);
526
527  sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
528
529  return buf;
530}
531
532static void
533init_hpux_thread_ops (void)
534{
535  hpux_thread_ops.to_shortname = "hpux-threads";
536  hpux_thread_ops.to_longname = "HPUX threads and pthread.";
537  hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
538  hpux_thread_ops.to_open = hpux_thread_open;
539  hpux_thread_ops.to_attach = hpux_thread_attach;
540  hpux_thread_ops.to_detach = hpux_thread_detach;
541  hpux_thread_ops.to_resume = hpux_thread_resume;
542  hpux_thread_ops.to_wait = hpux_thread_wait;
543  hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
544  hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
545  hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
546  hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
547  hpux_thread_ops.to_files_info = hpux_thread_files_info;
548  hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
549  hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
550  hpux_thread_ops.to_terminal_init = terminal_init_inferior;
551  hpux_thread_ops.to_terminal_inferior = terminal_inferior;
552  hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
553  hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
554  hpux_thread_ops.to_terminal_ours = terminal_ours;
555  hpux_thread_ops.to_terminal_info = child_terminal_info;
556  hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
557  hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
558  hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
559  hpux_thread_ops.to_can_run = hpux_thread_can_run;
560  hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
561  hpux_thread_ops.to_thread_alive = hpux_thread_alive;
562  hpux_thread_ops.to_stop = hpux_thread_stop;
563  hpux_thread_ops.to_stratum = process_stratum;
564  hpux_thread_ops.to_has_all_memory = 1;
565  hpux_thread_ops.to_has_memory = 1;
566  hpux_thread_ops.to_has_stack = 1;
567  hpux_thread_ops.to_has_registers = 1;
568  hpux_thread_ops.to_has_execution = 1;
569  hpux_thread_ops.to_magic = OPS_MAGIC;
570}
571
572void
573_initialize_hpux_thread (void)
574{
575  init_hpux_thread_ops ();
576  add_target (&hpux_thread_ops);
577
578  child_suppress_run = 1;
579  /* Hook into new_objfile notification.  */
580  observer_attach_new_objfile (hpux_thread_new_objfile);
581}
582