summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2005-05-31 09:43:04 +0000
committerdfr <dfr@FreeBSD.org>2005-05-31 09:43:04 +0000
commit874478d7fd90e4178b95bc5a6f3b15c0c057c491 (patch)
tree6e75a2cdc72929f6a8fcd18615399aea3228d568
parent0d07e4ee86c5f875d30d214612b6aea86b793a5a (diff)
downloadFreeBSD-src-874478d7fd90e4178b95bc5a6f3b15c0c057c491.zip
FreeBSD-src-874478d7fd90e4178b95bc5a6f3b15c0c057c491.tar.gz
Add support for XMM registers in GDB for x86 processors that support
SSE (or its successors). Reviewed by: marcel, davidxu MFC After: 2 weeks
-rw-r--r--gnu/usr.bin/gdb/arch/i386/config.h2
-rw-r--r--gnu/usr.bin/gdb/libgdb/fbsd-threads.c122
-rw-r--r--include/proc_service.h4
-rw-r--r--lib/libthread_db/arch/i386/libpthread_md.c14
-rw-r--r--lib/libthread_db/libc_r_db.c22
-rw-r--r--lib/libthread_db/libpthread_db.c100
-rw-r--r--lib/libthread_db/libpthread_db.h4
-rw-r--r--lib/libthread_db/libthr_db.c40
-rw-r--r--lib/libthread_db/thread_db.c19
-rw-r--r--lib/libthread_db/thread_db.h6
-rw-r--r--lib/libthread_db/thread_db_int.h4
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/i386/i386/ptrace_machdep.c62
-rw-r--r--sys/i386/include/ptrace.h5
-rw-r--r--sys/i386/include/reg.h12
15 files changed, 404 insertions, 13 deletions
diff --git a/gnu/usr.bin/gdb/arch/i386/config.h b/gnu/usr.bin/gdb/arch/i386/config.h
index 793a4f2..f21da4c 100644
--- a/gnu/usr.bin/gdb/arch/i386/config.h
+++ b/gnu/usr.bin/gdb/arch/i386/config.h
@@ -162,7 +162,7 @@
#define HAVE_PT_GETDBREGS 1
/* Define if <sys/ptrace.h> defines the PT_GETXMMREGS request. */
-/* #undef HAVE_PT_GETXMMREGS */
+#define HAVE_PT_GETXMMREGS
/* Define if libunwind library is being used. */
/* #undef HAVE_LIBUNWIND */
diff --git a/gnu/usr.bin/gdb/libgdb/fbsd-threads.c b/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
index 2dfdff4..6e9184d 100644
--- a/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
+++ b/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
@@ -110,10 +110,18 @@ static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
td_event_msg_t *msg);
static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
td_thrinfo_t *infop);
+#ifdef PT_GETXMMREGS
+static td_err_e (*td_thr_getxmmregs_p) (const td_thrhandle_t *th,
+ char *regset);
+#endif
static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
prfpregset_t *regset);
static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
prgregset_t gregs);
+#ifdef PT_GETXMMREGS
+static td_err_e (*td_thr_setxmmregs_p) (const td_thrhandle_t *th,
+ const char *fpregs);
+#endif
static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
const prfpregset_t *fpregs);
static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
@@ -786,6 +794,9 @@ fbsd_lwp_fetch_registers (int regno)
gregset_t gregs;
fpregset_t fpregs;
lwpid_t lwp;
+#ifdef PT_GETXMMREGS
+ char xmmregs[512];
+#endif
if (!target_has_execution)
{
@@ -800,10 +811,20 @@ fbsd_lwp_fetch_registers (int regno)
error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno));
supply_gregset (&gregs);
- if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1)
- error ("Cannot get lwp %d registers: %s\n ", lwp, safe_strerror (errno));
-
- supply_fpregset (&fpregs);
+#ifdef PT_GETXMMREGS
+ if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == 0)
+ {
+ i387_supply_fxsave (current_regcache, -1, xmmregs);
+ }
+ else
+ {
+#endif
+ if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1)
+ error ("Cannot get lwp %d registers: %s\n ", lwp, safe_strerror (errno));
+ supply_fpregset (&fpregs);
+#ifdef PT_GETXMMREGS
+ }
+#endif
}
static void
@@ -813,6 +834,9 @@ fbsd_thread_fetch_registers (int regno)
prfpregset_t fpregset;
td_thrhandle_t th;
td_err_e err;
+#ifdef PT_GETXMMREGS
+ char xmmregs[512];
+#endif
if (!IS_THREAD (inferior_ptid))
{
@@ -831,15 +855,26 @@ fbsd_thread_fetch_registers (int regno)
error ("Cannot fetch general-purpose registers for thread %d: Thread ID=%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 %d: Thread ID=%ld, %s",
- pid_to_thread_id (inferior_ptid),
- GET_THREAD (inferior_ptid), thread_db_err_str (err));
+#ifdef PT_GETXMMREGS
+ err = td_thr_getxmmregs_p (&th, xmmregs);
+ if (err == TD_OK)
+ {
+ i387_supply_fxsave (current_regcache, -1, xmmregs);
+ }
+ else
+ {
+#endif
+ err = td_thr_getfpregs_p (&th, &fpregset);
+ if (err != TD_OK)
+ error ("Cannot get floating-point registers for thread %d: Thread ID=%ld, %s",
+ pid_to_thread_id (inferior_ptid),
+ GET_THREAD (inferior_ptid), thread_db_err_str (err));
+ supply_fpregset (&fpregset);
+#ifdef PT_GETXMMREGS
+ }
+#endif
supply_gregset (gregset);
- supply_fpregset (&fpregset);
}
static void
@@ -848,6 +883,9 @@ fbsd_lwp_store_registers (int regno)
gregset_t gregs;
fpregset_t fpregs;
lwpid_t lwp;
+#ifdef PT_GETXMMREGS
+ char xmmregs[512];
+#endif
/* FIXME, is it possible ? */
if (!IS_LWP (inferior_ptid))
@@ -865,6 +903,20 @@ fbsd_lwp_store_registers (int regno)
if (ptrace (PT_SETREGS, lwp, (caddr_t) &gregs, 0) == -1)
error ("Cannot set lwp %d registers: %s\n", lwp, safe_strerror (errno));
+#ifdef PT_GETXMMREGS
+ if (regno != -1)
+ if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == -1)
+ goto noxmm;
+
+ i387_fill_fxsave (xmmregs, regno);
+ if (ptrace (PT_SETXMMREGS, lwp, xmmregs, 0) == -1)
+ goto noxmm;
+
+ return;
+
+noxmm:
+#endif
+
if (regno != -1)
if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1)
error ("Cannot get lwp %d float registers: %s\n", lwp,
@@ -883,6 +935,9 @@ fbsd_thread_store_registers (int regno)
prfpregset_t fpregset;
td_thrhandle_t th;
td_err_e err;
+#ifdef PT_GETXMMREGS
+ char xmmregs[512];
+#endif
if (!IS_THREAD (inferior_ptid))
{
@@ -913,12 +968,22 @@ fbsd_thread_store_registers (int regno)
fill_gregset (gregset, regno);
fill_fpregset (&fpregset, regno);
+#ifdef PT_GETXMMREGS
+ i387_fill_fxsave (xmmregs, regno);
+#endif
err = td_thr_setgregs_p (&th, gregset);
if (err != TD_OK)
error ("Cannot store general-purpose registers for thread %d: Thread ID=%d, %s",
pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid),
thread_db_err_str (err));
+
+#ifdef PT_GETXMMREGS
+ err = td_thr_setxmmregs_p (&th, xmmregs);
+ if (err == TD_OK)
+ return;
+#endif
+
err = td_thr_setfpregs_p (&th, &fpregset);
if (err != TD_OK)
error ("Cannot store floating-point registers for thread %d: Thread ID=%d, %s",
@@ -1351,8 +1416,14 @@ thread_db_load (void)
resolve(td_ta_map_lwp2thr);
resolve(td_ta_thr_iter);
resolve(td_thr_get_info);
+#ifdef PT_GETXMMREGS
+ resolve(td_thr_getxmmregs);
+#endif
resolve(td_thr_getfpregs);
resolve(td_thr_getgregs);
+#ifdef PT_GETXMMREGS
+ resolve(td_thr_setxmmregs);
+#endif
resolve(td_thr_setfpregs);
resolve(td_thr_setgregs);
resolve(td_thr_sstep);
@@ -1518,6 +1589,35 @@ ps_lsetfpregs (struct ps_prochandle *ph, lwpid_t lwpid,
return PS_OK;
}
+#ifdef PT_GETXMMREGS
+ps_err_e
+ps_lgetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, char *xmmregs)
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_ptid ();
+ inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
+ target_fetch_registers (-1);
+ i387_fill_fxsave (xmmregs, -1);
+ do_cleanups (old_chain);
+ return PS_OK;
+}
+
+ps_err_e
+ps_lsetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid,
+ const char *xmmregs)
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_ptid ();
+ inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
+ i387_supply_fxsave (current_regcache, -1, xmmregs);
+ target_store_registers (-1);
+ do_cleanups (old_chain);
+ return PS_OK;
+}
+#endif
+
ps_err_e
ps_lstop(struct ps_prochandle *ph, lwpid_t lwpid)
{
diff --git a/include/proc_service.h b/include/proc_service.h
index cc2111c..0299b95 100644
--- a/include/proc_service.h
+++ b/include/proc_service.h
@@ -51,6 +51,10 @@ ps_err_e ps_lgetfpregs(struct ps_prochandle *, lwpid_t, prfpregset_t *);
ps_err_e ps_lgetregs(struct ps_prochandle *, lwpid_t, prgregset_t);
ps_err_e ps_lsetfpregs(struct ps_prochandle *, lwpid_t, const prfpregset_t *);
ps_err_e ps_lsetregs(struct ps_prochandle *, lwpid_t, const prgregset_t);
+#ifdef __i386__
+ps_err_e ps_lgetxmmregs (struct ps_prochandle *, lwpid_t, char *);
+ps_err_e ps_lsetxmmregs (struct ps_prochandle *, lwpid_t, const char *);
+#endif
ps_err_e ps_lstop(struct ps_prochandle *, lwpid_t);
ps_err_e ps_pcontinue(struct ps_prochandle *);
ps_err_e ps_pdmodel(struct ps_prochandle *, int *);
diff --git a/lib/libthread_db/arch/i386/libpthread_md.c b/lib/libthread_db/arch/i386/libpthread_md.c
index 86bb88d..dc14e60 100644
--- a/lib/libthread_db/arch/i386/libpthread_md.c
+++ b/lib/libthread_db/arch/i386/libpthread_md.c
@@ -81,6 +81,20 @@ pt_ucontext_to_fpreg(const ucontext_t *uc, struct fpreg *r)
}
void
+pt_fxsave_to_ucontext(const char* r, ucontext_t *uc)
+{
+ if (has_xmm_regs)
+ memcpy(&uc->uc_mcontext.mc_fpstate, r, sizeof(struct savexmm));
+}
+
+void
+pt_ucontext_to_fxsave(const ucontext_t *uc, char *r)
+{
+ if (has_xmm_regs)
+ memcpy(r, &uc->uc_mcontext.mc_fpstate, sizeof(struct savexmm));
+}
+
+void
pt_md_init(void)
{
ucontext_t uc;
diff --git a/lib/libthread_db/libc_r_db.c b/lib/libthread_db/libc_r_db.c
index 78be702..10f7df1 100644
--- a/lib/libthread_db/libc_r_db.c
+++ b/lib/libthread_db/libc_r_db.c
@@ -228,6 +228,14 @@ libc_r_db_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *ti)
return ((err == PS_OK) ? TD_OK : TD_ERR);
}
+#ifdef __i386__
+static td_err_e
+libc_r_db_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave)
+{
+ return (TD_NOFPREGS);
+}
+#endif
+
static td_err_e
libc_r_db_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *r)
{
@@ -284,6 +292,14 @@ libc_r_db_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *ev)
return (0);
}
+#ifdef __i386__
+static td_err_e
+libc_r_db_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave)
+{
+ return (TD_NOFPREGS);
+}
+#endif
+
static td_err_e
libc_r_db_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *r)
{
@@ -324,5 +340,9 @@ struct ta_ops libc_r_db_ops = {
.to_thr_set_event = libc_r_db_thr_set_event,
.to_thr_setfpregs = libc_r_db_thr_setfpregs,
.to_thr_setgregs = libc_r_db_thr_setgregs,
- .to_thr_validate = libc_r_db_thr_validate
+ .to_thr_validate = libc_r_db_thr_validate,
+#ifdef __i386__
+ .to_thr_getxmmregs = libc_r_db_thr_getxmmregs,
+ .to_thr_setxmmregs = libc_r_db_thr_setxmmregs,
+#endif
};
diff --git a/lib/libthread_db/libpthread_db.c b/lib/libthread_db/libpthread_db.c
index 7f858e7..ea7f81c 100644
--- a/lib/libthread_db/libpthread_db.c
+++ b/lib/libthread_db/libpthread_db.c
@@ -641,6 +641,51 @@ pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
return (0);
}
+#ifdef __i386__
+static td_err_e
+pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave)
+{
+ const td_thragent_t *ta = th->th_ta;
+ struct kse_thr_mailbox tmbx;
+ psaddr_t tcb_addr, tmbx_addr, ptr;
+ lwpid_t lwp;
+ int ret;
+
+ return TD_ERR;
+
+ TDBG_FUNC();
+
+ ret = pt_validate(th);
+ if (ret)
+ return (ret);
+
+ if (ta->map[th->th_tid].type == PT_LWP) {
+ ret = ps_lgetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave);
+ return (P2T(ret));
+ }
+
+ ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
+ &tcb_addr, sizeof(tcb_addr));
+ if (ret != 0)
+ return (P2T(ret));
+ tmbx_addr = tcb_addr + ta->thread_off_tmbx;
+ ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
+ ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
+ if (ret != 0)
+ return (P2T(ret));
+ if (lwp != 0) {
+ ret = ps_lgetxmmregs(ta->ph, lwp, fxsave);
+ return (P2T(ret));
+ }
+
+ ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
+ if (ret != 0)
+ return (P2T(ret));
+ pt_ucontext_to_fxsave(&tmbx.tm_context, fxsave);
+ return (0);
+}
+#endif
+
static td_err_e
pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs)
{
@@ -723,6 +768,57 @@ pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs)
return (0);
}
+#ifdef __i386__
+static td_err_e
+pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave)
+{
+ const td_thragent_t *ta = th->th_ta;
+ struct kse_thr_mailbox tmbx;
+ psaddr_t tcb_addr, tmbx_addr, ptr;
+ lwpid_t lwp;
+ int ret;
+
+ return TD_ERR;
+
+ TDBG_FUNC();
+
+ ret = pt_validate(th);
+ if (ret)
+ return (ret);
+
+ if (ta->map[th->th_tid].type == PT_LWP) {
+ ret = ps_lsetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave);
+ return (P2T(ret));
+ }
+
+ ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
+ ta->thread_off_tcb,
+ &tcb_addr, sizeof(tcb_addr));
+ if (ret != 0)
+ return (P2T(ret));
+ tmbx_addr = tcb_addr + ta->thread_off_tmbx;
+ ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
+ ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
+ if (ret != 0)
+ return (P2T(ret));
+ if (lwp != 0) {
+ ret = ps_lsetxmmregs(ta->ph, lwp, fxsave);
+ return (P2T(ret));
+ }
+ /*
+ * Read a copy of context, this makes sure that registers
+ * not covered by structure reg won't be clobbered
+ */
+ ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
+ if (ret != 0)
+ return (P2T(ret));
+
+ pt_fxsave_to_ucontext(fxsave, &tmbx.tm_context);
+ ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
+ return (P2T(ret));
+}
+#endif
+
static td_err_e
pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs)
{
@@ -1009,4 +1105,8 @@ struct ta_ops libpthread_db_ops = {
/* FreeBSD specific extensions. */
.to_thr_sstep = pt_thr_sstep,
+#ifdef __i386__
+ .to_thr_getxmmregs = pt_thr_getxmmregs,
+ .to_thr_setxmmregs = pt_thr_setxmmregs,
+#endif
};
diff --git a/lib/libthread_db/libpthread_db.h b/lib/libthread_db/libpthread_db.h
index 7a17b79..5347d01 100644
--- a/lib/libthread_db/libpthread_db.h
+++ b/lib/libthread_db/libpthread_db.h
@@ -82,6 +82,10 @@ void pt_reg_to_ucontext(const struct reg *, ucontext_t *);
void pt_ucontext_to_reg(const ucontext_t *, struct reg *);
void pt_fpreg_to_ucontext(const struct fpreg *, ucontext_t *);
void pt_ucontext_to_fpreg(const ucontext_t *, struct fpreg *);
+#ifdef __i386__
+void pt_fxsave_to_ucontext(const char *, ucontext_t *);
+void pt_ucontext_to_fxsave(const ucontext_t *, char *);
+#endif
int pt_reg_sstep(struct reg *reg, int step);
#endif /* _LIBPTHREAD_DB_H_ */
diff --git a/lib/libthread_db/libthr_db.c b/lib/libthread_db/libthr_db.c
index 0bfa020..8986939 100644
--- a/lib/libthread_db/libthr_db.c
+++ b/lib/libthread_db/libthr_db.c
@@ -505,6 +505,24 @@ pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
return (0);
}
+#ifdef __i386__
+static td_err_e
+pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave)
+{
+ const td_thragent_t *ta = th->th_ta;
+ int ret;
+
+ TDBG_FUNC();
+
+ ret = pt_validate(th);
+ if (ret)
+ return (ret);
+
+ ret = ps_lgetxmmregs(ta->ph, th->th_tid, fxsave);
+ return (P2T(ret));
+}
+#endif
+
static td_err_e
pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs)
{
@@ -537,6 +555,24 @@ pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs)
return (P2T(ret));
}
+#ifdef __i386__
+static td_err_e
+pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave)
+{
+ const td_thragent_t *ta = th->th_ta;
+ int ret;
+
+ TDBG_FUNC();
+
+ ret = pt_validate(th);
+ if (ret)
+ return (ret);
+
+ ret = ps_lsetxmmregs(ta->ph, th->th_tid, fxsave);
+ return (P2T(ret));
+}
+#endif
+
static td_err_e
pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs)
{
@@ -742,4 +778,8 @@ struct ta_ops libthr_db_ops = {
/* FreeBSD specific extensions. */
.to_thr_sstep = pt_thr_sstep,
+#ifdef __i386__
+ .to_thr_getxmmregs = pt_thr_getxmmregs,
+ .to_thr_setxmmregs = pt_thr_setxmmregs,
+#endif
};
diff --git a/lib/libthread_db/thread_db.c b/lib/libthread_db/thread_db.c
index b1b1bcc..45400bf 100644
--- a/lib/libthread_db/thread_db.c
+++ b/lib/libthread_db/thread_db.c
@@ -184,6 +184,16 @@ td_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
return (ta->ta_ops->to_thr_get_info(th, info));
}
+#ifdef __i386__
+td_err_e
+td_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave)
+{
+ const td_thragent_t *ta = th->th_ta;
+ return (ta->ta_ops->to_thr_getxmmregs(th, fxsave));
+}
+#endif
+
+
td_err_e
td_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset)
{
@@ -205,6 +215,15 @@ td_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events)
return (ta->ta_ops->to_thr_set_event(th, events));
}
+#ifdef __i386__
+td_err_e
+td_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave)
+{
+ const td_thragent_t *ta = th->th_ta;
+ return (ta->ta_ops->to_thr_setxmmregs(th, fxsave));
+}
+#endif
+
td_err_e
td_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs)
{
diff --git a/lib/libthread_db/thread_db.h b/lib/libthread_db/thread_db.h
index 9dcc55e..a05274e 100644
--- a/lib/libthread_db/thread_db.h
+++ b/lib/libthread_db/thread_db.h
@@ -227,9 +227,15 @@ td_err_e td_thr_dbsuspend(const td_thrhandle_t *);
td_err_e td_thr_event_enable(const td_thrhandle_t *, int);
td_err_e td_thr_event_getmsg(const td_thrhandle_t *, td_event_msg_t *);
td_err_e td_thr_get_info(const td_thrhandle_t *, td_thrinfo_t *);
+#ifdef __i386__
+td_err_e td_thr_getxmmregs(const td_thrhandle_t *, char *);
+#endif
td_err_e td_thr_getfpregs(const td_thrhandle_t *, prfpregset_t *);
td_err_e td_thr_getgregs(const td_thrhandle_t *, prgregset_t);
td_err_e td_thr_set_event(const td_thrhandle_t *, td_thr_events_t *);
+#ifdef __i386__
+td_err_e td_thr_setxmmregs(const td_thrhandle_t *, const char *);
+#endif
td_err_e td_thr_setfpregs(const td_thrhandle_t *, const prfpregset_t *);
td_err_e td_thr_setgregs(const td_thrhandle_t *, const prgregset_t);
td_err_e td_thr_validate(const td_thrhandle_t *);
diff --git a/lib/libthread_db/thread_db_int.h b/lib/libthread_db/thread_db_int.h
index 7dc152c..2e5ecba 100644
--- a/lib/libthread_db/thread_db_int.h
+++ b/lib/libthread_db/thread_db_int.h
@@ -79,6 +79,10 @@ struct ta_ops {
/* FreeBSD specific extensions. */
td_err_e (*to_thr_sstep)(const td_thrhandle_t *, int);
+#if defined(__i386__)
+ td_err_e (*to_thr_getxmmregs)(const td_thrhandle_t *, char *);
+ td_err_e (*to_thr_setxmmregs)(const td_thrhandle_t *, const char *);
+#endif
};
#ifdef TD_DEBUG
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index ed37780..d58439c 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -293,6 +293,7 @@ i386/i386/nexus.c standard
i386/i386/perfmon.c optional perfmon
i386/i386/perfmon.c optional perfmon profiling-routine
i386/i386/pmap.c standard
+i386/i386/ptrace_machdep.c standard
i386/i386/support.s standard
i386/i386/swtch.s standard
i386/i386/sys_machdep.c standard
diff --git a/sys/i386/i386/ptrace_machdep.c b/sys/i386/i386/ptrace_machdep.c
new file mode 100644
index 0000000..545bb20
--- /dev/null
+++ b/sys/i386/i386/ptrace_machdep.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2005 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+
+int
+cpu_ptrace(struct thread *td, int req, void *addr, int data)
+{
+ int error;
+
+ if (!cpu_fxsr)
+ return (EINVAL);
+
+ switch (req) {
+ case PT_GETXMMREGS:
+ error = copyout(&td->td_pcb->pcb_save.sv_xmm, addr,
+ sizeof(td->td_pcb->pcb_save.sv_xmm));
+ break;
+
+ case PT_SETXMMREGS:
+ error = copyin(addr, &td->td_pcb->pcb_save.sv_xmm,
+ sizeof(td->td_pcb->pcb_save.sv_xmm));
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ return (error);
+}
diff --git a/sys/i386/include/ptrace.h b/sys/i386/include/ptrace.h
index eef24f8..24eb411 100644
--- a/sys/i386/include/ptrace.h
+++ b/sys/i386/include/ptrace.h
@@ -33,4 +33,9 @@
#ifndef _MACHINE_PTRACE_H_
#define _MACHINE_PTRACE_H_
+#define __HAVE_PTRACE_MACHDEP
+
+#define PT_GETXMMREGS (PT_FIRSTMACH + 0)
+#define PT_SETXMMREGS (PT_FIRSTMACH + 1)
+
#endif
diff --git a/sys/i386/include/reg.h b/sys/i386/include/reg.h
index 5060bb6..dbafd4b 100644
--- a/sys/i386/include/reg.h
+++ b/sys/i386/include/reg.h
@@ -114,6 +114,18 @@ struct fpreg {
unsigned char fpr_pad[64];
};
+struct xmmreg {
+ /*
+ * XXX should get struct from npx.h. Here we give a slightly
+ * simplified struct. This may be too much detail. Perhaps
+ * an array of unsigned longs is best.
+ */
+ unsigned long xmm_env[8];
+ unsigned char xmm_acc[8][16];
+ unsigned char xmm_reg[8][16];
+ unsigned char xmm_pad[224];
+};
+
/*
* Register set accessible via /proc/$pid/dbregs.
*/
OpenPOWER on IntegriCloud