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 {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to