ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/pack/freebsd/devel/gdb6/files/freebsd-uthread.c
Revision: 2
Committed: 2007-01-31T14:59:36-08:00 (18 years, 5 months ago) by douglas
Content type: text/x-c
Original Path: freebsd/gdb6/files/freebsd-uthread.c
File size: 24294 byte(s)
Log Message:
This needs fixing...

File Contents

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