Index: sys/machine/pc32/include/vmparam.h
===================================================================
RCS file: /home/dcvs/src/sys/machine/pc32/include/vmparam.h,v
retrieving revision 1.9
diff -u -r1.9 vmparam.h
--- sys/machine/pc32/include/vmparam.h	28 Dec 2006 18:29:06 -0000	1.9
+++ sys/machine/pc32/include/vmparam.h	11 Jan 2007 17:37:58 -0000
@@ -50,6 +50,9 @@
 
 #define VM_PROT_READ_IS_EXEC	/* if you can read -- then you can exec */
 
+/* I386 has a line where all code is executable: 0 - I386_MAX_EXE_ADDR */
+#define I386_MAX_EXE_ADDR 0x20000000	/* exec line */
+
 /*
  * Virtual memory related constants, all in bytes
  */
Index: sys/sys/mman.h
===================================================================
RCS file: /home/dcvs/src/sys/sys/mman.h,v
retrieving revision 1.8
diff -u -r1.8 mman.h
--- sys/sys/mman.h	27 Dec 2006 20:43:09 -0000	1.8
+++ sys/sys/mman.h	11 Jan 2007 17:37:58 -0000
@@ -76,6 +76,7 @@
 #define	MAP_HASSEMAPHORE 0x0200	/* region may contain semaphores */
 #define	MAP_STACK	 0x0400	/* region grows down, like a stack */
 #define	MAP_NOSYNC	 0x0800 /* page to but do not sync underlying file */
+#define	MAP_TRYFIXED	 0x1000	/* attempt hint address, even within heap */
 
 #ifdef _P1003_1B_VISIBLE
 /*
Index: sys/vm/vm_map.c
===================================================================
RCS file: /home/dcvs/src/sys/vm/vm_map.c,v
retrieving revision 1.55
diff -u -r1.55 vm_map.c
--- sys/vm/vm_map.c	7 Jan 2007 08:37:37 -0000	1.55
+++ sys/vm/vm_map.c	13 Jan 2007 12:59:26 -0000
@@ -94,6 +94,8 @@
 
 #include <sys/thread2.h>
 
+#include <sys/random.h>
+
 /*
  *	Virtual memory maps provide for the mapping, protection,
  *	and sharing of virtual memory objects.  In addition,
@@ -3419,6 +3421,32 @@
 }
 
 /*
+ * vm_map_hint: return the beginning of the best area suitable for
+ * creating a new mapping with "prot" protection.
+ */
+vm_offset_t
+vm_map_hint(struct proc *p, vm_prot_t prot)
+{
+    vm_offset_t addr;
+
+#ifdef __i386__
+    /*
+      * If executable skip first two pages, otherwise start
+      * after data + heap region.
+      */
+    if ((prot & VM_PROT_EXECUTE) &&
+         ((vm_offset_t)p->p_vmspace->vm_daddr >= I386_MAX_EXE_ADDR)) {
+	addr = (PAGE_SIZE*2) +
+            (karc4random() & (I386_MAX_EXE_ADDR / 2 - 1));
+        return (round_page(addr));
+    }
+#endif
+    addr = (vm_offset_t)p->p_vmspace->vm_daddr + MAXDSIZ;
+    addr += karc4random() & (MIN((256 * 1024 * 1024), MAXDSIZ) - 1);
+
+    return (round_page(addr));
+}
+/*
  *	vm_map_lookup_done:
  *
  *	Releases locks acquired by a vm_map_lookup
Index: sys/vm/vm_map.h
===================================================================
RCS file: /home/dcvs/src/sys/vm/vm_map.h,v
retrieving revision 1.29
diff -u -r1.29 vm_map.h
--- sys/vm/vm_map.h	11 Jan 2007 10:15:21 -0000	1.29
+++ sys/vm/vm_map.h	11 Jan 2007 17:37:58 -0000
@@ -438,6 +438,7 @@
 		 vm_prot_t, vm_prot_t, 
 		 int);
 int vm_map_findspace (vm_map_t, vm_offset_t, vm_size_t, vm_offset_t, vm_offset_t *);
+vm_offset_t vm_map_hint(struct proc *, vm_prot_t);
 int vm_map_inherit (vm_map_t, vm_offset_t, vm_offset_t, vm_inherit_t);
 void vm_map_init (struct vm_map *, vm_offset_t, vm_offset_t, pmap_t);
 int vm_map_insert (vm_map_t, int *, vm_object_t, vm_ooffset_t,
Index: sys/vm/vm_mmap.c
===================================================================
RCS file: /home/dcvs/src/sys/vm/vm_mmap.c,v
retrieving revision 1.37
diff -u -r1.37 vm_mmap.c
--- sys/vm/vm_mmap.c	28 Dec 2006 18:29:08 -0000	1.37
+++ sys/vm/vm_mmap.c	13 Jan 2007 10:17:31 -0000
@@ -238,10 +238,17 @@
 	 * There should really be a pmap call to determine a reasonable
 	 * location.
 	 */
-	else if (addr == 0 ||
-	    (addr >= round_page((vm_offset_t)vms->vm_taddr) &&
-	     addr < round_page((vm_offset_t)vms->vm_daddr + maxdsiz)))
-		addr = round_page((vm_offset_t)vms->vm_daddr + maxdsiz);
+	else {
+	    /*
+	     * not fixed: make sure we skip over the largest possible heap.
+	     * we will refine our guess later (e.g. to account for VAC, etc)
+	     */
+	    if (addr == 0)
+		addr = vm_map_hint(p, prot);
+	    else if (!(flags & MAP_TRYFIXED) &&
+		      addr < (vm_offset_t)p->p_vmspace->vm_daddr)
+		addr = vm_map_hint(p, prot);
+	}
 
 	if (flags & MAP_ANON) {
 		/*
