PERFORCE change 56616 for review
David Xu
davidxu at FreeBSD.org
Tue Jul 6 06:11:36 PDT 2004
http://perforce.freebsd.org/chv.cgi?CH=56616
Change 56616 by davidxu at 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;
}
More information about the p4-projects
mailing list