diff --git a/.gitattributes b/.gitattributes
index 1384c7f2d562a15149f8200d46663bfba8de6a6e..f791851919faf4d1bffadcc47b95f534bd08c5bf 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -60,6 +60,8 @@ libc/src/stdlib.c -text
 libc/src/strlen.c -text
 libc/src/syscall.s -text
 libc/src/write.c -text
+mixr/Makefile.in -text
+mixr/mixr.c -text
 p1/Makefile.in -text
 p1/p1callbacks.c -text
 rss/Makefile.in -text
diff --git a/configure.in b/configure.in
index b46ac9891b8eb0e3a00ad4f6212d896c83d87fa9..0c573ce379a272b8d7fbd5768d43ef64d62f6b10 100644
--- a/configure.in
+++ b/configure.in
@@ -72,6 +72,7 @@ enable_dir inferfn
 enable_dir rss
 enable_dir hookdynamic
 enable_dir canaries
+enable_dir mixr
 enable_dir cookbook
 enable_dir buffrecv
 enable_dir datashadow
diff --git a/mixr/Makefile.in b/mixr/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..9603c84722e8cf038a92ace9751205fbc6b3f7a0
--- /dev/null
+++ b/mixr/Makefile.in
@@ -0,0 +1,28 @@
+
+
+CC=@CC@
+CFLAGS=-fno-omit-frame-pointer @CFLAGS@
+LIB=@LIB@
+AR=@AR@
+AS=@AS@
+ASFLAGS=@ASFLAGS@
+
+OBJS=mixr.o
+
+
+.SUFFIXES: .o .s .c
+
+.c.o:
+	$(CC) $(CFLAGS) $(INCLUDE) -D__$(ARCH) -c $<
+
+.s.o:
+	$(AS) $(ASFLAGS) $<
+
+
+all: 	$(OBJS)
+	$(AR) -r $(LIB) $(OBJS)
+
+clean:
+	rm *.o
+	
+
diff --git a/mixr/mixr.c b/mixr/mixr.c
new file mode 100644
index 0000000000000000000000000000000000000000..74eb7ea4aaf79c0c36bfce1ddf54ec91d382f79c
--- /dev/null
+++ b/mixr/mixr.c
@@ -0,0 +1,350 @@
+#ifdef TEST
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#else
+#include <malloc.h>
+#include <stdint.h>
+#include <strlen.h>
+#include <itox.h>
+#endif
+
+#define PROT_NONE 0x0
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x4
+
+#define SYS_mprotect 10
+
+#define DT_ENTRY_SIZE 8
+#define DT_LENGTH_SIZE 8
+#define DT_FIXED_SIZE_SIZE 8
+#define DT_FIRST_ENTRY_OFFSET (DT_LENGTH_SIZE+DT_FIXED_SIZE_SIZE)
+
+#define PAGE_SIZE 4096
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#ifdef TEST
+#define MIXR_FIXED_SIZE (sizeof(int))
+#else
+#define MIXR_FIXED_SIZE (40)
+#endif
+
+#ifdef DEBUG
+	#define print_str_debug mixr_print_str
+	#define print_int_debug mixr_print_int
+	#define print_unsigned_long_long_debug mixr_print_unsigned_long_long
+#else
+	#define print_str_debug(a) 
+	#define print_int_debug(a) 
+	#define assert(a)
+#endif
+
+
+uint8_t swap_space[40];
+#ifdef DEBUG
+#define write_fd 2
+void mixr_print_str(char *s)
+{
+	write(write_fd,s,strlen(s));
+}
+void mixr_print_int(int x)
+{
+	char buf[100];
+	itox(x,buf);
+	write(write_fd,buf,strlen(buf));
+}
+void mixr_print_unsigned_long_long(unsigned long long x)
+{
+	char buf[100];
+	itox(x,buf);
+	write(write_fd,buf,strlen(buf));
+}
+#endif
+
+uint64_t read_random64(void) {
+	unsigned long long random_value = -1;
+	int fd = -1;
+	fd = open("/dev/urandom", 0x00);
+	if (fd != -1) {
+		read(fd, (void*)&random_value, sizeof(unsigned long long));
+		close(fd);
+	}
+	return random_value;
+}
+
+void _memcpy(void *dst, const void *src, unsigned long int len);
+void _memcpy(void *dst, const void *src, unsigned long int len) 
+{
+	unsigned long int i = 0;
+	for (i = 0; i<len; i++) {
+		((uint8_t*)(dst))[i] = ((uint8_t*)(src))[i];
+	}
+	return;
+}
+
+int _mprotect(void *addr, size_t len, int flags);
+int _mprotect(void *addr, size_t len, int flags)
+{
+#ifdef TEST
+	printf("_mprotect: addr: %llx\n", addr);
+	//return mprotect(addr, len, flags);
+	return 0;
+#else
+	return syscall(SYS_mprotect, addr, len, flags);
+#endif
+}
+
+uint64_t dt_table_length(void *dt_table_addr)
+{
+	uint64_t table_length = 0;
+
+	_memcpy(&table_length, (const void*)dt_table_addr, sizeof(uint64_t));
+
+	return table_length;
+}
+uint64_t dt_fixed_size(void *dt_table_addr)
+{
+	uint64_t fixed_size = 0;
+
+	_memcpy(&fixed_size,
+	       (const void*)(((uint64_t)dt_table_addr) + DT_LENGTH_SIZE),
+				 sizeof(uint64_t));
+
+	return fixed_size;
+}
+
+uint64_t dt_table_entry_address(void *dt_table_addr, unsigned int entry)
+{
+	uint64_t entry_offset = entry * DT_ENTRY_SIZE + DT_FIRST_ENTRY_OFFSET; 
+	return (((uint64_t)dt_table_addr)+entry_offset);
+}
+
+uint64_t dt_table_read_entry_address(void *dt_table_addr, unsigned int entry)
+{
+	uint64_t entry_address = 0;
+
+	_memcpy(&entry_address,
+	       (const void*)dt_table_entry_address(dt_table_addr, entry),
+				 sizeof(uint64_t));
+
+	return entry_address;
+}
+
+void dt_table_write_entry_address(void *dt_table_addr, unsigned int entry, uint64_t entry_address)
+{
+	_memcpy((void*)dt_table_entry_address(dt_table_addr, entry), 
+	       (const void*)&entry_address,
+				 sizeof(uint64_t));
+}
+
+void dt_table_swap_entry_addresses(void *dt_table_addr, unsigned int a, unsigned int b)
+{
+	uint64_t address_entry_a = dt_table_read_entry_address(dt_table_addr, a);
+	uint64_t address_entry_b = dt_table_read_entry_address(dt_table_addr, b);
+
+	dt_table_write_entry_address(dt_table_addr, a, address_entry_b);
+	dt_table_write_entry_address(dt_table_addr, b, address_entry_a);
+}
+
+void dt_table_swap_entry_contents(void *dt_table_addr, unsigned int a, unsigned int b)
+{
+	uint64_t fixed_size = 40; //dt_fixed_size(dt_table_addr);
+	//void *swap_space = (void*)malloc(fixed_size);
+	void *a_contents_addr = (void*)dt_table_read_entry_address(dt_table_addr,a);
+	void *b_contents_addr = (void*)dt_table_read_entry_address(dt_table_addr,b);
+	uint64_t table_length = (dt_table_length(dt_table_addr)*DT_ENTRY_SIZE) +
+	                         DT_FIXED_SIZE_SIZE +
+													 DT_LENGTH_SIZE;
+	/*
+	 * Three steps:
+	 * 1. mprotect + w
+	 * 2. copy
+	 * 3. mprotect - w
+	 * The assumption is that we are '-w' in these
+	 * pages when we start.
+	 */
+	_mprotect((void*)(((uint64_t)dt_table_addr)&PAGE_MASK),
+	          table_length + PAGE_SIZE,
+						PROT_READ|PROT_EXEC|PROT_WRITE);
+	_mprotect((void*)(((uint64_t)a_contents_addr)&PAGE_MASK),
+	          PAGE_SIZE + PAGE_SIZE,
+						PROT_READ|PROT_EXEC|PROT_WRITE);
+	_mprotect((void*)(((uint64_t)b_contents_addr)&PAGE_MASK),
+	          PAGE_SIZE + PAGE_SIZE,
+						PROT_READ|PROT_EXEC|PROT_WRITE);
+#ifdef DEBUG
+	print_str_debug("swap_space: ");
+	print_int_debug((void*)(&swap_space));
+	print_str_debug("\n");
+	print_str_debug("b_contents_addr: ");
+	print_int_debug(a_contents_addr);
+	print_str_debug("\n");
+	print_str_debug("fixed_size: ");
+	print_int_debug(fixed_size);
+	print_str_debug("\n");
+#endif
+
+	_memcpy((void*)(&swap_space), a_contents_addr, fixed_size);
+	_memcpy(a_contents_addr, b_contents_addr, fixed_size); 
+	_memcpy(b_contents_addr, (void*)(&swap_space), fixed_size); 
+
+#ifdef DEBUG
+	print_str_debug("a: ");
+	print_int_debug(dt_table_read_entry_address(dt_table_addr, a));
+	print_str_debug("\n ");
+	print_str_debug("b: ");
+	print_int_debug(dt_table_read_entry_address(dt_table_addr, b));
+	print_str_debug("\n ");
+#endif
+
+	dt_table_swap_entry_addresses(dt_table_addr, a, b);
+
+#ifdef DEBUG
+	print_str_debug("a: ");
+	print_int_debug(dt_table_read_entry_address(dt_table_addr, a));
+	print_str_debug("\n ");
+	print_str_debug("b: ");
+	print_int_debug(dt_table_read_entry_address(dt_table_addr, b));
+	print_str_debug("\n ");
+#endif
+
+	_mprotect((void*)(((uint64_t)dt_table_addr)&PAGE_MASK),
+	          table_length + PAGE_SIZE,
+						PROT_READ|PROT_EXEC);
+	_mprotect((void*)(((uint64_t)a_contents_addr)&PAGE_MASK),
+	          PAGE_SIZE + PAGE_SIZE,
+						PROT_READ|PROT_EXEC);
+	_mprotect((void*)(((uint64_t)b_contents_addr)&PAGE_MASK),
+	          PAGE_SIZE + PAGE_SIZE,
+						PROT_READ|PROT_EXEC);
+}
+
+#define get_rbp(output) \
+{ \
+	uint64_t _rbp_value = 0xfeed; \
+	asm volatile ("mov %%rbp, %0\n" \
+	    : "=r" (_rbp_value) \
+	   ); \
+	output = _rbp_value; \
+} \
+
+void zipr_hook_start(unsigned int id,
+                     unsigned long long rax,
+										 unsigned long long rsp)
+{
+	uint64_t table_addr = 0;
+	uint64_t table_length = 0;
+	uint64_t table_iterator = 2;
+	uint64_t ra = 0, rbp_value = 0;
+
+	table_addr = (uint64_t)id;
+	table_length = dt_table_length(table_addr);
+	//a = read_random64() % table_length;
+	//b = read_random64() % table_length;
+
+	get_rbp(rbp_value);
+
+	/*
+	 * The return value is 16 bytes above
+	 * the rbp.
+	 */
+	ra = *((uint64_t*)(rbp_value+0x8));
+
+#ifdef DEBUG
+	print_str_debug("rbp_value:");
+	print_int_debug(rbp_value);
+	print_str_debug("\n");
+	print_str_debug("ra:");
+	print_int_debug(ra);
+	print_str_debug("\n");
+#endif
+
+	for (table_iterator = 2; table_iterator<table_length; table_iterator+=2)
+	{
+		uint64_t a = table_iterator, b = a-1;
+#ifdef DEBUG
+		print_str_debug("Swapping:");
+		print_int_debug(a);
+		print_str_debug(":");
+		print_int_debug(dt_table_read_entry_address(table_addr, a));
+		print_str_debug("<->");
+		print_int_debug(b);
+		print_str_debug(":");
+		print_int_debug(dt_table_read_entry_address(table_addr, b));
+		print_str_debug("\n");
+#endif
+		if ((dt_table_read_entry_address(table_addr, a) <= ra &&
+		    (dt_table_read_entry_address(table_addr, a)+MIXR_FIXED_SIZE) >= ra) ||
+		    (dt_table_read_entry_address(table_addr, b) <= ra &&
+		    (dt_table_read_entry_address(table_addr, b)+MIXR_FIXED_SIZE) >= ra))
+		{
+#ifdef DEBUG
+			print_str_debug("Skipping swap ");
+			print_int_debug(a);
+			print_str_debug("<->");
+			print_int_debug(b);
+			print_str_debug(" because it is active.\n");
+#endif
+			continue;
+		}
+		dt_table_swap_entry_contents(table_addr, a, b);
+	}
+}
+
+#ifdef TEST
+int main()
+{
+	uint64_t table_entries = 11;
+	uint64_t table_fixed_size = MIXR_FIXED_SIZE;
+	uint64_t table_entry_address = 0xff00ff00;
+	void *table = (void*)malloc((table_entries*DT_ENTRY_SIZE)+DT_FIRST_ENTRY_OFFSET);
+	unsigned i = 0;
+
+	int nine = 9;
+	int ten = 10;
+
+	_memcpy(table, (const void*)&table_entries, sizeof(uint64_t));
+	_memcpy(table, (const void*)&table_entries, sizeof(uint64_t));
+	_memcpy((void*)(((uint64_t)table)+(DT_LENGTH_SIZE)),
+	       (const void*)&table_fixed_size,
+				 sizeof(uint64_t));
+
+	for (i = 0; i<table_entries-2; i++)
+	{
+		table_entry_address += 1;
+		printf("table_entry_address: (%d): %llx\n", i, table_entry_address);
+		dt_table_write_entry_address(table, i, table_entry_address);
+	}
+
+	dt_table_write_entry_address(table, 9, &nine);
+	dt_table_write_entry_address(table, 10, &ten);
+
+	printf("dt_table_length: %llu\n", dt_table_length(table));
+	printf("dt_fixed_size: %llu\n", dt_fixed_size(table));
+	printf("dt_table_read_entry_address(0): %llx\n", dt_table_read_entry_address(table, 0));
+	printf("dt_table_read_entry_address(5): %llx\n", dt_table_read_entry_address(table, 5));
+	printf("dt_table_read_entry_address(8): %llx\n", dt_table_read_entry_address(table, 8));
+
+	printf("swap 5 <-> 8\n");
+	dt_table_swap_entry_addresses(table, 5, 8);
+	
+	printf("dt_table_read_entry_address(5): %llx\n", dt_table_read_entry_address(table, 5));
+	printf("dt_table_read_entry_address(8): %llx\n", dt_table_read_entry_address(table, 8));
+	printf("swap 8 <-> 0\n");
+	dt_table_swap_entry_addresses(table, 0, 8);
+	printf("dt_table_read_entry_address(0): %llx\n", dt_table_read_entry_address(table, 0));
+	printf("dt_table_read_entry_address(8): %llx\n", dt_table_read_entry_address(table, 8));
+	
+	printf("dt_table_read_entry_address(9): %llx, %llx\n", dt_table_read_entry_address(table, 9), *((int*)dt_table_read_entry_address(table, 9)));
+	printf("dt_table_read_entry_address(10): %llx, %llx\n", dt_table_read_entry_address(table, 10), *((int*)dt_table_read_entry_address(table, 10)));
+	dt_table_swap_entry_contents(table, 10, 9);
+	printf("dt_table_read_entry_address(9): %llx, %llx\n", dt_table_read_entry_address(table, 9), *((int*)dt_table_read_entry_address(table, 9)));
+	printf("dt_table_read_entry_address(10): %llx, %llx\n", dt_table_read_entry_address(table, 10), *((int*)dt_table_read_entry_address(table, 10)));
+	return 0;
+}
+#endif