Index: sys/ptrace.h =================================================================== RCS file: /sources/netbsd/NetBSD-cvs/syssrc/sys/sys/ptrace.h,v retrieving revision 1.25 diff -u -r1.25 ptrace.h --- sys/ptrace.h 2002/05/09 15:44:46 1.25 +++ sys/ptrace.h 2002/07/25 00:39:46 @@ -48,6 +48,7 @@ #define PT_ATTACH 9 /* attach to running process */ #define PT_DETACH 10 /* detach from running process */ #define PT_IO 11 /* do I/O to/from the stopped process */ +#define PT_MEMMAP 12 /* memory map of child */ #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include /* machine-specific requests, if any */ @@ -67,6 +68,26 @@ #define PIOD_WRITE_D 2 /* write to D spcae */ #define PIOD_READ_I 3 /* read from I space */ #define PIOD_WRITE_I 4 /* write to I space */ + +struct ptrace_mem_map_desc { + void *pmmd_start; + void *pmmd_end; + int pmmd_flags; /* see below */ + int pmmd_wiredcount; + int pmmd_inheritance; + int pmmd_advice; +}; + +#define PMMD_LAST_ENTRY 0x001 +#define PMMD_PROT_READ 0x002 +#define PMMD_PROT_WRITE 0x004 +#define PMMD_PROT_EXEC 0x008 +#define PMMD_PROT_MAX_READ 0x010 +#define PMMD_PROT_MAX_WRITE 0x020 +#define PMMD_PROT_MAX_EXEC 0x040 +#define PMMD_COW 0x080 +#define PMMD_NEEDCOPY 0x100 +#define PMMD_OBJECT 0x200 #ifdef _KERNEL Index: kern/sys_process.c =================================================================== RCS file: /sources/netbsd/NetBSD-cvs/syssrc/sys/kern/sys_process.c,v retrieving revision 1.74 diff -u -r1.74 sys_process.c --- kern/sys_process.c 2002/05/09 15:44:45 1.74 +++ kern/sys_process.c 2002/07/25 04:36:22 @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -71,9 +72,13 @@ #include #include +#include #include +int proc_vnode_to_path(struct vnode *, char *, int, + struct proc *, struct proc *); + /* Macros to clear/set/test flags. */ #define SET(t, f) (t) |= (f) #define CLR(t, f) (t) &= ~(f) @@ -174,6 +179,7 @@ case PT_IO: case PT_KILL: case PT_DETACH: + case PT_MEMMAP: #ifdef PT_STEP case PT_STEP: #endif @@ -436,6 +442,115 @@ return (process_dofpregs(p, t, &uio)); } #endif + + case PT_MEMMAP: + { + struct vm_map *map = &t->p_vmspace->vm_map; + struct vm_map_entry *entry; + char *path; + int len; + + path = malloc(MAXPATHLEN * 4, M_TEMP, M_WAITOK); + if (path == NULL) + return ENOMEM; + *path = 0; + + if (map == &curproc->p_vmspace->vm_map) { + free(path, M_TEMP); + return EDEADLK; + } + + vm_map_lock_read(map); + + iov.iov_base = SCARG(uap, addr); + iov.iov_len = SCARG(uap, data); + uio.uio_iovcnt = 1; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = SCARG(uap, data); + uio.uio_segflg = UIO_USERSPACE; + uio.uio_rw = UIO_READ; + uio.uio_procp = p; + + for (entry = map->header.next; + entry != &map->header; + entry = entry->next) { + struct ptrace_mem_map_desc desc; + + memset(&desc, 0, sizeof(desc)); + + desc.pmmd_start = (void *)entry->start; + desc.pmmd_end = (void *)entry->end; + + if (entry->protection & VM_PROT_READ) + desc.pmmd_flags |= PMMD_PROT_READ; + if (entry->protection & VM_PROT_WRITE) + desc.pmmd_flags |= PMMD_PROT_WRITE; + if (entry->protection & VM_PROT_EXECUTE) + desc.pmmd_flags |= PMMD_PROT_EXEC; + + if (entry->max_protection & VM_PROT_READ) + desc.pmmd_flags |= PMMD_PROT_MAX_READ; + if (entry->max_protection & VM_PROT_WRITE) + desc.pmmd_flags |= PMMD_PROT_MAX_WRITE; + if (entry->max_protection & VM_PROT_EXECUTE) + desc.pmmd_flags |= PMMD_PROT_MAX_EXEC; + + if (entry->etype & UVM_ET_COPYONWRITE) + desc.pmmd_flags |= PMMD_COW; + if (entry->etype & UVM_ET_NEEDSCOPY) + desc.pmmd_flags |= PMMD_NEEDCOPY; + + desc.pmmd_wiredcount = entry->wired_count; + desc.pmmd_inheritance = entry->inheritance; + desc.pmmd_advice = entry->advice; + + + /* is this the last entry */ + if (entry->next == &map->header) + desc.pmmd_flags |= PMMD_LAST_ENTRY; + + if (UVM_ET_ISOBJ(entry) && + UVM_OBJ_IS_VNODE(entry->object.uvm_obj)) { + struct vnode *vp; + + vp = (struct vnode *) + entry->object.uvm_obj; + + desc.pmmd_flags |= PMMD_OBJECT; + error = proc_vnode_to_path(vp, path, + MAXPATHLEN * 4, curproc, t); + if (error == 0) { + len = strlen(path); + memset(path + len, 0, + MIN(MAXPATHLEN * 4 - len, + ALIGNBYTES + 1)); + len = ALIGN(len + 1); + } else { + len = ALIGN(1); + memset(path, 0, len); + } + } else + len = 0; + + if (sizeof(desc) + len > uio.uio_resid) { + error = ENOMEM; + break; + } + + error = uiomove(&desc, sizeof(desc), &uio); + if (error) + break; + error = uiomove(path, len, &uio); + if (error) + break; + } + vm_map_unlock_read(map); + free(path, M_TEMP); + + return (error); + } #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES Index: kern/vfs_getcwd.c =================================================================== RCS file: /sources/netbsd/NetBSD-cvs/syssrc/sys/kern/vfs_getcwd.c,v retrieving revision 1.15 diff -u -r1.15 vfs_getcwd.c --- kern/vfs_getcwd.c 2001/11/12 15:25:37 1.15 +++ kern/vfs_getcwd.c 2002/07/25 01:04:33 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_getcwd.c,v 1.14 2000/12/15 11:52:14 fvdl Exp $ */ +/* $NetBSD: vfs_getcwd.c,v 1.15 2001/11/12 15:25:37 lukem Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD$"); +__KERNEL_RCSID(0, "$NetBSD: vfs_getcwd.c,v 1.15 2001/11/12 15:25:37 lukem Exp $"); #include #include @@ -545,6 +545,63 @@ return 1; else return vn_isunder(r1, r2, p2); +} + +/* + * Try to find a pathname for a vnode. Since there is no mapping + * vnode -> parent directory, this needs the NAMECACHE_ENTER_REVERSE + * option to work (to make cache_revlookup succeed). + */ + +int +proc_vnode_to_path(struct vnode *, char *, int, struct proc *curp, struct proc *p); + +int +proc_vnode_to_path(vp, path, len, curp, p) + struct vnode *vp; + char *path; + int len; + struct proc *curp, *p; +{ + int error, lenused, elen; + char *bp, *bend; + struct vnode *dvp; + + bp = bend = &path[len]; + *(--bp) = '\0'; + + error = vget(vp, LK_EXCLUSIVE | LK_RETRY); + if (error != 0) + return error; + error = cache_revlookup(vp, &dvp, &bp, path); + vput(vp); + if (error != 0) + return (error == -1 ? ENOENT : error); + + error = vget(dvp, 0); + if (error != 0) + return error; + *(--bp) = '/'; + error = getcwd_common(dvp, NULL, &bp, path, len / 2, + GETCWD_CHECK_ACCESS, curp); + + /* + * Strip off emulation path for emulated processes looking at + * the maps file of a process of the same emulation. (Won't + * work if /emul/xxx is a symlink..) + */ + if (curp->p_emul == p->p_emul && curp->p_emul->e_path != NULL) { + elen = strlen(curp->p_emul->e_path); + if (!strncmp(bp, curp->p_emul->e_path, elen)) + bp = &bp[elen]; + } + + lenused = bend - bp; + + memcpy(path, bp, lenused); + path[lenused] = 0; + + return 0; } /*