Index: gnu/usr.bin/gdb/libgdb/fbsd-threads.c =========================================================================== --- gnu/usr.bin/gdb/libgdb/fbsd-threads.c 2008/03/13 03:14:06 #15 +++ gnu/usr.bin/gdb/libgdb/fbsd-threads.c 2008/03/13 03:14:06 @@ -111,22 +111,18 @@ 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_getxregs_p) (const td_thrhandle_t *th, + void *regs); static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, - prfpregset_t *regset); + struct fpreg *regs); 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 + struct reg *regs); +static td_err_e (*td_thr_setxregs_p) (const td_thrhandle_t *th, + const void *regs); static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, - const prfpregset_t *fpregs); + const struct fpreg *regs); static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, - prgregset_t gregs); + const struct reg *regs); static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, int event); static td_err_e (*td_thr_sstep_p) (td_thrhandle_t *th, int step); @@ -792,12 +788,10 @@ static void fbsd_lwp_fetch_registers (int regno) { - gregset_t gregs; - fpregset_t fpregs; + struct reg gregs; + struct fpreg fpregs; lwpid_t lwp; -#ifdef PT_GETXMMREGS - char xmmregs[512]; -#endif + char xregs[512]; if (!target_has_execution) { @@ -812,32 +806,26 @@ error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); supply_gregset (&gregs); -#ifdef PT_GETXMMREGS - if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == 0) + if (ptrace (PT_GETXREGS, lwp, xregs, 0) == 0) { - i387_supply_fxsave (current_regcache, -1, xmmregs); + i387_supply_fxsave (current_regcache, -1, xregs); } 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 fbsd_thread_fetch_registers (int regno) { - prgregset_t gregset; - prfpregset_t fpregset; + struct reg gregs; + struct fpreg fpregs; td_thrhandle_t th; td_err_e err; -#ifdef PT_GETXMMREGS - char xmmregs[512]; -#endif + char xregs[512]; if (!IS_THREAD (inferior_ptid)) { @@ -851,42 +839,36 @@ pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); - err = td_thr_getgregs_p (&th, gregset); + err = td_thr_getgregs_p (&th, &gregs); if (err != TD_OK) 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)); -#ifdef PT_GETXMMREGS - err = td_thr_getxmmregs_p (&th, xmmregs); + err = td_thr_getxregs_p (&th, xregs); if (err == TD_OK) { - i387_supply_fxsave (current_regcache, -1, xmmregs); + i387_supply_fxsave (current_regcache, -1, xregs); } else { -#endif - err = td_thr_getfpregs_p (&th, &fpregset); + err = td_thr_getfpregs_p (&th, &fpregs); 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 + supply_fpregset (&fpregs); } -#endif - supply_gregset (gregset); + supply_gregset (&gregs); } static void fbsd_lwp_store_registers (int regno) { - gregset_t gregs; - fpregset_t fpregs; + struct reg gregs; + struct fpreg fpregs; lwpid_t lwp; -#ifdef PT_GETXMMREGS - char xmmregs[512]; -#endif + char xregs[512]; /* FIXME, is it possible ? */ if (!IS_LWP (inferior_ptid)) @@ -904,19 +886,17 @@ 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; + if (ptrace (PT_GETXREGS, lwp, xregs, 0) == -1) + goto nox; - i387_fill_fxsave (xmmregs, regno); - if (ptrace (PT_SETXMMREGS, lwp, xmmregs, 0) == -1) - goto noxmm; + i387_fill_fxsave (xregs, regno); + if (ptrace (PT_SETXREGS, lwp, xregs, 0) == -1) + goto nox; return; -noxmm: -#endif +nox: if (regno != -1) if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) @@ -932,13 +912,11 @@ static void fbsd_thread_store_registers (int regno) { - prgregset_t gregset; - prfpregset_t fpregset; + struct reg gregs; + struct fpreg fpregs; td_thrhandle_t th; td_err_e err; -#ifdef PT_GETXMMREGS - char xmmregs[512]; -#endif + char xregs[512]; if (!IS_THREAD (inferior_ptid)) { @@ -958,15 +936,15 @@ char old_value[MAX_REGISTER_SIZE]; regcache_collect (regno, old_value); - err = td_thr_getgregs_p (&th, gregset); + err = td_thr_getgregs_p (&th, &gregs); if (err != TD_OK) error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err)); #ifdef PT_GETXMMREGS - err = td_thr_getxmmregs_p (&th, xmmregs); + err = td_thr_getxregs_p (&th, xregs); if (err != TD_OK) { #endif - err = td_thr_getfpregs_p (&th, &fpregset); + err = td_thr_getfpregs_p (&th, &fpregs); if (err != TD_OK) error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err)); #ifdef PT_GETXMMREGS @@ -975,22 +953,22 @@ supply_register (regno, old_value); } - fill_gregset (gregset, regno); - err = td_thr_setgregs_p (&th, gregset); + fill_gregset (gregs, regno); + err = td_thr_setgregs_p (&th, &gregs); 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 - i387_fill_fxsave (xmmregs, regno); - err = td_thr_setxmmregs_p (&th, xmmregs); + i387_fill_fxsave (xregs, regno); + err = td_thr_setxregs_p (&th, xregs); if (err == TD_OK) return; #endif - fill_fpregset (&fpregset, regno); - err = td_thr_setfpregs_p (&th, &fpregset); + fill_fpregset (&fpregs, regno); + err = td_thr_setfpregs_p (&th, &fpregs); if (err != TD_OK) error ("Cannot store floating-point registers for thread %d: Thread ID=%d, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), @@ -1065,7 +1043,7 @@ td_thrhandle_t th; td_thrinfo_t ti; td_err_e err; - gregset_t gregs; + struct reg gregs; lwpid_t lwp; if (IS_THREAD (ptid)) @@ -1465,14 +1443,10 @@ 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_getxregs); resolve(td_thr_getfpregs); resolve(td_thr_getgregs); -#ifdef PT_GETXMMREGS - resolve(td_thr_setxmmregs); -#endif + resolve(td_thr_setxregs); resolve(td_thr_setfpregs); resolve(td_thr_setgregs); resolve(td_thr_sstep); @@ -1591,7 +1565,7 @@ } ps_err_e -ps_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, prgregset_t gregset) +ps_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, struct reg *gregs) { struct cleanup *old_chain; @@ -1601,79 +1575,76 @@ inferior_ptid = BUILD_LWP (0, lwpid); target_fetch_registers (-1); - fill_gregset (gregset, -1); + fill_gregset (gregs, -1); do_cleanups (old_chain); return PS_OK; } ps_err_e -ps_lsetregs (struct ps_prochandle *ph, lwpid_t lwpid, const prgregset_t gregset) +ps_lsetregs (struct ps_prochandle *ph, lwpid_t lwpid, const struct reg *gregs) { struct cleanup *old_chain; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); - supply_gregset (gregset); + supply_gregset (gregs); target_store_registers (-1); do_cleanups (old_chain); return PS_OK; } ps_err_e -ps_lgetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, prfpregset_t *fpregset) +ps_lgetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, struct fpreg *fpregs) { struct cleanup *old_chain; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); target_fetch_registers (-1); - fill_fpregset (fpregset, -1); + fill_fpregset (fpregs, -1); do_cleanups (old_chain); return PS_OK; } ps_err_e ps_lsetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, - const prfpregset_t *fpregset) + const struct fpreg *fpregs) { struct cleanup *old_chain; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); - supply_fpregset (fpregset); + supply_fpregset (fpregs); target_store_registers (-1); do_cleanups (old_chain); return PS_OK; } -#ifdef PT_GETXMMREGS ps_err_e -ps_lgetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, char *xmmregs) +ps_lgetxregs (struct ps_prochandle *ph, lwpid_t lwpid, void *xregs) { 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); + i387_fill_fxsave (xregs, -1); do_cleanups (old_chain); return PS_OK; } ps_err_e -ps_lsetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, - const char *xmmregs) +ps_lsetxregs (struct ps_prochandle *ph, lwpid_t lwpid, const void *xregs) { struct cleanup *old_chain; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); - i387_supply_fxsave (current_regcache, -1, xmmregs); + i387_supply_fxsave (current_regcache, -1, xregs); target_store_registers (-1); do_cleanups (old_chain); return PS_OK; } -#endif ps_err_e ps_lstop(struct ps_prochandle *ph, lwpid_t lwpid) Index: include/proc_service.h =========================================================================== --- include/proc_service.h 2008/03/13 03:14:06 #4 +++ include/proc_service.h 2008/03/13 03:14:06 @@ -1,6 +1,6 @@ /* * Copyright (c) 2004 David Xu - * Copyright (c) 2004 Marcel Moolenaar + * Copyright (c) 2004-2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,23 +40,23 @@ PS_BADLID, /* Bad LWP Id. */ PS_BADPID, /* Bad process Id. */ PS_NOFREGS, /* FPU register set not available. */ - PS_NOSYM /* Symbol not found. */ + PS_NOSYM, /* Symbol not found. */ + PS_NOXREG /* No arch. dep. registers available. */ } ps_err_e; struct ps_prochandle; /* Opaque type. Defined by the implementor. */ __BEGIN_DECLS ps_err_e ps_lcontinue(struct ps_prochandle *, lwpid_t); -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_lgetfpregs(struct ps_prochandle *, lwpid_t, struct fpreg *); +ps_err_e ps_lgetregs(struct ps_prochandle *, lwpid_t, struct reg *); +ps_err_e ps_lgetxregs(struct ps_prochandle *, lwpid_t, void *); +ps_err_e ps_lgetxregsize(struct ps_prochandle *, lwpid_t, int *); +ps_err_e ps_linfo(struct ps_prochandle *, lwpid_t, void *); +ps_err_e ps_lsetfpregs(struct ps_prochandle *, lwpid_t, const struct fpreg *); +ps_err_e ps_lsetregs(struct ps_prochandle *, lwpid_t, const struct reg *); +ps_err_e ps_lsetxregs(struct ps_prochandle *, lwpid_t, const void *); ps_err_e ps_lstop(struct ps_prochandle *, lwpid_t); -ps_err_e ps_linfo(struct ps_prochandle *, lwpid_t, void *); ps_err_e ps_pcontinue(struct ps_prochandle *); ps_err_e ps_pdmodel(struct ps_prochandle *, int *); ps_err_e ps_pglobal_lookup(struct ps_prochandle *, const char *, const char *, Index: lib/libthread_db/Symbol.map =========================================================================== --- lib/libthread_db/Symbol.map 2008/03/13 03:14:06 #2 +++ lib/libthread_db/Symbol.map 2008/03/13 03:14:06 @@ -22,14 +22,13 @@ td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; -#if defined(i386) - td_thr_getxmmregs; - td_thr_setxmmregs; -#endif + td_thr_getxregs; + td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs; - td_thr_sstep; /* FreeBSD extension to GDB<->thread interface */ + td_thr_setxregs; + td_thr_sstep; # FreeBSD extension to GDB<->thread interface td_thr_tls_get_addr; td_thr_validate; }; Index: lib/libthread_db/arch/amd64/libc_r_md.c =========================================================================== --- lib/libthread_db/arch/amd64/libc_r_md.c 2008/03/13 03:14:06 #1 +++ lib/libthread_db/arch/amd64/libc_r_md.c 2008/03/13 03:14:06 @@ -31,11 +31,11 @@ #include void -libc_r_md_getgregs(jmp_buf jb, prgregset_t *r) +libc_r_md_getgregs(jmp_buf jb, struct reg *r) { } void -libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +libc_r_md_getfpregs(jmp_buf jb, struct fpreg *r) { } Index: lib/libthread_db/arch/i386/libc_r_md.c =========================================================================== --- lib/libthread_db/arch/i386/libc_r_md.c 2008/03/13 03:14:06 #1 +++ lib/libthread_db/arch/i386/libc_r_md.c 2008/03/13 03:14:06 @@ -31,7 +31,7 @@ #include void -libc_r_md_getgregs(jmp_buf jb, prgregset_t r) +libc_r_md_getgregs(jmp_buf jb, struct reg *r) { r->r_eip = jb->_jb[0]; r->r_ebx = jb->_jb[1]; @@ -43,6 +43,6 @@ } void -libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +libc_r_md_getfpregs(jmp_buf jb, struct fpreg *r) { } Index: lib/libthread_db/arch/ia64/libc_r_md.c =========================================================================== --- lib/libthread_db/arch/ia64/libc_r_md.c 2008/03/13 03:14:06 #1 +++ lib/libthread_db/arch/ia64/libc_r_md.c 2008/03/13 03:14:06 @@ -31,11 +31,11 @@ #include void -libc_r_md_getgregs(jmp_buf jb, prgregset_t *r) +libc_r_md_getgregs(jmp_buf jb, struct reg *r) { } void -libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +libc_r_md_getfpregs(jmp_buf jb, struct fpreg *r) { } Index: lib/libthread_db/arch/sparc64/libc_r_md.c =========================================================================== --- lib/libthread_db/arch/sparc64/libc_r_md.c 2008/03/13 03:14:06 #1 +++ lib/libthread_db/arch/sparc64/libc_r_md.c 2008/03/13 03:14:06 @@ -31,11 +31,11 @@ #include void -libc_r_md_getgregs(jmp_buf jb, prgregset_t *r) +libc_r_md_getgregs(jmp_buf jb, struct reg *r) { } void -libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +libc_r_md_getfpregs(jmp_buf jb, struct fpreg *r) { } Index: lib/libthread_db/libc_r_db.c =========================================================================== --- lib/libthread_db/libc_r_db.c 2008/03/13 03:14:06 #3 +++ lib/libthread_db/libc_r_db.c 2008/03/13 03:14:06 @@ -35,8 +35,8 @@ #include "thread_db_int.h" -void libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *); -void libc_r_md_getgregs(jmp_buf jb, prgregset_t); +void libc_r_md_getfpregs(jmp_buf jb, struct fpreg *); +void libc_r_md_getgregs(jmp_buf jb, struct reg *); struct td_thragent { TD_THRAGENT_FIELDS; @@ -228,16 +228,20 @@ return ((err == PS_OK) ? TD_OK : TD_ERR); } -#ifdef __i386__ +static td_err_e +libc_r_db_thr_getxregs(const td_thrhandle_t *th, void *xregs) +{ + return (TD_NOXREGS); +} + static td_err_e -libc_r_db_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) +libc_r_db_thr_getxregsize(const td_thrhandle_t *th, int *szp) { - return (TD_NOFPREGS); + return (TD_NOXREGS); } -#endif static td_err_e -libc_r_db_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *r) +libc_r_db_thr_getfpregs(const td_thrhandle_t *th, struct fpreg *r) { jmp_buf jb; const td_thragent_t *ta; @@ -262,7 +266,7 @@ } static td_err_e -libc_r_db_thr_getgregs(const td_thrhandle_t *th, prgregset_t r) +libc_r_db_thr_getgregs(const td_thrhandle_t *th, struct reg *r) { jmp_buf jb; const td_thragent_t *ta; @@ -292,22 +296,20 @@ return (0); } -#ifdef __i386__ static td_err_e -libc_r_db_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) +libc_r_db_thr_setxregs(const td_thrhandle_t *th, const void *xregs) { - return (TD_NOFPREGS); + return (TD_NOXREGS); } -#endif static td_err_e -libc_r_db_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *r) +libc_r_db_thr_setfpregs(const td_thrhandle_t *th, const struct fpreg *r) { return (TD_ERR); } static td_err_e -libc_r_db_thr_setgregs(const td_thrhandle_t *th, const prgregset_t r) +libc_r_db_thr_setgregs(const td_thrhandle_t *th, const struct reg *r) { return (TD_ERR); } @@ -337,12 +339,11 @@ .to_thr_get_info = libc_r_db_thr_get_info, .to_thr_getfpregs = libc_r_db_thr_getfpregs, .to_thr_getgregs = libc_r_db_thr_getgregs, + .to_thr_getxregs = libc_r_db_thr_getxregs, + .to_thr_getxregsize = libc_r_db_thr_getxregsize, .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_setxregs = libc_r_db_thr_setxregs, .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 }; Index: lib/libthread_db/libpthread_db.c =========================================================================== --- lib/libthread_db/libpthread_db.c 2008/03/13 03:14:06 #14 +++ lib/libthread_db/libpthread_db.c 2008/03/13 03:14:06 @@ -218,7 +218,7 @@ static td_err_e pt_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) { - prgregset_t gregs; + struct reg gregs; TAILQ_HEAD(, pthread) thread_list; psaddr_t pt, tcb_addr; lwpid_t lwp; @@ -266,7 +266,7 @@ return (P2T(ret)); } /* check lwp */ - ret = ps_lgetregs(ta->ph, ta->map[id].lwp, gregs); + ret = ps_lgetregs(ta->ph, ta->map[id].lwp, &gregs); if (ret != PS_OK) { /* no longer exists */ ta->map[id].type = PT_NONE; @@ -678,9 +678,14 @@ return (0); } -#ifdef __i386__ +static td_err_e +pt_thr_getxregsize(const td_thrhandle_t *th, int *sizep) +{ + return (TD_NOXREGS); +} + static td_err_e -pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) +pt_thr_getxregs(const td_thrhandle_t *th, void *xregs) { const td_thragent_t *ta = th->th_ta; struct kse_thr_mailbox tmbx; @@ -697,7 +702,7 @@ return (ret); if (ta->map[th->th_tid].type == PT_LWP) { - ret = ps_lgetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave); + ret = ps_lgetxregs(ta->ph, ta->map[th->th_tid].lwp, xregs); return (P2T(ret)); } @@ -711,20 +716,19 @@ if (ret != 0) return (P2T(ret)); if (lwp != 0) { - ret = ps_lgetxmmregs(ta->ph, lwp, fxsave); + ret = ps_lgetxregs(ta->ph, lwp, xregs); 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); + pt_ucontext_to_xreg(&tmbx.tm_context, xregs); return (0); } -#endif static td_err_e -pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs) +pt_thr_getfpregs(const td_thrhandle_t *th, struct fpreg *fpregs) { const td_thragent_t *ta = th->th_ta; struct kse_thr_mailbox tmbx; @@ -765,7 +769,7 @@ } static td_err_e -pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) +pt_thr_getgregs(const td_thrhandle_t *th, struct reg *gregs) { const td_thragent_t *ta = th->th_ta; struct kse_thr_mailbox tmbx; @@ -805,9 +809,8 @@ return (0); } -#ifdef __i386__ static td_err_e -pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) +pt_thr_setxregs(const td_thrhandle_t *th, const void *xregs) { const td_thragent_t *ta = th->th_ta; struct kse_thr_mailbox tmbx; @@ -824,7 +827,7 @@ return (ret); if (ta->map[th->th_tid].type == PT_LWP) { - ret = ps_lsetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave); + ret = ps_lsetxregs(ta->ph, ta->map[th->th_tid].lwp, xregs); return (P2T(ret)); } @@ -839,7 +842,7 @@ if (ret != 0) return (P2T(ret)); if (lwp != 0) { - ret = ps_lsetxmmregs(ta->ph, lwp, fxsave); + ret = ps_lsetxregs(ta->ph, lwp, xregs); return (P2T(ret)); } /* @@ -850,14 +853,13 @@ if (ret != 0) return (P2T(ret)); - pt_fxsave_to_ucontext(fxsave, &tmbx.tm_context); + pt_xreg_to_ucontext(xregs, &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) +pt_thr_setfpregs(const td_thrhandle_t *th, const struct fpreg *fpregs) { const td_thragent_t *ta = th->th_ta; struct kse_thr_mailbox tmbx; @@ -904,7 +906,7 @@ } static td_err_e -pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) +pt_thr_setgregs(const td_thrhandle_t *th, const struct reg *gregs) { const td_thragent_t *ta = th->th_ta; struct kse_thr_mailbox tmbx; @@ -1134,16 +1136,15 @@ .to_thr_get_info = pt_thr_get_info, .to_thr_getfpregs = pt_thr_getfpregs, .to_thr_getgregs = pt_thr_getgregs, + .to_thr_getxregs = pt_thr_getxregs, + .to_thr_getxregsize = pt_thr_getxregsize, .to_thr_set_event = pt_thr_set_event, .to_thr_setfpregs = pt_thr_setfpregs, .to_thr_setgregs = pt_thr_setgregs, + .to_thr_setxregs = pt_thr_setxregs, .to_thr_validate = pt_thr_validate, .to_thr_tls_get_addr = pt_thr_tls_get_addr, /* FreeBSD specific extensions. */ .to_thr_sstep = pt_thr_sstep, -#ifdef __i386__ - .to_thr_getxmmregs = pt_thr_getxmmregs, - .to_thr_setxmmregs = pt_thr_setxmmregs, -#endif }; Index: lib/libthread_db/libpthread_db.h =========================================================================== --- lib/libthread_db/libpthread_db.h 2008/03/13 03:14:06 #4 +++ lib/libthread_db/libpthread_db.h 2008/03/13 03:14:06 @@ -84,10 +84,9 @@ 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 +void pt_xreg_to_ucontext(const void *, ucontext_t *); +void pt_ucontext_to_xreg(const ucontext_t *, void *); + int pt_reg_sstep(struct reg *reg, int step); #endif /* _LIBPTHREAD_DB_H_ */ Index: lib/libthread_db/libthr_db.c =========================================================================== --- lib/libthread_db/libthr_db.c 2008/03/13 03:14:06 #12 +++ lib/libthread_db/libthr_db.c 2008/03/13 03:14:06 @@ -513,9 +513,14 @@ return (0); } -#ifdef __i386__ +static td_err_e +pt_thr_getxregsize(const td_thrhandle_t *th, int *sizep) +{ + return (TD_NOXREGS); +} + static td_err_e -pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) +pt_thr_getxregs(const td_thrhandle_t *th, void *xregs) { const td_thragent_t *ta = th->th_ta; int ret; @@ -526,13 +531,12 @@ if (ret) return (ret); - ret = ps_lgetxmmregs(ta->ph, th->th_tid, fxsave); + ret = ps_lgetxregs(ta->ph, th->th_tid, xregs); return (P2T(ret)); } -#endif static td_err_e -pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs) +pt_thr_getfpregs(const td_thrhandle_t *th, struct fpreg *fpregs) { const td_thragent_t *ta = th->th_ta; int ret; @@ -548,7 +552,7 @@ } static td_err_e -pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) +pt_thr_getgregs(const td_thrhandle_t *th, struct reg *gregs) { const td_thragent_t *ta = th->th_ta; int ret; @@ -563,9 +567,8 @@ return (P2T(ret)); } -#ifdef __i386__ static td_err_e -pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) +pt_thr_setxregs(const td_thrhandle_t *th, const void *xregs) { const td_thragent_t *ta = th->th_ta; int ret; @@ -576,13 +579,12 @@ if (ret) return (ret); - ret = ps_lsetxmmregs(ta->ph, th->th_tid, fxsave); + ret = ps_lsetxregs(ta->ph, th->th_tid, xregs); return (P2T(ret)); } -#endif static td_err_e -pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) +pt_thr_setfpregs(const td_thrhandle_t *th, const struct fpreg *fpregs) { const td_thragent_t *ta = th->th_ta; int ret; @@ -598,7 +600,7 @@ } static td_err_e -pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) +pt_thr_setgregs(const td_thrhandle_t *th, const struct reg *gregs) { const td_thragent_t *ta = th->th_ta; int ret; @@ -778,16 +780,15 @@ .to_thr_get_info = pt_thr_get_info, .to_thr_getfpregs = pt_thr_getfpregs, .to_thr_getgregs = pt_thr_getgregs, + .to_thr_getxregs = pt_thr_getxregs, + .to_thr_getxregsize = pt_thr_getxregsize, .to_thr_set_event = pt_thr_set_event, .to_thr_setfpregs = pt_thr_setfpregs, .to_thr_setgregs = pt_thr_setgregs, + .to_thr_setxregs = pt_thr_setxregs, .to_thr_validate = pt_thr_validate, .to_thr_tls_get_addr = pt_thr_tls_get_addr, /* FreeBSD specific extensions. */ .to_thr_sstep = pt_thr_sstep, -#ifdef __i386__ - .to_thr_getxmmregs = pt_thr_getxmmregs, - .to_thr_setxmmregs = pt_thr_setxmmregs, -#endif }; Index: lib/libthread_db/thread_db.c =========================================================================== --- lib/libthread_db/thread_db.c 2008/03/13 03:14:06 #4 +++ lib/libthread_db/thread_db.c 2008/03/13 03:14:06 @@ -182,25 +182,29 @@ 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) +td_thr_getxregs(const td_thrhandle_t *th, void *xreg) { const td_thragent_t *ta = th->th_ta; - return (ta->ta_ops->to_thr_getxmmregs(th, fxsave)); + return (ta->ta_ops->to_thr_getxregs(th, xreg)); } -#endif +td_err_e +td_thr_getxregsize(const td_thrhandle_t *th, int *sizep) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_getxregsize(th, sizep)); +} td_err_e -td_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) +td_thr_getfpregs(const td_thrhandle_t *th, struct fpreg *fpregs) { const td_thragent_t *ta = th->th_ta; - return (ta->ta_ops->to_thr_getfpregs(th, fpregset)); + return (ta->ta_ops->to_thr_getfpregs(th, fpregs)); } td_err_e -td_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) +td_thr_getgregs(const td_thrhandle_t *th, struct reg *gregs) { const td_thragent_t *ta = th->th_ta; return (ta->ta_ops->to_thr_getgregs(th, gregs)); @@ -213,24 +217,22 @@ 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) +td_thr_setxregs(const td_thrhandle_t *th, const void *xreg) { const td_thragent_t *ta = th->th_ta; - return (ta->ta_ops->to_thr_setxmmregs(th, fxsave)); + return (ta->ta_ops->to_thr_setxregs(th, xreg)); } -#endif td_err_e -td_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) +td_thr_setfpregs(const td_thrhandle_t *th, const struct fpreg *fpregs) { const td_thragent_t *ta = th->th_ta; return (ta->ta_ops->to_thr_setfpregs(th, fpregs)); } td_err_e -td_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) +td_thr_setgregs(const td_thrhandle_t *th, const struct reg *gregs) { const td_thragent_t *ta = th->th_ta; return (ta->ta_ops->to_thr_setgregs(th, gregs)); Index: lib/libthread_db/thread_db.h =========================================================================== --- lib/libthread_db/thread_db.h 2008/03/13 03:14:06 #6 +++ lib/libthread_db/thread_db.h 2008/03/13 03:14:06 @@ -227,17 +227,14 @@ 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_getfpregs(const td_thrhandle_t *, struct fpreg *); +td_err_e td_thr_getgregs(const td_thrhandle_t *, struct reg *); +td_err_e td_thr_getxregs(const td_thrhandle_t *, void *); +td_err_e td_thr_getxregsize(const td_thrhandle_t *, int *); 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_setfpregs(const td_thrhandle_t *, const struct fpreg *); +td_err_e td_thr_setgregs(const td_thrhandle_t *, const struct reg *); +td_err_e td_thr_setxregs(const td_thrhandle_t *, const void *); td_err_e td_thr_validate(const td_thrhandle_t *); td_err_e td_thr_tls_get_addr(const td_thrhandle_t *, void *, size_t, void **); Index: lib/libthread_db/thread_db_int.h =========================================================================== --- lib/libthread_db/thread_db_int.h 2008/03/13 03:14:06 #3 +++ lib/libthread_db/thread_db_int.h 2008/03/13 03:14:06 @@ -66,23 +66,22 @@ td_err_e (*to_thr_event_getmsg)(const td_thrhandle_t *, td_event_msg_t *); td_err_e (*to_thr_get_info)(const td_thrhandle_t *, td_thrinfo_t *); - td_err_e (*to_thr_getfpregs)(const td_thrhandle_t *, prfpregset_t *); - td_err_e (*to_thr_getgregs)(const td_thrhandle_t *, prgregset_t); + td_err_e (*to_thr_getfpregs)(const td_thrhandle_t *, struct fpreg *); + td_err_e (*to_thr_getgregs)(const td_thrhandle_t *, struct reg *); + td_err_e (*to_thr_getxregs)(const td_thrhandle_t *, void *); + td_err_e (*to_thr_getxregsize)(const td_thrhandle_t *, int *); td_err_e (*to_thr_set_event)(const td_thrhandle_t *, td_thr_events_t *); td_err_e (*to_thr_setfpregs)(const td_thrhandle_t *, - const prfpregset_t *); - td_err_e (*to_thr_setgregs)(const td_thrhandle_t *, const prgregset_t); + const struct fpreg *); + td_err_e (*to_thr_setgregs)(const td_thrhandle_t *, const struct reg *); + td_err_e (*to_thr_setxregs)(const td_thrhandle_t *, const void *); td_err_e (*to_thr_validate)(const td_thrhandle_t *); td_err_e (*to_thr_tls_get_addr)(const td_thrhandle_t *, void *, size_t, void **); /* 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 Index: sys/arm/arm/machdep.c =========================================================================== --- sys/arm/arm/machdep.c 2008/03/13 03:14:06 #28 +++ sys/arm/arm/machdep.c 2008/03/13 03:14:06 @@ -390,7 +390,7 @@ uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_READ; uio.uio_td = td; - return proc_rwmem(td->td_proc, &uio); + return ptrace_rwmem(td->td_proc, &uio); } static int @@ -409,7 +409,7 @@ uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_WRITE; uio.uio_td = td; - return proc_rwmem(td->td_proc, &uio); + return ptrace_rwmem(td->td_proc, &uio); } int Index: sys/compat/ia32/ia32_sysvec.c =========================================================================== --- sys/compat/ia32/ia32_sysvec.c 2008/03/13 03:14:06 #22 +++ sys/compat/ia32/ia32_sysvec.c 2008/03/13 03:14:06 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -64,10 +65,14 @@ #include #include +#ifdef __amd64__ +#include +#endif #include #include #include #include +#include #include #ifdef __amd64__ #include @@ -110,6 +115,24 @@ SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxvmem, CTLFLAG_RW, &ia32_maxvmem, 0, ""); TUNABLE_ULONG("compat.ia32.maxvmem", &ia32_maxvmem); +static struct ptregset ia32_regs = { + .rs_size = sizeof(struct reg32), + .rs_read = (ptregset_readf)fill_regs32, + .rs_write = (ptregset_writef)set_regs32 +}; + +static struct ptregset ia32_fpregs = { + .rs_size = sizeof(struct fpreg32), + .rs_read = (ptregset_readf)fill_fpregs32, + .rs_write = (ptregset_writef)set_fpregs32 +}; + +static struct ptregset ia32_dbregs = { + .rs_size = sizeof(struct dbreg32), + .rs_read = (ptregset_readf)fill_dbregs32, + .rs_write = (ptregset_writef)set_dbregs32 +}; + struct sysentvec ia32_freebsd_sysvec = { FREEBSD32_SYS_MAXSYSCALL, freebsd32_sysent, @@ -137,7 +160,10 @@ ia32_copyout_strings, ia32_setregs, ia32_fixlimit, - &ia32_maxssiz + &ia32_maxssiz, + &ia32_regs, + &ia32_fpregs, + &ia32_dbregs }; Index: sys/fs/procfs/procfs_ctl.c =========================================================================== --- sys/fs/procfs/procfs_ctl.c 2008/03/13 03:14:06 #27 +++ sys/fs/procfs/procfs_ctl.c 2008/03/13 03:14:06 @@ -245,7 +245,7 @@ * What does it mean to single step a threaded program? */ case PROCFS_CTL_STEP: - error = proc_sstep(FIRST_THREAD_IN_PROC(p)); /* XXXKSE */ + error = ptrace_sstep(FIRST_THREAD_IN_PROC(p)); /* XXXKSE */ PROC_UNLOCK(p); if (error) return (error); Index: sys/fs/procfs/procfs_dbregs.c =========================================================================== --- sys/fs/procfs/procfs_dbregs.c 2008/03/13 03:14:06 #17 +++ sys/fs/procfs/procfs_dbregs.c 2008/03/13 03:14:06 @@ -48,9 +48,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -59,41 +61,23 @@ #include #ifdef COMPAT_IA32 -#include -#include -#include - extern struct sysentvec ia32_freebsd_sysvec; -/* - * PROC(write, dbregs, td2, &r) becomes - * proc_write_dbregs(td2, &r) or - * proc_write_dbregs32(td2, &r32) - * - * UIOMOVE_FROMBUF(r, uio) becomes - * uiomove_frombuf(&r, sizeof(r), uio) or - * uiomove_frombuf(&r32, sizeof(r32), uio) - */ -#define PROC(d, w, t, r) wrap32 ? \ - proc_ ## d ## _ ## w ## 32(t, r ## 32) : \ - proc_ ## d ## _ ## w(t, r) -#define UIOMOVE_FROMBUF(k, u) wrap32 ? \ - uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \ - uiomove_frombuf(& k, sizeof(k), u) -#else -#define PROC(d, w, t, r) proc_ ## d ## _ ## w(t, r) -#define UIOMOVE_FROMBUF(k, u) uiomove_frombuf(& k, sizeof(k), u) #endif +static struct ptregset default_dbreg = { + .rs_size = sizeof(struct dbreg), + .rs_read = (ptregset_readf)fill_dbregs, + .rs_write = (ptregset_writef)set_dbregs +}; + int procfs_doprocdbregs(PFS_FILL_ARGS) { + struct ptregset *rs; + struct sysentvec *sv; + struct thread *td2; + void *buf; int error; - struct dbreg r; - struct thread *td2; -#ifdef COMPAT_IA32 - struct dbreg32 r32; - int wrap32 = 0; -#endif if (uio->uio_offset != 0) return (0); @@ -105,31 +89,38 @@ return (EPERM); } + sv = p->p_sysent; + rs = (sv->sv_dbreg != NULL) ? sv->sv_dbreg : &default_dbreg; + PROC_UNLOCK(p); + +#ifdef COMPAT_IA32 + if (td->td_proc->p_sysent == &ia32_freebsd_sysvec && + sv != &ia32_freebsd_sysvec) + return (EINVAL); +#endif + + buf = malloc(rs->rs_size, M_TEMP, M_WAITOK); + if (buf == NULL) + return (ENOMEM); + + PROC_LOCK(p); /* XXXKSE: */ td2 = FIRST_THREAD_IN_PROC(p); -#ifdef COMPAT_IA32 - if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) { - if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) { - PROC_UNLOCK(p); - return (EINVAL); - } - wrap32 = 1; - } -#endif - error = PROC(read, dbregs, td2, &r); + error = ptrace_read_regf(td2, buf, rs->rs_read); if (error == 0) { PROC_UNLOCK(p); - error = UIOMOVE_FROMBUF(r, uio); + error = uiomove_frombuf(buf, rs->rs_size, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { - if (!P_SHOULDSTOP(p)) /* XXXKSE should be P_TRACED? */ + if (!P_SHOULDSTOP(p)) error = EBUSY; else /* XXXKSE: */ - error = PROC(write, dbregs, td2, &r); + error = ptrace_write_regf(td2, buf, rs->rs_write); } PROC_UNLOCK(p); + free(buf, M_TEMP); return (error); } Index: sys/fs/procfs/procfs_fpregs.c =========================================================================== --- sys/fs/procfs/procfs_fpregs.c 2008/03/13 03:14:06 #16 +++ sys/fs/procfs/procfs_fpregs.c 2008/03/13 03:14:06 @@ -42,9 +42,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -53,41 +55,23 @@ #include #ifdef COMPAT_IA32 -#include -#include -#include - extern struct sysentvec ia32_freebsd_sysvec; -/* - * PROC(write, fpregs, td2, &r) becomes - * proc_write_fpregs(td2, &r) or - * proc_write_fpregs32(td2, &r32) - * - * UIOMOVE_FROMBUF(r, uio) becomes - * uiomove_frombuf(&r, sizeof(r), uio) or - * uiomove_frombuf(&r32, sizeof(r32), uio) - */ -#define PROC(d, w, t, r) wrap32 ? \ - proc_ ## d ## _ ## w ## 32(t, r ## 32) : \ - proc_ ## d ## _ ## w(t, r) -#define UIOMOVE_FROMBUF(k, u) wrap32 ? \ - uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \ - uiomove_frombuf(& k, sizeof(k), u) -#else -#define PROC(d, w, t, r) proc_ ## d ## _ ## w(t, r) -#define UIOMOVE_FROMBUF(k, u) uiomove_frombuf(& k, sizeof(k), u) #endif +static struct ptregset default_fpreg = { + .rs_size = sizeof(struct fpreg), + .rs_read = (ptregset_readf)fill_fpregs, + .rs_write = (ptregset_writef)set_fpregs +}; + int procfs_doprocfpregs(PFS_FILL_ARGS) { + struct ptregset *rs; + struct sysentvec *sv; + struct thread *td2; + void *buf; int error; - struct fpreg r; - struct thread *td2; -#ifdef COMPAT_IA32 - struct fpreg32 r32; - int wrap32 = 0; -#endif if (uio->uio_offset != 0) return (0); @@ -99,21 +83,27 @@ return (EPERM); } + sv = p->p_sysent; + rs = (sv->sv_fpreg != NULL) ? sv->sv_fpreg : &default_fpreg; + PROC_UNLOCK(p); + +#ifdef COMPAT_IA32 + if (td->td_proc->p_sysent == &ia32_freebsd_sysvec && + sv != &ia32_freebsd_sysvec) + return (EINVAL); +#endif + + buf = malloc(rs->rs_size, M_TEMP, M_WAITOK); + if (buf == NULL) + return (ENOMEM); + + PROC_LOCK(p); /* XXXKSE: */ td2 = FIRST_THREAD_IN_PROC(p); -#ifdef COMPAT_IA32 - if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) { - if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) { - PROC_UNLOCK(p); - return (EINVAL); - } - wrap32 = 1; - } -#endif - error = PROC(read, fpregs, td2, &r); + error = ptrace_read_regf(td2, buf, rs->rs_read); if (error == 0) { PROC_UNLOCK(p); - error = UIOMOVE_FROMBUF(r, uio); + error = uiomove_frombuf(buf, rs->rs_size, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { @@ -121,9 +111,10 @@ error = EBUSY; else /* XXXKSE: */ - error = PROC(write, fpregs, td2, &r); + error = ptrace_write_regf(td2, buf, rs->rs_write); } PROC_UNLOCK(p); + free(buf, M_TEMP); return (error); } Index: sys/fs/procfs/procfs_mem.c =========================================================================== --- sys/fs/procfs/procfs_mem.c 2008/03/13 03:14:06 #9 +++ sys/fs/procfs/procfs_mem.c 2008/03/13 03:14:06 @@ -65,7 +65,7 @@ error = p_candebug(td, p); PROC_UNLOCK(p); if (error == 0) - error = proc_rwmem(p, uio); + error = ptrace_rwmem(p, uio); return (error); } Index: sys/fs/procfs/procfs_regs.c =========================================================================== --- sys/fs/procfs/procfs_regs.c 2008/03/13 03:14:06 #16 +++ sys/fs/procfs/procfs_regs.c 2008/03/13 03:14:06 @@ -42,9 +42,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -53,41 +55,23 @@ #include #ifdef COMPAT_IA32 -#include -#include -#include - extern struct sysentvec ia32_freebsd_sysvec; -/* - * PROC(write, regs, td2, &r) becomes - * proc_write_regs(td2, &r) or - * proc_write_regs32(td2, &r32) - * - * UIOMOVE_FROMBUF(r, uio) becomes - * uiomove_frombuf(&r, sizeof(r), uio) or - * uiomove_frombuf(&r32, sizeof(r32), uio) - */ -#define PROC(d, w, t, r) wrap32 ? \ - proc_ ## d ## _ ## w ## 32(t, r ## 32) : \ - proc_ ## d ## _ ## w(t, r) -#define UIOMOVE_FROMBUF(k, u) wrap32 ? \ - uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \ - uiomove_frombuf(& k, sizeof(k), u) -#else -#define PROC(d, w, t, r) proc_ ## d ## _ ## w(t, r) -#define UIOMOVE_FROMBUF(k, u) uiomove_frombuf(& k, sizeof(k), u) #endif +static struct ptregset default_reg = { + .rs_size = sizeof(struct reg), + .rs_read = (ptregset_readf)fill_regs, + .rs_write = (ptregset_writef)set_regs +}; + int procfs_doprocregs(PFS_FILL_ARGS) { + struct ptregset *rs; + struct sysentvec *sv; + struct thread *td2; + void *buf; int error; - struct reg r; - struct thread *td2; -#ifdef COMPAT_IA32 - struct reg32 r32; - int wrap32 = 0; -#endif if (uio->uio_offset != 0) return (0); @@ -99,21 +83,27 @@ return (EPERM); } + sv = p->p_sysent; + rs = (sv->sv_reg != NULL) ? sv->sv_reg : &default_reg; + PROC_UNLOCK(p); + +#ifdef COMPAT_IA32 + if (td->td_proc->p_sysent == &ia32_freebsd_sysvec && + sv != &ia32_freebsd_sysvec) + return (EINVAL); +#endif + + buf = malloc(rs->rs_size, M_TEMP, M_WAITOK); + if (buf == NULL) + return (ENOMEM); + + PROC_LOCK(p); /* XXXKSE: */ td2 = FIRST_THREAD_IN_PROC(p); -#ifdef COMPAT_IA32 - if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) { - if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) { - PROC_UNLOCK(p); - return (EINVAL); - } - wrap32 = 1; - } -#endif - error = PROC(read, regs, td2, &r); + error = ptrace_read_regf(td2, buf, rs->rs_read); if (error == 0) { PROC_UNLOCK(p); - error = UIOMOVE_FROMBUF(r, uio); + error = uiomove_frombuf(buf, rs->rs_size, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { @@ -121,9 +111,10 @@ error = EBUSY; else /* XXXKSE: */ - error = PROC(write, regs, td2, &r); + error = ptrace_write_regf(td2, buf, rs->rs_write); } PROC_UNLOCK(p); + free(buf, M_TEMP); return (error); } Index: sys/i386/linux/linux_ptrace.c =========================================================================== --- sys/i386/linux/linux_ptrace.c 2008/03/13 03:14:06 #18 +++ sys/i386/linux/linux_ptrace.c 2008/03/13 03:14:06 @@ -269,13 +269,13 @@ case PTRACE_POKETEXT: case PTRACE_POKEDATA: case PTRACE_KILL: - error = kern_ptrace(td, req, pid, addr, uap->data); + error = kern_ptrace(td, req, pid, 0, addr, uap->data); break; case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: { /* need to preserve return value */ int rval = td->td_retval[0]; - error = kern_ptrace(td, req, pid, addr, 0); + error = kern_ptrace(td, req, pid, 0, addr, 0); if (error == 0) error = copyout(td->td_retval, (void *)uap->data, sizeof(l_int)); @@ -283,20 +283,20 @@ break; } case PTRACE_DETACH: - error = kern_ptrace(td, PT_DETACH, pid, (void *)1, + error = kern_ptrace(td, PT_DETACH, pid, 0, (void *)1, map_signum(uap->data)); break; case PTRACE_SINGLESTEP: case PTRACE_CONT: - error = kern_ptrace(td, req, pid, (void *)1, + error = kern_ptrace(td, req, pid, 0, (void *)1, map_signum(uap->data)); break; case PTRACE_ATTACH: - error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data); + error = kern_ptrace(td, PT_ATTACH, pid, 0, addr, uap->data); break; case PTRACE_GETREGS: /* Linux is using data where FreeBSD is using addr */ - error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0); + error = kern_ptrace(td, PT_GETREGS, pid, 0, &u.bsd_reg, 0); if (error == 0) { map_regs_to_linux(&u.bsd_reg, &r.reg); error = copyout(&r.reg, (void *)uap->data, @@ -308,12 +308,13 @@ error = copyin((void *)uap->data, &r.reg, sizeof(r.reg)); if (error == 0) { map_regs_from_linux(&u.bsd_reg, &r.reg); - error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0); + error = kern_ptrace(td, PT_SETREGS, pid, 0, &u.bsd_reg, + 0); } break; case PTRACE_GETFPREGS: /* Linux is using data where FreeBSD is using addr */ - error = kern_ptrace(td, PT_GETFPREGS, pid, &u.bsd_fpreg, 0); + error = kern_ptrace(td, PT_GETFPREGS, pid, 0, &u.bsd_fpreg, 0); if (error == 0) { map_fpregs_to_linux(&u.bsd_fpreg, &r.fpreg); error = copyout(&r.fpreg, (void *)uap->data, @@ -325,7 +326,7 @@ error = copyin((void *)uap->data, &r.fpreg, sizeof(r.fpreg)); if (error == 0) { map_fpregs_from_linux(&u.bsd_fpreg, &r.fpreg); - error = kern_ptrace(td, PT_SETFPREGS, pid, + error = kern_ptrace(td, PT_SETFPREGS, pid, 0, &u.bsd_fpreg, 0); } break; @@ -429,7 +430,8 @@ * as necessary. */ if (uap->addr < sizeof(struct linux_pt_reg)) { - error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0); + error = kern_ptrace(td, PT_GETREGS, pid, 0, &u.bsd_reg, + 0); if (error != 0) break; @@ -444,7 +446,8 @@ (l_int)uap->data; map_regs_from_linux(&u.bsd_reg, &r.reg); - error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0); + error = kern_ptrace(td, PT_SETREGS, pid, 0, &u.bsd_reg, + 0); } /* @@ -452,8 +455,8 @@ */ if (uap->addr >= LINUX_DBREG_OFFSET && uap->addr <= LINUX_DBREG_OFFSET + LINUX_DBREG_SIZE) { - error = kern_ptrace(td, PT_GETDBREGS, pid, &u.bsd_dbreg, - 0); + error = kern_ptrace(td, PT_GETDBREGS, pid, 0, + &u.bsd_dbreg, 0); if (error != 0) break; @@ -467,7 +470,7 @@ *(l_int *)((char *)&u.bsd_dbreg + uap->addr) = uap->data; - error = kern_ptrace(td, PT_SETDBREGS, pid, + error = kern_ptrace(td, PT_SETDBREGS, pid, 0, &u.bsd_dbreg, 0); } Index: sys/ia64/ia64/machdep.c =========================================================================== --- sys/ia64/ia64/machdep.c 2008/03/13 03:14:06 #190 +++ sys/ia64/ia64/machdep.c 2008/03/13 03:14:06 @@ -1132,9 +1132,9 @@ uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_WRITE; uio.uio_td = td; - error = proc_rwmem(td->td_proc, &uio); + error = ptrace_rwmem(td->td_proc, &uio); /* - * XXX proc_rwmem() doesn't currently return ENOSPC, + * XXX ptrace_rwmem() doesn't currently return ENOSPC, * so I think it can bogusly return 0. Neither do * we allow short writes. */ Index: sys/kern/imgact_elf.c =========================================================================== --- sys/kern/imgact_elf.c 2008/03/13 03:14:06 #87 +++ sys/kern/imgact_elf.c 2008/03/13 03:14:06 @@ -1,7 +1,8 @@ /*- - * Copyright (c) 2000 David O'Brien * Copyright (c) 1995-1996 Søren Schmidt * Copyright (c) 1996 Peter Wemm + * Copyright (c) 2000 David O'Brien + * Copyright (c) 2005 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -937,23 +938,20 @@ static void cb_put_phdr(vm_map_entry_t, void *); static void cb_size_segment(vm_map_entry_t, void *); static void each_writable_segment(struct thread *, segment_callback, void *); -static int __elfN(corehdr)(struct thread *, struct vnode *, struct ucred *, - int, void *, size_t); static void __elfN(puthdr)(struct thread *, void *, size_t *, int); static void __elfN(putnote)(void *, size_t *, const char *, int, const void *, size_t); int -__elfN(coredump)(td, vp, limit) - struct thread *td; - struct vnode *vp; - off_t limit; +__elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit) { + struct sseg_closure seginfo; struct ucred *cred = td->td_ucred; - int error = 0; - struct sseg_closure seginfo; + Elf_Phdr *php; void *hdr; - size_t hdrsize; + off_t offset; + size_t pre_hdrsz, post_hdrsz; + int error; /* Size the program segments. */ seginfo.count = 0; @@ -965,41 +963,45 @@ * a dry run of generating it. Nothing is written, but the * size is calculated. */ - hdrsize = 0; - __elfN(puthdr)(td, (void *)NULL, &hdrsize, seginfo.count); + pre_hdrsz = 0; + __elfN(puthdr)(td, (void *)NULL, &pre_hdrsz, seginfo.count); - if (hdrsize + seginfo.size >= limit) + if (pre_hdrsz + seginfo.size >= limit) return (EFAULT); /* - * Allocate memory for building the header, fill it up, + * Allocate memory for building the headers, fill it up, * and write it out. */ - hdr = malloc(hdrsize, M_TEMP, M_WAITOK); - if (hdr == NULL) { + hdr = malloc(pre_hdrsz, M_TEMP, M_WAITOK | M_ZERO); + if (hdr == NULL) return (EINVAL); - } - error = __elfN(corehdr)(td, vp, cred, seginfo.count, hdr, hdrsize); + + post_hdrsz = 0; + __elfN(puthdr)(td, hdr, &post_hdrsz, seginfo.count); + + /* + * We allow that pre-sizing over-estimates. It is not acceptable + * that we overrun the buffer. + */ + KASSERT(pre_hdrsz >= post_hdrsz, + ("%s: pre_hdrsz < post_hdrsz", __func__)); + + /* Write it to the core file. */ + error = vn_rdwr_inchunks(UIO_WRITE, vp, hdr, post_hdrsz, (off_t)0, + UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NOCRED, NULL, td); /* Write the contents of all of the writable segments. */ - if (error == 0) { - Elf_Phdr *php; - off_t offset; - int i; - - php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; - offset = hdrsize; - for (i = 0; i < seginfo.count; i++) { - error = vn_rdwr_inchunks(UIO_WRITE, vp, - (caddr_t)(uintptr_t)php->p_vaddr, - php->p_filesz, offset, UIO_USERSPACE, - IO_UNIT | IO_DIRECT, cred, NOCRED, NULL, - curthread); /* XXXKSE */ - if (error != 0) - break; - offset += php->p_filesz; - php++; - } + offset = post_hdrsz; + php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; + while (error == 0 && seginfo.count > 0) { + error = vn_rdwr_inchunks(UIO_WRITE, vp, + (caddr_t)(uintptr_t)php->p_vaddr, php->p_filesz, + offset, UIO_USERSPACE, IO_UNIT | IO_DIRECT, cred, + NOCRED, NULL, td); + offset += php->p_filesz; + php++; + seginfo.count--; } free(hdr, M_TEMP); @@ -1011,9 +1013,7 @@ * program header entry. */ static void -cb_put_phdr(entry, closure) - vm_map_entry_t entry; - void *closure; +cb_put_phdr(vm_map_entry_t entry, void *closure) { struct phdr_closure *phc = (struct phdr_closure *)closure; Elf_Phdr *phdr = phc->phdr; @@ -1043,9 +1043,7 @@ * the number of segments and their total size. */ static void -cb_size_segment(entry, closure) - vm_map_entry_t entry; - void *closure; +cb_size_segment(vm_map_entry_t entry, void *closure) { struct sseg_closure *ssc = (struct sseg_closure *)closure; @@ -1059,10 +1057,7 @@ * caller-supplied data. */ static void -each_writable_segment(td, func, closure) - struct thread *td; - segment_callback func; - void *closure; +each_writable_segment(struct thread *td, segment_callback func, void *closure) { struct proc *p = td->td_proc; vm_map_t map = &p->p_vmspace->vm_map; @@ -1119,32 +1114,6 @@ vm_map_unlock_read(map); } -/* - * Write the core file header to the file, including padding up to - * the page boundary. - */ -static int -__elfN(corehdr)(td, vp, cred, numsegs, hdr, hdrsize) - struct thread *td; - struct vnode *vp; - struct ucred *cred; - int numsegs; - size_t hdrsize; - void *hdr; -{ - size_t off; - - /* Fill in the header. */ - bzero(hdr, hdrsize); - off = 0; - __elfN(puthdr)(td, hdr, &off, numsegs); - - /* Write it to the core file. */ - return (vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0, - UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NOCRED, NULL, - td)); /* XXXKSE */ -} - #if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 typedef struct prstatus32 elf_prstatus_t; typedef struct prpsinfo32 elf_prpsinfo_t; Index: sys/kern/sys_process.c =========================================================================== --- sys/kern/sys_process.c 2008/03/13 03:14:06 #77 +++ sys/kern/sys_process.c 2008/03/13 03:14:06 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -60,10 +61,6 @@ #include #ifdef COMPAT_IA32 -#include -#include -#include - extern struct sysentvec ia32_freebsd_sysvec; struct ptrace_io_desc32 { @@ -74,32 +71,6 @@ }; #endif -/* - * Functions implemented using PROC_ACTION(): - * - * proc_read_regs(proc, regs) - * Get the current user-visible register set from the process - * and copy it into the regs structure (). - * The process is stopped at the time read_regs is called. - * - * proc_write_regs(proc, regs) - * Update the current register set from the passed in regs - * structure. Take care to avoid clobbering special CPU - * registers or privileged bits in the PSL. - * Depending on the architecture this may have fix-up work to do, - * especially if the IAR or PCW are modified. - * The process is stopped at the time write_regs is called. - * - * proc_read_fpregs, proc_write_fpregs - * deal with the floating point register set, otherwise as above. - * - * proc_read_dbregs, proc_write_dbregs - * deal with the processor debug register set, otherwise as above. - * - * proc_sstep(proc) - * Arrange for the process to trap after executing a single instruction. - */ - #define PROC_ACTION(action) do { \ int error; \ \ @@ -112,105 +83,28 @@ } while(0) int -proc_read_regs(struct thread *td, struct reg *regs) +ptrace_read_regf(struct thread *td, void *reg, ptregset_readf f) { - PROC_ACTION(fill_regs(td, regs)); + PROC_ACTION((*f)(td, reg)); } int -proc_write_regs(struct thread *td, struct reg *regs) +ptrace_write_regf(struct thread *td, const void *reg, ptregset_writef f) { - PROC_ACTION(set_regs(td, regs)); + PROC_ACTION((*f)(td, reg)); } int -proc_read_dbregs(struct thread *td, struct dbreg *dbregs) -{ - - PROC_ACTION(fill_dbregs(td, dbregs)); -} - -int -proc_write_dbregs(struct thread *td, struct dbreg *dbregs) -{ - - PROC_ACTION(set_dbregs(td, dbregs)); -} - -/* - * Ptrace doesn't support fpregs at all, and there are no security holes - * or translations for fpregs, so we can just copy them. - */ -int -proc_read_fpregs(struct thread *td, struct fpreg *fpregs) -{ - - PROC_ACTION(fill_fpregs(td, fpregs)); -} - -int -proc_write_fpregs(struct thread *td, struct fpreg *fpregs) -{ - - PROC_ACTION(set_fpregs(td, fpregs)); -} - -#ifdef COMPAT_IA32 -/* For 32 bit binaries, we need to expose the 32 bit regs layouts. */ -int -proc_read_regs32(struct thread *td, struct reg32 *regs32) -{ - - PROC_ACTION(fill_regs32(td, regs32)); -} - -int -proc_write_regs32(struct thread *td, struct reg32 *regs32) -{ - - PROC_ACTION(set_regs32(td, regs32)); -} - -int -proc_read_dbregs32(struct thread *td, struct dbreg32 *dbregs32) -{ - - PROC_ACTION(fill_dbregs32(td, dbregs32)); -} - -int -proc_write_dbregs32(struct thread *td, struct dbreg32 *dbregs32) -{ - - PROC_ACTION(set_dbregs32(td, dbregs32)); -} - -int -proc_read_fpregs32(struct thread *td, struct fpreg32 *fpregs32) -{ - - PROC_ACTION(fill_fpregs32(td, fpregs32)); -} - -int -proc_write_fpregs32(struct thread *td, struct fpreg32 *fpregs32) -{ - - PROC_ACTION(set_fpregs32(td, fpregs32)); -} -#endif - -int -proc_sstep(struct thread *td) +ptrace_sstep(struct thread *td) { PROC_ACTION(ptrace_single_step(td)); } int -proc_rwmem(struct proc *p, struct uio *uio) +ptrace_rwmem(struct proc *p, struct uio *uio) { vm_map_t map; vm_object_t backing_object, object = NULL; @@ -348,153 +242,168 @@ }; #endif -#ifdef COMPAT_IA32 -/* - * This CPP subterfuge is to try and reduce the number of ifdefs in - * the body of the code. - * COPYIN(uap->addr, &r.reg, sizeof r.reg); - * becomes either: - * copyin(uap->addr, &r.reg, sizeof r.reg); - * or - * copyin(uap->addr, &r.reg32, sizeof r.reg32); - * .. except this is done at runtime. - */ -#define COPYIN(u, k, s) wrap32 ? \ - copyin(u, k ## 32, s ## 32) : \ - copyin(u, k, s) -#define COPYOUT(k, u, s) wrap32 ? \ - copyout(k ## 32, u, s ## 32) : \ - copyout(k, u, s) -#else -#define COPYIN(u, k, s) copyin(u, k, s) -#define COPYOUT(k, u, s) copyout(k, u, s) -#endif int ptrace(struct thread *td, struct ptrace_args *uap) { - /* - * XXX this obfuscation is to reduce stack usage, but the register - * structs may be too large to put on the stack anyway. - */ - union { - struct ptrace_io_desc piod; - struct ptrace_lwpinfo pl; - struct dbreg dbreg; - struct fpreg fpreg; - struct reg reg; -#ifdef COMPAT_IA32 - struct dbreg32 dbreg32; - struct fpreg32 fpreg32; - struct reg32 reg32; - struct ptrace_io_desc32 piod32; -#endif - } r; void *addr; - int error = 0; -#ifdef COMPAT_IA32 - int wrap32 = 0; + struct sysentvec *sv; + struct proc *p; + struct thread *td2; + size_t bufsz; + int error; + lwpid_t tid; - if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) - wrap32 = 1; -#endif AUDIT_ARG(pid, uap->pid); AUDIT_ARG(cmd, uap->req); AUDIT_ARG(addr, uap->addr); AUDIT_ARG(value, uap->data); - addr = &r; + + tid = 0; + if (uap->req == PT_TRACE_ME) { + p = td->td_proc; + PROC_LOCK(p); + } else { + if (uap->pid <= PID_MAX) { + p = pfind(uap->pid); + if (p == NULL) + return (ESRCH); + } else { + tid = uap->pid; + sx_slock(&allproc_lock); + FOREACH_PROC_IN_SYSTEM(p) { + PROC_LOCK(p); + mtx_lock_spin(&sched_lock); + FOREACH_THREAD_IN_PROC(p, td2) { + if (td2->td_tid == tid) + break; + } + mtx_unlock_spin(&sched_lock); + if (td2 != NULL) + break; /* proc lock held */ + PROC_UNLOCK(p); + } + sx_sunlock(&allproc_lock); + if (p == NULL) + return (ESRCH); + uap->pid = p->p_pid; + } + } + + sv = p->p_sysent; + switch (uap->req) { case PT_GETREGS: + case PT_SETREGS: + bufsz = (sv->sv_reg != NULL) ? sv->sv_reg->rs_size : + sizeof(struct reg); + break; case PT_GETFPREGS: + case PT_SETFPREGS: + bufsz = (sv->sv_fpreg != NULL) ? sv->sv_fpreg->rs_size : + sizeof(struct fpreg); + break; case PT_GETDBREGS: + case PT_SETDBREGS: + bufsz = (sv->sv_dbreg != NULL) ? sv->sv_dbreg->rs_size : + sizeof(struct dbreg); + break; + case PT_GETXREGSIZE: + bufsz = sizeof(size_t); + break; + case PT_GETXREGS: + case PT_SETXREGS: + if (uap->data < 0 || uap->data >= sv->sv_nxregs) { + PROC_UNLOCK(p); + return (EINVAL); + } + bufsz = sv->sv_xregs[uap->data].rs_size; + break; case PT_LWPINFO: + bufsz = sizeof(struct ptrace_lwpinfo); + break; + case PT_IO: +#ifdef COMPAT_IA32 + if (sv == &ia32_freebsd_sysvec) + bufsz = sizeof(struct ptrace_io_desc32); + else +#endif + bufsz = sizeof(struct ptrace_io_desc); + break; + default: + bufsz = 0; break; + } + PROC_UNLOCK(p); + + if (bufsz != 0) { + addr = malloc(bufsz, M_TEMP, M_WAITOK); + if (addr == NULL) + return (ENOMEM); + } else + addr = uap->addr; + + switch (uap->req) { case PT_SETREGS: - error = COPYIN(uap->addr, &r.reg, sizeof r.reg); - break; case PT_SETFPREGS: - error = COPYIN(uap->addr, &r.fpreg, sizeof r.fpreg); - break; case PT_SETDBREGS: - error = COPYIN(uap->addr, &r.dbreg, sizeof r.dbreg); - break; + case PT_SETXREGS: case PT_IO: - error = COPYIN(uap->addr, &r.piod, sizeof r.piod); + error = copyin(uap->addr, addr, bufsz); break; default: - addr = uap->addr; + error = 0; break; } if (error) - return (error); + goto out; - error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data); + error = kern_ptrace(td, uap->req, uap->pid, tid, addr, uap->data); if (error) - return (error); + goto out; switch (uap->req) { - case PT_IO: - error = COPYOUT(&r.piod, uap->addr, sizeof r.piod); - break; + case PT_LWPINFO: + if (uap->data < bufsz) + bufsz = uap->data; + /* FALLTHROUGH */ case PT_GETREGS: - error = COPYOUT(&r.reg, uap->addr, sizeof r.reg); - break; case PT_GETFPREGS: - error = COPYOUT(&r.fpreg, uap->addr, sizeof r.fpreg); - break; case PT_GETDBREGS: - error = COPYOUT(&r.dbreg, uap->addr, sizeof r.dbreg); + case PT_GETXREGSIZE: + case PT_GETXREGS: + case PT_IO: + error = copyout(addr, uap->addr, bufsz); break; - case PT_LWPINFO: - error = copyout(&r.pl, uap->addr, uap->data); + default: + error = 0; break; } +out: + if (bufsz > 0) + free(addr, M_TEMP); return (error); } -#undef COPYIN -#undef COPYOUT - -#ifdef COMPAT_IA32 -/* - * PROC_READ(regs, td2, addr); - * becomes either: - * proc_read_regs(td2, addr); - * or - * proc_read_regs32(td2, addr); - * .. except this is done at runtime. There is an additional - * complication in that PROC_WRITE disallows 32 bit consumers - * from writing to 64 bit address space targets. - */ -#define PROC_READ(w, t, a) wrap32 ? \ - proc_read_ ## w ## 32(t, a) : \ - proc_read_ ## w (t, a) -#define PROC_WRITE(w, t, a) wrap32 ? \ - (safe ? proc_write_ ## w ## 32(t, a) : EINVAL ) : \ - proc_write_ ## w (t, a) -#else -#define PROC_READ(w, t, a) proc_read_ ## w (t, a) -#define PROC_WRITE(w, t, a) proc_write_ ## w (t, a) -#endif int -kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) +kern_ptrace(struct thread *td, int req, pid_t pid, lwpid_t tid, void *addr, int data) { struct iovec iov; struct uio uio; - struct proc *curp, *p, *pp; + struct proc *p, *pp; + struct sysentvec *sv; struct thread *td2 = NULL; struct ptrace_io_desc *piod = NULL; struct ptrace_lwpinfo *pl; + ptregset_readf fread; + ptregset_writef fwrite; int error, write, tmp, num; int proctree_locked = 0; - lwpid_t tid = 0, *buf; + lwpid_t *buf; #ifdef COMPAT_IA32 - int wrap32 = 0, safe = 0; struct ptrace_io_desc32 *piod32 = NULL; #endif - curp = td->td_proc; - /* Lock proctree before locking the process. */ switch (req) { case PT_TRACE_ME: @@ -517,35 +426,31 @@ p = td->td_proc; PROC_LOCK(p); } else { - if (pid <= PID_MAX) { - if ((p = pfind(pid)) == NULL) { - if (proctree_locked) - sx_xunlock(&proctree_lock); - return (ESRCH); + p = pfind(pid); + if (p == NULL) { + if (proctree_locked) + sx_xunlock(&proctree_lock); + return (ESRCH); + } + if (tid != 0) { + PROC_SLOCK(p); + FOREACH_THREAD_IN_PROC(p, td2) { + if (td2->td_tid == tid) + break; } - } else { - /* this is slow, should be optimized */ - sx_slock(&allproc_lock); - FOREACH_PROC_IN_SYSTEM(p) { - PROC_LOCK(p); - PROC_SLOCK(p); - FOREACH_THREAD_IN_PROC(p, td2) { - if (td2->td_tid == pid) - break; - } - PROC_SUNLOCK(p); - if (td2 != NULL) - break; /* proc lock held */ + PROC_SUNLOCK(p); + if (td2 == NULL) { PROC_UNLOCK(p); - } - sx_sunlock(&allproc_lock); - if (p == NULL) { if (proctree_locked) sx_xunlock(&proctree_lock); return (ESRCH); } - tid = pid; - pid = p->p_pid; + } else { + if ((p->p_flag & P_STOPPED_TRACE) != 0) { + td2 = p->p_xthread; + KASSERT(td2 != NULL, ("NULL p_xthread")); + } else + td2 = FIRST_THREAD_IN_PROC(p); } } AUDIT_ARG(process, p); @@ -568,28 +473,7 @@ goto fail; } - if (tid == 0) { - if ((p->p_flag & P_STOPPED_TRACE) != 0) { - KASSERT(p->p_xthread != NULL, ("NULL p_xthread")); - td2 = p->p_xthread; - } else { - td2 = FIRST_THREAD_IN_PROC(p); - } - tid = td2->td_tid; - } - -#ifdef COMPAT_IA32 /* - * Test if we're a 32 bit client and what the target is. - * Set the wrap controls accordingly. - */ - if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) { - if (td2->td_proc->p_sysent == &ia32_freebsd_sysvec) - safe = 1; - wrap32 = 1; - } -#endif - /* * Permissions check */ switch (req) { @@ -611,8 +495,9 @@ } /* Can't trace an ancestor if you're being traced. */ - if (curp->p_flag & P_TRACED) { - for (pp = curp->p_pptr; pp != NULL; pp = pp->p_pptr) { + if (td->td_proc->p_flag & P_TRACED) { + for (pp = td->td_proc->p_pptr; pp != NULL; + pp = pp->p_pptr) { if (pp == p) { error = EINVAL; goto fail; @@ -626,7 +511,7 @@ case PT_CLEARSTEP: /* Allow thread to clear single step for itself */ - if (td->td_tid == tid) + if (td->td_tid == td2->td_tid) break; /* FALLTHROUGH */ @@ -674,7 +559,7 @@ /* * Actually do the requests */ - + sv = td2->td_proc->p_sysent; td->td_retval[0] = 0; switch (req) { @@ -835,14 +720,14 @@ uio.uio_segflg = UIO_SYSSPACE; /* i.e.: the uap */ uio.uio_rw = write ? UIO_WRITE : UIO_READ; uio.uio_td = td; - error = proc_rwmem(p, &uio); + error = ptrace_rwmem(p, &uio); if (uio.uio_resid != 0) { /* - * XXX proc_rwmem() doesn't currently return ENOSPC, + * XXX ptrace_rwmem() doesn't currently return ENOSPC, * so I think write() can bogusly return 0. * XXX what happens for short writes? We don't want * to write partial data. - * XXX proc_rwmem() returns EPERM for other invalid + * XXX ptrace_rwmem() returns EPERM for other invalid * addresses. Convert this to EINVAL. Does this * clobber returns of EPERM for other reasons? */ @@ -856,12 +741,13 @@ case PT_IO: #ifdef COMPAT_IA32 - if (wrap32) { + if (sv == &ia32_freebsd_sysvec) { piod32 = addr; iov.iov_base = (void *)(uintptr_t)piod32->piod_addr; iov.iov_len = piod32->piod_len; uio.uio_offset = (off_t)(uintptr_t)piod32->piod_offs; uio.uio_resid = piod32->piod_len; + tmp = piod32->piod_op; } else #endif { @@ -870,16 +756,13 @@ iov.iov_len = piod->piod_len; uio.uio_offset = (off_t)(uintptr_t)piod->piod_offs; uio.uio_resid = piod->piod_len; + tmp = piod->piod_op; } uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_segflg = UIO_USERSPACE; uio.uio_td = td; -#ifdef COMPAT_IA32 - tmp = wrap32 ? piod32->piod_op : piod->piod_op; -#else - tmp = piod->piod_op; -#endif + switch (tmp) { case PIOD_READ_D: case PIOD_READ_I: @@ -894,9 +777,9 @@ goto out; } PROC_UNLOCK(p); - error = proc_rwmem(p, &uio); + error = ptrace_rwmem(p, &uio); #ifdef COMPAT_IA32 - if (wrap32) + if (sv == &ia32_freebsd_sysvec) piod32->piod_len -= uio.uio_resid; else #endif @@ -909,27 +792,64 @@ goto sendsig; /* in PT_CONTINUE above */ case PT_SETREGS: - error = PROC_WRITE(regs, td2, addr); + fwrite = (sv->sv_reg != NULL) ? sv->sv_reg->rs_write : + (ptregset_writef)set_regs; + error = ptrace_write_regf(td2, addr, fwrite); break; case PT_GETREGS: - error = PROC_READ(regs, td2, addr); + fread = (sv->sv_reg != NULL) ? sv->sv_reg->rs_read : + (ptregset_readf)fill_regs; + error = ptrace_read_regf(td2, addr, fread); break; case PT_SETFPREGS: - error = PROC_WRITE(fpregs, td2, addr); + fwrite = (sv->sv_fpreg != NULL) ? sv->sv_fpreg->rs_write : + (ptregset_writef)set_fpregs; + error = ptrace_write_regf(td2, addr, fwrite); break; case PT_GETFPREGS: - error = PROC_READ(fpregs, td2, addr); + fread = (sv->sv_fpreg != NULL) ? sv->sv_fpreg->rs_read : + (ptregset_readf)fill_fpregs; + error = ptrace_read_regf(td2, addr, fread); break; case PT_SETDBREGS: - error = PROC_WRITE(dbregs, td2, addr); + fwrite = (sv->sv_dbreg != NULL) ? sv->sv_dbreg->rs_write : + (ptregset_writef)set_dbregs; + error = ptrace_write_regf(td2, addr, fwrite); break; case PT_GETDBREGS: - error = PROC_READ(dbregs, td2, addr); + fread = (sv->sv_dbreg != NULL) ? sv->sv_dbreg->rs_read : + (ptregset_readf)fill_dbregs; + error = ptrace_read_regf(td2, addr, fread); + break; + + case PT_SETXREGS: + if (data >= 0 && data < sv->sv_nxregs) { + fwrite = sv->sv_xregs[data].rs_write; + error = ptrace_write_regf(td2, addr, fwrite); + } else + error = EINVAL; + break; + + case PT_GETXREGSIZE: + if (data >= 0 && data < sv->sv_nxregs) { + memcpy(addr, &sv->sv_xregs[data].rs_size, + sizeof(size_t)); + error = 0; + } else + error = EINVAL; + break; + + case PT_GETXREGS: + if (data >= 0 && data < sv->sv_nxregs) { + fread = sv->sv_xregs[data].rs_read; + error = ptrace_read_regf(td2, addr, fread); + } else + error = EINVAL; break; case PT_LWPINFO: @@ -1009,8 +929,6 @@ sx_xunlock(&proctree_lock); return (error); } -#undef PROC_READ -#undef PROC_WRITE /* * Stop a process because of a debugging event; Index: sys/sys/core.h =========================================================================== *** /dev/null Thu Mar 13 03:11:00 2008 --- sys/sys/core.h Thu Mar 13 03:14:10 2008 *************** *** 0 **** --- 1,79 ---- + /*- + * Copyright (c) 2005, 2006 Marcel Moolenaar + * 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 ``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 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. + * + * $FreeBSD$ + */ + + #ifndef _SYS_CORE_H_ + #define _SYS_CORE_H_ + + /* + * The auxiliary information in a core file is constructed according to the + * definitions in this header. The information thus constructed is stored in + * a core file in a file format specific manner. For ELF based core files, + * it is stored in one or more PT_NOTE sections. The PT_NOTE section is the + * container for the information. + * + * The definitions in this header are designed with the following properties + * in mind: + * 1. The creation of a core file and the auxiliary information contained + * in it can be based on independent sub-procedures with limited scope. + * As such, the context in which each bit of information is placed is + * mostly unknown to the procedure that constructs the information. + * 2. The amount of auxiliary information is highly dynamic. Not only is + * there variation between platforms, there's also variation possible + * based on options and settings. + * 3. The tools that process core files and in particular the auxiliary + * information must be able to extract the information they know and + * care about without being programmed for each and every variation. + * + * Auxiliary process and thread information is stored as a sequence of + * (tag,align,size,value) quadruples. The tag describes what information is + * being provided, the size specifies how many bytes the information + * occupies, the align specifies the alignment constraints and the value is + * the actual information. This scheme allows any consumer to scan the + * sequence of quadruples and extract whatever information it knows or cares + * about, without having to understand all the information. Also, it avoids + * the typical problems that structure-based approaches have, which is that + * third-party software and cross-tools often need to hardcode structure + * offsets to access the information as they cannot always depend on the + * original definition of the structure. + */ + + struct core_quadruple { + uint32_t cq_tag:12; + uint32_t cq_align:4; + uint32_t cq_size:16; + uint8_t cq_data[]; + }; + + #define CT_TAG_NOTHING 0x000 + #define CT_TAG_OSRELDATE 0x001 + #define CT_TAG_PID 0x002 + #define CT_TAG_COMM 0x003 + #define CT_TAG_SIGNAL 0x004 + #define CT_TAG_LWPID 0x005 + + #endif /* _SYS_CORE_H_ */ Index: sys/sys/elf_common.h =========================================================================== --- sys/sys/elf_common.h 2008/03/13 03:14:06 #15 +++ sys/sys/elf_common.h 2008/03/13 03:14:06 @@ -398,11 +398,18 @@ executable contains code using a static thread-local storage scheme. */ -/* Values for n_type. Used in core files. */ +/* Values for n_type. Used by 6.x and older core files. */ #define NT_PRSTATUS 1 /* Process status. */ #define NT_FPREGSET 2 /* Floating point registers. */ #define NT_PRPSINFO 3 /* Process state info. */ +/* Note types used by Core/NG (7.x and up). */ +#define _NT_CORE(x) ((ET_CORE << 16) | ((x) & 0xffff)) +#define NT_CORE_PROC _NT_CORE(0x0000) +#define NT_CORE_THREAD _NT_CORE(0x0001) +#define NT_CORE_KERNEL _NT_CORE(0x0100) +#define NT_CORE_CPU _NT_CORE(0x0101) + /* Symbol Binding - ELFNN_ST_BIND - st_info */ #define STB_LOCAL 0 /* Local symbol */ #define STB_GLOBAL 1 /* Global symbol */ Index: sys/sys/procfs.h =========================================================================== --- sys/sys/procfs.h 2008/03/13 03:14:06 #4 +++ sys/sys/procfs.h 2008/03/13 03:14:06 @@ -65,7 +65,6 @@ gregset_t pr_reg; /* General purpose registers (1) */ } prstatus_t; -typedef gregset_t prgregset_t[1]; typedef fpregset_t prfpregset_t; #define PRFNAMESZ 16 /* Maximum command length saved */ Index: sys/sys/ptrace.h =========================================================================== --- sys/sys/ptrace.h 2008/03/13 03:14:06 #18 +++ sys/sys/ptrace.h 2008/03/13 03:14:06 @@ -67,6 +67,11 @@ #define PT_SETFPREGS 36 /* set floating-point registers */ #define PT_GETDBREGS 37 /* get debugging registers */ #define PT_SETDBREGS 38 /* set debugging registers */ +/* Machine-specific extra register sets. */ +#define PT_GETXREGSIZE 39 /* get size of extra register set. */ +#define PT_GETXREGS 40 /* get extra register set */ +#define PT_SETXREGS 41 /* set extra register set */ + #define PT_FIRSTMACH 64 /* for machine-specific requests */ #include /* machine-specific requests, if any */ @@ -122,34 +127,29 @@ #endif /* - * These are prototypes for functions that implement some of the - * debugging functionality exported by procfs / linprocfs and by the - * ptrace(2) syscall. They used to be part of procfs, but they don't - * really belong there. + * A meta-structure to describe a register set. These are used by ptrace(2) + * to read and write the various register sets. These include struct reg, + * struct fpreg and struct dbreg. These meta-structures are pointed to from + * struct sysentvec. + */ +typedef int (*ptregset_readf)(struct thread *, void *); +typedef int (*ptregset_writef)(struct thread *, const void *); +struct ptregset { + size_t rs_size; /* Size of the register set. */ + ptregset_readf rs_read; + ptregset_writef rs_write; +}; + +/* + * Prototypes exported by ptrace(2) for use by procfs and/or linprocfs. */ -struct reg; -struct fpreg; -struct dbreg; struct uio; -int proc_read_regs(struct thread *_td, struct reg *_reg); -int proc_write_regs(struct thread *_td, struct reg *_reg); -int proc_read_fpregs(struct thread *_td, struct fpreg *_fpreg); -int proc_write_fpregs(struct thread *_td, struct fpreg *_fpreg); -int proc_read_dbregs(struct thread *_td, struct dbreg *_dbreg); -int proc_write_dbregs(struct thread *_td, struct dbreg *_dbreg); -int proc_sstep(struct thread *_td); -int proc_rwmem(struct proc *_p, struct uio *_uio); -#ifdef COMPAT_IA32 -struct reg32; -struct fpreg32; -struct dbreg32; -int proc_read_regs32(struct thread *_td, struct reg32 *_reg32); -int proc_write_regs32(struct thread *_td, struct reg32 *_reg32); -int proc_read_fpregs32(struct thread *_td, struct fpreg32 *_fpreg32); -int proc_write_fpregs32(struct thread *_td, struct fpreg32 *_fpreg32); -int proc_read_dbregs32(struct thread *_td, struct dbreg32 *_dbreg32); -int proc_write_dbregs32(struct thread *_td, struct dbreg32 *_dbreg32); -#endif + +int ptrace_read_regf(struct thread *, void *, ptregset_readf); +int ptrace_rwmem(struct proc *, struct uio *); +int ptrace_sstep(struct thread *); +int ptrace_write_regf(struct thread *, const void *, ptregset_writef); + #else /* !_KERNEL */ #include Index: sys/sys/syscallsubr.h =========================================================================== --- sys/sys/syscallsubr.h 2008/03/13 03:14:06 #46 +++ sys/sys/syscallsubr.h 2008/03/13 03:14:06 @@ -124,8 +124,8 @@ int kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name); int kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset); -int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, - int data); +int kern_ptrace(struct thread *td, int req, pid_t pid, lwpid_t tid, + void *addr, int data); int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset); int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, enum uio_seg bufseg, int count); Index: sys/sys/sysent.h =========================================================================== --- sys/sys/sysent.h 2008/03/13 03:14:06 #24 +++ sys/sys/sysent.h 2008/03/13 03:14:06 @@ -63,6 +63,7 @@ }; struct image_params; +struct ptregset; struct __sigset; struct trapframe; struct vnode; @@ -100,6 +101,13 @@ void (*sv_setregs)(struct thread *, u_long, u_long, u_long); void (*sv_fixlimit)(struct rlimit *, int); u_long *sv_maxssiz; + + /* ptrace(2) unification */ + struct ptregset *sv_reg; + struct ptregset *sv_fpreg; + struct ptregset *sv_dbreg; + int sv_nxregs; /* Number of extra register sets */ + struct ptregset *sv_xregs; /* Sizes for each extra register set */ }; #ifdef _KERNEL