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 /* This module implements a sort of half target that sits between the
21 machine-independent parts of GDB and the ptrace interface (infptrace.c) to
22 provide access to the FreeBSD user-mode thread implementation.
24 FreeBSD threads are true user-mode threads, which are invoked via
25 the pthread_* interfaces. These are mostly implemented in
26 user-space, with all thread context kept in various structures that
27 live in the user's heap. For the most part, the kernel has no
28 knowlege of these threads.
30 Based largely on hpux-thread.c
35 * $FreeBSD: src/gnu/usr.bin/binutils/gdb/freebsd-uthread.c,v 1.3.2.4 2003/01/06 11:28:54 fjoe Exp $
36 * $DragonFly: src/gnu/usr.bin/binutils214/gdb/Attic/freebsd-uthread.c,v 1.1 2004/02/01 08:53:04 dillon Exp $
40 #include <sys/queue.h>
43 #include "gdbthread.h"
51 extern int child_suppress_run;
52 extern struct target_ops child_ops; /* target vector for inftarg.c */
54 extern void _initialize_freebsd_uthread PARAMS ((void));
56 static int main_pid = -1; /* Real process ID */
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 static struct cleanup * save_inferior_pid PARAMS ((void));
67 static void restore_inferior_pid PARAMS ((int pid));
69 static void freebsd_uthread_resume PARAMS ((int pid, int step,
70 enum target_signal signo));
72 static void init_freebsd_uthread_ops PARAMS ((void));
74 static struct target_ops freebsd_uthread_ops;
75 static struct target_thread_vector freebsd_uthread_vec;
81 save_inferior_pid - Save inferior_pid on the cleanup list
82 restore_inferior_pid - Restore inferior_pid from the cleanup list
86 struct cleanup *save_inferior_pid ()
87 void restore_inferior_pid (int pid)
91 These two functions act in unison to restore inferior_pid in
96 inferior_pid is a global variable that needs to be changed by many of
97 these routines before calling functions in procfs.c. In order to
98 guarantee that inferior_pid gets restored (in case of errors), you
99 need to call save_inferior_pid before changing it. At the end of the
100 function, you should invoke do_cleanups to restore it.
104 static struct cleanup *
107 return make_cleanup ((make_cleanup_func) restore_inferior_pid,
108 (void *)(intptr_t) inferior_pid);
112 restore_inferior_pid (pid)
118 static int find_active_thread PARAMS ((void));
120 struct cached_pthread {
130 static int cached_thread;
131 static struct cached_pthread cached_pthread;
132 static CORE_ADDR cached_pthread_addr;
134 #define THREADID_TID(id) ((id) >> 17)
135 #define THREADID_PID(id) ((id) & ((1 << 17) - 1))
137 LIST_HEAD(idmaplist, idmap);
140 LIST_ENTRY(idmap) link;
145 #define MAPHASH_SIZE 257
147 #define TID_MAX 16383
149 static int tid_to_hash[TID_MAX + 1]; /* set to map_hash index */
150 static struct idmaplist map_hash[MAPHASH_SIZE];
151 static int next_free_tid = TID_MIN; /* first available tid */
152 static int last_free_tid = TID_MIN; /* first unavailable */
154 static CORE_ADDR P_thread_next_offset;
155 static CORE_ADDR P_thread_uniqueid_offset;
156 static CORE_ADDR P_thread_state_offset;
157 static CORE_ADDR P_thread_name_offset;
158 static CORE_ADDR P_thread_ctx_offset;
159 static CORE_ADDR P_thread_PS_RUNNING_value;
160 static CORE_ADDR P_thread_PS_DEAD_value;
162 static int next_offset;
163 static int uniqueid_offset;
164 static int state_offset;
165 static int name_offset;
166 static int ctx_offset;
167 static int PS_RUNNING_value;
168 static int PS_DEAD_value;
170 #define UNIQUEID_HASH(id) (id % MAPHASH_SIZE)
171 #define TID_ADD1(tid) (((tid) + 1) == TID_MAX + 1 \
172 ? TID_MIN : (tid) + 1)
173 #define IS_TID_FREE(tid) (tid_to_hash[tid] == -1)
179 int tid = next_free_tid;
181 tid_to_hash[tid] = h;
182 next_free_tid = TID_ADD1(next_free_tid);
183 if (next_free_tid == last_free_tid)
187 for (i = last_free_tid; TID_ADD1(i) != last_free_tid; i = TID_ADD1(i))
190 if (TID_ADD1(i) == last_free_tid)
192 error("too many threads");
196 for (i = TID_ADD1(i); IS_TID_FREE(i); i = TID_ADD1(i))
208 int h = UNIQUEID_HASH(uniqueid);
211 LIST_FOREACH(im, &map_hash[h], link)
212 if (im->uniqueid == uniqueid)
213 return (im->tid << 17) + main_pid;
215 im = xmalloc(sizeof(struct idmap));
216 im->uniqueid = uniqueid;
217 im->tid = get_new_tid(h);
218 LIST_INSERT_HEAD(&map_hash[h], im, link);
220 return (im->tid << 17) + main_pid;
227 int tid = THREADID_TID(pid);
228 int h = tid_to_hash[tid];
233 LIST_FOREACH(im, &map_hash[h], link)
239 LIST_REMOVE(im, link);
240 tid_to_hash[tid] = -1;
244 #define READ_OFFSET(field) read_memory(P_thread_##field##_offset, \
245 (char *) &field##_offset, \
246 sizeof(field##_offset))
248 #define READ_VALUE(name) read_memory(P_thread_##name##_value, \
249 (char *) &name##_value, \
250 sizeof(name##_value))
253 read_thread_offsets ()
256 READ_OFFSET(uniqueid);
261 READ_VALUE(PS_RUNNING);
265 #define READ_FIELD(ptr, T, field, result) \
266 read_memory ((ptr) + field##_offset, (char *) &(result), sizeof result)
269 read_pthread_uniqueid (ptr)
273 READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
278 read_pthread_next (ptr)
282 READ_FIELD(ptr, CORE_ADDR, next, next);
287 read_cached_pthread (ptr, cache)
289 struct cached_pthread *cache;
291 READ_FIELD(ptr, u_int64_t, uniqueid, cache->uniqueid);
292 READ_FIELD(ptr, int, state, cache->state);
293 READ_FIELD(ptr, CORE_ADDR, name, cache->name);
294 READ_FIELD(ptr, ucontext_t, ctx, cache->ctx);
298 find_active_thread ()
305 read_memory ((CORE_ADDR)P_thread_run,
309 return find_pid(read_pthread_uniqueid(ptr));
312 static CORE_ADDR find_pthread_addr PARAMS ((int thread));
313 static struct cached_pthread * find_pthread PARAMS ((int thread));
316 find_pthread_addr (thread)
321 if (thread == cached_thread)
322 return cached_pthread_addr;
324 read_memory ((CORE_ADDR)P_thread_list,
330 if (find_pid(read_pthread_uniqueid(ptr)) == thread)
332 cached_thread = thread;
333 cached_pthread_addr = ptr;
334 read_cached_pthread(ptr, &cached_pthread);
337 ptr = read_pthread_next(ptr);
343 static struct cached_pthread *
344 find_pthread (thread)
349 if (thread == cached_thread)
350 return &cached_pthread;
352 read_memory ((CORE_ADDR)P_thread_list,
358 if (find_pid(read_pthread_uniqueid(ptr)) == thread)
360 cached_thread = thread;
361 cached_pthread_addr = ptr;
362 read_cached_pthread(ptr, &cached_pthread);
363 return &cached_pthread;
365 ptr = read_pthread_next(ptr);
369 error ("Can't find pthread %d,%d",
370 THREADID_TID(thread), THREADID_PID(thread));
376 /* Most target vector functions from here on actually just pass through to
377 inftarg.c, as they don't need to do anything specific for threads. */
381 freebsd_uthread_open (arg, from_tty)
385 child_ops.to_open (arg, from_tty);
388 /* Attach to process PID, then initialize for debugging it
389 and wait for the trace-trap that results from attaching. */
392 freebsd_uthread_attach (args, from_tty)
396 child_ops.to_attach (args, from_tty);
397 push_target (&freebsd_uthread_ops);
398 freebsd_uthread_attaching = 1;
401 /* After an attach, see if the target is threaded */
404 freebsd_uthread_post_attach (pid)
407 if (freebsd_uthread_active)
409 read_thread_offsets ();
413 bind_target_thread_vector (&freebsd_uthread_vec);
415 inferior_pid = find_active_thread ();
417 add_thread (inferior_pid);
421 unpush_target (&freebsd_uthread_ops);
422 push_target (&child_ops);
425 freebsd_uthread_attaching = 0;
428 /* Take a program previously attached to and detaches it.
429 The program resumes execution and will no longer stop
430 on signals, etc. We'd better not have left any breakpoints
431 in the program or it'll die when it hits one. For this
432 to work, it may be necessary for the process to have been
433 previously attached. It *might* work if the program was
434 started via the normal ptrace (PTRACE_TRACEME). */
437 freebsd_uthread_detach (args, from_tty)
441 child_ops.to_detach (args, from_tty);
444 /* Resume execution of process PID. If STEP is nozero, then
445 just single step it. If SIGNAL is nonzero, restart it with that
446 signal activated. We may have to convert pid from a thread-id to an LWP id
450 freebsd_uthread_resume (pid, step, signo)
453 enum target_signal signo;
455 struct cleanup *old_chain;
457 if (freebsd_uthread_attaching)
459 child_ops.to_resume (pid, step, signo);
463 old_chain = save_inferior_pid ();
465 pid = inferior_pid = main_pid;
467 child_ops.to_resume (pid, step, signo);
471 do_cleanups (old_chain);
474 /* Wait for any threads to stop. We may have to convert PID from a thread id
475 to a LWP id, and vice versa on the way out. */
478 freebsd_uthread_wait (pid, ourstatus)
480 struct target_waitstatus *ourstatus;
483 struct cleanup *old_chain;
485 if (freebsd_uthread_attaching)
487 return child_ops.to_wait (pid, ourstatus);
490 old_chain = save_inferior_pid ();
492 inferior_pid = main_pid;
497 rtnval = child_ops.to_wait (pid, ourstatus);
501 rtnval = find_active_thread ();
502 if (!in_thread_list (rtnval))
506 do_cleanups (old_chain);
513 static char jmpmap[NUM_REGS] = /* map reg to jmp_buf */
537 static char jmpmap[NUM_REGS] = {
538 4, 5, 6, 7, 8, 9, 10, 11, /* v0 - t6 */
539 12, 13, 14, 15, 16, 17, 18, 19, /* t7 - fp */
540 20, 21, 22, 23, 24, 25, 26, 27, /* a0 - t9 */
541 28, 29, 30, 31, 32, 33, 34, 35, /* t10 - zero */
542 37, 38, 39, 40, 41, 42, 43, 44, /* f0 - f7 */
543 45, 46, 47, 48, 49, 50, 51, 52, /* f8 - f15 */
544 53, 54, 55, 56, 57, 58, 59, 60, /* f16 - f23 */
545 61, 62, 63, 64, 65, 66, 67, 68, /* f24 - f31 */
552 freebsd_uthread_fetch_registers (regno)
555 struct cached_pthread *thread;
556 struct cleanup *old_chain;
558 int first_regno, last_regno;
562 if (freebsd_uthread_attaching)
564 child_ops.to_fetch_registers (regno);
568 thread = find_pthread (inferior_pid);
570 old_chain = save_inferior_pid ();
572 active = (inferior_pid == find_active_thread());
574 inferior_pid = main_pid;
578 child_ops.to_fetch_registers (regno);
580 do_cleanups (old_chain);
588 last_regno = NUM_REGS - 1;
596 regbase = (register_t*) &thread->ctx.jb[0];
599 for (regno = first_regno; regno <= last_regno; regno++)
601 if (regmap[regno] == -1)
602 child_ops.to_fetch_registers (regno);
604 supply_register (regno, (char*) ®base[regmap[regno]]);
607 do_cleanups (old_chain);
611 freebsd_uthread_store_registers (regno)
614 struct cached_pthread *thread;
616 struct cleanup *old_chain;
617 int first_regno, last_regno;
621 if (freebsd_uthread_attaching)
623 child_ops.to_store_registers (regno);
627 thread = find_pthread (inferior_pid);
629 old_chain = save_inferior_pid ();
631 inferior_pid = main_pid;
633 if (thread->state == PS_RUNNING_value)
635 child_ops.to_store_registers (regno);
637 do_cleanups (old_chain);
645 last_regno = NUM_REGS - 1;
653 regbase = (u_int32_t*) &thread->ctx.jb[0];
656 ptr = find_pthread_addr (inferior_pid);
657 for (regno = first_regno; regno <= last_regno; regno++)
659 if (regmap[regno] == -1)
660 child_ops.to_store_registers (regno);
663 u_int32_t *reg = ®base[regmap[regno]];
666 /* Hang onto cached value */
667 memcpy(reg, registers + REGISTER_BYTE (regno),
668 REGISTER_RAW_SIZE (regno));
670 /* And push out to inferior */
671 off = (char *) reg - (char *) thread;
672 write_memory (ptr + off,
673 registers + REGISTER_BYTE (regno),
674 REGISTER_RAW_SIZE (regno));
678 do_cleanups (old_chain);
681 /* Get ready to modify the registers array. On machines which store
682 individual registers, this doesn't need to do anything. On machines
683 which store all the registers in one fell swoop, this makes sure
684 that registers contains all the registers from the program being
688 freebsd_uthread_prepare_to_store ()
690 struct cleanup *old_chain;
692 if (freebsd_uthread_attaching)
694 child_ops.to_prepare_to_store ();
698 old_chain = save_inferior_pid ();
699 inferior_pid = main_pid;
701 child_ops.to_prepare_to_store ();
703 do_cleanups (old_chain);
707 freebsd_uthread_xfer_memory (memaddr, myaddr, len, dowrite, target)
712 struct target_ops *target; /* ignored */
715 struct cleanup *old_chain;
717 if (freebsd_uthread_attaching)
719 return child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
722 old_chain = save_inferior_pid ();
724 inferior_pid = main_pid;
726 retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
728 do_cleanups (old_chain);
733 /* Print status information about what we're accessing. */
736 freebsd_uthread_files_info (ignore)
737 struct target_ops *ignore;
739 child_ops.to_files_info (ignore);
743 freebsd_uthread_kill_inferior ()
745 inferior_pid = main_pid;
746 child_ops.to_kill ();
750 freebsd_uthread_notice_signals (pid)
753 struct cleanup *old_chain;
754 old_chain = save_inferior_pid ();
755 inferior_pid = main_pid;
757 child_ops.to_notice_signals (pid);
759 do_cleanups (old_chain);
762 /* Fork an inferior process, and start debugging it with /proc. */
765 freebsd_uthread_create_inferior (exec_file, allargs, env)
770 child_ops.to_create_inferior (exec_file, allargs, env);
772 if (inferior_pid && freebsd_uthread_active)
774 read_thread_offsets ();
776 main_pid = inferior_pid;
778 push_target (&freebsd_uthread_ops);
779 bind_target_thread_vector (&freebsd_uthread_vec);
781 inferior_pid = find_active_thread ();
783 add_thread (inferior_pid);
787 /* This routine is called to find out if the inferior is using threads.
788 We check for the _thread_run and _thread_list globals. */
791 freebsd_uthread_new_objfile (objfile)
792 struct objfile *objfile;
794 struct minimal_symbol *ms;
798 freebsd_uthread_active = 0;
802 ms = lookup_minimal_symbol ("_thread_run", NULL, objfile);
807 P_thread_run = SYMBOL_VALUE_ADDRESS (ms);
809 ms = lookup_minimal_symbol ("_thread_list", NULL, objfile);
814 P_thread_list = SYMBOL_VALUE_ADDRESS (ms);
816 #define OFFSET_SYM(field) "_thread_" #field "_offset"
817 #define LOOKUP_OFFSET(field) \
819 ms = lookup_minimal_symbol (OFFSET_SYM(field), NULL, objfile); \
822 P_thread_##field##_offset = SYMBOL_VALUE_ADDRESS (ms); \
825 #define VALUE_SYM(name) "_thread_" #name "_value"
826 #define LOOKUP_VALUE(name) \
828 ms = lookup_minimal_symbol (VALUE_SYM(name), NULL, objfile); \
831 P_thread_##name##_value = SYMBOL_VALUE_ADDRESS (ms); \
835 LOOKUP_OFFSET(uniqueid);
836 LOOKUP_OFFSET(state);
840 LOOKUP_VALUE(PS_RUNNING);
841 LOOKUP_VALUE(PS_DEAD);
843 freebsd_uthread_active = 1;
847 freebsd_uthread_has_exited (pid, wait_status, exit_status)
852 int t = child_ops.to_has_exited (pid, wait_status, exit_status);
858 /* Clean up after the inferior dies. */
861 freebsd_uthread_mourn_inferior ()
863 inferior_pid = main_pid; /* don't bother to restore inferior_pid */
864 child_ops.to_mourn_inferior ();
865 unpush_target (&freebsd_uthread_ops);
868 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
871 freebsd_uthread_can_run ()
873 return child_suppress_run;
877 freebsd_uthread_thread_alive (pid)
880 struct cleanup *old_chain;
881 struct cached_pthread *thread;
884 if (freebsd_uthread_attaching)
888 * We can get called from child_ops.to_wait() which passes the underlying
889 * pid (without a thread number).
891 if (THREADID_TID(pid) == 0)
894 old_chain = save_inferior_pid ();
895 inferior_pid = main_pid;
897 if (find_pthread_addr (pid) != 0)
899 thread = find_pthread (pid);
900 ret = (thread->state != PS_DEAD_value);
903 do_cleanups (old_chain);
912 freebsd_uthread_stop ()
914 struct cleanup *old_chain;
915 old_chain = save_inferior_pid ();
916 inferior_pid = main_pid;
918 child_ops.to_stop ();
920 do_cleanups (old_chain);
924 freebsd_uthread_find_new_threads ()
929 struct cleanup *old_chain;
931 old_chain = save_inferior_pid ();
932 inferior_pid = main_pid;
934 read_memory ((CORE_ADDR)P_thread_list,
940 READ_FIELD(ptr, int, state, state);
941 READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
942 if (state != PS_DEAD_value &&
943 !in_thread_list (find_pid(uniqueid)))
944 add_thread (find_pid(uniqueid));
945 ptr = read_pthread_next(ptr);
948 do_cleanups (old_chain);
953 /* MUST MATCH enum pthread_state */
954 static const char *statenames[] = {
978 freebsd_uthread_get_thread_info (ref, selection, info)
981 struct gdb_ext_thread_info *info;
984 struct cached_pthread *thread = find_pthread (pid);
985 struct cleanup *old_chain;
987 old_chain = save_inferior_pid ();
988 inferior_pid = main_pid;
990 memset(&info->threadid, 0, OPAQUETHREADBYTES);
992 memcpy(&info->threadid, ref, sizeof *ref);
993 info->active = thread->state == PS_RUNNING_value;
994 strcpy(info->display, statenames[thread->state]);
996 read_memory ((CORE_ADDR) thread->name, info->shortname, 32);
998 strcpy(info->shortname, "");
1000 do_cleanups (old_chain);
1005 freebsd_uthread_pid_to_str (pid)
1008 static char buf[30];
1010 if (STREQ (current_target.to_shortname, "freebsd-uthreads"))
1011 sprintf (buf, "process %d, thread %d\0",
1012 THREADID_PID(pid), THREADID_TID(pid));
1014 sprintf (buf, "process %d\0", pid);
1021 init_freebsd_uthread_ops ()
1023 freebsd_uthread_ops.to_shortname = "freebsd-uthreads";
1024 freebsd_uthread_ops.to_longname = "FreeBSD uthreads";
1025 freebsd_uthread_ops.to_doc = "FreeBSD user threads support.";
1026 freebsd_uthread_ops.to_open = freebsd_uthread_open;
1027 freebsd_uthread_ops.to_attach = freebsd_uthread_attach;
1028 freebsd_uthread_ops.to_post_attach = freebsd_uthread_post_attach;
1029 freebsd_uthread_ops.to_detach = freebsd_uthread_detach;
1030 freebsd_uthread_ops.to_resume = freebsd_uthread_resume;
1031 freebsd_uthread_ops.to_wait = freebsd_uthread_wait;
1032 freebsd_uthread_ops.to_fetch_registers = freebsd_uthread_fetch_registers;
1033 freebsd_uthread_ops.to_store_registers = freebsd_uthread_store_registers;
1034 freebsd_uthread_ops.to_prepare_to_store = freebsd_uthread_prepare_to_store;
1035 freebsd_uthread_ops.to_xfer_memory = freebsd_uthread_xfer_memory;
1036 freebsd_uthread_ops.to_files_info = freebsd_uthread_files_info;
1037 freebsd_uthread_ops.to_insert_breakpoint = memory_insert_breakpoint;
1038 freebsd_uthread_ops.to_remove_breakpoint = memory_remove_breakpoint;
1039 freebsd_uthread_ops.to_terminal_init = terminal_init_inferior;
1040 freebsd_uthread_ops.to_terminal_inferior = terminal_inferior;
1041 freebsd_uthread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1042 freebsd_uthread_ops.to_terminal_ours = terminal_ours;
1043 freebsd_uthread_ops.to_terminal_info = child_terminal_info;
1044 freebsd_uthread_ops.to_kill = freebsd_uthread_kill_inferior;
1045 freebsd_uthread_ops.to_create_inferior = freebsd_uthread_create_inferior;
1046 freebsd_uthread_ops.to_has_exited = freebsd_uthread_has_exited;
1047 freebsd_uthread_ops.to_mourn_inferior = freebsd_uthread_mourn_inferior;
1048 freebsd_uthread_ops.to_can_run = freebsd_uthread_can_run;
1049 freebsd_uthread_ops.to_notice_signals = freebsd_uthread_notice_signals;
1050 freebsd_uthread_ops.to_thread_alive = freebsd_uthread_thread_alive;
1051 freebsd_uthread_ops.to_stop = freebsd_uthread_stop;
1052 freebsd_uthread_ops.to_stratum = process_stratum;
1053 freebsd_uthread_ops.to_has_all_memory = 1;
1054 freebsd_uthread_ops.to_has_memory = 1;
1055 freebsd_uthread_ops.to_has_stack = 1;
1056 freebsd_uthread_ops.to_has_registers = 1;
1057 freebsd_uthread_ops.to_has_execution = 1;
1058 freebsd_uthread_ops.to_has_thread_control = 0;
1059 freebsd_uthread_ops.to_magic = OPS_MAGIC;
1061 freebsd_uthread_vec.find_new_threads = freebsd_uthread_find_new_threads;
1062 freebsd_uthread_vec.get_thread_info = freebsd_uthread_get_thread_info;
1066 _initialize_freebsd_uthread ()
1068 init_freebsd_uthread_ops ();
1069 add_target (&freebsd_uthread_ops);
1071 child_suppress_run = 1;