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