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