Subject: Re: PT_MEMMAP
To: Gregory McGarry <g.mcgarry@ieee.org>
From: Love <lha@stacken.kth.se>
List: tech-kern
Date: 07/22/2002 11:35:27
Gregory McGarry <g.mcgarry@ieee.org> writes:

> Love wrote:
>  
> > I want to add PT_MEMMAP to ptrace so gdb can get the memory mapping of a
> > process. A implemation are available in [1]. Patches for current gdb are in
> > [2].
[...]
> 
> Do you want the memory map of the traced process or the parent process?

Of course I want the traced process, thanks. That explains why it couldn't
dump all memory regions. :)

I added an updated patch, I changed so you can't dump your own memory
mapping, but then you can't attach to yourself so that shouldn't be a
problem.

Love

Index: sys_process.c
===================================================================
RCS file: /sources/netbsd/NetBSD-cvs/syssrc/sys/kern/sys_process.c,v
retrieving revision 1.74
diff -u -u -w -r1.74 sys_process.c
--- sys_process.c	2002/05/09 15:44:45	1.74
+++ sys_process.c	2002/07/21 23:30:26
@@ -71,6 +71,7 @@
 #include <sys/syscallargs.h>
 
 #include <uvm/uvm_extern.h>
+#include <uvm/uvm.h>
 
 #include <machine/reg.h>
 
@@ -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,77 @@
 			return (process_dofpregs(p, t, &uio));
 		}
 #endif
+
+ 	case  PT_MEMMAP:
+	        {
+			struct vm_map *map = &t->p_vmspace->vm_map;
+			struct vm_map_entry *entry;
+
+			if (map == &curproc->p_vmspace->vm_map)
+				return EDEADLK;
+
+			vm_map_lock_read(map);			
+
+			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;
+			
+			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;
+			}
+			vm_map_unlock_read(map);
+
+			return (error);
+		}
 
 #ifdef __HAVE_PTRACE_MACHDEP
 	PTRACE_MACHDEP_REQUEST_CASES