* Fix some cases where NULL was used but 0 was meant (and vice versa).
[dragonfly.git] / gnu / usr.bin / gdb / libgdb / freebsd-uthread.c
1 /* Low level interface for debugging FreeBSD user 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, Boston, MA 02111-1307, USA.  */
19
20 /* $FreeBSD: ports/devel/gdb6/files/freebsd-uthread.c,v 1.2 2004/06/20 18:45:36 obrien Exp $ */
21 /* $DragonFly: src/gnu/usr.bin/gdb/libgdb/freebsd-uthread.c,v 1.4 2008/06/05 18:06:30 swildner Exp $ */
22
23 /* This module implements a sort of half target that sits between the
24    machine-independent parts of GDB and the ptrace interface (infptrace.c) to
25    provide access to the FreeBSD user-mode thread implementation.
26
27    FreeBSD threads are true user-mode threads, which are invoked via
28    the pthread_* interfaces.  These are mostly implemented in
29    user-space, with all thread context kept in various structures that
30    live in the user's heap.  For the most part, the kernel has no
31    knowlege of these threads.
32
33    Based largely on hpux-thread.c
34
35    */
36
37
38 #include "defs.h"
39 #include <sys/queue.h>
40 #include <signal.h>
41 #include <setjmp.h>
42 #include <string.h>
43 #include "gdbthread.h"
44 #include "target.h"
45 #include "inferior.h"
46 #include <fcntl.h>
47 #include <ucontext.h>
48 #include <unistd.h>
49 #include <sys/stat.h>
50 #include "gdbcore.h"
51 #include "regcache.h"
52
53 extern int child_suppress_run;
54 extern struct target_ops child_ops; /* target vector for inftarg.c */
55
56 extern void _initialize_freebsd_uthread PARAMS ((void));
57
58 /* Set to true while we are part-way through attaching */
59 static int freebsd_uthread_attaching;
60
61 static int freebsd_uthread_active = 0;
62 static CORE_ADDR P_thread_list;
63 static CORE_ADDR P_thread_run;
64 static CORE_ADDR P_thread_kern_thread;
65
66 /* Pointer to the next function on the objfile event chain.  */
67 static void (*target_new_objfile_chain) (struct objfile *objfile);
68
69 static void freebsd_uthread_resume PARAMS ((ptid_t pid, int step,
70                                         enum target_signal signo));
71
72 static void init_freebsd_uthread_ops PARAMS ((void));
73
74 static struct target_ops freebsd_uthread_ops;
75 \f
76 static ptid_t find_active_ptid PARAMS ((void));
77
78 struct cached_pthread {
79   u_int64_t             uniqueid;
80   int                   state;
81   CORE_ADDR             name;
82   union {
83     ucontext_t  uc;
84     jmp_buf     jb;
85   }                     ctx;
86 };
87
88 static ptid_t cached_ptid;
89 static struct cached_pthread cached_pthread;
90 static CORE_ADDR cached_pthread_addr;
91
92 LIST_HEAD(idmaplist, idmap);
93
94 struct idmap {
95     LIST_ENTRY(idmap)   link;
96     u_int64_t           uniqueid;
97     int                 tid;
98 };
99
100 #define MAPHASH_SIZE    257
101 #define TID_MIN         1
102 #define TID_MAX         16383
103
104 static int tid_to_hash[TID_MAX + 1];            /* set to map_hash index */
105 static struct idmaplist map_hash[MAPHASH_SIZE];
106 static int next_free_tid = TID_MIN;             /* first available tid */
107 static int last_free_tid = TID_MIN;             /* first unavailable */
108
109 static CORE_ADDR P_thread_next_offset;
110 static CORE_ADDR P_thread_uniqueid_offset;
111 static CORE_ADDR P_thread_state_offset;
112 static CORE_ADDR P_thread_name_offset;
113 static CORE_ADDR P_thread_ctx_offset;
114 static CORE_ADDR P_thread_PS_RUNNING_value;
115 static CORE_ADDR P_thread_PS_DEAD_value;
116
117 static int next_offset;
118 static int uniqueid_offset;
119 static int state_offset;
120 static int name_offset;
121 static int ctx_offset;
122 static int PS_RUNNING_value;
123 static int PS_DEAD_value;
124
125 #define UNIQUEID_HASH(id)       (id % MAPHASH_SIZE)
126 #define TID_ADD1(tid)           (((tid) + 1) == TID_MAX + 1 \
127                                  ? TID_MIN : (tid) + 1)
128 #define IS_TID_FREE(tid)        (tid_to_hash[tid] == -1)
129
130 static int
131 get_new_tid(int h)
132 {
133   int tid = next_free_tid;
134
135   tid_to_hash[tid] = h;
136   next_free_tid = TID_ADD1(next_free_tid);
137   if (next_free_tid == last_free_tid)
138     {
139       int i;
140
141       for (i = last_free_tid; TID_ADD1(i) != last_free_tid; i = TID_ADD1(i))
142         if (IS_TID_FREE(i))
143           break;
144       if (TID_ADD1(i) == last_free_tid)
145         {
146           error("too many threads");
147           return 0;
148         }
149       next_free_tid = i;
150       for (i = TID_ADD1(i); IS_TID_FREE(i); i = TID_ADD1(i))
151         ;
152       last_free_tid = i;
153     }
154
155   return tid;
156 }
157
158 static ptid_t
159 find_ptid(u_int64_t uniqueid)
160 {
161   int h = UNIQUEID_HASH(uniqueid);
162   struct idmap *im;
163
164   LIST_FOREACH(im, &map_hash[h], link)
165     if (im->uniqueid == uniqueid)
166       return MERGEPID(PIDGET(inferior_ptid), im->tid);
167
168   im = xmalloc(sizeof(struct idmap));
169   im->uniqueid = uniqueid;
170   im->tid = get_new_tid(h);
171   LIST_INSERT_HEAD(&map_hash[h], im, link);
172
173   return MERGEPID(PIDGET(inferior_ptid), im->tid);
174 }
175
176 static void
177 free_ptid(ptid_t ptid)
178 {
179   int tid = TIDGET(ptid);
180   int h = tid_to_hash[tid];
181   struct idmap *im;
182
183   if (!tid) return;
184
185   LIST_FOREACH(im, &map_hash[h], link)
186     if (im->tid == tid)
187       break;
188
189   if (!im) return;
190
191   LIST_REMOVE(im, link);
192   tid_to_hash[tid] = -1;
193   free(im);
194 }
195
196 #define READ_OFFSET(field) read_memory(P_thread_##field##_offset,       \
197                                        (char *) &field##_offset,        \
198                                        sizeof(field##_offset))
199
200 #define READ_VALUE(name) read_memory(P_thread_##name##_value,   \
201                                      (char *) &name##_value,    \
202                                      sizeof(name##_value))
203
204 static void
205 read_thread_offsets (void)
206 {
207   READ_OFFSET(next);
208   READ_OFFSET(uniqueid);
209   READ_OFFSET(state);
210   READ_OFFSET(name);
211   READ_OFFSET(ctx);
212
213   READ_VALUE(PS_RUNNING);
214   READ_VALUE(PS_DEAD);
215 }
216
217 #define READ_FIELD(ptr, T, field, result) \
218   read_memory ((ptr) + field##_offset, (char *) &(result), sizeof result)
219
220 static u_int64_t
221 read_pthread_uniqueid (CORE_ADDR ptr)
222 {
223   u_int64_t uniqueid;
224   READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
225   return uniqueid;
226 }
227
228 static CORE_ADDR
229 read_pthread_next (CORE_ADDR ptr)
230 {
231   CORE_ADDR next;
232   READ_FIELD(ptr, CORE_ADDR, next, next);
233   return next;
234 }
235
236 static void
237 read_cached_pthread (CORE_ADDR ptr, struct cached_pthread *cache)
238 {
239   READ_FIELD(ptr, u_int64_t,    uniqueid,       cache->uniqueid);
240   READ_FIELD(ptr, int,          state,          cache->state);
241   READ_FIELD(ptr, CORE_ADDR,    name,           cache->name);
242   READ_FIELD(ptr, ucontext_t,   ctx,            cache->ctx);
243 }
244
245 static ptid_t
246 find_active_ptid (void)
247 {
248   CORE_ADDR ptr;
249
250   read_memory ((CORE_ADDR)P_thread_run,
251                (char *)&ptr,
252                sizeof ptr);
253
254   return find_ptid(read_pthread_uniqueid(ptr));
255 }
256
257 static CORE_ADDR find_pthread_addr PARAMS ((ptid_t ptid));
258 static struct cached_pthread * find_pthread PARAMS ((ptid_t ptid));
259
260 static CORE_ADDR
261 find_pthread_addr (ptid_t ptid)
262 {
263   CORE_ADDR ptr;
264
265   if (ptid_equal(ptid, cached_ptid))
266     return cached_pthread_addr;
267
268   read_memory ((CORE_ADDR)P_thread_list,
269                (char *)&ptr,
270                sizeof ptr);
271
272   while (ptr != 0)
273     {
274       if (ptid_equal(find_ptid(read_pthread_uniqueid(ptr)), ptid))
275         {
276           cached_ptid = ptid;
277           cached_pthread_addr = ptr;
278           read_cached_pthread(ptr, &cached_pthread);
279           return ptr;
280         }
281       ptr = read_pthread_next(ptr);
282     }
283
284   return 0;
285 }
286
287 static struct cached_pthread *
288 find_pthread (ptid_t ptid)
289 {
290   CORE_ADDR ptr;
291
292   if (ptid_equal(ptid, cached_ptid))
293     return &cached_pthread;
294
295   read_memory ((CORE_ADDR)P_thread_list,
296                (char *)&ptr,
297                sizeof ptr);
298
299   /*
300    * uthreads might not be initialized yet, so we have to use the
301    * kernel thread instead.
302    */
303   if (ptr == 0)
304           ptr = P_thread_kern_thread;
305
306   while (ptr != 0)
307     {
308       if (ptid_equal(find_ptid(read_pthread_uniqueid(ptr)), ptid))
309         {
310           cached_ptid = ptid;
311           cached_pthread_addr = ptr;
312           read_cached_pthread(ptr, &cached_pthread);
313           return &cached_pthread;
314         }
315       ptr = read_pthread_next(ptr);
316     }
317
318 #if 0
319   error ("Can't find pthread %d,%d", PIDGET(ptid), TIDGET(ptid));
320 #endif
321   return NULL;
322 }
323
324 \f
325 /* Most target vector functions from here on actually just pass through to
326    inftarg.c, as they don't need to do anything specific for threads.  */
327
328 /* ARGSUSED */
329 static void
330 freebsd_uthread_open (char *arg, int from_tty)
331 {
332   child_ops.to_open (arg, from_tty);
333 }
334
335 /* Attach to process PID, then initialize for debugging it
336    and wait for the trace-trap that results from attaching.  */
337
338 static void
339 freebsd_uthread_attach (char *args, int from_tty)
340 {
341   child_ops.to_attach (args, from_tty);
342   push_target (&freebsd_uthread_ops);
343   freebsd_uthread_attaching = 1;
344 }
345
346 /* After an attach, see if the target is threaded */
347
348 static void
349 freebsd_uthread_post_attach (int pid)
350 {
351   if (freebsd_uthread_active)
352     {
353       read_thread_offsets ();
354       inferior_ptid = find_active_ptid ();
355       add_thread (inferior_ptid);
356     }
357   else
358     {
359       unpush_target (&freebsd_uthread_ops);
360       push_target (&child_ops);
361     }
362
363   freebsd_uthread_attaching = 0;
364 }
365
366 /* Take a program previously attached to and detaches it.
367    The program resumes execution and will no longer stop
368    on signals, etc.  We'd better not have left any breakpoints
369    in the program or it'll die when it hits one.  For this
370    to work, it may be necessary for the process to have been
371    previously attached.  It *might* work if the program was
372    started via the normal ptrace (PTRACE_TRACEME).  */
373
374 static void
375 freebsd_uthread_detach (char *args, int from_tty)
376 {
377   child_ops.to_detach (args, from_tty);
378 }
379
380 /* Resume execution of process PID.  If STEP is nozero, then
381    just single step it.  If SIGNAL is nonzero, restart it with that
382    signal activated.  We may have to convert pid from a thread-id to an LWP id
383    for procfs.  */
384
385 static void
386 freebsd_uthread_resume (ptid_t ptid, int step, enum target_signal signo)
387 {
388   if (freebsd_uthread_attaching)
389     {
390       child_ops.to_resume (ptid, step, signo);
391       return;
392     }
393
394   child_ops.to_resume (ptid, step, signo);
395   cached_ptid = MERGEPID(0, 0);
396 }
397
398 /* Wait for any threads to stop.  We may have to convert PID from a thread id
399    to a LWP id, and vice versa on the way out.  */
400
401 static ptid_t
402 freebsd_uthread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
403 {
404   ptid_t rtnval;
405
406   if (freebsd_uthread_attaching)
407     {
408       return child_ops.to_wait (ptid, ourstatus);
409     }
410
411   rtnval = child_ops.to_wait (ptid, ourstatus);
412
413   if (PIDGET(rtnval) >= 0)
414     {
415       rtnval = find_active_ptid ();
416       if (!in_thread_list (rtnval))
417         add_thread (rtnval);
418     }
419
420   return rtnval;
421 }
422
423 /* XXX: this needs to be selected by target, not [build] host */
424 #ifdef __i386__
425
426 #include "i386-tdep.h"
427
428 static char sigmap[I386_SSE_NUM_REGS] = /* map reg to sigcontext  */
429 {
430   12,                           /* eax */
431   11,                           /* ecx */
432   10,                           /* edx */
433   9,                            /* ebx */
434   8,                            /* esp */
435   7,                            /* ebp */
436   6,                            /* esi */
437   5,                            /* edi */
438   15,                           /* eip */
439   17,                           /* eflags */
440   16,                           /* cs */
441   19,                           /* ss */
442   4,                            /* ds */
443   3,                            /* es */
444   2,                            /* fs */
445   1,                            /* gs */
446   -1, -1, -1, -1, -1, -1, -1,   /* st0-st7 */
447   -1, -1, -1, -1, -1, -1, -1,   /* fctrl-fop */
448   -1, -1, -1, -1, -1, -1, -1,   /* xmm0-xmm7 */
449   -1,                           /* mxcsr */
450 };
451
452 static char jmpmap[I386_SSE_NUM_REGS] = /* map reg to jmp_buf */
453 {
454   6,                            /* eax */
455   -1,                           /* ecx */
456   -1,                           /* edx */
457   1,                            /* ebx */
458   2,                            /* esp */
459   3,                            /* ebp */
460   4,                            /* esi */
461   5,                            /* edi */
462   0,                            /* eip */
463   -1,                           /* eflags */
464   -1,                           /* cs */
465   -1,                           /* ss */
466   -1,                           /* ds */
467   -1,                           /* es */
468   -1,                           /* fs */
469   -1,                           /* gs */
470   -1, -1, -1, -1, -1, -1, -1,   /* st0-st7 */
471   -1, -1, -1, -1, -1, -1, -1,   /* fctrl-fop */
472   -1, -1, -1, -1, -1, -1, -1,   /* xmm0-xmm7 */
473   -1,                           /* mxcsr */
474 };
475
476 #endif
477
478 #ifdef __amd64__
479
480 #include "amd64-tdep.h"
481
482 // XXX:DEO      not fully ported from i386 yet!!
483
484
485 #define AMD64_NUM_REGS_TOTAL    57
486
487 static char sigmap[AMD64_NUM_REGS_TOTAL] = /* map reg to sigcontext  */
488 {
489   7,                            /* %rax */
490   8,                            /* %rbx */
491   4,                            /* %rcx */
492   3,                            /* %rdx */
493   2,                            /* %rsi */
494   1,                            /* %rdi */
495   9,                            /* %rbp */
496   23,                           /* %rsp */
497   5,                            /* %r8 */
498   6,                            /* %r9 */
499   10,                           /* %r10 */
500   11,                           /* %r11 */
501   12,                           /* %r12 */
502   13,                           /* %r13 */
503   14,                           /* %r14 */
504   15,                           /* %r15 */
505   20,                           /* %rip */
506   18,                           /* %eflags */
507   21, 24, -1, -1, -1, -1,       /* %cs - %gs */
508   -1, -1, -1, -1, -1 -1, -1, -1,/* %st0 - %st7 */
509   -1, -1, -1, -1, -1 -1, -1, -1,/* %fctrl - %fop */
510   -1, -1, -1, -1, -1 -1, -1, -1,/* %xmm0 - %xmm7 */
511   -1, -1, -1, -1, -1 -1, -1, -1,/* %xmm8 - %xmm15 */
512   -1,                           /* %mxcsr */
513 };
514
515 static char jmpmap[AMD64_NUM_REGS_TOTAL] = /* map reg to jmp_buf */
516 {
517   -1,                           /* %rax */
518   1,                            /* %rbx */
519   -1,                           /* %rcx */
520   -1,                           /* %rdx */
521   -1,                           /* %rsi */
522   -1,                           /* %rdi */
523   3,                            /* %rbp */
524   2,                            /* %rsp */
525   -1,                           /* %r8 */
526   -1,                           /* %r9 */
527   -1,                           /* %r10 */
528   -1,                           /* %r11 */
529   4,                            /* %r12 */
530   5,                            /* %r13 */
531   6,                            /* %r14 */
532   7,                            /* %r15 */
533   0,                            /* %rip */
534   -1,                           /* %eflags */
535   -1, -1, -1, -1, -1, -1,       /* %cs - %gs */
536   -1, -1, -1, -1, -1 -1, -1, -1,/* %st0 - %st7 */
537   -1, -1, -1, -1, -1 -1, -1, -1,/* %fctrl - %fop */
538   -1, -1, -1, -1, -1 -1, -1, -1,/* %xmm0 - %xmm7 */
539   -1, -1, -1, -1, -1 -1, -1, -1,/* %xmm8 - %xmm15 */
540   -1,                           /* %mxcsr */
541 };
542
543 #endif
544
545 #ifdef __alpha__
546
547 #include "alpha-tdep.h"
548
549 static char sigmap[ALPHA_NUM_REGS] =    /* map reg to sigcontext  */
550 {
551   1,  2,  3,  4,  5,  6,  7,  8,  /* v0 - t6 */
552   9,  10, 11, 12, 13, 14, 15, 16, /* t7 - fp */
553   17, 18, 19, 20, 21, 22, 23, 24, /* a0 - t9 */
554   25, 26, 27, 28, 29, 30, 31, 32, /* t10 - zero */
555   38, 39, 40, 41, 42, 43, 44, 45, /* f0 - f7 */
556   46, 47, 48, 49, 50, 51, 52, 53, /* f8 - f15 */
557   54, 55, 56, 57, 58, 59, 60, 61, /* f16 - f23 */
558   62, 63, 64, 65, 66, 67, 68, 69, /* f24 - f31 */
559   33, -1                          /* pc, vfp */
560 };
561 static char jmpmap[ALPHA_NUM_REGS] = {
562   4,  5,  6,  7,  8,  9,  10, 11, /* v0 - t6 */
563   12, 13, 14, 15, 16, 17, 18, 19, /* t7 - fp */
564   20, 21, 22, 23, 24, 25, 26, 27, /* a0 - t9 */
565   28, 29, 30, 31, 32, 33, 34, 35, /* t10 - zero */
566   37, 38, 39, 40, 41, 42, 43, 44, /* f0 - f7 */
567   45, 46, 47, 48, 49, 50, 51, 52, /* f8 - f15 */
568   53, 54, 55, 56, 57, 58, 59, 60, /* f16 - f23 */
569   61, 62, 63, 64, 65, 66, 67, 68, /* f24 - f31 */
570   2,  -1,                         /* pc, vfp */
571 };
572
573 #endif
574
575 #ifdef __sparc64__
576
577 static char sigmap[125] =       /* map reg to sigcontext  */
578 {
579   -1
580 };
581 static char jmpmap[125] = {
582   -1
583 };
584
585 #endif
586
587 static void
588 freebsd_uthread_fetch_registers (int regno)
589 {
590   struct cached_pthread *thread;
591   int active;
592   int first_regno, last_regno;
593   register_t *regbase;
594   char *regmap;
595
596   if (freebsd_uthread_attaching || TIDGET(inferior_ptid) == 0)
597     {
598       child_ops.to_fetch_registers (regno);
599       return;
600     }
601
602   thread = find_pthread (inferior_ptid);
603   active = (ptid_equal(inferior_ptid, find_active_ptid()));
604
605   if (active)
606     {
607       child_ops.to_fetch_registers (regno);
608       return;
609     }
610
611   if (regno == -1)
612     {
613       first_regno = 0;
614       last_regno = NUM_REGS - 1;
615     }
616   else
617     {
618       first_regno = regno;
619       last_regno = regno;
620     }
621
622   regbase = (register_t*) &thread->ctx.jb[0];
623   regmap = jmpmap;
624
625   for (regno = first_regno; regno <= last_regno; regno++)
626     {
627       if (regmap[regno] == -1)
628         child_ops.to_fetch_registers (regno);
629       else
630         if (thread)
631           supply_register (regno, (char*) &regbase[regmap[regno]]);
632         else
633           supply_register (regno, NULL);
634     }
635 }
636
637 static void
638 freebsd_uthread_store_registers (int regno)
639 {
640   struct cached_pthread *thread;
641   CORE_ADDR ptr;
642   int first_regno, last_regno;
643   u_int32_t *regbase;
644   char *regmap;
645
646   if (freebsd_uthread_attaching)
647     {
648       child_ops.to_store_registers (regno);
649       return;
650     }
651
652   thread = find_pthread (inferior_ptid);
653
654   if (thread->state == PS_RUNNING_value)
655     {
656       child_ops.to_store_registers (regno);
657       return;
658     }
659
660   if (regno == -1)
661     {
662       first_regno = 0;
663       last_regno = NUM_REGS - 1;
664     }
665   else
666     {
667       first_regno = regno;
668       last_regno = regno;
669     }
670
671   regbase = (u_int32_t*) &thread->ctx.jb[0];
672   regmap = jmpmap;
673
674   ptr = find_pthread_addr (inferior_ptid);
675   for (regno = first_regno; regno <= last_regno; regno++)
676     {
677       if (regmap[regno] == -1)
678         child_ops.to_store_registers (regno);
679       else
680         {
681           u_int32_t *reg = &regbase[regmap[regno]];
682           int off;
683
684           /* Hang onto cached value */
685 /*DEO:XXX*/
686           memcpy(reg, deprecated_registers /*regcache_collect ()*/+ DEPRECATED_REGISTER_BYTE (regno),
687                  DEPRECATED_REGISTER_RAW_SIZE (regno));
688
689           /* And push out to inferior */
690           off = (char *) reg - (char *) thread;
691           write_memory (ptr + off, 
692 /*DEO:XXX*/
693                         deprecated_registers /*regcache_collect ()*/+ DEPRECATED_REGISTER_BYTE (regno),
694                         DEPRECATED_REGISTER_RAW_SIZE (regno));
695         }
696     }
697 }
698
699 /* Get ready to modify the registers array.  On machines which store
700    individual registers, this doesn't need to do anything.  On machines
701    which store all the registers in one fell swoop, this makes sure
702    that registers contains all the registers from the program being
703    debugged.  */
704
705 static void
706 freebsd_uthread_prepare_to_store (void)
707 {
708   child_ops.to_prepare_to_store ();
709 }
710
711 static int
712 freebsd_uthread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
713                              int dowrite, struct mem_attrib *attrib,
714                              struct target_ops *target)
715 {
716   return child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite,
717                                    attrib, target);
718 }
719
720 /* Print status information about what we're accessing.  */
721
722 static void
723 freebsd_uthread_files_info (struct target_ops *ignore)
724 {
725   child_ops.to_files_info (ignore);
726 }
727
728 static void
729 freebsd_uthread_kill_inferior (void)
730 {
731   child_ops.to_kill ();
732 }
733
734 static void
735 freebsd_uthread_notice_signals (ptid_t ptid)
736 {
737   child_ops.to_notice_signals (ptid);
738 }
739
740 /* Fork an inferior process, and start debugging it with /proc.  */
741
742 static void
743 freebsd_uthread_create_inferior (char *exec_file, char *allargs, char **env,
744                                  int from_tty)
745 {
746   child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
747
748   if (PIDGET(inferior_ptid) && freebsd_uthread_active)
749     {
750       read_thread_offsets ();
751       push_target (&freebsd_uthread_ops);
752       inferior_ptid = find_active_ptid ();
753       add_thread (inferior_ptid);
754     }
755 }
756
757 /* This routine is called to find out if the inferior is using threads.
758    We check for the _thread_run and _thread_list globals. */
759
760 void
761 freebsd_uthread_new_objfile (struct objfile *objfile)
762 {
763   struct minimal_symbol *ms;
764
765   if (!objfile)
766     {
767       freebsd_uthread_active = 0;
768       return;
769     }
770
771   ms = lookup_minimal_symbol ("_thread_run", NULL, objfile);
772
773   if (!ms)
774     return;
775
776   P_thread_run = SYMBOL_VALUE_ADDRESS (ms);
777
778   ms = lookup_minimal_symbol ("_thread_list", NULL, objfile);
779
780   if (!ms)
781     return;
782
783   P_thread_list = SYMBOL_VALUE_ADDRESS (ms);
784
785   ms = lookup_minimal_symbol ("_thread_kern_thread", NULL, objfile);
786
787   if (!ms)
788     return;
789
790   P_thread_kern_thread = SYMBOL_VALUE_ADDRESS (ms);
791
792 #define OFFSET_SYM(field)       "_thread_" #field "_offset"
793 #define LOOKUP_OFFSET(field)                                            \
794   do {                                                                  \
795       ms = lookup_minimal_symbol (OFFSET_SYM(field), NULL, objfile);    \
796       if (!ms)                                                          \
797         return;                                                         \
798       P_thread_##field##_offset = SYMBOL_VALUE_ADDRESS (ms);            \
799   } while (0);
800
801 #define VALUE_SYM(name)         "_thread_" #name "_value"
802 #define LOOKUP_VALUE(name)                                              \
803   do {                                                                  \
804        ms = lookup_minimal_symbol (VALUE_SYM(name), NULL, objfile);     \
805       if (!ms)                                                          \
806         return;                                                         \
807       P_thread_##name##_value = SYMBOL_VALUE_ADDRESS (ms);              \
808   } while (0);
809
810   LOOKUP_OFFSET(next);
811   LOOKUP_OFFSET(uniqueid);
812   LOOKUP_OFFSET(state);
813   LOOKUP_OFFSET(name);
814   LOOKUP_OFFSET(ctx);
815
816   LOOKUP_VALUE(PS_RUNNING);
817   LOOKUP_VALUE(PS_DEAD);
818
819   freebsd_uthread_active = 1;
820 }
821
822 /* Clean up after the inferior dies.  */
823
824 static void
825 freebsd_uthread_mourn_inferior ()
826 {
827   child_ops.to_mourn_inferior ();
828   unpush_target (&freebsd_uthread_ops);
829 }
830
831 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
832
833 static int
834 freebsd_uthread_can_run ()
835 {
836   return child_suppress_run;
837 }
838
839 static int
840 freebsd_uthread_thread_alive (ptid_t ptid)
841 {
842   struct cached_pthread *thread;
843   int ret = 0;
844
845   if (freebsd_uthread_attaching)
846     return 1;
847
848   /*
849    * We can get called from child_ops.to_wait() which passes the underlying
850    * pid (without a thread number).
851    */
852   if (TIDGET(ptid) == 0)
853     return 1;
854
855   if (find_pthread_addr (ptid) != 0)
856     {
857       thread = find_pthread (ptid);
858       ret = (thread->state != PS_DEAD_value);
859     }
860
861   if (!ret)
862     free_ptid(ptid);
863
864   return ret;
865 }
866
867 static void
868 freebsd_uthread_stop (void)
869 {
870   child_ops.to_stop ();
871 }
872
873 static void
874 freebsd_uthread_find_new_threads (void)
875 {
876   CORE_ADDR ptr;
877   int state;
878   u_int64_t uniqueid;
879
880   read_memory ((CORE_ADDR)P_thread_list,
881                (char *)&ptr,
882                sizeof ptr);
883
884   while (ptr != 0)
885     {
886       READ_FIELD(ptr, int, state, state);
887       READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
888       if (state != PS_DEAD_value &&
889           !in_thread_list (find_ptid(uniqueid)))
890         add_thread (find_ptid(uniqueid));
891       ptr = read_pthread_next(ptr);
892     }
893 }
894
895 /* MUST MATCH enum pthread_state */
896 static const char *statenames[] = {
897   "RUNNING",
898   "SIGTHREAD",
899   "MUTEX_WAIT",
900   "COND_WAIT",
901   "FDLR_WAIT",
902   "FDLW_WAIT",
903   "FDR_WAIT",
904   "FDW_WAIT",
905   "POLL_WAIT",
906   "FILE_WAIT",
907   "SELECT_WAIT",
908   "SLEEP_WAIT",
909   "WAIT_WAIT",
910   "SIGSUSPEND",
911   "SIGWAIT",
912   "SPINBLOCK",
913   "JOIN",
914   "SUSPENDED",
915   "DEAD",
916   "DEADLOCK",
917 };
918
919 #if 0
920
921 static int
922 freebsd_uthread_get_thread_info (ref, selection, info)
923      gdb_threadref *ref;
924      int selection;
925      struct gdb_ext_thread_info *info;
926 {
927   int pid = *ref;
928   struct cached_pthread *thread = find_pthread (pid);
929   struct cleanup *old_chain;
930
931   old_chain = save_inferior_pid ();
932   inferior_pid = main_pid;
933
934   memset(&info->threadid, 0, OPAQUETHREADBYTES);
935
936   memcpy(&info->threadid, ref, sizeof *ref);
937   info->active = thread->state == PS_RUNNING_value;
938   strcpy(info->display, statenames[thread->state]);
939   if (thread->name)
940     read_memory ((CORE_ADDR) thread->name, info->shortname, 32);
941   else
942     strcpy(info->shortname, "");
943
944   do_cleanups (old_chain);
945   return (0);
946 }
947
948 #endif
949
950 char *
951 freebsd_uthread_pid_to_str (ptid_t ptid)
952 {
953   static char buf[30];
954
955   if (DEPRECATED_STREQ (current_target.to_shortname, "freebsd-uthreads"))
956     sprintf (buf, "Process %d, Thread %ld",
957              PIDGET(ptid), TIDGET(ptid));
958   else
959     sprintf (buf, "Process %d", PIDGET(ptid));
960
961   return buf;
962 }
963
964 \f
965 static void
966 init_freebsd_uthread_ops ()
967 {
968   freebsd_uthread_ops.to_shortname = "freebsd-uthreads";
969   freebsd_uthread_ops.to_longname = "FreeBSD uthreads";
970   freebsd_uthread_ops.to_doc = "FreeBSD user threads support.";
971   freebsd_uthread_ops.to_open = freebsd_uthread_open;
972   freebsd_uthread_ops.to_attach = freebsd_uthread_attach;
973   freebsd_uthread_ops.to_post_attach = freebsd_uthread_post_attach;
974   freebsd_uthread_ops.to_detach = freebsd_uthread_detach;
975   freebsd_uthread_ops.to_resume = freebsd_uthread_resume;
976   freebsd_uthread_ops.to_wait = freebsd_uthread_wait;
977   freebsd_uthread_ops.to_fetch_registers = freebsd_uthread_fetch_registers;
978   freebsd_uthread_ops.to_store_registers = freebsd_uthread_store_registers;
979   freebsd_uthread_ops.to_prepare_to_store = freebsd_uthread_prepare_to_store;
980   freebsd_uthread_ops.to_xfer_memory = freebsd_uthread_xfer_memory;
981   freebsd_uthread_ops.to_files_info = freebsd_uthread_files_info;
982   freebsd_uthread_ops.to_insert_breakpoint = memory_insert_breakpoint;
983   freebsd_uthread_ops.to_remove_breakpoint = memory_remove_breakpoint;
984   freebsd_uthread_ops.to_terminal_init = terminal_init_inferior;
985   freebsd_uthread_ops.to_terminal_inferior = terminal_inferior;
986   freebsd_uthread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
987   freebsd_uthread_ops.to_terminal_ours = terminal_ours;
988   freebsd_uthread_ops.to_terminal_info = child_terminal_info;
989   freebsd_uthread_ops.to_kill = freebsd_uthread_kill_inferior;
990   freebsd_uthread_ops.to_create_inferior = freebsd_uthread_create_inferior;
991   freebsd_uthread_ops.to_mourn_inferior = freebsd_uthread_mourn_inferior;
992   freebsd_uthread_ops.to_can_run = freebsd_uthread_can_run;
993   freebsd_uthread_ops.to_notice_signals = freebsd_uthread_notice_signals;
994   freebsd_uthread_ops.to_thread_alive = freebsd_uthread_thread_alive;
995   freebsd_uthread_ops.to_stop = freebsd_uthread_stop;
996   freebsd_uthread_ops.to_stratum = process_stratum;
997   freebsd_uthread_ops.to_has_all_memory = 1;
998   freebsd_uthread_ops.to_has_memory = 1;
999   freebsd_uthread_ops.to_has_stack = 1;
1000   freebsd_uthread_ops.to_has_registers = 1;
1001   freebsd_uthread_ops.to_has_execution = 1;
1002   freebsd_uthread_ops.to_has_thread_control = 0;
1003   freebsd_uthread_ops.to_magic = OPS_MAGIC;
1004   freebsd_uthread_ops.to_find_new_threads = freebsd_uthread_find_new_threads;
1005   freebsd_uthread_ops.to_pid_to_str = freebsd_uthread_pid_to_str;
1006 #if 0
1007   freebsd_uthread_vec.get_thread_info = freebsd_uthread_get_thread_info;
1008 #endif
1009 }
1010
1011 void
1012 _initialize_freebsd_uthread ()
1013 {
1014   init_freebsd_uthread_ops ();
1015   add_target (&freebsd_uthread_ops);
1016
1017   target_new_objfile_chain = deprecated_target_new_objfile_hook;
1018   deprecated_target_new_objfile_hook = freebsd_uthread_new_objfile;
1019
1020   child_suppress_run = 1;
1021 }