OSDN Git Service

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