From owner-p4-projects@FreeBSD.ORG Tue Jul 6 13:11:35 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 4D20816A4E1; Tue, 6 Jul 2004 13:11:35 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id ED87616A4CF for ; Tue, 6 Jul 2004 13:11:34 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id E23A443D41 for ; Tue, 6 Jul 2004 13:11:34 +0000 (GMT) (envelope-from davidxu@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.11/8.12.11) with ESMTP id i66DBYsd022040 for ; Tue, 6 Jul 2004 13:11:34 GMT (envelope-from davidxu@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.11/8.12.11/Submit) id i66DBYwI022037 for perforce@freebsd.org; Tue, 6 Jul 2004 13:11:34 GMT (envelope-from davidxu@freebsd.org) Date: Tue, 6 Jul 2004 13:11:34 GMT Message-Id: <200407061311.i66DBYwI022037@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to davidxu@freebsd.org using -f From: David Xu To: Perforce Change Reviews Subject: PERFORCE change 56616 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Jul 2004 13:11:36 -0000 http://perforce.freebsd.org/chv.cgi?CH=56616 Change 56616 by davidxu@davidxu_alona on 2004/07/06 13:10:38 Use the new mechanism in ptrace to resume only one thread. Some cosmetic changes. Affected files ... .. //depot/projects/davidxu_ksedbg/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#7 edit Differences ... ==== //depot/projects/davidxu_ksedbg/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#7 (text+ko) ==== @@ -49,6 +49,8 @@ /* This module's target vector. */ static struct target_ops thread_db_ops; +static struct target_ops base_ops; + /* Pointer to the next function on the objfile event chain. */ static void (*target_new_objfile_chain) (struct objfile *objfile); @@ -66,6 +68,11 @@ /* Connection to the libthread_db library. */ static td_thragent_t *thread_agent; +/* The inactive M:N thread gdb is trying to single step it */ +static ptid_t single_step_inactive_thread; + +static CORE_ADDR single_step_inactive_thread_pc; + /* Pointers to the libthread_db functions. */ static td_err_e (*td_init_p) (void); @@ -101,11 +108,9 @@ static td_err_e (*td_thr_sstep_p) (td_thrhandle_t *th, int step); -static td_err_e (*td_ta_activated_p) (td_thragent_t *ta, int *activated); +static td_err_e (*td_ta_tsd_iter_p) (const td_thragent_t *ta, + td_key_iter_f *func, void *data); -static td_err_e (*td_ta_tsd_iter_p) (const td_thragent_t *ta, td_key_iter_f *func, - void *data); - /* Prototypes for local functions. */ static void fbsd_thread_find_new_threads (void); @@ -294,6 +299,7 @@ case TD_OK: /* The thread library was detected. Activate the thread_db target. */ + base_ops = current_target; push_target (&thread_db_ops); using_thread_db = 1; @@ -365,6 +371,14 @@ return ptrace (req, GET_LWP (ptid), 0, 0) == 0; } + /* + * For M:N thread, we need to tell UTS to set/unset single step + * flag at context switch time, the flag will be written into + * thread mailbox. This becauses some architecture may not have + * machine single step flag in ucontext, so we put the flag in mailbox, + * when the thread switches back, kse_switchin restores the single step + * state. + */ td_thrhandle_t th; if (td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th) == 0) { @@ -374,53 +388,96 @@ return 0; } -static int -resume_callback (struct thread_info *info, void *ta) -{ - single_step (info->ptid, 0); - return 0; -} - static void fbsd_thread_resume (ptid_t ptid, int step, enum target_signal signo) { - int resume_all, ret, pid; td_thrhandle_t th; - struct thread_info *ti; - + td_thrinfo_t ti; + ptid_t work_ptid; + int resume_all, ret; + long lwp; + #if 0 - printf_filtered("%s ptid=%d.%x.%x step=%d\n", __func__, + printf_filtered("%s ptid=%ld.%ld.%ld step=%d\n", __func__, GET_PID(ptid), GET_LWP(ptid), GET_THREAD(ptid), step); + printf_filtered("%s inferior_ptid=%ld.%ld.%ld\n", __func__, + GET_PID(inferior_ptid), GET_LWP(inferior_ptid), GET_THREAD(inferior_ptid)); #endif - if (proc_handle.pid == 0) { child_resume (ptid, step, signo); return; } - pid = PIDGET(ptid); - if (pid == -1 || !step) + if (GET_PID(ptid) != -1 && step != 0) { - pid = PIDGET (inferior_ptid); - resume_all = 1; + resume_all = 0; + work_ptid = ptid; } else { - resume_all = 0; + resume_all = 1; + work_ptid = inferior_ptid; } - if (PIDGET (ptid) == -1) - ptid = inferior_ptid; + /* + * Whether it is going to resume one thread or not, + * we always set/unset single step state for the thread according to + * step parameter. + */ + if (!single_step(work_ptid, step)) + error ("single_step failed"); - if (resume_all) - iterate_over_threads(resume_callback, 0); + lwp = 0; + if (!resume_all) + { + /* only resume one thread */ + lwp = GET_LWP (work_ptid); + if (lwp == 0) + { + /* check a user thread */ + ret = td_ta_map_id2thr_p (thread_agent, + GET_THREAD(work_ptid), &th); + if (ret) + error(thread_db_err_str (ret)); + ret = td_thr_get_info_p (&th, &ti); + if (ret) + error(thread_db_err_str (ret)); + lwp = ti.ti_lid; + /* + * if we are single stepping an inactive M:N thread, + * we insert all breakpoints, and resume all threads, + * the inactive thread may or may not be scheduled to + * run, but if it runs, it may hit a breakpoint and + * becomes the current event thread, after it hit a + * breakpoint, the thread will stay in kernel until + * debugger resumes it. In that case, gdb will single + * step it again, but because it was already an active + * thread, we can use ptrace to resume it just as 1:1 + * thread. + */ + if (lwp == 0) + { + printf_filtered("resuming inactive thread\n"); + if (breakpoint_here_p (read_pc_pid (work_ptid)) != + no_breakpoint_here) + { + single_step_inactive_thread_pc = read_pc_pid (work_ptid); + single_step_inactive_thread = work_ptid; + /* XXX + * We need to give UTS to a hint to prefer scheduling + * the thread. + */ + insert_breakpoints (); + } + } + } + } - if (!single_step (ptid, step)) - error ("single step failed"); + if (lwp == 0) + lwp = proc_handle.pid; - if (ptrace (PT_CONTINUE, pid, (caddr_t)1, - target_signal_to_host(signo)) == -1) + if (ptrace (PT_CONTINUE, lwp, (caddr_t)1, target_signal_to_host(signo))) perror_with_name ("PT_CONTINUE"); } @@ -429,6 +486,8 @@ { ptid_t ret; lwpid_t lwp; + CORE_ADDR stop_pc; + unsigned char buf; ret = child_ops.to_wait (ptid, ourstatus); if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED) @@ -438,8 +497,29 @@ ret = thread_from_lwp (BUILD_LWP (lwp, GET_PID (ret))); if (!in_thread_list (ret)) add_thread (ret); + printf_filtered("signal=%d\n", ourstatus->value.sig); + /* + * if we previously single stepping inactive threads, + * the inactive threads now becomes active, + * we should tell gdb to ignore the event and resume + * thread again. + */ + if (ourstatus->value.sig == TARGET_SIGNAL_TRAP) + { + stop_pc = read_pc_pid (ret) - DECR_PC_AFTER_BREAK; + target_read_memory(stop_pc, &buf, 1); + printf_filtered("stop_pc=%x data:%x, breakpoint?:%d\n", + stop_pc, buf, breakpoint_here_p(stop_pc)); + if (ptid_equal(ret, single_step_inactive_thread) && + stop_pc == single_step_inactive_thread_pc) + { + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + } + } } + single_step_inactive_thread = minus_one_ptid; + single_step_inactive_thread_pc = 0; return (ret); } @@ -455,22 +535,23 @@ fbsd_lwp_fetch_registers (int regno) { gregset_t gregs; + fpregset_t fpregs; lwpid_t lwp; +#if 0 /* FIXME, is it possible ? */ if (!IS_LWP (inferior_ptid)) { child_ops.to_fetch_registers (regno); return; } - +#endif lwp = GET_LWP (inferior_ptid); if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); supply_gregset (&gregs); - fpregset_t fpregs; if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) error ("Cannot get lwp %d registers: %s\n ", lwp, safe_strerror (errno)); @@ -493,18 +574,21 @@ err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); if (err != TD_OK) - error ("Cannot find thread %ld: %s", - (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); + error ("Cannot find thread %d: TID=%ld, %s", + pid_to_thread_id (inferior_ptid), + GET_THREAD (inferior_ptid), thread_db_err_str (err)); err = td_thr_getgregs_p (&th, gregset); if (err != TD_OK) - error ("Cannot fetch general-purpose registers for thread %ld: %s", - (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); + error ("Cannot fetch general-purpose registers for thread %d: TID=%ld, %s", + pid_to_thread_id (inferior_ptid), + GET_THREAD (inferior_ptid), thread_db_err_str (err)); err = td_thr_getfpregs_p (&th, &fpregset); if (err != TD_OK) - error ("Cannot get floating-point registers for thread %ld: %s", - (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); + error ("Cannot get floating-point registers for thread %d: TID=%ld, %s", + pid_to_thread_id (inferior_ptid), + GET_THREAD (inferior_ptid), thread_db_err_str (err)); supply_gregset (gregset); supply_fpregset (&fpregset); @@ -513,6 +597,8 @@ static void fbsd_lwp_store_registers (int regno) { + gregset_t gregs; + fpregset_t fpregs; lwpid_t lwp; /* FIXME, is it possible ? */ @@ -523,21 +609,18 @@ } lwp = GET_LWP (inferior_ptid); - - gregset_t gregs; + if (regno != -1) + if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) + error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); - if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) - error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); - fill_gregset (&gregs, regno); - if (ptrace (PT_SETREGS, lwp, (caddr_t) &gregs, 0) == -1) - error ("Cannot set lwp %d registers: %s\n", lwp, safe_strerror (errno)); + error ("Cannot set lwp %d registers: %s\n", lwp, safe_strerror (errno)); - fpregset_t fpregs; - if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) - error ("Cannot get lwp %d float registers: %s\n", lwp, - safe_strerror (errno)); + if (regno != -1) + if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) + error ("Cannot get lwp %d float registers: %s\n", lwp, + safe_strerror (errno)); fill_fpregset (&fpregs, regno); if (ptrace (PT_SETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) @@ -561,29 +644,38 @@ err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); if (err != TD_OK) - error ("Cannot find thread %lx: %s", - (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); + error ("Cannot find thread %d: TID=%ld, %s", + pid_to_thread_id (inferior_ptid), + GET_THREAD (inferior_ptid), + thread_db_err_str (err)); if (regno != -1) { - char raw[MAX_REGISTER_SIZE]; + char old_value[MAX_REGISTER_SIZE]; - deprecated_read_register_gen (regno, raw); - fbsd_thread_fetch_registers (-1); - supply_register (regno, raw); + regcache_collect (regno, old_value); + err = td_thr_getgregs_p (&th, gregset); + if (err != TD_OK) + error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err)); + err = td_thr_getfpregs_p (&th, &fpregset); + if (err != TD_OK) + error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err)); + supply_register (regno, old_value); } - fill_gregset (gregset, -1); - fill_fpregset (&fpregset, -1); + fill_gregset (gregset, regno); + fill_fpregset (&fpregset, regno); err = td_thr_setgregs_p (&th, gregset); if (err != TD_OK) - error ("Cannot store general-purpose registers for thread %lx: %s", - (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); + error ("Cannot store general-purpose registers for thread %d: TID=%d, %s", + pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), + thread_db_err_str (err)); err = td_thr_setfpregs_p (&th, &fpregset); if (err != TD_OK) - error ("Cannot store floating-point registers for thread %lx: %s", - (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); + error ("Cannot store floating-point registers for thread %d: TID=%d, %s", + pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), + thread_db_err_str (err)); } static void @@ -609,8 +701,10 @@ { if (proc_handle.pid == 0) { - /* The child process is now the actual multi-threaded - program. Snatch its process ID... */ + /* + * The child process is now the actual multi-threaded + * program. Snatch its process ID... + */ proc_handle.pid = GET_PID (ptid); fbsd_thread_find_new_threads (); @@ -621,8 +715,10 @@ static void fbsd_thread_mourn_inferior (void) { - /* Forget about the child's process ID. We shouldn't need it - anymore. */ + /* + * Forget about the child's process ID. We shouldn't need it + * anymore. + */ proc_handle.pid = 0; child_ops.to_mourn_inferior (); @@ -646,7 +742,7 @@ if (err != TD_OK) return 0; - /* A zombie thread. */ + /* A zombie thread. */ if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) return 0; @@ -657,17 +753,16 @@ /* we sometimes are called with lwp == 0 */ return 1; } - else - { - err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); - /* - * if the lwp was already mapped to user thread, don't use it - * directly, please use user thread id instead. - */ - if (err == TD_OK) - return 0; - } - + + err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); + + /* + * if the lwp was already mapped to user thread, don't use it + * directly, please use user thread id instead. + */ + if (err == TD_OK) + return 0; + /* check lwp in kernel */ return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0; } @@ -721,23 +816,23 @@ err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); if (err != TD_OK) - error ("Cannot find thread %lx: %s", + error ("Cannot find thread, TID=%ld, %s", GET_THREAD (ptid), thread_db_err_str (err)); err = td_thr_get_info_p (&th, &ti); if (err != TD_OK) - error ("Cannot get thread info for thread %lx: %s", + error ("Cannot get thread info, TID=%ld, %s", GET_THREAD (ptid), thread_db_err_str (err)); if (ti.ti_lid != 0) { - snprintf (buf, sizeof (buf), "Thread %lx (LWP %d)", - (long) ti.ti_tid, ti.ti_lid); + snprintf (buf, sizeof (buf), "TID %ld (LWP %d)", + GET_THREAD (ptid), ti.ti_lid); } else { - snprintf (buf, sizeof (buf), "Thread %lx (%s)", - (long) ti.ti_tid, thread_db_state_str (ti.ti_state)); + snprintf (buf, sizeof (buf), "TID %ld (%s)", + GET_THREAD (ptid), thread_db_state_str (ti.ti_state)); } return buf; @@ -761,9 +856,8 @@ name = "???"; else name = DEPRECATED_SYMBOL_NAME (ms); - + printf_filtered ("Destructor %p <%s>\n", destructor, name); - return 0; } @@ -858,10 +952,6 @@ if (td_thr_sstep_p == NULL) return 0; - td_ta_activated_p = dlsym (handle, "td_ta_activated"); - if (td_ta_activated_p == NULL) - return 0; - td_ta_tsd_iter_p = dlsym (handle, "td_ta_tsd_iter"); if (td_ta_tsd_iter_p == NULL) return 0; @@ -897,9 +987,9 @@ target_new_objfile_hook = fbsd_thread_new_objfile; } else - { + { printf_filtered("%s: can not load %s.\n", __func__, LIBTHREAD_DB_SO); - } + } } /* proc service functions */ @@ -910,6 +1000,7 @@ va_start (args, fmt); vfprintf_filtered (gdb_stderr, fmt, args); + va_end (args); } ps_err_e @@ -956,7 +1047,7 @@ ps_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, prgregset_t gregset) { /* should check data modal, .core or process ? */ - if (ptrace (PT_GETREGS, lwpid, (caddr_t)gregset, 0) == -1) + if (ptrace (PT_GETREGS, lwpid, (caddr_t) gregset, 0) == -1) return PS_ERR; return PS_OK; } @@ -996,7 +1087,7 @@ ps_lsetstep (struct ps_prochandle *ph, lwpid_t lwp, int step) { if (ptrace ((step ? PT_SETSTEP : PT_CLEARSTEP), lwp, 0, 0)) - return PS_ERR; + return PS_ERR; return PS_OK; }