OSDN Git Service

* ocd.h (ocd_xfer_memory): Add ``attrib'' parameter.
[pf3gnuchains/pf3gnuchains3x.git] / gdb / hpux-thread.c
1 /* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
2    Copyright 1996, 1999, 2001 Free Software Foundation, Inc.
3
4    This file is part of GDB.
5
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.
10
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.
15
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.  */
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
31  */
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"
42 #include "regcache.h"
43 #include <fcntl.h>
44 #include <sys/stat.h>
45 #include "gdbcore.h"
46
47 extern int child_suppress_run;
48 extern struct target_ops child_ops;     /* target vector for inftarg.c */
49
50 extern void _initialize_hpux_thread (void);
51
52 struct string_map
53   {
54     int num;
55     char *str;
56   };
57
58 static int hpux_thread_active = 0;
59
60 static int main_pid;            /* Real process ID */
61
62 static CORE_ADDR P_cma__g_known_threads;
63 static CORE_ADDR P_cma__g_current_thread;
64
65 static struct cleanup *save_inferior_pid (void);
66
67 static void restore_inferior_pid (int pid);
68
69 static void hpux_thread_resume (int pid, int step, enum target_signal signo);
70
71 static void init_hpux_thread_ops (void);
72
73 static struct target_ops hpux_thread_ops;
74 \f
75 /*
76
77    LOCAL FUNCTION
78
79    save_inferior_pid - Save inferior_pid on the cleanup list
80    restore_inferior_pid - Restore inferior_pid from the cleanup list
81
82    SYNOPSIS
83
84    struct cleanup *save_inferior_pid ()
85    void restore_inferior_pid (int pid)
86
87    DESCRIPTION
88
89    These two functions act in unison to restore inferior_pid in
90    case of an error.
91
92    NOTES
93
94    inferior_pid is a global variable that needs to be changed by many of
95    these routines before calling functions in procfs.c.  In order to
96    guarantee that inferior_pid gets restored (in case of errors), you
97    need to call save_inferior_pid before changing it.  At the end of the
98    function, you should invoke do_cleanups to restore it.
99
100  */
101
102
103 static struct cleanup *
104 save_inferior_pid (void)
105 {
106   return make_cleanup (restore_inferior_pid, inferior_pid);
107 }
108
109 static void
110 restore_inferior_pid (int pid)
111 {
112   inferior_pid = pid;
113 }
114 \f
115 static int find_active_thread (void);
116
117 static int cached_thread;
118 static int cached_active_thread;
119 static cma__t_int_tcb cached_tcb;
120
121 static int
122 find_active_thread (void)
123 {
124   static cma__t_int_tcb tcb;
125   CORE_ADDR tcb_ptr;
126
127   if (cached_active_thread != 0)
128     return cached_active_thread;
129
130   read_memory ((CORE_ADDR) P_cma__g_current_thread,
131                (char *) &tcb_ptr,
132                sizeof tcb_ptr);
133
134   read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
135
136   return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid;
137 }
138
139 static cma__t_int_tcb *find_tcb (int thread);
140
141 static cma__t_int_tcb *
142 find_tcb (int thread)
143 {
144   cma__t_known_object queue_header;
145   cma__t_queue *queue_ptr;
146
147   if (thread == cached_thread)
148     return &cached_tcb;
149
150   read_memory ((CORE_ADDR) P_cma__g_known_threads,
151                (char *) &queue_header,
152                sizeof queue_header);
153
154   for (queue_ptr = queue_header.queue.flink;
155        queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
156        queue_ptr = cached_tcb.threads.flink)
157     {
158       cma__t_int_tcb *tcb_ptr;
159
160       tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
161
162       read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
163
164       if (cached_tcb.header.type == cma__c_obj_tcb)
165         if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
166           {
167             cached_thread = thread;
168             return &cached_tcb;
169           }
170     }
171
172   error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
173   return NULL;
174 }
175 \f
176 /* Most target vector functions from here on actually just pass through to
177    inftarg.c, as they don't need to do anything specific for threads.  */
178
179 /* ARGSUSED */
180 static void
181 hpux_thread_open (char *arg, int from_tty)
182 {
183   child_ops.to_open (arg, from_tty);
184 }
185
186 /* Attach to process PID, then initialize for debugging it
187    and wait for the trace-trap that results from attaching.  */
188
189 static void
190 hpux_thread_attach (char *args, int from_tty)
191 {
192   child_ops.to_attach (args, from_tty);
193
194   /* XXX - might want to iterate over all the threads and register them. */
195 }
196
197 /* Take a program previously attached to and detaches it.
198    The program resumes execution and will no longer stop
199    on signals, etc.  We'd better not have left any breakpoints
200    in the program or it'll die when it hits one.  For this
201    to work, it may be necessary for the process to have been
202    previously attached.  It *might* work if the program was
203    started via the normal ptrace (PTRACE_TRACEME).  */
204
205 static void
206 hpux_thread_detach (char *args, int from_tty)
207 {
208   child_ops.to_detach (args, from_tty);
209 }
210
211 /* Resume execution of process PID.  If STEP is nozero, then
212    just single step it.  If SIGNAL is nonzero, restart it with that
213    signal activated.  We may have to convert pid from a thread-id to an LWP id
214    for procfs.  */
215
216 static void
217 hpux_thread_resume (int pid, int step, enum target_signal signo)
218 {
219   struct cleanup *old_chain;
220
221   old_chain = save_inferior_pid ();
222
223   pid = inferior_pid = main_pid;
224
225 #if 0
226   if (pid != -1)
227     {
228       pid = thread_to_lwp (pid, -2);
229       if (pid == -2)            /* Inactive thread */
230         error ("This version of Solaris can't start inactive threads.");
231     }
232 #endif
233
234   child_ops.to_resume (pid, step, signo);
235
236   cached_thread = 0;
237   cached_active_thread = 0;
238
239   do_cleanups (old_chain);
240 }
241
242 /* Wait for any threads to stop.  We may have to convert PID from a thread id
243    to a LWP id, and vice versa on the way out.  */
244
245 static int
246 hpux_thread_wait (int pid, struct target_waitstatus *ourstatus)
247 {
248   int rtnval;
249   struct cleanup *old_chain;
250
251   old_chain = save_inferior_pid ();
252
253   inferior_pid = main_pid;
254
255   if (pid != -1)
256     pid = main_pid;
257
258   rtnval = child_ops.to_wait (pid, ourstatus);
259
260   rtnval = find_active_thread ();
261
262   do_cleanups (old_chain);
263
264   return rtnval;
265 }
266
267 static char regmap[NUM_REGS] =
268 {
269   -2, -1, -1, 0, 4, 8, 12, 16, 20, 24,  /* flags, r1 -> r9 */
270   28, 32, 36, 40, 44, 48, 52, 56, 60, -1,       /* r10 -> r19 */
271   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,       /* r20 -> r29 */
272
273   /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
274   -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
275
276   /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
277   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
278
279   /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
280   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
281
282   -1, -1, -1, -1,               /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
283   144, -1, -1, -1, -1, -1, -1, -1,      /* fpsr, fpe1 -> fpe7 */
284   -1, -1, -1, -1, -1, -1, -1, -1,       /* fr4 -> fr7 */
285   -1, -1, -1, -1, -1, -1, -1, -1,       /* fr8 -> fr11 */
286   136, -1, 128, -1, 120, -1, 112, -1,   /* fr12 -> fr15 */
287   104, -1, 96, -1, 88, -1, 80, -1,      /* fr16 -> fr19 */
288   72, -1, 64, -1, -1, -1, -1, -1,       /* fr20 -> fr23 */
289   -1, -1, -1, -1, -1, -1, -1, -1,       /* fr24 -> fr27 */
290   -1, -1, -1, -1, -1, -1, -1, -1,       /* fr28 -> fr31 */
291 };
292
293 static void
294 hpux_thread_fetch_registers (int regno)
295 {
296   cma__t_int_tcb tcb, *tcb_ptr;
297   struct cleanup *old_chain;
298   int i;
299   int first_regno, last_regno;
300
301   tcb_ptr = find_tcb (inferior_pid);
302
303   old_chain = save_inferior_pid ();
304
305   inferior_pid = main_pid;
306
307   if (tcb_ptr->state == cma__c_state_running)
308     {
309       child_ops.to_fetch_registers (regno);
310
311       do_cleanups (old_chain);
312
313       return;
314     }
315
316   if (regno == -1)
317     {
318       first_regno = 0;
319       last_regno = NUM_REGS - 1;
320     }
321   else
322     {
323       first_regno = regno;
324       last_regno = regno;
325     }
326
327   for (regno = first_regno; regno <= last_regno; regno++)
328     {
329       if (regmap[regno] == -1)
330         child_ops.to_fetch_registers (regno);
331       else
332         {
333           unsigned char buf[MAX_REGISTER_RAW_SIZE];
334           CORE_ADDR sp;
335
336           sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
337
338           if (regno == FLAGS_REGNUM)
339             /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
340             memset (buf, '\000', REGISTER_RAW_SIZE (regno));
341           else if (regno == SP_REGNUM)
342             store_address (buf, sizeof sp, sp);
343           else if (regno == PC_REGNUM)
344             read_memory (sp - 20, buf, REGISTER_RAW_SIZE (regno));
345           else
346             read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
347
348           supply_register (regno, buf);
349         }
350     }
351
352   do_cleanups (old_chain);
353 }
354
355 static void
356 hpux_thread_store_registers (int regno)
357 {
358   cma__t_int_tcb tcb, *tcb_ptr;
359   struct cleanup *old_chain;
360   int i;
361   int first_regno, last_regno;
362
363   tcb_ptr = find_tcb (inferior_pid);
364
365   old_chain = save_inferior_pid ();
366
367   inferior_pid = main_pid;
368
369   if (tcb_ptr->state == cma__c_state_running)
370     {
371       child_ops.to_store_registers (regno);
372
373       do_cleanups (old_chain);
374
375       return;
376     }
377
378   if (regno == -1)
379     {
380       first_regno = 0;
381       last_regno = NUM_REGS - 1;
382     }
383   else
384     {
385       first_regno = regno;
386       last_regno = regno;
387     }
388
389   for (regno = first_regno; regno <= last_regno; regno++)
390     {
391       if (regmap[regno] == -1)
392         child_ops.to_store_registers (regno);
393       else
394         {
395           unsigned char buf[MAX_REGISTER_RAW_SIZE];
396           CORE_ADDR sp;
397
398           sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
399
400           if (regno == FLAGS_REGNUM)
401             child_ops.to_store_registers (regno);       /* Let lower layer handle this... */
402           else if (regno == SP_REGNUM)
403             {
404               write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
405                             registers + REGISTER_BYTE (regno),
406                             REGISTER_RAW_SIZE (regno));
407               tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
408                 (extract_address (registers + REGISTER_BYTE (regno), REGISTER_RAW_SIZE (regno)) + 160);
409             }
410           else if (regno == PC_REGNUM)
411             write_memory (sp - 20,
412                           registers + REGISTER_BYTE (regno),
413                           REGISTER_RAW_SIZE (regno));
414           else
415             write_memory (sp + regmap[regno],
416                           registers + REGISTER_BYTE (regno),
417                           REGISTER_RAW_SIZE (regno));
418         }
419     }
420
421   do_cleanups (old_chain);
422 }
423
424 /* Get ready to modify the registers array.  On machines which store
425    individual registers, this doesn't need to do anything.  On machines
426    which store all the registers in one fell swoop, this makes sure
427    that registers contains all the registers from the program being
428    debugged.  */
429
430 static void
431 hpux_thread_prepare_to_store (void)
432 {
433   child_ops.to_prepare_to_store ();
434 }
435
436 static int
437 hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
438                          int dowrite, struct mem_attrib *attribs,
439                          struct target_ops *target)
440 {
441   int retval;
442   struct cleanup *old_chain;
443
444   old_chain = save_inferior_pid ();
445
446   inferior_pid = main_pid;
447
448   retval = 
449     child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
450
451   do_cleanups (old_chain);
452
453   return retval;
454 }
455
456 /* Print status information about what we're accessing.  */
457
458 static void
459 hpux_thread_files_info (struct target_ops *ignore)
460 {
461   child_ops.to_files_info (ignore);
462 }
463
464 static void
465 hpux_thread_kill_inferior (void)
466 {
467   child_ops.to_kill ();
468 }
469
470 static void
471 hpux_thread_notice_signals (int pid)
472 {
473   child_ops.to_notice_signals (pid);
474 }
475
476 /* Fork an inferior process, and start debugging it with /proc.  */
477
478 static void
479 hpux_thread_create_inferior (char *exec_file, char *allargs, char **env)
480 {
481   child_ops.to_create_inferior (exec_file, allargs, env);
482
483   if (hpux_thread_active)
484     {
485       main_pid = inferior_pid;
486
487       push_target (&hpux_thread_ops);
488
489       inferior_pid = find_active_thread ();
490
491       add_thread (inferior_pid);
492     }
493 }
494
495 /* This routine is called whenever a new symbol table is read in, or when all
496    symbol tables are removed.  libthread_db can only be initialized when it
497    finds the right variables in libthread.so.  Since it's a shared library,
498    those variables don't show up until the library gets mapped and the symbol
499    table is read in.  */
500
501 /* This new_objfile event is now managed by a chained function pointer. 
502  * It is the callee's responsability to call the next client on the chain.
503  */
504
505 /* Saved pointer to previous owner of the new_objfile event. */
506 static void (*target_new_objfile_chain) (struct objfile *);
507
508 void
509 hpux_thread_new_objfile (struct objfile *objfile)
510 {
511   struct minimal_symbol *ms;
512
513   if (!objfile)
514     {
515       hpux_thread_active = 0;
516       goto quit;
517     }
518
519   ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
520
521   if (!ms)
522     goto quit;
523
524   P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
525
526   ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
527
528   if (!ms)
529     goto quit;
530
531   P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
532
533   hpux_thread_active = 1;
534 quit:
535   /* Call predecessor on chain, if any. */
536   if (target_new_objfile_chain)
537     target_new_objfile_chain (objfile);
538 }
539
540 /* Clean up after the inferior dies.  */
541
542 static void
543 hpux_thread_mourn_inferior (void)
544 {
545   child_ops.to_mourn_inferior ();
546 }
547
548 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
549
550 static int
551 hpux_thread_can_run (void)
552 {
553   return child_suppress_run;
554 }
555
556 static int
557 hpux_thread_alive (int pid)
558 {
559   return 1;
560 }
561
562 static void
563 hpux_thread_stop (void)
564 {
565   child_ops.to_stop ();
566 }
567 \f
568 /* Convert a pid to printable form. */
569
570 char *
571 hpux_pid_to_str (int pid)
572 {
573   static char buf[100];
574
575   sprintf (buf, "Thread %d", pid >> 16);
576
577   return buf;
578 }
579 \f
580 static void
581 init_hpux_thread_ops (void)
582 {
583   hpux_thread_ops.to_shortname = "hpux-threads";
584   hpux_thread_ops.to_longname = "HPUX threads and pthread.";
585   hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
586   hpux_thread_ops.to_open = hpux_thread_open;
587   hpux_thread_ops.to_attach = hpux_thread_attach;
588   hpux_thread_ops.to_detach = hpux_thread_detach;
589   hpux_thread_ops.to_resume = hpux_thread_resume;
590   hpux_thread_ops.to_wait = hpux_thread_wait;
591   hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
592   hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
593   hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
594   hpux_thread_ops.to_xfer_memory = hpux_thread_xfer_memory;
595   hpux_thread_ops.to_files_info = hpux_thread_files_info;
596   hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
597   hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
598   hpux_thread_ops.to_terminal_init = terminal_init_inferior;
599   hpux_thread_ops.to_terminal_inferior = terminal_inferior;
600   hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
601   hpux_thread_ops.to_terminal_ours = terminal_ours;
602   hpux_thread_ops.to_terminal_info = child_terminal_info;
603   hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
604   hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
605   hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
606   hpux_thread_ops.to_can_run = hpux_thread_can_run;
607   hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
608   hpux_thread_ops.to_thread_alive = hpux_thread_alive;
609   hpux_thread_ops.to_stop = hpux_thread_stop;
610   hpux_thread_ops.to_stratum = process_stratum;
611   hpux_thread_ops.to_has_all_memory = 1;
612   hpux_thread_ops.to_has_memory = 1;
613   hpux_thread_ops.to_has_stack = 1;
614   hpux_thread_ops.to_has_registers = 1;
615   hpux_thread_ops.to_has_execution = 1;
616   hpux_thread_ops.to_magic = OPS_MAGIC;
617 }
618
619 void
620 _initialize_hpux_thread (void)
621 {
622   init_hpux_thread_ops ();
623   add_target (&hpux_thread_ops);
624
625   child_suppress_run = 1;
626   /* Hook into new_objfile notification. */
627   target_new_objfile_chain = target_new_objfile_hook;
628   target_new_objfile_hook  = hpux_thread_new_objfile;
629 }