Author: marcel
Date: Sun Mar  7 00:05:44 2010
New Revision: 204813
URL: http://svn.freebsd.org/changeset/base/204813

Log:
  MFC revs 203696, 203708, 203783 and 203788:
  Add PT_VM_TIMESTAMP and PT_VM_ENTRY so that the tracing process can
  obtain the memory map of the traced process.
  
  Requested by: kib@

Modified:
  stable/8/sys/kern/sys_process.c
  stable/8/sys/sys/ptrace.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/netinet/   (props changed)

Modified: stable/8/sys/kern/sys_process.c
==============================================================================
--- stable/8/sys/kern/sys_process.c     Sat Mar  6 23:01:10 2010        
(r204812)
+++ stable/8/sys/kern/sys_process.c     Sun Mar  7 00:05:44 2010        
(r204813)
@@ -72,6 +72,20 @@ struct ptrace_io_desc32 {
        u_int32_t       piod_addr;
        u_int32_t       piod_len;
 };
+
+struct ptrace_vm_entry32 {
+       int             pve_entry;
+       int             pve_timestamp;
+       uint32_t        pve_start;
+       uint32_t        pve_end;
+       uint32_t        pve_offset;
+       u_int           pve_prot;
+       u_int           pve_pathlen;
+       int32_t         pve_fileid;
+       u_int           pve_fsid;
+       uint32_t        pve_path;
+};
+
 #endif
 
 /*
@@ -339,6 +353,148 @@ proc_rwmem(struct proc *p, struct uio *u
        return (error);
 }
 
+static int
+ptrace_vm_entry(struct thread *td, struct proc *p, struct ptrace_vm_entry *pve)
+{
+       struct vattr vattr;
+       vm_map_t map;
+       vm_map_entry_t entry;
+       vm_object_t obj, tobj, lobj;
+       struct vmspace *vm;
+       struct vnode *vp;
+       char *freepath, *fullpath;
+       u_int pathlen;
+       int error, index, vfslocked;
+
+       error = 0;
+       obj = NULL;
+
+       vm = vmspace_acquire_ref(p);
+       map = &vm->vm_map;
+       vm_map_lock_read(map);
+
+       do {
+               entry = map->header.next;
+               index = 0;
+               while (index < pve->pve_entry && entry != &map->header) {
+                       entry = entry->next;
+                       index++;
+               }
+               if (index != pve->pve_entry) {
+                       error = EINVAL;
+                       break;
+               }
+               while (entry != &map->header &&
+                   (entry->eflags & MAP_ENTRY_IS_SUB_MAP) != 0) {
+                       entry = entry->next;
+                       index++;
+               }
+               if (entry == &map->header) {
+                       error = ENOENT;
+                       break;
+               }
+
+               /* We got an entry. */
+               pve->pve_entry = index + 1;
+               pve->pve_timestamp = map->timestamp;
+               pve->pve_start = entry->start;
+               pve->pve_end = entry->end - 1;
+               pve->pve_offset = entry->offset;
+               pve->pve_prot = entry->protection;
+
+               /* Backing object's path needed? */
+               if (pve->pve_pathlen == 0)
+                       break;
+
+               pathlen = pve->pve_pathlen;
+               pve->pve_pathlen = 0;
+
+               obj = entry->object.vm_object;
+               if (obj != NULL)
+                       VM_OBJECT_LOCK(obj);
+       } while (0);
+
+       vm_map_unlock_read(map);
+       vmspace_free(vm);
+
+       pve->pve_fsid = VNOVAL;
+       pve->pve_fileid = VNOVAL;
+
+       if (error == 0 && obj != NULL) {
+               lobj = obj;
+               for (tobj = obj; tobj != NULL; tobj = tobj->backing_object) {
+                       if (tobj != obj)
+                               VM_OBJECT_LOCK(tobj);
+                       if (lobj != obj)
+                               VM_OBJECT_UNLOCK(lobj);
+                       lobj = tobj;
+                       pve->pve_offset += tobj->backing_object_offset;
+               }
+               vp = (lobj->type == OBJT_VNODE) ? lobj->handle : NULL;
+               if (vp != NULL)
+                       vref(vp);
+               if (lobj != obj)
+                       VM_OBJECT_UNLOCK(lobj);
+               VM_OBJECT_UNLOCK(obj);
+
+               if (vp != NULL) {
+                       freepath = NULL;
+                       fullpath = NULL;
+                       vn_fullpath(td, vp, &fullpath, &freepath);
+                       vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+                       vn_lock(vp, LK_SHARED | LK_RETRY);
+                       if (VOP_GETATTR(vp, &vattr, td->td_ucred) == 0) {
+                               pve->pve_fileid = vattr.va_fileid;
+                               pve->pve_fsid = vattr.va_fsid;
+                       }
+                       vput(vp);
+                       VFS_UNLOCK_GIANT(vfslocked);
+
+                       if (fullpath != NULL) {
+                               pve->pve_pathlen = strlen(fullpath) + 1;
+                               if (pve->pve_pathlen <= pathlen) {
+                                       error = copyout(fullpath, pve->pve_path,
+                                           pve->pve_pathlen);
+                               } else
+                                       error = ENAMETOOLONG;
+                       }
+                       if (freepath != NULL)
+                               free(freepath, M_TEMP);
+               }
+       }
+
+       return (error);
+}
+
+#ifdef COMPAT_IA32
+static int      
+ptrace_vm_entry32(struct thread *td, struct proc *p,
+    struct ptrace_vm_entry32 *pve32)
+{
+       struct ptrace_vm_entry pve;
+       int error;
+
+       pve.pve_entry = pve32->pve_entry;
+       pve.pve_pathlen = pve32->pve_pathlen;
+       pve.pve_path = (void *)(uintptr_t)pve32->pve_path;
+
+       error = ptrace_vm_entry(td, p, &pve);
+       if (error == 0) {
+               pve32->pve_entry = pve.pve_entry;
+               pve32->pve_timestamp = pve.pve_timestamp;
+               pve32->pve_start = pve.pve_start;
+               pve32->pve_end = pve.pve_end;
+               pve32->pve_offset = pve.pve_offset;
+               pve32->pve_prot = pve.pve_prot;
+               pve32->pve_fileid = pve.pve_fileid;
+               pve32->pve_fsid = pve.pve_fsid;
+       }
+
+       pve32->pve_pathlen = pve.pve_pathlen;
+       return (error);
+}
+#endif /* COMPAT_IA32 */
+
 /*
  * Process debugging system call.
  */
@@ -382,6 +538,7 @@ ptrace(struct thread *td, struct ptrace_
        union {
                struct ptrace_io_desc piod;
                struct ptrace_lwpinfo pl;
+               struct ptrace_vm_entry pve;
                struct dbreg dbreg;
                struct fpreg fpreg;
                struct reg reg;
@@ -390,6 +547,7 @@ ptrace(struct thread *td, struct ptrace_
                struct fpreg32 fpreg32;
                struct reg32 reg32;
                struct ptrace_io_desc32 piod32;
+               struct ptrace_vm_entry32 pve32;
 #endif
        } r;
        void *addr;
@@ -422,6 +580,9 @@ ptrace(struct thread *td, struct ptrace_
        case PT_IO:
                error = COPYIN(uap->addr, &r.piod, sizeof r.piod);
                break;
+       case PT_VM_ENTRY:
+               error = COPYIN(uap->addr, &r.pve, sizeof r.pve);
+               break;
        default:
                addr = uap->addr;
                break;
@@ -434,6 +595,9 @@ ptrace(struct thread *td, struct ptrace_
                return (error);
 
        switch (uap->req) {
+       case PT_VM_ENTRY:
+               error = COPYOUT(&r.pve, uap->addr, sizeof r.pve);
+               break;
        case PT_IO:
                error = COPYOUT(&r.piod, uap->addr, sizeof r.piod);
                break;
@@ -970,6 +1134,21 @@ kern_ptrace(struct thread *td, int req, 
                PROC_LOCK(p);
                break;
 
+       case PT_VM_TIMESTAMP:
+               td->td_retval[0] = p->p_vmspace->vm_map.timestamp;
+               break;
+
+       case PT_VM_ENTRY:
+               PROC_UNLOCK(p);
+#ifdef COMPAT_IA32
+               if (wrap32)
+                       error = ptrace_vm_entry32(td, p, addr);
+               else
+#endif
+               error = ptrace_vm_entry(td, p, addr);
+               PROC_LOCK(p);
+               break;
+
        default:
 #ifdef __HAVE_PTRACE_MACHDEP
                if (req >= PT_FIRSTMACH) {

Modified: stable/8/sys/sys/ptrace.h
==============================================================================
--- stable/8/sys/sys/ptrace.h   Sat Mar  6 23:01:10 2010        (r204812)
+++ stable/8/sys/sys/ptrace.h   Sun Mar  7 00:05:44 2010        (r204813)
@@ -67,6 +67,10 @@
 #define PT_SETFPREGS    36     /* set floating-point registers */
 #define PT_GETDBREGS    37     /* get debugging registers */
 #define PT_SETDBREGS    38     /* set debugging registers */
+
+#define        PT_VM_TIMESTAMP 40      /* Get VM version (timestamp) */
+#define        PT_VM_ENTRY     41      /* Get VM map (entry) */
+
 #define PT_FIRSTMACH    64     /* for machine-specific requests */
 #include <machine/ptrace.h>    /* machine-specific requests, if any */
 
@@ -98,6 +102,20 @@ struct ptrace_lwpinfo {
        sigset_t        pl_siglist;     /* LWP pending signal */
 };
 
+/* Argument structure for PT_VM_ENTRY. */
+struct ptrace_vm_entry {
+       int             pve_entry;      /* Entry number used for iteration. */
+       int             pve_timestamp;  /* Generation number of VM map. */
+       u_long          pve_start;      /* Start VA of range. */
+       u_long          pve_end;        /* End VA of range (incl). */
+       u_long          pve_offset;     /* Offset in backing object. */
+       u_int           pve_prot;       /* Protection of memory range. */
+       u_int           pve_pathlen;    /* Size of path. */
+       long            pve_fileid;     /* File ID. */
+       uint32_t        pve_fsid;       /* File system ID. */
+       char            *pve_path;      /* Path name of object. */
+};
+
 #ifdef _KERNEL
 
 #define        PTRACESTOP_SC(p, td, flag)                              \
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to