From a519300ee3bf4b167bae1f98832c83212a65cf7d Mon Sep 17 00:00:00 2001
From: whh8b <whh8b@git.zephyr-software.com>
Date: Wed, 24 Feb 2016 23:35:48 +0000
Subject: [PATCH] Upgrade to support relative rws.

---
 mixr/mixr.c | 362 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 311 insertions(+), 51 deletions(-)

diff --git a/mixr/mixr.c b/mixr/mixr.c
index 74eb7ea..1d618f9 100644
--- a/mixr/mixr.c
+++ b/mixr/mixr.c
@@ -13,14 +13,18 @@
 #include <itox.h>
 #endif
 
+#include <mixr_rw.h>
+
 #define PROT_NONE 0x0
 #define PROT_READ 0x1
 #define PROT_WRITE 0x2
 #define PROT_EXEC 0x4
 
+#ifndef TEST
 #define SYS_mprotect 10
+#endif
 
-#define DT_ENTRY_SIZE 8
+#define DT_ENTRY_SIZE (8+2)
 #define DT_LENGTH_SIZE 8
 #define DT_FIXED_SIZE_SIZE 8
 #define DT_FIRST_ENTRY_OFFSET (DT_LENGTH_SIZE+DT_FIXED_SIZE_SIZE)
@@ -37,6 +41,7 @@
 #ifdef DEBUG
 	#define print_str_debug mixr_print_str
 	#define print_int_debug mixr_print_int
+	#define print_addr_debug mixr_print_addr
 	#define print_unsigned_long_long_debug mixr_print_unsigned_long_long
 #else
 	#define print_str_debug(a) 
@@ -45,7 +50,8 @@
 #endif
 
 
-uint8_t swap_space[40];
+uint8_t swap_space[MIXR_FIXED_SIZE];
+
 #ifdef DEBUG
 #define write_fd 2
 void mixr_print_str(char *s)
@@ -64,6 +70,10 @@ void mixr_print_unsigned_long_long(unsigned long long x)
 	itox(x,buf);
 	write(write_fd,buf,strlen(buf));
 }
+void mixr_print_addr(void *x)
+{
+	mixr_print_unsigned_long_long((unsigned long long)x);
+}
 #endif
 
 uint64_t read_random64(void) {
@@ -87,11 +97,19 @@ void _memcpy(void *dst, const void *src, unsigned long int len)
 	return;
 }
 
+void make_writable(void *addr, size_t len)
+{
+}
+
+void make_unwritable(void *addr, size_t len)
+{
+}
+
 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);
+	printf("_mprotect: addr: %p\n", addr);
 	//return mprotect(addr, len, flags);
 	return 0;
 #else
@@ -99,6 +117,53 @@ int _mprotect(void *addr, size_t len, int flags)
 #endif
 }
 
+uint16_t rw_table_entry_count(void *rw_table_addr)
+{
+	uint16_t entry_count = 0;
+
+	_memcpy(&entry_count, (const void*)rw_table_addr, sizeof(uint16_t));
+
+	return entry_count;
+}
+
+struct rw_table_entry rw_table_read_entry(void *rw_table_addr, unsigned int entry)
+{
+	struct rw_table_entry rw_entry = {};
+	void *entry_address = NULL;
+	uint16_t entry_count = rw_table_entry_count(rw_table_addr);
+
+	if (entry_count < entry)
+		return rw_entry;
+
+	entry_address = (void*)(rw_table_addr + 
+	                        entry*RW_TABLE_ENTRY_SIZE +
+	                        RW_TABLE_HEADER_SIZE);
+	_memcpy(&rw_entry, entry_address, sizeof(struct rw_table_entry));
+
+	return rw_entry;
+}
+
+void rw_table_write_entry(void *rw_table_addr, unsigned int entry, struct rw_table_entry rw_entry)
+{
+	void *entry_address = NULL;
+	uint16_t entry_count = rw_table_entry_count(rw_table_addr);
+
+	if (entry_count < entry)
+		return;
+
+	entry_address = (void*)(rw_table_addr + 
+	                        entry*RW_TABLE_ENTRY_SIZE +
+	                        RW_TABLE_HEADER_SIZE);
+	_memcpy(entry_address, &rw_entry, sizeof(struct rw_table_entry));
+}
+
+#ifdef TEST
+void rw_table_print_entry(struct rw_table_entry rw_entry)
+{
+	printf("RW Entry: {%hd, 0x%hhx, 0x%hhx, 0x%lx}\n", rw_entry.instruction_offset,rw_entry.rewrite_offset, rw_entry.rewrite_length,rw_entry.absolute_value);
+}
+#endif
+
 uint64_t dt_table_length(void *dt_table_addr)
 {
 	uint64_t table_length = 0;
@@ -121,7 +186,7 @@ uint64_t dt_fixed_size(void *dt_table_addr)
 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);
+	return (uint64_t)(dt_table_addr+entry_offset);
 }
 
 uint64_t dt_table_read_entry_address(void *dt_table_addr, unsigned int entry)
@@ -135,6 +200,15 @@ uint64_t dt_table_read_entry_address(void *dt_table_addr, unsigned int entry)
 	return entry_address;
 }
 
+uint16_t dt_table_read_entry_offset(void *dt_table_addr, unsigned int entry)
+{
+	uint16_t entry_offset;
+	_memcpy(&entry_offset,
+	        (const void*)(dt_table_entry_address(dt_table_addr, entry)+8),
+					sizeof(uint16_t));
+	return entry_offset;
+}
+
 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), 
@@ -142,6 +216,13 @@ void dt_table_write_entry_address(void *dt_table_addr, unsigned int entry, uint6
 				 sizeof(uint64_t));
 }
 
+void dt_table_write_entry_offset(void *dt_table_addr, unsigned int entry, uint16_t entry_offset)
+{
+	_memcpy((void*)(dt_table_entry_address(dt_table_addr, entry)+8), 
+	       (const void*)&entry_offset,
+				 sizeof(uint16_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);
@@ -153,7 +234,7 @@ void dt_table_swap_entry_addresses(void *dt_table_addr, unsigned int a, unsigned
 
 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);
+	uint64_t fixed_size = MIXR_FIXED_SIZE;
 	//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);
@@ -168,21 +249,21 @@ void dt_table_swap_entry_contents(void *dt_table_addr, unsigned int a, unsigned
 	 * The assumption is that we are '-w' in these
 	 * pages when we start.
 	 */
-	_mprotect((void*)(((uint64_t)dt_table_addr)&PAGE_MASK),
+	_mprotect((void*)(((uintptr_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),
+	_mprotect((void*)(((uintptr_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),
+	_mprotect((void*)(((uintptr_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_addr_debug((void*)(&swap_space));
 	print_str_debug("\n");
 	print_str_debug("b_contents_addr: ");
-	print_int_debug(a_contents_addr);
+	print_addr_debug(a_contents_addr);
 	print_str_debug("\n");
 	print_str_debug("fixed_size: ");
 	print_int_debug(fixed_size);
@@ -196,10 +277,10 @@ void dt_table_swap_entry_contents(void *dt_table_addr, unsigned int a, unsigned
 #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("\n");
 	print_str_debug("b: ");
 	print_int_debug(dt_table_read_entry_address(dt_table_addr, b));
-	print_str_debug("\n ");
+	print_str_debug("\n");
 #endif
 
 	dt_table_swap_entry_addresses(dt_table_addr, a, b);
@@ -207,19 +288,91 @@ void dt_table_swap_entry_contents(void *dt_table_addr, unsigned int a, unsigned
 #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("\n");
 	print_str_debug("b: ");
 	print_int_debug(dt_table_read_entry_address(dt_table_addr, b));
-	print_str_debug("\n ");
+	print_str_debug("\n");
 #endif
 
-	_mprotect((void*)(((uint64_t)dt_table_addr)&PAGE_MASK),
+	_mprotect((void*)((uintptr_t)(dt_table_addr)&PAGE_MASK),
 	          table_length + PAGE_SIZE,
 						PROT_READ|PROT_EXEC);
-	_mprotect((void*)(((uint64_t)a_contents_addr)&PAGE_MASK),
+	_mprotect((void*)((uintptr_t)(a_contents_addr)&PAGE_MASK),
 	          PAGE_SIZE + PAGE_SIZE,
 						PROT_READ|PROT_EXEC);
-	_mprotect((void*)(((uint64_t)b_contents_addr)&PAGE_MASK),
+	_mprotect((void*)((uintptr_t)(b_contents_addr)&PAGE_MASK),
+	          PAGE_SIZE + PAGE_SIZE,
+						PROT_READ|PROT_EXEC);
+}
+
+void mixr_do_rw(uint64_t dollop_start, struct rw_table_entry rw_entry)
+{
+	uint64_t next_pc_address = dollop_start + rw_entry.instruction_offset;
+	uint64_t relative = next_pc_address - rw_entry.rewrite_offset;
+	void *rw_val = NULL;
+	uint8_t rw8_val;
+	uint16_t rw16_val;
+	uint32_t rw32_val;
+	uint64_t rw48_val;
+	uint64_t rw64_val;
+
+#if DEBUG
+	print_str_debug("Abs ");
+	print_unsigned_long_long_debug(rw_entry.absolute_value);
+	print_str_debug(" to (0x");
+	print_addr_debug((void*)next_pc_address);
+	print_str_debug(") ");
+	print_int_debug(rw_entry.absolute_value-next_pc_address);
+	print_str_debug(" at ");
+	print_addr_debug((void*)relative);
+	print_str_debug("\n");
+#endif
+
+	switch (rw_entry.rewrite_length)
+	{
+		case 0x0:
+		{
+			rw8_val = rw_entry.absolute_value-next_pc_address;
+			rw_val = (void*)&rw8_val;
+			break;
+		}
+		case 0x1:
+		{
+			rw16_val = rw_entry.absolute_value-next_pc_address;
+			rw_val = (void*)&rw16_val;
+			break;
+		}
+		case 0x3:
+		{
+			rw32_val = rw_entry.absolute_value-next_pc_address;
+			rw_val = (void*)&rw32_val;
+			break;
+		}
+		case 0x5:
+		{
+			rw48_val = rw_entry.absolute_value-next_pc_address;
+			rw_val = (void*)&rw48_val;
+			break;
+		}
+		case 0x7:
+		{
+			rw64_val = rw_entry.absolute_value-next_pc_address;
+			rw_val = (void*)&rw64_val;
+			break;
+		}
+	}
+#ifdef DEBUG
+	if (rw_val == NULL)
+		rw_val = 0xdead;
+#else
+	assert(rw_val);
+#endif
+
+	_mprotect((void*)(((uintptr_t)relative)&PAGE_MASK),
+	          PAGE_SIZE + PAGE_SIZE,
+						PROT_READ|PROT_EXEC|PROT_WRITE);
+	_memcpy((void*)relative, rw_val, rw_entry.rewrite_length);
+	_mprotect((void*)(((uintptr_t)relative)&PAGE_MASK),
 	          PAGE_SIZE + PAGE_SIZE,
 						PROT_READ|PROT_EXEC);
 }
@@ -233,16 +386,16 @@ void dt_table_swap_entry_contents(void *dt_table_addr, unsigned int a, unsigned
 	output = _rbp_value; \
 } \
 
-void zipr_hook_start(unsigned int id,
+void zipr_hook_start(unsigned long long id,
                      unsigned long long rax,
 										 unsigned long long rsp)
 {
-	uint64_t table_addr = 0;
+	void *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_addr = (void*)id;
 	table_length = dt_table_length(table_addr);
 	//a = read_random64() % table_length;
 	//b = read_random64() % table_length;
@@ -257,31 +410,46 @@ void zipr_hook_start(unsigned int id,
 
 #ifdef DEBUG
 	print_str_debug("rbp_value:");
-	print_int_debug(rbp_value);
+	print_unsigned_long_long_debug(rbp_value);
 	print_str_debug("\n");
 	print_str_debug("ra:");
-	print_int_debug(ra);
+	print_unsigned_long_long_debug(ra);
 	print_str_debug("\n");
 #endif
-
+#if 1
 	for (table_iterator = 2; table_iterator<table_length; table_iterator+=2)
 	{
 		uint64_t a = table_iterator, b = a-1;
+		uint64_t dt_address_a = dt_table_read_entry_address(table_addr, a);
+		uint16_t dt_offset_a = dt_table_read_entry_offset(table_addr, a);
+		uint64_t rw_address_a = dt_address_a + dt_offset_a;
+		uint16_t rw_entry_count_a = rw_table_entry_count((void*)rw_address_a);
+		uint64_t dt_address_b = dt_table_read_entry_address(table_addr, b);
+		uint16_t dt_offset_b = dt_table_read_entry_offset(table_addr, b);
+		uint64_t rw_address_b = dt_address_b + dt_offset_b;
+		uint16_t rw_entry_count_b = rw_table_entry_count((void*)rw_address_b);
+		uint16_t rw_entry_count_iterator = 0;
 #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_unsigned_long_long_debug(a);
+		print_str_debug(": (");
+		print_addr_debug((void*)dt_address_a);
+		print_str_debug(",");
+		print_int_debug(dt_offset_a);
+		print_str_debug(" #");
+		print_int_debug(rw_entry_count_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");
+		print_str_debug(": (");
+		print_addr_debug((void*)dt_address_b);
+		print_str_debug(",");
+		print_int_debug(dt_offset_b);
+		print_str_debug(" #");
+		print_int_debug(rw_entry_count_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))
+		if ((dt_address_a <= ra && (dt_address_a+MIXR_FIXED_SIZE) >= ra) ||
+		    (dt_address_b <= ra && (dt_address_b+MIXR_FIXED_SIZE) >= ra))
 		{
 #ifdef DEBUG
 			print_str_debug("Skipping swap ");
@@ -293,21 +461,59 @@ void zipr_hook_start(unsigned int id,
 			continue;
 		}
 		dt_table_swap_entry_contents(table_addr, a, b);
+
+		/*
+		 * Rewrite a.
+		 */
+		for (rw_entry_count_iterator = 0;
+		     rw_entry_count_iterator<rw_entry_count_a;
+				 rw_entry_count_iterator++)
+		{
+			/*
+			 * Since we already swapped, the old a is now
+			 * at b. To reuse variable assignments from above,
+			 * this looks more confusing.
+			 */
+			mixr_do_rw(dt_address_b,
+			           rw_table_read_entry((void*)(dt_address_b+dt_offset_a),
+								                     rw_entry_count_iterator));
+		}
+		/*
+		 * Rewrite b.
+		 */
+		for (rw_entry_count_iterator = 0;
+		     rw_entry_count_iterator<rw_entry_count_b;
+				 rw_entry_count_iterator++)
+		{
+			/*
+			 * Since we already swapped, the old b is now
+			 * at a. To reuse variable assignments from above,
+			 * this looks more confusing.
+			 */
+			mixr_do_rw(dt_address_a,
+			           rw_table_read_entry((void*)(dt_address_a+dt_offset_b),
+								                     rw_entry_count_iterator));
+		}
 	}
+#endif
 }
 
 #ifdef TEST
-int main()
+void test_dollop_table(void) 
 {
 	uint64_t table_entries = 11;
 	uint64_t table_fixed_size = MIXR_FIXED_SIZE;
 	uint64_t table_entry_address = 0xff00ff00;
+	uint16_t table_entry_offset = 0;
 	void *table = (void*)malloc((table_entries*DT_ENTRY_SIZE)+DT_FIRST_ENTRY_OFFSET);
 	unsigned i = 0;
 
 	int nine = 9;
 	int ten = 10;
 
+	uint16_t nine_offset = 0x9;
+	uint16_t ten_offset = 0xa;
+
 	_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)),
@@ -317,34 +523,88 @@ int main()
 	for (i = 0; i<table_entries-2; i++)
 	{
 		table_entry_address += 1;
-		printf("table_entry_address: (%d): %llx\n", i, table_entry_address);
+		table_entry_offset += 1;
+		printf("table_entry_address: (%d): %lx\n", i, table_entry_address);
+		printf("table_entry_offset: (%d): %hx\n", i, table_entry_offset);
 		dt_table_write_entry_address(table, i, table_entry_address);
+		dt_table_write_entry_offset(table, i, table_entry_offset);
 	}
 
-	dt_table_write_entry_address(table, 9, &nine);
-	dt_table_write_entry_address(table, 10, &ten);
+	dt_table_write_entry_address(table, 9, (uint64_t)&nine);
+	dt_table_write_entry_offset(table, 9, nine_offset);
+	dt_table_write_entry_address(table, 10, (uint64_t)&ten);
+	dt_table_write_entry_offset(table, 10, ten_offset);
 
-	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("dt_table_length: %lu\n", dt_table_length(table));
+	printf("dt_fixed_size: %lu\n", dt_fixed_size(table));
+	printf("dt_table_read_entry_address(0): %lx\n", dt_table_read_entry_address(table, 0));
+	printf("dt_table_read_entry_address(5): %lx\n", dt_table_read_entry_address(table, 5));
+	printf("dt_table_read_entry_address(8): %lx\n", dt_table_read_entry_address(table, 8));
+	printf("dt_table_read_entry_offset(0): %hx\n", dt_table_read_entry_offset(table, 0));
+	printf("dt_table_read_entry_offset(5): %hx\n", dt_table_read_entry_offset(table, 5));
+	printf("dt_table_read_entry_offset(8): %hx\n", dt_table_read_entry_offset(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("dt_table_read_entry_address(5): %lx\n", dt_table_read_entry_address(table, 5));
+	printf("dt_table_read_entry_offset(5): %hx\n", dt_table_read_entry_offset(table, 5));
+	printf("dt_table_read_entry_address(8): %lx\n", dt_table_read_entry_address(table, 8));
+	printf("dt_table_read_entry_offset(8): %hx\n", dt_table_read_entry_offset(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(0): %lx\n", dt_table_read_entry_address(table, 0));
+	printf("dt_table_read_entry_offset(0): %hx\n", dt_table_read_entry_offset(table, 0));
+	printf("dt_table_read_entry_address(8): %lx\n", dt_table_read_entry_address(table, 8));
+	printf("dt_table_read_entry_offset(8): %hx\n", dt_table_read_entry_offset(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)));
+	printf("dt_table_read_entry_address(9): %lx, %x\n", dt_table_read_entry_address(table, 9), *((int*)dt_table_read_entry_address(table, 9)));
+	printf("dt_table_read_entry_offset(9): %hx\n", dt_table_read_entry_offset(table, 9));
+	printf("dt_table_read_entry_address(10): %lx, %x\n", dt_table_read_entry_address(table, 10), *((int*)dt_table_read_entry_address(table, 10)));
+	printf("dt_table_read_entry_offset(10): %hx\n", dt_table_read_entry_offset(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)));
+
+	printf("dt_table_read_entry_address(9): %lx, %x\n", dt_table_read_entry_address(table, 9), *((int*)dt_table_read_entry_address(table, 9)));
+	printf("dt_table_read_entry_offset(9): %hx\n", dt_table_read_entry_offset(table, 9));
+	printf("dt_table_read_entry_address(10): %lx, %x\n", dt_table_read_entry_address(table, 10), *((int*)dt_table_read_entry_address(table, 10)));
+	printf("dt_table_read_entry_offset(10): %hx\n", dt_table_read_entry_offset(table, 10));
+}
+
+void test_rw_table(void)
+{
+	struct rw_table_header *rw_table = NULL;
+	int entry_count = 11;
+	struct rw_table_entry entry_ten = {1, 2, 3, 4};
+	struct rw_table_entry entry_eleven = {11, 22, 33, 44};
+	struct rw_table_entry entry_fiftyk = {111, 222, 333, 444};
+
+	rw_table = (struct rw_table_header*)malloc(sizeof(struct rw_table_header) + (entry_count*sizeof(struct rw_table_entry)));
+
+	rw_table->entry_count = 11;
+
+	rw_table_write_entry((void*)rw_table, 10, entry_ten);
+	rw_table_write_entry((void*)rw_table, 11, entry_eleven);
+
+	/*
+	 * Will fail out -- entry too high.
+	 */
+	rw_table_write_entry((void*)rw_table, 50000, entry_fiftyk);
+
+	rw_table_print_entry(rw_table_read_entry((void*)rw_table, 10));
+	rw_table_print_entry(rw_table_read_entry((void*)rw_table, 11));
+
+	/*
+	 * Will return 0'd rw_table_entry -- entry too high.
+	 */
+	rw_table_print_entry(rw_table_read_entry((void*)rw_table, 50000));
+}
+
+int main()
+{
+	test_rw_table();
+	test_dollop_table();
 	return 0;
 }
 #endif
-- 
GitLab