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