1/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU
2   debugger.
3
4   Copyright 1996, 1998, 1999, 2000, 2001, 2004 Free Software
5   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 2 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, write to the Free Software
21   Foundation, Inc., 59 Temple Place - Suite 330,
22   Boston, MA 02111-1307, USA.  */
23
24/* This module implements a sort of half target that sits between the
25   machine-independent parts of GDB and the ptrace interface (infptrace.c) to
26   provide access to the HPUX user-mode thread implementation.
27
28   HPUX threads are true user-mode threads, which are invoked via the cma_*
29   and pthread_* (DCE and Posix respectivly) interfaces.  These are mostly
30   implemented in user-space, with all thread context kept in various
31   structures that live in the user's heap.  For the most part, the kernel has
32   no knowlege of these threads.
33
34 */
35
36#include "defs.h"
37
38#define _CMA_NOWRAPPERS_
39
40#include <cma_tcb_defs.h>
41#include <cma_deb_core.h>
42#include "gdbthread.h"
43#include "target.h"
44#include "inferior.h"
45#include "regcache.h"
46#include <fcntl.h>
47#include "gdb_stat.h"
48#include "gdbcore.h"
49
50extern int child_suppress_run;
51
52extern void _initialize_hpux_thread (void);
53
54struct string_map
55  {
56    int num;
57    char *str;
58  };
59
60static int hpux_thread_active = 0;
61
62static ptid_t main_ptid;		/* Real process ID */
63
64static CORE_ADDR P_cma__g_known_threads;
65static CORE_ADDR P_cma__g_current_thread;
66
67static void hpux_thread_resume (ptid_t ptid, int step,
68                                enum target_signal signo);
69
70static void init_hpux_thread_ops (void);
71
72static struct target_ops hpux_thread_ops;
73
74static ptid_t find_active_thread (void);
75
76static int cached_thread;
77static cma__t_int_tcb cached_tcb;
78
79static ptid_t
80find_active_thread (void)
81{
82  static cma__t_int_tcb tcb;
83  CORE_ADDR tcb_ptr;
84
85  read_memory ((CORE_ADDR) P_cma__g_current_thread,
86	       (char *) &tcb_ptr,
87	       sizeof tcb_ptr);
88
89  read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
90
91  return (ptid_build (PIDGET (main_ptid), 0,
92                      cma_thread_get_unique (&tcb.prolog.client_thread)));
93}
94
95static cma__t_int_tcb *find_tcb (ptid_t ptid);
96
97static cma__t_int_tcb *
98find_tcb (ptid_t ptid)
99{
100  cma__t_known_object queue_header;
101  cma__t_queue *queue_ptr;
102  int thread = ptid_get_tid (ptid);
103
104  if (thread == cached_thread)
105    return &cached_tcb;
106
107  read_memory ((CORE_ADDR) P_cma__g_known_threads,
108	       (char *) &queue_header,
109	       sizeof queue_header);
110
111  for (queue_ptr = queue_header.queue.flink;
112       queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
113       queue_ptr = cached_tcb.threads.flink)
114    {
115      cma__t_int_tcb *tcb_ptr;
116
117      tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
118
119      read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
120
121      if (cached_tcb.header.type == cma__c_obj_tcb)
122	if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread)
123	  {
124	    cached_thread = thread;
125	    return &cached_tcb;
126	  }
127    }
128
129  error ("Can't find TCB %d", thread);
130  return NULL;
131}
132
133/* Most target vector functions from here on actually just pass through to
134   inftarg.c, as they don't need to do anything specific for threads.  */
135
136static void
137hpux_thread_open (char *arg, int from_tty)
138{
139  deprecated_child_ops.to_open (arg, from_tty);
140}
141
142/* Attach to process PID, then initialize for debugging it
143   and wait for the trace-trap that results from attaching.  */
144
145static void
146hpux_thread_attach (char *args, int from_tty)
147{
148  deprecated_child_ops.to_attach (args, from_tty);
149
150  /* XXX - might want to iterate over all the threads and register them. */
151}
152
153/* Take a program previously attached to and detaches it.
154   The program resumes execution and will no longer stop
155   on signals, etc.  We'd better not have left any breakpoints
156   in the program or it'll die when it hits one.  For this
157   to work, it may be necessary for the process to have been
158   previously attached.  It *might* work if the program was
159   started via the normal ptrace (PTRACE_TRACEME).  */
160
161static void
162hpux_thread_detach (char *args, int from_tty)
163{
164  deprecated_child_ops.to_detach (args, from_tty);
165}
166
167/* Resume execution of process PID.  If STEP is nozero, then
168   just single step it.  If SIGNAL is nonzero, restart it with that
169   signal activated.  We may have to convert pid from a thread-id to an LWP id
170   for procfs.  */
171
172static void
173hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
174{
175  struct cleanup *old_chain;
176
177  old_chain = save_inferior_ptid ();
178
179  ptid = main_ptid;
180  inferior_ptid = main_ptid;
181
182#if 0
183  if (pid != -1)
184    {
185      pid = thread_to_lwp (pid, -2);
186      if (pid == -2)		/* Inactive thread */
187	error ("This version of Solaris can't start inactive threads.");
188    }
189#endif
190
191  deprecated_child_ops.to_resume (ptid, step, signo);
192
193  cached_thread = 0;
194
195  do_cleanups (old_chain);
196}
197
198/* Wait for any threads to stop.  We may have to convert PID from a thread id
199   to a LWP id, and vice versa on the way out.  */
200
201static ptid_t
202hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
203{
204  ptid_t rtnval;
205  struct cleanup *old_chain;
206
207  old_chain = save_inferior_ptid ();
208
209  inferior_ptid = main_ptid;
210
211  if (!ptid_equal (ptid, minus_one_ptid))
212    ptid = main_ptid;
213
214  rtnval = deprecated_child_ops.to_wait (ptid, ourstatus);
215
216  rtnval = find_active_thread ();
217
218  do_cleanups (old_chain);
219
220  return rtnval;
221}
222
223static char regmap[NUM_REGS] =
224{
225  -2, -1, -1, 0, 4, 8, 12, 16, 20, 24,	/* flags, r1 -> r9 */
226  28, 32, 36, 40, 44, 48, 52, 56, 60, -1,	/* r10 -> r19 */
227  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/* r20 -> r29 */
228
229  /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
230  -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
231
232  /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
233  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
234
235  /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
236  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
237
238  -1, -1, -1, -1,		/* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
239  144, -1, -1, -1, -1, -1, -1, -1,	/* fpsr, fpe1 -> fpe7 */
240  -1, -1, -1, -1, -1, -1, -1, -1,	/* fr4 -> fr7 */
241  -1, -1, -1, -1, -1, -1, -1, -1,	/* fr8 -> fr11 */
242  136, -1, 128, -1, 120, -1, 112, -1,	/* fr12 -> fr15 */
243  104, -1, 96, -1, 88, -1, 80, -1,	/* fr16 -> fr19 */
244  72, -1, 64, -1, -1, -1, -1, -1,	/* fr20 -> fr23 */
245  -1, -1, -1, -1, -1, -1, -1, -1,	/* fr24 -> fr27 */
246  -1, -1, -1, -1, -1, -1, -1, -1,	/* fr28 -> fr31 */
247};
248
249static void
250hpux_thread_fetch_registers (int regno)
251{
252  cma__t_int_tcb tcb, *tcb_ptr;
253  struct cleanup *old_chain;
254  int i;
255  int first_regno, last_regno;
256
257  tcb_ptr = find_tcb (inferior_ptid);
258
259  old_chain = save_inferior_ptid ();
260
261  inferior_ptid = main_ptid;
262
263  if (tcb_ptr->state == cma__c_state_running)
264    {
265      deprecated_child_ops.to_fetch_registers (regno);
266
267      do_cleanups (old_chain);
268
269      return;
270    }
271
272  if (regno == -1)
273    {
274      first_regno = 0;
275      last_regno = NUM_REGS - 1;
276    }
277  else
278    {
279      first_regno = regno;
280      last_regno = regno;
281    }
282
283  for (regno = first_regno; regno <= last_regno; regno++)
284    {
285      if (regmap[regno] == -1)
286	deprecated_child_ops.to_fetch_registers (regno);
287      else
288	{
289	  unsigned char buf[MAX_REGISTER_SIZE];
290	  CORE_ADDR sp;
291
292	  sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
293
294	  if (regno == FLAGS_REGNUM)
295	    /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
296	    memset (buf, '\000', register_size (current_gdbarch, regno));
297	  else if (regno == SP_REGNUM)
298	    store_unsigned_integer (buf, sizeof sp, sp);
299	  else if (regno == PC_REGNUM)
300	    read_memory (sp - 20, buf, register_size (current_gdbarch, regno));
301	  else
302	    read_memory (sp + regmap[regno], buf, register_size (current_gdbarch, regno));
303
304	  regcache_raw_supply (current_regcache, regno, buf);
305	}
306    }
307
308  do_cleanups (old_chain);
309}
310
311static void
312hpux_thread_store_registers (int regno)
313{
314  cma__t_int_tcb tcb, *tcb_ptr;
315  struct cleanup *old_chain;
316  int i;
317  int first_regno, last_regno;
318
319  tcb_ptr = find_tcb (inferior_ptid);
320
321  old_chain = save_inferior_ptid ();
322
323  inferior_ptid = main_ptid;
324
325  if (tcb_ptr->state == cma__c_state_running)
326    {
327      deprecated_child_ops.to_store_registers (regno);
328
329      do_cleanups (old_chain);
330
331      return;
332    }
333
334  if (regno == -1)
335    {
336      first_regno = 0;
337      last_regno = NUM_REGS - 1;
338    }
339  else
340    {
341      first_regno = regno;
342      last_regno = regno;
343    }
344
345  for (regno = first_regno; regno <= last_regno; regno++)
346    {
347      if (regmap[regno] == -1)
348	deprecated_child_ops.to_store_registers (regno);
349      else
350	{
351	  unsigned char buf[MAX_REGISTER_SIZE];
352	  CORE_ADDR sp;
353
354	  sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
355
356	  if (regno == FLAGS_REGNUM)
357	    deprecated_child_ops.to_store_registers (regno);	/* Let lower layer handle this... */
358	  else if (regno == SP_REGNUM)
359	    {
360	      write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
361			    &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
362			    register_size (current_gdbarch, regno));
363	      tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
364		(extract_unsigned_integer (&deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
365					   register_size (current_gdbarch, regno)) + 160);
366	    }
367	  else if (regno == PC_REGNUM)
368	    write_memory (sp - 20,
369			  &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
370			  register_size (current_gdbarch, regno));
371	  else
372	    write_memory (sp + regmap[regno],
373			  &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],
374			  register_size (current_gdbarch, regno));
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
388hpux_thread_prepare_to_store (void)
389{
390  deprecated_child_ops.to_prepare_to_store ();
391}
392
393static int
394hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
395			 int dowrite, struct mem_attrib *attribs,
396			 struct target_ops *target)
397{
398  int retval;
399  struct cleanup *old_chain;
400
401  old_chain = save_inferior_ptid ();
402
403  inferior_ptid = main_ptid;
404
405  retval =
406    deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
407
408  do_cleanups (old_chain);
409
410  return retval;
411}
412
413/* Print status information about what we're accessing.  */
414
415static void
416hpux_thread_files_info (struct target_ops *ignore)
417{
418  deprecated_child_ops.to_files_info (ignore);
419}
420
421static void
422hpux_thread_kill_inferior (void)
423{
424  deprecated_child_ops.to_kill ();
425}
426
427static void
428hpux_thread_notice_signals (ptid_t ptid)
429{
430  deprecated_child_ops.to_notice_signals (ptid);
431}
432
433/* Fork an inferior process, and start debugging it with /proc.  */
434
435static void
436hpux_thread_create_inferior (char *exec_file, char *allargs, char **env,
437			     int from_tty)
438{
439  deprecated_child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
440
441  if (hpux_thread_active)
442    {
443      main_ptid = inferior_ptid;
444
445      push_target (&hpux_thread_ops);
446
447      inferior_ptid = find_active_thread ();
448
449      add_thread (inferior_ptid);
450    }
451}
452
453/* This routine is called whenever a new symbol table is read in, or when all
454   symbol tables are removed.  libthread_db can only be initialized when it
455   finds the right variables in libthread.so.  Since it's a shared library,
456   those variables don't show up until the library gets mapped and the symbol
457   table is read in.  */
458
459/* This new_objfile event is now managed by a chained function pointer.
460 * It is the callee's responsability to call the next client on the chain.
461 */
462
463/* Saved pointer to previous owner of the new_objfile event. */
464static void (*target_new_objfile_chain) (struct objfile *);
465
466void
467hpux_thread_new_objfile (struct objfile *objfile)
468{
469  struct minimal_symbol *ms;
470
471  if (!objfile)
472    {
473      hpux_thread_active = 0;
474      goto quit;
475    }
476
477  ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
478
479  if (!ms)
480    goto quit;
481
482  P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
483
484  ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
485
486  if (!ms)
487    goto quit;
488
489  P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
490
491  hpux_thread_active = 1;
492quit:
493  /* Call predecessor on chain, if any. */
494  if (target_new_objfile_chain)
495    target_new_objfile_chain (objfile);
496}
497
498/* Clean up after the inferior dies.  */
499
500static void
501hpux_thread_mourn_inferior (void)
502{
503  deprecated_child_ops.to_mourn_inferior ();
504}
505
506/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
507
508static int
509hpux_thread_can_run (void)
510{
511  return child_suppress_run;
512}
513
514static int
515hpux_thread_alive (ptid_t ptid)
516{
517  return 1;
518}
519
520static void
521hpux_thread_stop (void)
522{
523  deprecated_child_ops.to_stop ();
524}
525
526/* Convert a pid to printable form. */
527
528char *
529hpux_pid_to_str (ptid_t ptid)
530{
531  static char buf[100];
532  int pid = PIDGET (ptid);
533
534  sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
535
536  return buf;
537}
538
539static void
540init_hpux_thread_ops (void)
541{
542  hpux_thread_ops.to_shortname = "hpux-threads";
543  hpux_thread_ops.to_longname = "HPUX threads and pthread.";
544  hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
545  hpux_thread_ops.to_open = hpux_thread_open;
546  hpux_thread_ops.to_attach = hpux_thread_attach;
547  hpux_thread_ops.to_detach = hpux_thread_detach;
548  hpux_thread_ops.to_resume = hpux_thread_resume;
549  hpux_thread_ops.to_wait = hpux_thread_wait;
550  hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
551  hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
552  hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
553  hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
554  hpux_thread_ops.to_files_info = hpux_thread_files_info;
555  hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
556  hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
557  hpux_thread_ops.to_terminal_init = terminal_init_inferior;
558  hpux_thread_ops.to_terminal_inferior = terminal_inferior;
559  hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
560  hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
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;
568  hpux_thread_ops.to_thread_alive = hpux_thread_alive;
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
580_initialize_hpux_thread (void)
581{
582  init_hpux_thread_ops ();
583  add_target (&hpux_thread_ops);
584
585  child_suppress_run = 1;
586  /* Hook into new_objfile notification. */
587  target_new_objfile_chain = deprecated_target_new_objfile_hook;
588  deprecated_target_new_objfile_hook  = hpux_thread_new_objfile;
589}
590