Adds a new ptrace call PT_MEMMAP that returns all the processes memory mappings, if all the mappings wont fit, ENOMEM will be returned. The ptrace(2) data argument is the size of the addr argument. 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/06/04 01:08:17 @@ -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,25 @@ #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 #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/19 19:41:18 @@ -71,6 +71,7 @@ #include #include +#include #include @@ -174,6 +175,7 @@ case PT_IO: case PT_KILL: case PT_DETACH: + case PT_MEMMAP: #ifdef PT_STEP case PT_STEP: #endif @@ -436,6 +438,76 @@ return (process_dofpregs(p, t, &uio)); } #endif + + case PT_MEMMAP: + { + struct vm_map *map = &p->p_vmspace->vm_map; + struct vm_map_entry *entry; + + iov.iov_base = SCARG(uap, addr); + iov.iov_len = SCARG(uap, data); + 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; + + if (map != &curproc->p_vmspace->vm_map) + vm_map_lock_read(map); + + for (entry = map->header.next; + entry != &map->header; + entry = entry->next) { + struct ptrace_mem_map_desc desc; + + if (sizeof(desc) > uio.uio_resid) { + error = ENOMEM; + break; + } + + 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; + + error = uiomove(&desc, sizeof(desc), &uio); + if (error) + break; + } + if (map != &curproc->p_vmspace->vm_map) + vm_map_unlock_read(map); + + return (error); + } #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES