Date: Mon, 29 Jun 2015 07:07:24 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r284919 - in head/sys: amd64/amd64 i386/i386 x86/include Message-ID: <201506290707.t5T77O3p039691@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Mon Jun 29 07:07:24 2015 New Revision: 284919 URL: https://svnweb.freebsd.org/changeset/base/284919 Log: Add x86 PT_GETFSBASE, PT_GETGSBASE machine-depended ptrace requests to obtain the thread %fs and %gs bases. Add x86 PT_SETFSBASE and PT_SETGSBASE requests to set the bases from debuggers. The set requests, similarly to the sysarch({I386,AMD64}_SET_FSBASE), override the corresponding segment registers. The main purpose of the operations is to retrieve and modify the tcb address for debuggee. Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Modified: head/sys/amd64/amd64/ptrace_machdep.c head/sys/i386/i386/ptrace_machdep.c head/sys/x86/include/ptrace.h Modified: head/sys/amd64/amd64/ptrace_machdep.c ============================================================================== --- head/sys/amd64/amd64/ptrace_machdep.c Mon Jun 29 06:59:08 2015 (r284918) +++ head/sys/amd64/amd64/ptrace_machdep.c Mon Jun 29 07:07:24 2015 (r284919) @@ -36,8 +36,12 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/ptrace.h> #include <sys/sysent.h> +#include <vm/vm.h> +#include <vm/pmap.h> #include <machine/md_var.h> #include <machine/pcb.h> +#include <machine/frame.h> +#include <machine/vmparam.h> static int cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data) @@ -110,6 +114,20 @@ cpu_ptrace_xstate(struct thread *td, int return (error); } +static void +cpu_ptrace_setbase(struct thread *td, int req, register_t r) +{ + + if (req == PT_SETFSBASE) { + td->td_pcb->pcb_fsbase = r; + td->td_frame->tf_fs = _ufssel; + } else { + td->td_pcb->pcb_gsbase = r; + td->td_frame->tf_gs = _ugssel; + } + set_pcb_flags(td->td_pcb, PCB_FULL_IRET); +} + #ifdef COMPAT_FREEBSD32 #define PT_I386_GETXMMREGS (PT_FIRSTMACH + 0) #define PT_I386_SETXMMREGS (PT_FIRSTMACH + 1) @@ -118,6 +136,7 @@ static int cpu32_ptrace(struct thread *td, int req, void *addr, int data) { struct savefpu *fpstate; + uint32_t r; int error; switch (req) { @@ -142,6 +161,29 @@ cpu32_ptrace(struct thread *td, int req, error = cpu_ptrace_xstate(td, req, addr, data); break; + case PT_GETFSBASE: + case PT_GETGSBASE: + if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) { + error = EINVAL; + break; + } + r = req == PT_GETFSBASE ? td->td_pcb->pcb_fsbase : + td->td_pcb->pcb_gsbase; + error = copyout(&r, addr, sizeof(r)); + break; + + case PT_SETFSBASE: + case PT_SETGSBASE: + if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) { + error = EINVAL; + break; + } + error = copyin(addr, &r, sizeof(r)); + if (error != 0) + break; + cpu_ptrace_setbase(td, req, r); + break; + default: error = EINVAL; break; @@ -154,6 +196,7 @@ cpu32_ptrace(struct thread *td, int req, int cpu_ptrace(struct thread *td, int req, void *addr, int data) { + register_t *r, rv; int error; #ifdef COMPAT_FREEBSD32 @@ -176,6 +219,25 @@ cpu_ptrace(struct thread *td, int req, v error = cpu_ptrace_xstate(td, req, addr, data); break; + case PT_GETFSBASE: + case PT_GETGSBASE: + r = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsbase : + &td->td_pcb->pcb_gsbase; + error = copyout(r, addr, sizeof(*r)); + break; + + case PT_SETFSBASE: + case PT_SETGSBASE: + error = copyin(addr, &rv, sizeof(rv)); + if (error != 0) + break; + if (rv >= VM_MAXUSER_ADDRESS) { + error = EINVAL; + break; + } + cpu_ptrace_setbase(td, req, rv); + break; + default: error = EINVAL; break; Modified: head/sys/i386/i386/ptrace_machdep.c ============================================================================== --- head/sys/i386/i386/ptrace_machdep.c Mon Jun 29 06:59:08 2015 (r284918) +++ head/sys/i386/i386/ptrace_machdep.c Mon Jun 29 07:07:24 2015 (r284919) @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/proc.h> #include <sys/ptrace.h> +#include <machine/frame.h> #include <machine/md_var.h> #include <machine/pcb.h> @@ -115,8 +116,8 @@ cpu_ptrace_xstate(struct thread *td, int } #endif -int -cpu_ptrace(struct thread *td, int req, void *addr, int data) +static int +cpu_ptrace_xmm(struct thread *td, int req, void *addr, int data) { #ifdef CPU_ENABLE_SSE struct savexmm *fpstate; @@ -155,3 +156,51 @@ cpu_ptrace(struct thread *td, int req, v return (EINVAL); #endif } + +int +cpu_ptrace(struct thread *td, int req, void *addr, int data) +{ + struct segment_descriptor *sdp, sd; + register_t r; + int error; + + switch (req) { + case PT_GETXMMREGS: + case PT_SETXMMREGS: + case PT_GETXSTATE_OLD: + case PT_SETXSTATE_OLD: + case PT_GETXSTATE_INFO: + case PT_GETXSTATE: + case PT_SETXSTATE: + error = cpu_ptrace_xmm(td, req, addr, data); + break; + + case PT_GETFSBASE: + case PT_GETGSBASE: + sdp = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsd : + &td->td_pcb->pcb_gsd; + r = sdp->sd_hibase << 24 | sdp->sd_lobase; + error = copyout(&r, addr, sizeof(r)); + break; + + case PT_SETFSBASE: + case PT_SETGSBASE: + error = copyin(addr, &r, sizeof(r)); + if (error != 0) + break; + fill_based_sd(&sd, r); + if (req == PT_SETFSBASE) { + td->td_pcb->pcb_fsd = sd; + td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL); + } else { + td->td_pcb->pcb_gsd = sd; + td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); + } + break; + + default: + return (EINVAL); + } + + return (error); +} Modified: head/sys/x86/include/ptrace.h ============================================================================== --- head/sys/x86/include/ptrace.h Mon Jun 29 06:59:08 2015 (r284918) +++ head/sys/x86/include/ptrace.h Mon Jun 29 07:07:24 2015 (r284919) @@ -51,6 +51,10 @@ #define PT_GETXSTATE_INFO (PT_FIRSTMACH + 4) #define PT_GETXSTATE (PT_FIRSTMACH + 5) #define PT_SETXSTATE (PT_FIRSTMACH + 6) +#define PT_GETFSBASE (PT_FIRSTMACH + 7) +#define PT_SETFSBASE (PT_FIRSTMACH + 8) +#define PT_GETGSBASE (PT_FIRSTMACH + 9) +#define PT_SETGSBASE (PT_FIRSTMACH + 10) /* Argument structure for PT_GETXSTATE_INFO. */ struct ptrace_xstate_info {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506290707.t5T77O3p039691>