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