diff --git a/.gitattributes b/.gitattributes
index 44c20fbe564448f3c2ba5742c5a68db34f605c3d..e2cd211cdea7ccac509ac318fb01222fd5678c77 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -11,7 +11,10 @@ non_overlapping_heap/tests/Makefile -text
 non_overlapping_heap/tests/inputfile -text
 non_overlapping_heap/tests/test1.c -text
 non_overlapping_heap/tests/test2.c -text
+non_overlapping_libraries/Notes -text
+non_overlapping_libraries/eglibc-2.19-debian-ubuntu-base.tar.gz -text
 non_overlapping_libraries/ld-linux-x86-64.so.2 -text
+non_overlapping_libraries/nol_eglibc-2.19.patch -text
 non_overlapping_libraries/patchelf -text
 /postgres_setup.sh -text
 /set_command_envs -text
diff --git a/non_overlapping_libraries/Notes b/non_overlapping_libraries/Notes
new file mode 100644
index 0000000000000000000000000000000000000000..adacb4b3a38d8ee4c6e0fc4b0b30c06fdbf22d3b
--- /dev/null
+++ b/non_overlapping_libraries/Notes
@@ -0,0 +1,42 @@
+Hello there!
+
+This is the file set for the non-overlapping libraries implementation. The core
+concept behind this pass is to modify ld-linux.so for the target binary, so the
+load process for the libraries can take advantage of the full non-overlapping-x
+concept to prevent exploitable addressees from being common.
+
+Patching ld means that we end up having to do a build in the context of glibc6.
+This is somewhat of a drag - it's not a very fast thing to build, and plenty of
+odd things happen in the various contexts in which it works. In order to ensure
+that you can build and patch glibc later, I've included, along with the library
+binary, the source code for eglibc-2.19 and the patch that can be applied to it
+to make the binary. To build, untar and enter the eglibc-2.19 directory, and do
+the command "make -f debian/rules build -j 16" (replace 16 with something which
+makes sense for your system - I've run it with up to 64 without problems). This
+will generate the target binary in build-tree/amd64-libc/elf/.
+
+Next comes the issue of using it in the MVEE properly. Unfortunately for us, we
+cannot use the existing alias infrastructure to override ld.so for a binary. It
+is suspected that this is due to the actual loading of the ld binary being done
+by the kernel, and thereby avoiding the alias machinery. In any case, we cannot
+simply replace the library blob. Instead, we need to use patchelf, which should
+handle changing the interpreter section of your target binary's ELF headers. In
+doing this, we can target each variant at a different ld.so. Unfortunately, the
+different ld.sos have to all be extremely similar (you can't mix no-nol and nol
+ld.sos), since they still need to have the same syscall usage patterns. For the
+diversity to happen in the memory mapping, nol uses a set of config files. This
+file, defined to be at "/variant_specific/nolnoh_config" (but aliased by config
+generation to be in each variant's directory). Each config contains at most two
+integers - [numvariants [variantindex]]. If neither is provided, nol assumes 64
+variants - this is a sort of fallback mode, in case the config file doesn't get
+generated. The base config file for each variant contains just the total number
+of variants. In this case, nol randomly chooses a variant index for each __mmap
+call overridden in ld, but limits it to that number of variants total, allowing
+for probabalistic and structured variants to be run together. When both numbers
+are specified in the config file, ld uses that exact variant index in every one
+of the allocations, allowing for the provable guarantees to be established.
+
+The use of a config file is a bit at odds with the design of other mvee bits. I
+only did so because, unfortunately, getting the environment variables for info,
+while normally good, is not possible in the very early stages of the loader. In
+this case, we have almost nothing initialized, mapped, or loaded yet.
diff --git a/non_overlapping_libraries/eglibc-2.19-debian-ubuntu-base.tar.gz.REMOVED.git-id b/non_overlapping_libraries/eglibc-2.19-debian-ubuntu-base.tar.gz.REMOVED.git-id
new file mode 100644
index 0000000000000000000000000000000000000000..c56cf09cf396a5afb2155a997dac5fcfe2aa548e
--- /dev/null
+++ b/non_overlapping_libraries/eglibc-2.19-debian-ubuntu-base.tar.gz.REMOVED.git-id
@@ -0,0 +1 @@
+c898a6aa334917b293886f591b170b37e6630560
\ No newline at end of file
diff --git a/non_overlapping_libraries/nol_eglibc-2.19.patch b/non_overlapping_libraries/nol_eglibc-2.19.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d5d0fa869003d2f455efaa609bc94c81d69c6f18
--- /dev/null
+++ b/non_overlapping_libraries/nol_eglibc-2.19.patch
@@ -0,0 +1,260 @@
+diff -Naur original_glibc/eglibc-2.19/elf/dl-cfar-nol.h eglibc-2.19/elf/dl-cfar-nol.h
+--- original_glibc/eglibc-2.19/elf/dl-cfar-nol.h	1969-12-31 19:00:00.000000000 -0500
++++ eglibc-2.19/elf/dl-cfar-nol.h	2016-03-30 11:32:53.671941958 -0400
+@@ -0,0 +1,5 @@
++#ifndef DL_CFAR_NOL_H
++#define DL_CFAR_NOL_H
++void * weak_function
++__cfar_nol_mmap(void* address, size_t length, int protect, int flags, int filedes, off_t offset);
++#endif
+diff -Naur original_glibc/eglibc-2.19/elf/dl-load.c eglibc-2.19/elf/dl-load.c
+--- original_glibc/eglibc-2.19/elf/dl-load.c	2016-03-29 17:32:07.000000000 -0400
++++ eglibc-2.19/elf/dl-load.c	2016-03-29 17:07:41.111316062 -0400
+@@ -38,6 +38,7 @@
+ #include <stap-probe.h>
+ 
+ #include <dl-dst.h>
++#include <dl-cfar-nol.h>
+ 
+ /* On some systems, no flag bits are given to specify file mapping.  */
+ #ifndef MAP_FILE
+@@ -1290,7 +1291,7 @@
+ 		   - MAP_BASE_ADDR (l));
+ 
+ 	/* Remember which part of the address space this object uses.  */
+-	l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
++	l->l_map_start = (ElfW(Addr)) __cfar_nol_mmap ((void *) mappref, maplength,
+ 					      c->prot,
+ 					      MAP_COPY|MAP_FILE,
+ 					      fd, c->mapoff);
+diff -Naur original_glibc/eglibc-2.19/elf/dl-minimal.c eglibc-2.19/elf/dl-minimal.c
+--- original_glibc/eglibc-2.19/elf/dl-minimal.c	2014-01-03 12:51:28.000000000 -0500
++++ eglibc-2.19/elf/dl-minimal.c	2016-03-30 12:18:25.867143040 -0400
+@@ -18,6 +18,7 @@
+ 
+ #include <errno.h>
+ #include <limits.h>
++#include <fcntl.h>
+ #include <string.h>
+ #include <tls.h>
+ #include <unistd.h>
+@@ -28,6 +29,7 @@
+ #include <_itoa.h>
+ 
+ #include <assert.h>
++#include <dl-cfar-nol.h>
+ 
+ /* Minimal `malloc' allocator for use while loading shared libraries.
+    No block is ever freed.  */
+@@ -45,6 +47,202 @@
+ 						char **endptr, int base);
+ 
+ 
++#define PROB_NUM_VARIANTS 64
++int nthisvar = 0;
++int nnumvar  = 1;
++int randfd   = 0;
++int pagesize = 0;
++int initialized = 0;
++
++// rounding up to alignments is important and useful
++size_t rounduptomultiple(size_t length, int roundto) {
++	size_t remainder = length % roundto;
++	if(remainder == 0) {
++		return length;
++	}
++	return length + roundto - remainder;
++}
++
++// we need page alignment for a few things - mmap works much better with it
++size_t rounduptopagemultiple(size_t length) {
++	if(pagesize == 0) {
++		pagesize = getpagesize();
++	}
++	return rounduptomultiple(length, pagesize);
++}
++
++bool can_open_config(void) {
++	int fd = __open("/variant_specific/nolnoh_config",O_RDONLY);
++	if(fd == -1)
++		return false;
++	__close(fd);
++	return true;
++}
++
++int atoi_micro(const char* str) {
++	int ret = 0;
++	while(*str >= '0' && *str <= '9') {
++		ret = ret * 10;
++		ret += *str - '0';
++		++str;
++	}
++	return ret;
++}
++
++int get_config_vars(void) {
++	int fd = __open("/variant_specific/nolnoh_config",O_RDONLY);
++	if(fd == -1)
++		return -1;
++	int bufsize = 17;
++	char buf[bufsize];
++	int i;
++	for(i=0;i<bufsize;i++) {
++		buf[i]='\0';
++	}
++	ssize_t nr = __read(fd, buf, bufsize-1);
++	if(nr == 0) {
++		// we read 0 of the tokens from the file, since we read absolutely nothing
++		__close(fd);
++		return 0;
++	}
++	nnumvar = atoi_micro(buf);
++	// note that this currently caps at 512 variants, increase this number if necessary to support more
++	if(nnumvar <= 0 || nnumvar > 512) {
++		// wasn't a valid value
++		nnumvar = 0;
++		__close(fd);
++		return 0;
++	}
++	int mode = 0;
++	// get the second number
++	for(i=0;i<bufsize;i++) {
++		if(buf[i] == '\0') {
++			__close(fd);
++			return 1;
++		}
++		if(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\r' || buf[i] == '\n') {
++			mode = 1;
++		}
++		if(mode == 1 && buf[i] >= '0' && buf[i] <= '9') {
++			nthisvar = atoi_micro(buf+i);
++			// now sanity check it
++			if(nthisvar >= nnumvar || nthisvar < 0) {
++				nthisvar = 0;
++				__close(fd);
++				return 1;
++			}
++			__close(fd);
++			return 2;
++		}
++	}
++	// we reached the end of the string in an unexpected manner; just say that the thing we have works
++	__close(fd);
++	return 1;
++}
++
++void * weak_function
++__cfar_nol_mmap(void* address, size_t length, int protect, int flags, int filedes, off_t offset) {
++	if((initialized == 0) || (initialized == 1 && can_open_config())) {
++		int parsed = get_config_vars();
++		if(parsed <= 0) {
++			//neither nnumvar nor nthivar are set
++			// if we don't know how many variants, try doing randomization of up to 64
++			if(randfd == 0) {
++				// run in probabalistic mode, since we didn't find the arguments for proper indexing
++				randfd = __open("/dev/cfar_urandom",O_RDONLY);
++			}
++			// we're either going to use nthisvar in the ultimate failsafe mode where we don't do the randomization, or we're going to ignore it; either way, it's 0
++			nthisvar = 0;
++			// now check if it's still 0, or if it actually set up properly this time
++			if(randfd != 0) {
++				// we don't use nthisvar, just nnumvar and a random choice
++				nnumvar = PROB_NUM_VARIANTS;
++			} else {
++				// if we don't have our randomness source, and we don't have structured info, just behave as normal mmap
++				// (with the two extra mprotect calls, so syscall alignment is preserved)
++				nnumvar = 1;
++			}
++		} else if (parsed == 1) {
++			//nnumvar is set, but not nthisvar
++			// if we don't know how many variants, try doing randomization of up to 64
++			if(randfd == 0) {
++				// run in probabalistic mode, since we didn't find the arguments for proper indexing
++				randfd = __open("/dev/cfar_urandom",O_RDONLY);
++			}
++			// we're either going to use nthisvar in the ultimate failsafe mode where we don't do the randomization, or we're going to ignore it; either way, it's 0
++			nthisvar = 0;
++			// if randfd is still 0, we just default to the safe case; in any case, we're done here
++		} else if (parsed == 2) {
++			//nthisvar and nnumvar have been set, we're done here
++		}
++		initialized++;
++	}
++#ifdef DEBUG
++	printf("entering mmap call\n");
++#endif
++	// figure out what index we are in a randomized context
++
++	if(
++			(address && (flags & MAP_FIXED))	// must use normal mmap, since the program is now guaranteed the destination address or failure
++			|| (flags & MAP_SHARED)			// we're sharing between multiple programs, which is complex enough as it is - alignment is important, and we'd have to do funky stuff to ensure non-overlappingness with this regardless
++	  ) {
++		// don't modify the arguments - we unfortunately can't touch this much, since it's going to be mapped in a way that we can't nicely diversify (yet)
++		return __mmap(address, length, protect, flags, filedes, offset);
++	} else {
++		// we're diversified now - do fancier stuff
++		size_t alignedlength = length;
++		void* new_mapping = MAP_FAILED;
++		// get the nthisvar for this run
++		if(randfd != 0) {
++			// we're in probabalistic mode
++			uint32_t target = 0;
++			read(randfd, &target, 4);
++			nthisvar = (int)(target % nnumvar);
++		}
++		// branch on whether this is a file-backed allocation or not
++		if (flags & MAP_ANONYMOUS) {
++			// if it's a non-file mapping, just allocate a larger area, and then use part of that
++#if defined(MAP_ALIGN)
++			// gotta round up to the next barrier, but this only matters on solaris (in theory)
++			// support it as soon as it actually comes up
++			length = rounduptomultiple(length, address);
++#endif
++			// we want to allocate a bit more space - this is so that each variant gets its own part of the allocated segment, in a non-overlapping fashion
++			// let's keep page alignment the same
++			alignedlength = rounduptopagemultiple(length);
++			length = alignedlength * nnumvar;
++			new_mapping = __mmap(address, length, protect, flags, filedes, offset);
++
++			// now that we've done the call, handle the result and return
++			if(new_mapping == MAP_FAILED) {
++				// it failed, and if we were to retry, it would diverge anyway - just return the failure
++				// alternatively, we had to do just a normal mmap, so just return the pointer
++				return new_mapping;
++			}
++
++			// in the event that we got the memory and such, mprotect the other portions so that they won't be able to be accesssed improperly
++			mprotect(new_mapping, alignedlength * nthisvar, PROT_NONE);
++			mprotect(new_mapping + alignedlength * (nthisvar+1), alignedlength * (nnumvar - (nthisvar + 1)), PROT_NONE);
++#ifdef DEBUG
++			printf("returning new mapping at %p\n", new_mapping + alignedlength * nthisvar);
++#endif
++			return new_mapping + alignedlength * nthisvar;
++		} else {
++			// for file mappings, handle them by repeated allocation of the required size and selection of the currect index
++			int i=0;
++			for(i=0; i < nnumvar; i++) {
++				if(i == nthisvar) {
++					new_mapping = __mmap(address, length, protect, flags, filedes, offset);
++				} else {
++					// ignored region
++					__mmap(address, length, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
++				}
++			}
++			return new_mapping;
++		}
++	}
++}
++
+ /* Allocate an aligned memory block.  */
+ void * weak_function
+ __libc_memalign (size_t align, size_t n)
+@@ -74,7 +272,7 @@
+ 	    return NULL;
+ 	  nup = GLRO(dl_pagesize);
+ 	}
+-      page = __mmap (0, nup, PROT_READ|PROT_WRITE,
++      page = __cfar_nol_mmap (0, nup, PROT_READ|PROT_WRITE,
+ 		     MAP_ANON|MAP_PRIVATE, -1, 0);
+       if (page == MAP_FAILED)
+ 	return NULL;