svn commit: r284919 - in head/sys: amd64/amd64 i386/i386 x86/include
Konstantin Belousov
kib at FreeBSD.org
Mon Jun 29 07:07:25 UTC 2015
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 {
More information about the svn-src-head
mailing list