1 /* Low level interface for debugging FreeBSD user threads for GDB, the GNU debugger.
2 Copyright 1996, 1999 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
20 /* $FreeBSD: ports/devel/gdb6/files/freebsd-uthread.c,v 1.2 2004/06/20 18:45:36 obrien Exp $ */
21 /* $DragonFly: src/gnu/usr.bin/gdb/gdb/Attic/freebsd-uthread.c,v 1.2 2004/10/24 18:05:10 joerg Exp $ */
23 /* This module implements a sort of half target that sits between the
24 machine-independent parts of GDB and the ptrace interface (infptrace.c) to
25 provide access to the FreeBSD user-mode thread implementation.
27 FreeBSD threads are true user-mode threads, which are invoked via
28 the pthread_* interfaces. These are mostly implemented in
29 user-space, with all thread context kept in various structures that
30 live in the user's heap. For the most part, the kernel has no
31 knowlege of these threads.
33 Based largely on hpux-thread.c
39 #include <sys/queue.h>
43 #include "gdbthread.h"
53 extern int child_suppress_run;
54 extern struct target_ops child_ops; /* target vector for inftarg.c */
56 extern void _initialize_freebsd_uthread PARAMS ((void));
58 /* Set to true while we are part-way through attaching */
59 static int freebsd_uthread_attaching;
61 static int freebsd_uthread_active = 0;
62 static CORE_ADDR P_thread_list;
63 static CORE_ADDR P_thread_run;
65 /* Pointer to the next function on the objfile event chain. */
66 static void (*target_new_objfile_chain) (struct objfile *objfile);
68 static void freebsd_uthread_resume PARAMS ((ptid_t pid, int step,
69 enum target_signal signo));
71 static void init_freebsd_uthread_ops PARAMS ((void));
73 static struct target_ops freebsd_uthread_ops;
75 static ptid_t find_active_ptid PARAMS ((void));
77 struct cached_pthread {
87 static ptid_t cached_ptid;
88 static struct cached_pthread cached_pthread;
89 static CORE_ADDR cached_pthread_addr;
91 LIST_HEAD(idmaplist, idmap);
94 LIST_ENTRY(idmap) link;
99 #define MAPHASH_SIZE 257
101 #define TID_MAX 16383
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 */
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;
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;
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)
132 int tid = next_free_tid;
134 tid_to_hash[tid] = h;
135 next_free_tid = TID_ADD1(next_free_tid);
136 if (next_free_tid == last_free_tid)
140 for (i = last_free_tid; TID_ADD1(i) != last_free_tid; i = TID_ADD1(i))
143 if (TID_ADD1(i) == last_free_tid)
145 error("too many threads");
149 for (i = TID_ADD1(i); IS_TID_FREE(i); i = TID_ADD1(i))
158 find_ptid(u_int64_t uniqueid)
160 int h = UNIQUEID_HASH(uniqueid);
163 LIST_FOREACH(im, &map_hash[h], link)
164 if (im->uniqueid == uniqueid)
165 return MERGEPID(PIDGET(inferior_ptid), im->tid);
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);
172 return MERGEPID(PIDGET(inferior_ptid), im->tid);
176 free_ptid(ptid_t ptid)
178 int tid = TIDGET(ptid);
179 int h = tid_to_hash[tid];
184 LIST_FOREACH(im, &map_hash[h], link)
190 LIST_REMOVE(im, link);
191 tid_to_hash[tid] = -1;
195 #define READ_OFFSET(field) read_memory(P_thread_##field##_offset, \
196 (char *) &field##_offset, \
197 sizeof(field##_offset))
199 #define READ_VALUE(name) read_memory(P_thread_##name##_value, \
200 (char *) &name##_value, \
201 sizeof(name##_value))
204 read_thread_offsets (void)
207 READ_OFFSET(uniqueid);
212 READ_VALUE(PS_RUNNING);
216 #define READ_FIELD(ptr, T, field, result) \
217 read_memory ((ptr) + field##_offset, (char *) &(result), sizeof result)
220 read_pthread_uniqueid (CORE_ADDR ptr)
223 READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
228 read_pthread_next (CORE_ADDR ptr)
231 READ_FIELD(ptr, CORE_ADDR, next, next);
236 read_cached_pthread (CORE_ADDR ptr, struct cached_pthread *cache)
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);
245 find_active_ptid (void)
249 read_memory ((CORE_ADDR)P_thread_run,
253 return find_ptid(read_pthread_uniqueid(ptr));
256 static CORE_ADDR find_pthread_addr PARAMS ((ptid_t ptid));
257 static struct cached_pthread * find_pthread PARAMS ((ptid_t ptid));
260 find_pthread_addr (ptid_t ptid)
264 if (ptid_equal(ptid, cached_ptid))
265 return cached_pthread_addr;
267 read_memory ((CORE_ADDR)P_thread_list,
273 if (ptid_equal(find_ptid(read_pthread_uniqueid(ptr)), ptid))
276 cached_pthread_addr = ptr;
277 read_cached_pthread(ptr, &cached_pthread);
280 ptr = read_pthread_next(ptr);
286 static struct cached_pthread *
287 find_pthread (ptid_t ptid)
291 if (ptid_equal(ptid, cached_ptid))
292 return &cached_pthread;
294 read_memory ((CORE_ADDR)P_thread_list,
300 if (ptid_equal(find_ptid(read_pthread_uniqueid(ptr)), ptid))
303 cached_pthread_addr = ptr;
304 read_cached_pthread(ptr, &cached_pthread);
305 return &cached_pthread;
307 ptr = read_pthread_next(ptr);
311 error ("Can't find pthread %d,%d", PIDGET(ptid), TIDGET(ptid));
317 /* Most target vector functions from here on actually just pass through to
318 inftarg.c, as they don't need to do anything specific for threads. */
322 freebsd_uthread_open (char *arg, int from_tty)
324 child_ops.to_open (arg, from_tty);
327 /* Attach to process PID, then initialize for debugging it
328 and wait for the trace-trap that results from attaching. */
331 freebsd_uthread_attach (char *args, int from_tty)
333 child_ops.to_attach (args, from_tty);
334 push_target (&freebsd_uthread_ops);
335 freebsd_uthread_attaching = 1;
338 /* After an attach, see if the target is threaded */
341 freebsd_uthread_post_attach (int pid)
343 if (freebsd_uthread_active)
345 read_thread_offsets ();
346 inferior_ptid = find_active_ptid ();
347 add_thread (inferior_ptid);
351 unpush_target (&freebsd_uthread_ops);
352 push_target (&child_ops);
355 freebsd_uthread_attaching = 0;
358 /* Take a program previously attached to and detaches it.
359 The program resumes execution and will no longer stop
360 on signals, etc. We'd better not have left any breakpoints
361 in the program or it'll die when it hits one. For this
362 to work, it may be necessary for the process to have been
363 previously attached. It *might* work if the program was
364 started via the normal ptrace (PTRACE_TRACEME). */
367 freebsd_uthread_detach (char *args, int from_tty)
369 child_ops.to_detach (args, from_tty);
372 /* Resume execution of process PID. If STEP is nozero, then
373 just single step it. If SIGNAL is nonzero, restart it with that
374 signal activated. We may have to convert pid from a thread-id to an LWP id
378 freebsd_uthread_resume (ptid_t ptid, int step, enum target_signal signo)
380 if (freebsd_uthread_attaching)
382 child_ops.to_resume (ptid, step, signo);
386 child_ops.to_resume (ptid, step, signo);
387 cached_ptid = MERGEPID(0, 0);
390 /* Wait for any threads to stop. We may have to convert PID from a thread id
391 to a LWP id, and vice versa on the way out. */
394 freebsd_uthread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
398 if (freebsd_uthread_attaching)
400 return child_ops.to_wait (ptid, ourstatus);
403 rtnval = child_ops.to_wait (ptid, ourstatus);
405 if (PIDGET(rtnval) >= 0)
407 rtnval = find_active_ptid ();
408 if (!in_thread_list (rtnval))
415 /* XXX: this needs to be selected by target, not [build] host */
418 #include "i386-tdep.h"
420 static char sigmap[I386_SSE_NUM_REGS] = /* map reg to sigcontext */
438 -1, -1, -1, -1, -1, -1, -1, /* st0-st7 */
439 -1, -1, -1, -1, -1, -1, -1, /* fctrl-fop */
440 -1, -1, -1, -1, -1, -1, -1, /* xmm0-xmm7 */
444 static char jmpmap[I386_SSE_NUM_REGS] = /* map reg to jmp_buf */
462 -1, -1, -1, -1, -1, -1, -1, /* st0-st7 */
463 -1, -1, -1, -1, -1, -1, -1, /* fctrl-fop */
464 -1, -1, -1, -1, -1, -1, -1, /* xmm0-xmm7 */
472 #include "amd64-tdep.h"
474 // XXX:DEO not fully ported from i386 yet!!
476 static char sigmap[AMD64_NUM_REGS_TOTAL] = /* map reg to sigcontext */
494 -1, -1, -1, -1, -1, -1, -1, /* st0-st7 */
495 -1, -1, -1, -1, -1, -1, -1, /* fctrl-fop */
496 -1, -1, -1, -1, -1, -1, -1, /* xmm0-xmm7 */
500 static char jmpmap[AMD64_NUM_REGS_TOTAL] = /* map reg to jmp_buf */
518 -1, -1, -1, -1, -1, -1, -1, /* st0-st7 */
519 -1, -1, -1, -1, -1, -1, -1, /* fctrl-fop */
520 -1, -1, -1, -1, -1, -1, -1, /* xmm0-xmm7 */
528 #include "alpha-tdep.h"
530 static char sigmap[ALPHA_NUM_REGS] = /* map reg to sigcontext */
532 1, 2, 3, 4, 5, 6, 7, 8, /* v0 - t6 */
533 9, 10, 11, 12, 13, 14, 15, 16, /* t7 - fp */
534 17, 18, 19, 20, 21, 22, 23, 24, /* a0 - t9 */
535 25, 26, 27, 28, 29, 30, 31, 32, /* t10 - zero */
536 38, 39, 40, 41, 42, 43, 44, 45, /* f0 - f7 */
537 46, 47, 48, 49, 50, 51, 52, 53, /* f8 - f15 */
538 54, 55, 56, 57, 58, 59, 60, 61, /* f16 - f23 */
539 62, 63, 64, 65, 66, 67, 68, 69, /* f24 - f31 */
542 static char jmpmap[ALPHA_NUM_REGS] = {
543 4, 5, 6, 7, 8, 9, 10, 11, /* v0 - t6 */
544 12, 13, 14, 15, 16, 17, 18, 19, /* t7 - fp */
545 20, 21, 22, 23, 24, 25, 26, 27, /* a0 - t9 */
546 28, 29, 30, 31, 32, 33, 34, 35, /* t10 - zero */
547 37, 38, 39, 40, 41, 42, 43, 44, /* f0 - f7 */
548 45, 46, 47, 48, 49, 50, 51, 52, /* f8 - f15 */
549 53, 54, 55, 56, 57, 58, 59, 60, /* f16 - f23 */
550 61, 62, 63, 64, 65, 66, 67, 68, /* f24 - f31 */
558 static char sigmap[125] = /* map reg to sigcontext */
562 static char jmpmap[125] = {
569 freebsd_uthread_fetch_registers (int regno)
571 struct cached_pthread *thread;
573 int first_regno, last_regno;
577 if (freebsd_uthread_attaching || TIDGET(inferior_ptid) == 0)
579 child_ops.to_fetch_registers (regno);
583 thread = find_pthread (inferior_ptid);
584 active = (ptid_equal(inferior_ptid, find_active_ptid()));
588 child_ops.to_fetch_registers (regno);
595 last_regno = NUM_REGS - 1;
603 regbase = (register_t*) &thread->ctx.jb[0];
606 for (regno = first_regno; regno <= last_regno; regno++)
608 if (regmap[regno] == -1)
609 child_ops.to_fetch_registers (regno);
612 supply_register (regno, (char*) ®base[regmap[regno]]);
614 supply_register (regno, NULL);
619 freebsd_uthread_store_registers (int regno)
621 struct cached_pthread *thread;
623 int first_regno, last_regno;
627 if (freebsd_uthread_attaching)
629 child_ops.to_store_registers (regno);
633 thread = find_pthread (inferior_ptid);
635 if (thread->state == PS_RUNNING_value)
637 child_ops.to_store_registers (regno);
644 last_regno = NUM_REGS - 1;
652 regbase = (u_int32_t*) &thread->ctx.jb[0];
655 ptr = find_pthread_addr (inferior_ptid);
656 for (regno = first_regno; regno <= last_regno; regno++)
658 if (regmap[regno] == -1)
659 child_ops.to_store_registers (regno);
662 u_int32_t *reg = ®base[regmap[regno]];
665 /* Hang onto cached value */
667 memcpy(reg, deprecated_registers /*regcache_collect ()*/+ DEPRECATED_REGISTER_BYTE (regno),
668 DEPRECATED_REGISTER_RAW_SIZE (regno));
670 /* And push out to inferior */
671 off = (char *) reg - (char *) thread;
672 write_memory (ptr + off,
674 deprecated_registers /*regcache_collect ()*/+ DEPRECATED_REGISTER_BYTE (regno),
675 DEPRECATED_REGISTER_RAW_SIZE (regno));
680 /* Get ready to modify the registers array. On machines which store
681 individual registers, this doesn't need to do anything. On machines
682 which store all the registers in one fell swoop, this makes sure
683 that registers contains all the registers from the program being
687 freebsd_uthread_prepare_to_store (void)
689 child_ops.to_prepare_to_store ();
693 freebsd_uthread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
694 int dowrite, struct mem_attrib *attrib,
695 struct target_ops *target)
697 return child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite,
701 /* Print status information about what we're accessing. */
704 freebsd_uthread_files_info (struct target_ops *ignore)
706 child_ops.to_files_info (ignore);
710 freebsd_uthread_kill_inferior (void)
712 child_ops.to_kill ();
716 freebsd_uthread_notice_signals (ptid_t ptid)
718 child_ops.to_notice_signals (ptid);
721 /* Fork an inferior process, and start debugging it with /proc. */
724 freebsd_uthread_create_inferior (char *exec_file, char *allargs, char **env,
727 child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
729 if (PIDGET(inferior_ptid) && freebsd_uthread_active)
731 read_thread_offsets ();
732 push_target (&freebsd_uthread_ops);
733 inferior_ptid = find_active_ptid ();
734 add_thread (inferior_ptid);
738 /* This routine is called to find out if the inferior is using threads.
739 We check for the _thread_run and _thread_list globals. */
742 freebsd_uthread_new_objfile (struct objfile *objfile)
744 struct minimal_symbol *ms;
748 freebsd_uthread_active = 0;
752 ms = lookup_minimal_symbol ("_thread_run", NULL, objfile);
757 P_thread_run = SYMBOL_VALUE_ADDRESS (ms);
759 ms = lookup_minimal_symbol ("_thread_list", NULL, objfile);
764 P_thread_list = SYMBOL_VALUE_ADDRESS (ms);
766 #define OFFSET_SYM(field) "_thread_" #field "_offset"
767 #define LOOKUP_OFFSET(field) \
769 ms = lookup_minimal_symbol (OFFSET_SYM(field), NULL, objfile); \
772 P_thread_##field##_offset = SYMBOL_VALUE_ADDRESS (ms); \
775 #define VALUE_SYM(name) "_thread_" #name "_value"
776 #define LOOKUP_VALUE(name) \
778 ms = lookup_minimal_symbol (VALUE_SYM(name), NULL, objfile); \
781 P_thread_##name##_value = SYMBOL_VALUE_ADDRESS (ms); \
785 LOOKUP_OFFSET(uniqueid);
786 LOOKUP_OFFSET(state);
790 LOOKUP_VALUE(PS_RUNNING);
791 LOOKUP_VALUE(PS_DEAD);
793 freebsd_uthread_active = 1;
796 /* Clean up after the inferior dies. */
799 freebsd_uthread_mourn_inferior ()
801 child_ops.to_mourn_inferior ();
802 unpush_target (&freebsd_uthread_ops);
805 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
808 freebsd_uthread_can_run ()
810 return child_suppress_run;
814 freebsd_uthread_thread_alive (ptid_t ptid)
816 struct cached_pthread *thread;
819 if (freebsd_uthread_attaching)
823 * We can get called from child_ops.to_wait() which passes the underlying
824 * pid (without a thread number).
826 if (TIDGET(ptid) == 0)
829 if (find_pthread_addr (ptid) != 0)
831 thread = find_pthread (ptid);
832 ret = (thread->state != PS_DEAD_value);
842 freebsd_uthread_stop (void)
844 child_ops.to_stop ();
848 freebsd_uthread_find_new_threads (void)
854 read_memory ((CORE_ADDR)P_thread_list,
860 READ_FIELD(ptr, int, state, state);
861 READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
862 if (state != PS_DEAD_value &&
863 !in_thread_list (find_ptid(uniqueid)))
864 add_thread (find_ptid(uniqueid));
865 ptr = read_pthread_next(ptr);
869 /* MUST MATCH enum pthread_state */
870 static const char *statenames[] = {
896 freebsd_uthread_get_thread_info (ref, selection, info)
899 struct gdb_ext_thread_info *info;
902 struct cached_pthread *thread = find_pthread (pid);
903 struct cleanup *old_chain;
905 old_chain = save_inferior_pid ();
906 inferior_pid = main_pid;
908 memset(&info->threadid, 0, OPAQUETHREADBYTES);
910 memcpy(&info->threadid, ref, sizeof *ref);
911 info->active = thread->state == PS_RUNNING_value;
912 strcpy(info->display, statenames[thread->state]);
914 read_memory ((CORE_ADDR) thread->name, info->shortname, 32);
916 strcpy(info->shortname, "");
918 do_cleanups (old_chain);
925 freebsd_uthread_pid_to_str (ptid_t ptid)
929 if (DEPRECATED_STREQ (current_target.to_shortname, "freebsd-uthreads"))
930 sprintf (buf, "Process %d, Thread %ld",
931 PIDGET(ptid), TIDGET(ptid));
933 sprintf (buf, "Process %d", PIDGET(ptid));
940 init_freebsd_uthread_ops ()
942 freebsd_uthread_ops.to_shortname = "freebsd-uthreads";
943 freebsd_uthread_ops.to_longname = "FreeBSD uthreads";
944 freebsd_uthread_ops.to_doc = "FreeBSD user threads support.";
945 freebsd_uthread_ops.to_open = freebsd_uthread_open;
946 freebsd_uthread_ops.to_attach = freebsd_uthread_attach;
947 freebsd_uthread_ops.to_post_attach = freebsd_uthread_post_attach;
948 freebsd_uthread_ops.to_detach = freebsd_uthread_detach;
949 freebsd_uthread_ops.to_resume = freebsd_uthread_resume;
950 freebsd_uthread_ops.to_wait = freebsd_uthread_wait;
951 freebsd_uthread_ops.to_fetch_registers = freebsd_uthread_fetch_registers;
952 freebsd_uthread_ops.to_store_registers = freebsd_uthread_store_registers;
953 freebsd_uthread_ops.to_prepare_to_store = freebsd_uthread_prepare_to_store;
954 freebsd_uthread_ops.to_xfer_memory = freebsd_uthread_xfer_memory;
955 freebsd_uthread_ops.to_files_info = freebsd_uthread_files_info;
956 freebsd_uthread_ops.to_insert_breakpoint = memory_insert_breakpoint;
957 freebsd_uthread_ops.to_remove_breakpoint = memory_remove_breakpoint;
958 freebsd_uthread_ops.to_terminal_init = terminal_init_inferior;
959 freebsd_uthread_ops.to_terminal_inferior = terminal_inferior;
960 freebsd_uthread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
961 freebsd_uthread_ops.to_terminal_ours = terminal_ours;
962 freebsd_uthread_ops.to_terminal_info = child_terminal_info;
963 freebsd_uthread_ops.to_kill = freebsd_uthread_kill_inferior;
964 freebsd_uthread_ops.to_create_inferior = freebsd_uthread_create_inferior;
965 freebsd_uthread_ops.to_mourn_inferior = freebsd_uthread_mourn_inferior;
966 freebsd_uthread_ops.to_can_run = freebsd_uthread_can_run;
967 freebsd_uthread_ops.to_notice_signals = freebsd_uthread_notice_signals;
968 freebsd_uthread_ops.to_thread_alive = freebsd_uthread_thread_alive;
969 freebsd_uthread_ops.to_stop = freebsd_uthread_stop;
970 freebsd_uthread_ops.to_stratum = process_stratum;
971 freebsd_uthread_ops.to_has_all_memory = 1;
972 freebsd_uthread_ops.to_has_memory = 1;
973 freebsd_uthread_ops.to_has_stack = 1;
974 freebsd_uthread_ops.to_has_registers = 1;
975 freebsd_uthread_ops.to_has_execution = 1;
976 freebsd_uthread_ops.to_has_thread_control = 0;
977 freebsd_uthread_ops.to_magic = OPS_MAGIC;
978 freebsd_uthread_ops.to_find_new_threads = freebsd_uthread_find_new_threads;
979 freebsd_uthread_ops.to_pid_to_str = freebsd_uthread_pid_to_str;
981 freebsd_uthread_vec.get_thread_info = freebsd_uthread_get_thread_info;
986 _initialize_freebsd_uthread ()
988 init_freebsd_uthread_ops ();
989 add_target (&freebsd_uthread_ops);
991 target_new_objfile_chain = deprecated_target_new_objfile_hook;
992 deprecated_target_new_objfile_hook = freebsd_uthread_new_objfile;
994 child_suppress_run = 1;