diff options
author | dfr <dfr@FreeBSD.org> | 2005-05-31 09:43:04 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2005-05-31 09:43:04 +0000 |
commit | 874478d7fd90e4178b95bc5a6f3b15c0c057c491 (patch) | |
tree | 6e75a2cdc72929f6a8fcd18615399aea3228d568 | |
parent | 0d07e4ee86c5f875d30d214612b6aea86b793a5a (diff) | |
download | FreeBSD-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.h | 2 | ||||
-rw-r--r-- | gnu/usr.bin/gdb/libgdb/fbsd-threads.c | 122 | ||||
-rw-r--r-- | include/proc_service.h | 4 | ||||
-rw-r--r-- | lib/libthread_db/arch/i386/libpthread_md.c | 14 | ||||
-rw-r--r-- | lib/libthread_db/libc_r_db.c | 22 | ||||
-rw-r--r-- | lib/libthread_db/libpthread_db.c | 100 | ||||
-rw-r--r-- | lib/libthread_db/libpthread_db.h | 4 | ||||
-rw-r--r-- | lib/libthread_db/libthr_db.c | 40 | ||||
-rw-r--r-- | lib/libthread_db/thread_db.c | 19 | ||||
-rw-r--r-- | lib/libthread_db/thread_db.h | 6 | ||||
-rw-r--r-- | lib/libthread_db/thread_db_int.h | 4 | ||||
-rw-r--r-- | sys/conf/files.i386 | 1 | ||||
-rw-r--r-- | sys/i386/i386/ptrace_machdep.c | 62 | ||||
-rw-r--r-- | sys/i386/include/ptrace.h | 5 | ||||
-rw-r--r-- | sys/i386/include/reg.h | 12 |
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. */ |