diff --git a/.gitignore b/.gitignore
index 18f3af526f613fcef9c38093cc5acb022359f4c3..909a827a011796b266e5d3b138ad212431106e44 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,8 @@
 install/
+build/
 manifest.txt.config
+libzafl/src/*.so
+libzafl/src/*.os
+manifest.txt.config
+.sconsign.dblite
+*.swp
diff --git a/zfuzz/README.md b/zfuzz/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ff2fbddf863a55b75ec96e1cf24ef7774c17accb
--- /dev/null
+++ b/zfuzz/README.md
@@ -0,0 +1 @@
+All things related to fuzzing at Zephyr
\ No newline at end of file
diff --git a/zfuzz/afl_transforms/.gitignore b/zfuzz/afl_transforms/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3afee3475a10291c108cdf6a4681978e0ac638b5
--- /dev/null
+++ b/zfuzz/afl_transforms/.gitignore
@@ -0,0 +1,2 @@
+build
+.sconsign.dblite
diff --git a/zfuzz/afl_transforms/SConscript b/zfuzz/afl_transforms/SConscript
new file mode 100644
index 0000000000000000000000000000000000000000..6d2b16becae3add613347f79ac97f9cee0b8eaa9
--- /dev/null
+++ b/zfuzz/afl_transforms/SConscript
@@ -0,0 +1,32 @@
+import shutil
+import os
+import tarfile
+
+Import('env')
+
+(sysname, nodename, release, version, machine)=os.uname()
+
+env.Append(CXXFLAGS=" -Wall -Werror")
+env.Append(LINKFLAGS=" -Wall -Werror -Wl,-unresolved-symbols=ignore-in-shared-libs ")
+
+env['BASE_IRDB_LIBS']="irdb-core"
+
+
+# pebliss requires iconv, which needs to be explicit on cygwin.
+if "CYGWIN" in sysname:
+	# add tuple of 1 item!
+	env['BASE_IRDB_LIBS']=env['BASE_IRDB_LIBS']+("iconv",)
+
+Export('env')
+
+libs=SConscript("tools/SConscript", variant_dir='scons_build/tools')
+
+pedi = Command( target = "./testoutput",
+		source = "./SConscript",
+                action = "cd "+os.environ['SECURITY_TRANSFORMS_HOME']+" ; " +os.environ['PEDI_HOME']+"/pedi -m manifest.txt ; cd -" )
+
+Depends(pedi,libs)
+
+
+Default( pedi )
+
diff --git a/zfuzz/afl_transforms/SConstruct b/zfuzz/afl_transforms/SConstruct
new file mode 100644
index 0000000000000000000000000000000000000000..0fadf113a8aa7183159e564f5186366602b37169
--- /dev/null
+++ b/zfuzz/afl_transforms/SConstruct
@@ -0,0 +1,45 @@
+import os
+import sys
+
+
+
+(sysname, nodename, release, version, machine)=os.uname()
+
+env=Environment()
+
+
+# default build options
+env.Replace(CFLAGS="-fPIC -Wall  ")
+env.Replace(CXXFLAGS="-fPIC -Wall  ")
+env.Replace(LINKFLAGS="-fPIC -Wall  ")
+
+# parse arguments
+env.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME'])
+env.Replace(SMPSA_HOME=os.environ['SMPSA_HOME'])
+env.Replace(IRDB_SDK=os.environ['IRDB_SDK'])
+env.Replace(AFL_TRANSFORMS=os.environ['AFL_TRANSFORMS'])
+env.Replace(debug=ARGUMENTS.get("debug",0))
+
+
+if int(env['debug']) == 1:
+        print "Setting debug mode"
+        env.Append(CFLAGS=" -g ")
+        env.Append(CXXFLAGS=" -g ")
+        env.Append(LINKFLAGS=" -g ")
+else:
+        print "Setting release mode"
+        env.Append(CFLAGS=" -O3 ")
+        env.Append(CXXFLAGS=" -O3 ")
+        env.Append(LINKFLAGS=" -O3 ")
+
+
+# add extra flag for solaris.
+if sysname == "SunOS":
+        env.Append(LINKFLAGS=" -L/opt/csw/lib -DSOLARIS  ")
+        env.Append(CFLAGS=" -I/opt/csw/include -DSOLARIS ")
+        env.Append(CXXFLAGS=" -I/opt/csw/include -DSOLARIS  ")
+
+
+Export('env')
+SConscript("SConscript", variant_dir='build')
+
diff --git a/zfuzz/afl_transforms/tools/SConscript b/zfuzz/afl_transforms/tools/SConscript
new file mode 100644
index 0000000000000000000000000000000000000000..f30fe37c68d95dc0ba828dbc50077427b2f3f562
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/SConscript
@@ -0,0 +1,18 @@
+import os
+
+Import('env')
+
+dirs='''
+	laf
+	zax
+	'''
+
+
+nobuild_dirs='''
+	'''
+
+tools=[]
+for i in Split(dirs):
+	tools=tools+SConscript(os.path.join(i,"SConscript"))
+
+Return('tools')
diff --git a/zfuzz/afl_transforms/tools/laf/SConscript b/zfuzz/afl_transforms/tools/laf/SConscript
new file mode 100644
index 0000000000000000000000000000000000000000..6e620a5caee8574ea01071979e8a4f4fd7f4b6dd
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/SConscript
@@ -0,0 +1,34 @@
+import os
+
+
+
+Import('env')
+
+# import and create a copy of the environment so we don't screw up anyone elses env.
+myenv=env.Clone()
+
+cpppath=''' 
+	 $IRDB_SDK/include 
+	 $SECURITY_TRANSFORMS_HOME/libtransform/include 
+	 $SECURITY_TRANSFORMS_HOME/libMEDSannotation/include 
+	 $SECURITY_TRANSFORMS_HOME/libIRDB/include 
+	 $SMPSA_HOME/include
+	'''
+
+
+files=Glob( Dir('.').srcnode().abspath+"/*.cpp")
+
+
+pgm="laf.exe"
+
+LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
+LIBS=Split("stars "+ env.subst('$BASE_IRDB_LIBS')+ "  irdb-cfg irdb-util irdb-transform irdb-deep MEDSannotation jsoncpp ") 
+myenv=myenv.Clone(CPPPATH=Split(cpppath))
+myenv.Append(CXXFLAGS = " -std=c++11 -Wall -g ")
+pgm=myenv.Program(pgm,  files,  LIBPATH=LIBPATH, LIBS=LIBS)
+install=myenv.Install("$SECURITY_TRANSFORMS_HOME/plugins_install/", pgm)
+Default(install)
+
+	
+	
+Return('install')
diff --git a/zfuzz/afl_transforms/tools/laf/SConstruct b/zfuzz/afl_transforms/tools/laf/SConstruct
new file mode 100644
index 0000000000000000000000000000000000000000..c96332f0422ad5df0853931209219d9a2e20bc17
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/SConstruct
@@ -0,0 +1,6 @@
+
+
+
+env=Environment()
+Export('env')
+lib=SConscript("SConscript")
diff --git a/zfuzz/afl_transforms/tools/laf/laf.cpp b/zfuzz/afl_transforms/tools/laf/laf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8f94168a43117438a28504bb464530efcbc59aea
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/laf.cpp
@@ -0,0 +1,464 @@
+/***************************************************************************
+ * Copyright (c)  2018-2019  Zephyr Software LLC. All rights reserved.
+ *
+ * This software is furnished under a license and/or other restrictive
+ * terms and may be used and copied only in accordance with such terms
+ * and the inclusion of the above copyright notice. This software or
+ * any other copies thereof may not be provided or otherwise made
+ * available to any other person without the express written consent
+ * of an authorized representative of Zephyr Software LCC. Title to,
+ * ownership of, and all rights in the software is retained by
+ * Zephyr Software LCC.
+ *
+ * Zephyr Software LLC. Proprietary Information
+ *
+ * Unless otherwise specified, the information contained in this
+ * directory, following this legend, and/or referenced herein is
+ * Zephyr Software LLC. (Zephyr) Proprietary Information.
+ *
+ * CONTACT INFO
+ *
+ * E-mail: jwd@zephyr-software.com
+ **************************************************************************/
+
+#include "laf.hpp"
+
+using namespace std;
+using namespace IRDB_SDK;
+using namespace Laf;
+using namespace MEDS_Annotation;
+
+#define ALLOF(a) begin(a),end(a)
+#define FIRSTOF(a) (*(begin(a)))
+
+Laf_t::Laf_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, bool p_verbose)
+	:
+	Transform(p_variantIR),
+	m_dbinterface(p_dbinterface),
+	m_verbose(p_verbose)
+{
+	m_split_compare = true;
+	m_split_branch = true;
+
+	auto deep_analysis=DeepAnalysis_t::factory(getFileIR());
+	leaf_functions = deep_analysis->getLeafFunctions();
+	dead_registers = deep_analysis->getDeadRegisters();
+
+	m_blacklist.insert("init");
+	m_blacklist.insert("_init");
+	m_blacklist.insert("start");
+	m_blacklist.insert("_start");
+	m_blacklist.insert("fini");
+	m_blacklist.insert("_fini");
+	m_blacklist.insert("register_tm_clones");
+	m_blacklist.insert("deregister_tm_clones");
+	m_blacklist.insert("frame_dummy");
+	m_blacklist.insert("__do_global_ctors_aux");
+	m_blacklist.insert("__do_global_dtors_aux");
+	m_blacklist.insert("__libc_csu_init");
+	m_blacklist.insert("__libc_csu_fini");
+	m_blacklist.insert("__libc_start_main");
+	m_blacklist.insert("__gmon_start__");
+	m_blacklist.insert("__cxa_atexit");
+	m_blacklist.insert("__cxa_finalize");
+	m_blacklist.insert("__assert_fail");
+	m_blacklist.insert("free");
+	m_blacklist.insert("fnmatch");
+	m_blacklist.insert("readlinkat");
+	m_blacklist.insert("malloc");
+	m_blacklist.insert("calloc");
+	m_blacklist.insert("realloc");
+	m_blacklist.insert("argp_failure");
+	m_blacklist.insert("argp_help");
+	m_blacklist.insert("argp_state_help");
+	m_blacklist.insert("argp_error");
+	m_blacklist.insert("argp_parse");
+
+	m_skip_byte_cmp = 0;
+}
+
+RegisterSet_t Laf_t::getDeadRegs(Instruction_t* insn) const
+{
+	auto it = dead_registers -> find(insn);
+	if(it != dead_registers->end())
+		return it->second;
+	return RegisterSet_t();
+}
+
+// return intersection of candidates and allowed general-purpose registers
+RegisterSet_t Laf_t::getFreeRegs(const RegisterSet_t& candidates, const RegisterSet_t& allowed) const
+{
+	RegisterIDSet_t free_regs;
+	set_intersection(ALLOF(candidates), ALLOF(allowed), std::inserter(free_regs,free_regs.begin()));
+	return free_regs;
+}
+
+bool Laf_t::isBlacklisted(Function_t *p_func) const
+{
+	return (p_func->getName()[0] == '.' || 
+	        p_func->getName().find("@plt") != string::npos ||
+	        p_func->getName().find("__libc_") != string::npos ||
+	        m_blacklist.find(p_func->getName())!=m_blacklist.end());
+}
+
+void Laf_t::setSplitCompare(bool p_val)
+{
+	m_split_compare = p_val;
+}
+
+void Laf_t::setSplitBranch(bool p_val)
+{
+	m_split_branch = p_val;
+}
+
+bool Laf_t::getSplitCompare() const
+{
+	return m_split_compare;
+}
+
+bool Laf_t::getSplitBranch() const
+{
+	return m_split_branch;
+}
+
+bool Laf_t::hasLeafAnnotation(Function_t* fn) const
+{
+	auto it = leaf_functions -> find(fn);
+	return (it != leaf_functions->end());
+}
+
+int Laf_t::execute()
+{
+	if (getSplitCompare())
+		doSplitCompare();
+
+	return 1;
+}
+
+// handle comparisons of the form: 
+//                c:  cmp [rbp - 4], 0x12345678    or c:  cmp reg, 0x12345678
+//                jcc:  jne foobar
+void Laf_t::doSplitCompare(Instruction_t* p_instr, bool p_honor_red_zone)
+{
+	const auto d_cp = DecodedInstruction_t::factory(p_instr);
+	const auto &d_c = *d_cp;
+
+	const auto immediate = d_c.getImmediate();
+	auto jcc = p_instr->getFallthrough();
+	const auto d_cbrp = DecodedInstruction_t::factory(jcc); 
+	const auto &d_cbr = *d_cbrp;
+	const auto is_jne = (d_cbr.getMnemonic() == "jne");
+	const auto is_je = !is_jne;
+	auto orig_jcc_fallthrough = jcc->getFallthrough();
+	auto orig_jcc_target = jcc->getTarget();
+	auto allowed_regs = RegisterSet_t({rn_RAX, rn_RBX, rn_RCX, rn_RDX, rn_R8, rn_R9, rn_R10, rn_R11, rn_R12, rn_R13, rn_R14, rn_R15});
+
+	cout << "found comparison: " << p_instr->getDisassembly() << " immediate: " << hex << immediate << " " << jcc->getDisassembly() << endl;
+
+	const auto dead_regs = getDeadRegs(p_instr);
+
+	if (d_c.getOperand(0)->isRegister())
+	{
+		const auto r = d_c.getOperand(0)->getString();
+		const auto reg = Register::getRegister(r);
+		allowed_regs.erase(reg);
+	}
+
+//	auto save_temp = true;
+	auto free_regs = getFreeRegs(dead_regs, allowed_regs);
+	auto free_reg = string(); 
+
+	if (free_regs.size() > 0)
+	{
+//		save_temp = false;
+		const auto first_free_register = FIRSTOF(free_regs);
+		free_regs.erase(first_free_register);
+		free_reg = registerToString(convertRegisterTo32bit(first_free_register));
+	}
+	
+	// for now, skip if no free register
+	if (free_regs.size() == 0)
+	{
+		cout << "no free register, skipping: " << p_instr->getBaseID() << ": " << p_instr->getDisassembly() << endl;
+		return;
+	}
+
+	if (p_honor_red_zone)
+		p_instr = insertAssemblyBefore(p_instr, "lea rsp, [rsp-128]");
+
+	string s;
+
+	if (is_jne)
+		cout << "is jump not equal" << endl;
+	else
+		cout << "is jump equal" << endl;
+
+	auto byte0 = immediate >> 24;	              // high byte
+	auto byte1 = (immediate&0xff0000) >> 16;	
+	auto byte2 = (immediate&0xff00) >> 8;	
+	auto byte3 = immediate&0xff;	              // low byte
+
+	if (byte0 == 0x0 && byte1 == 0x0 && byte2 == 0x0)
+	{
+		cout << "skip as immediate is only 1 byte: 0x" << immediate << endl;
+		return;
+	}
+
+	cout <<"    bytes: 0x" << hex << byte0 << byte1 << byte2 << byte3 << endl;
+
+
+	auto init_sequence = string();
+
+	if (d_c.getOperand(0)->isRegister())
+	{
+		// cmp eax, 0x12345678
+		stringstream ss;
+		ss << "mov " << free_reg << ", " << d_c.getOperand(0)->getString();
+		init_sequence = ss.str();
+	}
+	else
+	{
+		// cmp dword [rbp - 4], 0x12345678 
+		const auto memopp = d_c.getOperand(0);
+		const auto &memop = *memopp;
+		init_sequence = "mov " + free_reg + ", dword [ " + memop.getString() + " ]";
+	}
+
+	// @todo: save/restore free register r15d 
+	cout << "decompose sequence: assume free register: " << free_reg << endl;
+	cout << "init sequence is: " << init_sequence << endl;
+
+
+/*
+		mov eax, dword [rbp - 4]
+		sar eax, 0x18
+		cmp eax, 0x12
+		jne j
+*/
+	stringstream ss;
+	auto t = (Instruction_t*) NULL;
+
+	s = init_sequence;
+	getFileIR()->registerAssembly(p_instr, s);
+	cout << s << endl;
+
+	s = "sar " + free_reg + ", 0x18";
+	t = insertAssemblyAfter(p_instr, s);
+	cout << s << endl;
+
+	ss.str("");
+	ss << "cmp " << free_reg << ", 0x" << hex << byte0;
+	s = ss.str();
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	s = "jne 0";
+	t = insertAssemblyAfter(t, s);
+	if (is_je) {
+		t->setTarget(orig_jcc_fallthrough);
+		cout << "target: original fallthrough ";
+	}
+	else {
+		t->setTarget(orig_jcc_target);
+		cout << "target: original target ";
+	}
+
+	cout << s << endl;
+
+/*
+		mov eax, dword [rbp - 4]
+		and eax, 0xff0000
+		sar eax, 0x10
+		cmp eax, 0x34
+		jne xxx
+*/
+	s = init_sequence;
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	s = "and " + free_reg + ", 0xff0000";
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	s = "sar " + free_reg + ", 0x10";
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	ss.str("");
+	ss << "cmp " << free_reg << ", 0x" << hex << byte1;
+	s = ss.str();
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	s = "jne 0";
+	t = insertAssemblyAfter(t, s);
+	if (is_je) {
+		t->setTarget(orig_jcc_fallthrough);
+		cout << "target: original fallthrough ";
+	}
+	else {
+		t->setTarget(orig_jcc_target);
+		cout << "target: original target ";
+	}
+	cout << s << endl;
+
+/*
+		mov    eax,DWORD PTR [rbp-0x4]
+		and    eax,0xff00
+		sar    eax,0x8
+		cmp    eax,0x56
+		jne    xxx
+*/
+	s = init_sequence;
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	s = "and " + free_reg + ", 0xff00";
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	s = "sar " + free_reg + ", 0x8";
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	ss.str("");
+	ss << "cmp " << free_reg << ", 0x" << hex << byte2;
+	s = ss.str();
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	s = "jne 0";
+	t = insertAssemblyAfter(t, s);
+	if (is_je) {
+		t->setTarget(orig_jcc_fallthrough);
+		cout << "target: original fallthrough ";
+	}
+	else {
+		t->setTarget(orig_jcc_target);
+		cout << "target: original target ";
+	}
+	cout << s << endl;
+
+/*
+  4005e4:	8b 45 fc             	mov    eax,DWORD PTR [rbp-0x4]
+  4005e7:	0f b6 c0             	movzx  eax,al
+  4005ea:	83 f8 78             	cmp    eax,0x78
+  4005ed:	75 07                	jne    4005f6 <main+0x80>
+*/
+	s = init_sequence;
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	s = "and " + free_reg + ", 0xff";
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	ss.str("");
+	ss << "cmp " << free_reg << ", 0x" << hex << byte3;
+	s = ss.str();
+	t = insertAssemblyAfter(t, s);
+	cout << s << endl;
+
+	if (p_honor_red_zone)
+		t = insertAssemblyAfter(t, "lea rsp, [rsp+128]");
+
+	if (is_je)
+		s = "je 0";
+	else
+		s = "jne 0";
+	t = insertAssemblyAfter(t, s);
+	t->setTarget(orig_jcc_target);
+	t->setFallthrough(orig_jcc_fallthrough);
+	cout << "target: original target   fallthrough: original fallthrough ";
+	cout << s << endl;
+
+}
+
+int Laf_t::doSplitCompare()
+{
+/*
+	// look for cmp against constant
+0000000000400526 <main>:
+  400535:	81 7d fc 78 56 34 12 	cmp    DWORD PTR [rbp-0x4],0x12345678
+  40053c:	75 0a                	jne    400548 <main+0x22>
+  40054e:	c3                   	ret    
+
+	// decompose into series of 1-byte comparisons
+  4005b9:	8b 45 fc             	mov    eax,DWORD PTR [rbp-0x4]
+  4005bc:	c1 f8 18             	sar    eax,0x18
+  4005bf:	83 f8 12             	cmp    eax,0x12
+  4005c2:	75 32                	jne    4005f6 <main+0x80>
+  4005c4:	8b 45 fc             	mov    eax,DWORD PTR [rbp-0x4]
+  4005c7:	25 00 00 ff 00       	and    eax,0xff0000
+  4005cc:	c1 f8 10             	sar    eax,0x10
+  4005cf:	83 f8 34             	cmp    eax,0x34
+  4005d2:	75 22                	jne    4005f6 <main+0x80>
+  4005d4:	8b 45 fc             	mov    eax,DWORD PTR [rbp-0x4]
+  4005d7:	25 00 ff 00 00       	and    eax,0xff00
+  4005dc:	c1 f8 08             	sar    eax,0x8
+  4005df:	83 f8 56             	cmp    eax,0x56
+  4005e2:	75 12                	jne    4005f6 <main+0x80>
+  4005e4:	8b 45 fc             	mov    eax,DWORD PTR [rbp-0x4]
+  4005e7:	0f b6 c0             	movzx  eax,al
+  4005ea:	83 f8 78             	cmp    eax,0x78
+  4005ed:	75 07                	jne    4005f6 <main+0x80>
+  4005ef:	b8 01 00 00 00       	mov    eax,0x1
+  4005f4:	eb 05                	jmp    4005fb <main+0x85>
+  4005f6:	b8 00 00 00 00       	mov    eax,0x0
+  4005fb:	c9                   	leave  
+  4005fc:	c3                   	ret    
+*/
+
+	auto to_split_compare = vector<Instruction_t*>(); 
+	for(auto func : getFileIR()->getFunctions())
+	{
+		if (isBlacklisted(func))
+			continue;
+
+		 for(auto i : func->getInstructions())
+		 {
+			const auto dp = DecodedInstruction_t::factory(i);
+			const auto &d = *dp;
+			if (d.getMnemonic()!="cmp") continue;
+			if (d.getOperands().size()!=2) continue;
+			if (!d.getOperand(1)->isConstant()) continue;
+			if (d.getOperand(0)->getArgumentSizeInBytes()!=4) continue;
+			if (!i->getFallthrough()) continue;
+			const auto fp = DecodedInstruction_t::factory(i->getFallthrough());
+			const auto &f = *fp;
+			if (f.getMnemonic() != "je" && f.getMnemonic() !="jeq" && f.getMnemonic() !="jne") continue;
+			
+			// these values are easy for fuzzer to guess
+			const auto imm = d.getImmediate();
+			if (imm == 0 || imm == 1 || imm == -1 || imm == 0xff || imm == 0xffff)
+				continue;
+
+			// nothing to split if it's just a 1-byte compare
+			const auto byte0 = imm >> 24;	              // high byte
+			const auto byte1 = (imm&0xff0000) >> 16;	
+			const auto byte2 = (imm&0xff00) >> 8;	
+//			const auto byte3 = imm&0xff;	              // low byte
+			const auto byteCmp = (byte0 == 0x0 && byte1 == 0x0 && byte2 == 0x0);
+			if (byteCmp)
+			{
+				m_skip_byte_cmp++;
+				continue;
+			}
+
+			// we now have a cmp instruction to decompose
+			if (d.getOperand(0)->isRegister() || d.getOperand(0)->isMemory())
+				to_split_compare.push_back(i);
+		};
+
+	};
+
+	// transform each comparison that needs to be decomposed
+	for(auto c : to_split_compare)
+	{
+		auto honorRedZone = true;
+		honorRedZone = hasLeafAnnotation(c->getFunction());
+		doSplitCompare(c, honorRedZone);
+	}
+
+	return 1;	 // true means success
+}
diff --git a/zfuzz/afl_transforms/tools/laf/laf.hpp b/zfuzz/afl_transforms/tools/laf/laf.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1a2f7b408267e8d5833e9197a0a41e106203986d
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/laf.hpp
@@ -0,0 +1,50 @@
+#ifndef _ZAFL_LAF_H
+#define _ZAFL_LAF_H
+
+#include <memory>
+
+#include <irdb-core>
+#include <irdb-transform>
+#include <irdb-util>
+#include <irdb-deep>
+#include <libMEDSAnnotation.h>
+
+namespace Laf
+{
+	using RegisterSet_t = IRDB_SDK::RegisterIDSet_t;
+// the actual transform.
+class Laf_t : public IRDB_SDK::Transform
+{
+public:
+	// explicitly disable default and copy constructors
+	Laf_t() = delete;
+	Laf_t(const Laf::Laf_t&) = delete;
+	Laf_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, bool p_verbose=false);
+	int execute();
+	void setSplitCompare(bool);
+	void setSplitBranch(bool);
+	bool getSplitCompare() const;
+	bool getSplitBranch() const;
+
+private:
+	RegisterSet_t getDeadRegs(IRDB_SDK::Instruction_t* insn) const;
+	RegisterSet_t getFreeRegs(const RegisterSet_t& candidates, const RegisterSet_t& allowed) const;
+	void doSplitCompare(IRDB_SDK::Instruction_t*, bool p_honor_red_zone);
+	int doSplitCompare();
+	bool isBlacklisted(IRDB_SDK::Function_t*) const;
+	bool hasLeafAnnotation(IRDB_SDK::Function_t* fn) const;
+
+private:
+	IRDB_SDK::pqxxDB_t &m_dbinterface;
+	std::unique_ptr<IRDB_SDK::FunctionSet_t>      leaf_functions;
+	std::unique_ptr<IRDB_SDK::DeadRegisterMap_t>  dead_registers;
+	bool m_verbose;
+	bool m_split_compare;
+	bool m_split_branch;
+	std::set<std::string> m_blacklist;
+	size_t m_skip_byte_cmp;
+};
+
+} 
+
+#endif
diff --git a/zfuzz/afl_transforms/tools/laf/laf_driver.cpp b/zfuzz/afl_transforms/tools/laf/laf_driver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f069b3bc9e65fe765ffc5192deec5e64cbd03d54
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/laf_driver.cpp
@@ -0,0 +1,163 @@
+/***************************************************************************
+ * Copyright (c)  2018  Zephyr Software LLC. All rights reserved.
+ *
+ * This software is furnished under a license and/or other restrictive
+ * terms and may be used and copied only in accordance with such terms
+ * and the inclusion of the above copyright notice. This software or
+ * any other copies thereof may not be provided or otherwise made
+ * available to any other person without the express written consent
+ * of an authorized representative of Zephyr Software LCC. Title to,
+ * ownership of, and all rights in the software is retained by
+ * Zephyr Software LCC.
+ *
+ * Zephyr Software LLC. Proprietary Information
+ *
+ * Unless otherwise specified, the information contained in this
+ * directory, following this legend, and/or referenced herein is
+ * Zephyr Software LLC. (Zephyr) Proprietary Information.
+ *
+ * CONTACT INFO
+ *
+ * E-mail: jwd@zephyr-software.com
+ **************************************************************************/
+
+#include <getopt.h>
+
+#include "laf.hpp"
+
+using namespace std;
+using namespace IRDB_SDK;
+using namespace Laf;
+
+void usage(char* name)
+{
+	cerr<<"Usage: "<<name<<" <variant_id>\n";
+	cerr<<"\t[--verbose | -v]                       Verbose mode                  "<<endl;
+	cerr<<"\t[--enable-split-compare | -c]          Enable split compare          "<<endl;
+	cerr<<"\t[--disable-split-compare | -c]         Disable split compare          "<<endl;
+	cerr<<"\t[--enable-split-branch | -b]           Enable split branch          "<<endl;
+	cerr<<"\t[--disable-split-branch | -B]          Disable split branch          "<<endl;
+	cerr<<"[--help,--usage,-?,-h]                   Display this message           "<<endl;
+}
+
+int main(int argc, char **argv)
+{
+	if(argc < 2)
+	{
+		usage(argv[0]);
+		exit(1);
+	}
+
+	string programName(argv[0]);
+	auto variantID = atoi(argv[1]);
+	auto verbose=false;
+	auto split_compare = true;
+	auto split_branch = true;
+
+	// Parse some options for the transform
+	static struct option long_options[] = {
+		{"verbose", no_argument, 0, 'v'},
+		{"help", no_argument, 0, 'h'},
+		{"usage", no_argument, 0, '?'},
+		{"enable-split-compare", no_argument, 0, 'c'},
+		{"disable-split-compare", no_argument, 0, 'C'},
+		{"enable-split-branch", no_argument, 0, 'b'},
+		{"disable-split-branch", no_argument, 0, 'B'},
+		{0,0,0,0}
+	};
+
+	const char* short_opts="v?h";
+	while(true)
+	{
+		int index = 0;
+		int c = getopt_long(argc, argv, short_opts, long_options, &index);
+		if(c == -1)
+			break;
+		switch(c)
+		{
+		case 'v':
+			verbose=true;
+			break;
+		case '?':
+		case 'h':
+			usage(argv[0]);
+			exit(1);
+			break;
+		case 'c':
+			split_compare=true;
+			break;
+		case 'C':
+			split_compare=false;
+			break;
+		case 'b':
+			split_branch=true;
+			break;
+		case 'B':
+			split_branch=false;
+			break;
+		default:
+			break;
+		}
+	}
+
+
+	/* setup the interface to the sql server */
+	auto pqxx_interface=pqxxDB_t::factory();
+	BaseObj_t::setInterface(pqxx_interface.get());
+
+	auto pidp=VariantID_t::factory(variantID);
+	assert(pidp->isRegistered()==true);
+
+	bool one_success = false;
+	for(set<File_t*>::iterator it=pidp->getFiles().begin();
+	        it!=pidp->getFiles().end();
+	        ++it)
+	{
+		File_t* this_file = *it;
+		auto firp = FileIR_t::factory(pidp.get(), this_file);
+
+		cout<<"Transforming "<<this_file->getURL()<<endl;
+
+		assert(firp && pidp);
+
+		try
+		{
+			Laf_t laf(*pqxx_interface, firp.get(), verbose);
+			laf.setSplitCompare(split_compare);
+			laf.setSplitBranch(split_branch);
+
+			int success=laf.execute();
+
+			if (success)
+			{
+				cout<<"Writing changes for "<<this_file->getURL()<<endl;
+				one_success = true;
+				firp->writeToDB();
+			}
+			else
+			{
+				cout<<"Skipping (no changes) "<<this_file->getURL()<<endl;
+			}
+		}
+		catch (DatabaseError_t pnide)
+		{
+			cerr << programName << ": Unexpected database error: " << pnide << "file url: " << this_file->getURL() << endl;
+			exit(1);
+		}
+		catch (...)
+		{
+			cerr << programName << ": Unexpected error file url: " << this_file->getURL() << endl;
+			exit(1);
+		}
+	} // end file iterator
+
+	// if any transforms for any files succeeded, we commit
+	if (one_success)
+	{
+		cout<<"Commiting changes...\n";
+		pqxx_interface->commit();
+	}
+
+	return 0;
+}
+
diff --git a/zfuzz/afl_transforms/tools/laf/test/Makefile b/zfuzz/afl_transforms/tools/laf/test/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..b023fbca013ef749c3e65eaa90032be7a0b36184
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/test/Makefile
@@ -0,0 +1,19 @@
+all: test0.laf test0.laf.zafl
+
+test_afl: test4.c
+	g++ test4.c -o $@
+
+test_afl.laf: test_afl
+	$(PSZ) test_afl $@ --critical-step laf=on -s meds_static=off -s rida=on
+
+test0.exe: test0.c
+	g++ test0.c -o $@
+
+test0.laf: test0.exe
+	$(PSZ) test0.exe $@ --critical-step laf=on -s meds_static=off -s rida=on
+
+test0.laf.zafl: test0.exe
+	zafl.sh $< $@ --enable-split-compare
+
+clean:
+	rm -fr peasoup_exec* *.o test_afl test_afl.laf test0.exe test0.laf a.out a.exe
diff --git a/zfuzz/afl_transforms/tools/laf/test/run_tests.sh b/zfuzz/afl_transforms/tools/laf/test/run_tests.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f0c5982a7ef9a6226774221e2334e7670431a4b6
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/test/run_tests.sh
@@ -0,0 +1,46 @@
+make clean test0.laf.zafl
+
+cleanup() {
+	rm test0.*.out
+	make clean
+}
+
+report_failure() {
+	echo "Test $1: FAIL"
+	cleanup
+	exit 1
+}
+
+report_success() {
+	echo "Test $1: PASS"
+
+}
+
+echo "1" | ./test0.exe > test0.exe.out
+echo "1" | ./test0.laf.zafl > test0.laf.out
+diff test0.exe.out test0.laf.out
+if [ ! $? -eq 0 ]; then
+	report_failure "equality"
+else
+	report_success "equality"
+fi
+
+echo "2" | ./test0.exe > test0.exe.out
+echo "2" | ./test0.laf.zafl > test0.laf.out
+if [ ! $? -eq 0 ]; then
+	report_failure "inequality"
+else
+	report_success "inequality"
+fi
+
+echo "4" | ./test0.exe > test0.exe.out
+echo "4" | ./test0.laf.zafl > test0.laf.out
+if [ ! $? -eq 0 ]; then
+	report_failure "inequality"
+else
+	report_success "inequality"
+fi
+
+echo Sanity tests passed
+cleanup
+exit 0
diff --git a/zfuzz/afl_transforms/tools/laf/test/test.c b/zfuzz/afl_transforms/tools/laf/test/test.c
new file mode 100644
index 0000000000000000000000000000000000000000..4fd335a46c6a027dcb3c170dcd0efe7009c8a1e5
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/test/test.c
@@ -0,0 +1,12 @@
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+	int x = 0;
+	std::cin >> std::hex >> x;
+	if (x == 0x01000000)
+            abort();
+	return 0;
+}
diff --git a/zfuzz/afl_transforms/tools/laf/test/test0.c b/zfuzz/afl_transforms/tools/laf/test/test0.c
new file mode 100644
index 0000000000000000000000000000000000000000..a9f5dc637a3fbbb479b885b279af98547d16d79f
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/test/test0.c
@@ -0,0 +1,41 @@
+#include <unistd.h>
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAX_CHARS 1024
+
+// #define K 1234567
+#define K 2
+
+int half(int i) {
+	return i / 2;
+}
+
+int main(int argc, char **argv)
+{
+	int x;
+	volatile int y;
+	char buf[MAX_CHARS+1];
+
+	fgets(buf, MAX_CHARS, stdin);
+	x = atoi(buf);
+	if (x == K)  {
+		fprintf(stdout, "x(%d) is equal to K(%d)\n", x, K);
+	}
+
+	if (x != K) {
+		fprintf(stdout, "x(%d) is not equal to K(%d)\n", x, K);
+	}
+
+	y = half(x);
+	
+	if (y == K)  {
+		fprintf(stdout, "y(%d) is equal to K(%d)\n", y, K);
+	}
+
+	if (y != K) {
+		fprintf(stdout, "y(%d) is not equal to K(%d)\n", y, K);
+	}
+	return 0;
+}
diff --git a/zfuzz/afl_transforms/tools/laf/test/test2.c b/zfuzz/afl_transforms/tools/laf/test/test2.c
new file mode 100644
index 0000000000000000000000000000000000000000..6c3740ea211d420951c30be35f41b4aec7af32de
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/test/test2.c
@@ -0,0 +1,12 @@
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+	int x = 0;
+	std::cin >> std::hex >> x;
+	if (x != 0x01000000)
+            abort();
+	return 0;
+}
diff --git a/zfuzz/afl_transforms/tools/laf/test/test4.c b/zfuzz/afl_transforms/tools/laf/test/test4.c
new file mode 100644
index 0000000000000000000000000000000000000000..6b242c872436d39efba023459ed9922901d9c639
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/laf/test/test4.c
@@ -0,0 +1,20 @@
+#include <unistd.h>
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+	int x;
+
+	read(0, &x, 4);
+//	if (x == 33620225) // 0x02010101
+//	if (x == 3791716609) // 0xe2010101
+//	if (x == 16843057) 
+//	if (x == 16851249) 
+//		if (x == 0x7c3f) 
+	if (x == 0x237c3f) 
+//	if (x == 0x3f7c1234) 
+            abort();
+	return 0;
+}
diff --git a/zfuzz/afl_transforms/tools/zax/SConscript b/zfuzz/afl_transforms/tools/zax/SConscript
new file mode 100644
index 0000000000000000000000000000000000000000..31be205feb583a2da4f072e29648bd22bd2cf3ac
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/SConscript
@@ -0,0 +1,32 @@
+import os
+
+
+
+Import('env')
+
+# import and create a copy of the environment so we don't screw up anyone elses env.
+myenv=env.Clone()
+
+cpppath=''' 
+	 $IRDB_SDK/include 
+	 $SECURITY_TRANSFORMS_HOME/include
+	 $SMPSA_HOME/include
+	'''
+
+
+files=Glob( Dir('.').srcnode().abspath+"/*.cpp")
+
+
+pgm="zax.exe"
+
+LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
+LIBS=Split("stars "+ env.subst('$BASE_IRDB_LIBS')+ "  irdb-cfg irdb-util irdb-transform irdb-elfdep irdb-deep ") 
+myenv=myenv.Clone(CPPPATH=Split(cpppath))
+myenv.Append(CXXFLAGS = " -std=c++11 -Wall -g -fmax-errors=2 ")
+pgm=myenv.Program(pgm,  files,  LIBPATH=LIBPATH, LIBS=LIBS)
+install=myenv.Install("$SECURITY_TRANSFORMS_HOME/plugins_install/", pgm)
+Default(install)
+
+	
+	
+Return('install')
diff --git a/zfuzz/afl_transforms/tools/zax/SConstruct b/zfuzz/afl_transforms/tools/zax/SConstruct
new file mode 100644
index 0000000000000000000000000000000000000000..c96332f0422ad5df0853931209219d9a2e20bc17
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/SConstruct
@@ -0,0 +1,6 @@
+
+
+
+env=Environment()
+Export('env')
+lib=SConscript("SConscript")
diff --git a/zfuzz/afl_transforms/tools/zax/critical_edge_breaker.cpp b/zfuzz/afl_transforms/tools/zax/critical_edge_breaker.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f40b0071a9440be5a576da855eab87d3cb8dcfb
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/critical_edge_breaker.cpp
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * Copyright (c)  2018-2019  Zephyr Software LLC. All rights reserved.
+ *
+ * This software is furnished under a license and/or other restrictive
+ * terms and may be used and copied only in accordance with such terms
+ * and the inclusion of the above copyright notice. This software or
+ * any other copies thereof may not be provided or otherwise made
+ * available to any other person without the express written consent
+ * of an authorized representative of Zephyr Software LCC. Title to,
+ * ownership of, and all rights in the software is retained by
+ * Zephyr Software LCC.
+ *
+ * Zephyr Software LLC. Proprietary Information
+ *
+ * Unless otherwise specified, the information contained in this
+ * directory, following this legend, and/or referenced herein is
+ * Zephyr Software LLC. (Zephyr) Proprietary Information.
+ *
+ * CONTACT INFO
+ *
+ * E-mail: jwd@zephyr-software.com
+ **************************************************************************/
+
+#include <irdb-cfg>
+#include <irdb-transform>
+#include "critical_edge_breaker.hpp"
+
+using namespace std;
+using namespace IRDB_SDK;
+using namespace Zafl;
+
+CriticalEdgeBreaker_t::CriticalEdgeBreaker_t(IRDB_SDK::FileIR_t *p_IR, set<string> p_blacklist, const bool p_verbose) :
+	m_IR(p_IR),
+	m_blacklist(p_blacklist),
+	m_verbose(p_verbose),
+	m_extra_nodes(0)
+{
+	breakCriticalEdges();
+}
+
+unsigned CriticalEdgeBreaker_t::getNumberExtraNodes() const
+{
+	return m_extra_nodes;
+}
+
+// iterate over each function and break critical edges
+void CriticalEdgeBreaker_t::breakCriticalEdges()
+{
+	auto is_blacklisted = [this](const Function_t* f) -> bool
+		{
+		  const auto fname = f->getName();
+		  return (fname[0] == '.' || fname.find("@plt") != string::npos || m_blacklist.find(fname)!=m_blacklist.end());
+		};
+
+	for ( auto &f : m_IR->getFunctions() )
+	{
+		if (!f) continue;
+		if (is_blacklisted(f)) continue;
+
+		if (f->getEntryPoint())
+			m_extra_nodes += breakCriticalEdges(f);
+	}
+}
+
+//
+// break critical edges by inserting an afl-instrumented dummy node
+// if A --> B is a critical edge, break critical edge by adding C to yield:
+//         A --> C --> B
+//        
+unsigned CriticalEdgeBreaker_t::breakCriticalEdges(Function_t* p_func)
+{
+	auto cfgp = ControlFlowGraph_t::factory(p_func);
+	auto &cfg = *cfgp;
+
+	auto ceap = CriticalEdges_t::factory(cfg, false);
+	auto &cea = *ceap;
+	
+	const auto critical_edges = cea.getAllCriticalEdges();
+	auto num_critical_edges_instrumented = 0;
+
+	cout << endl;
+	cout << "Breaking critical edges for function: " << p_func->getName();
+	cout << " - " << critical_edges.size() << " critical edges detected" << endl;
+
+	if (m_verbose)
+	{
+		cout << "Original CFG: " << endl;
+		cout << cfg << endl;
+	}
+
+	for (const auto &edge : critical_edges)
+	{
+		auto source_block = get<0>(edge);
+		auto target_block = get<1>(edge);
+
+		auto last_instruction_in_source_block = source_block->getInstructions()[source_block->getInstructions().size()-1];
+		auto first_instruction_in_target_block = target_block->getInstructions()[0];
+
+		if (source_block->endsInConditionalBranch())
+		{
+			const auto func = last_instruction_in_source_block->getFunction();
+
+			if (last_instruction_in_source_block->getTarget() == first_instruction_in_target_block)
+			{
+				auto jmp=m_IR->addNewInstruction(nullptr,func);	
+				setInstructionAssembly(m_IR, jmp, "jmp 0", nullptr, first_instruction_in_target_block);
+				jmp->setComment("break_critical_edge_jmp");
+
+				last_instruction_in_source_block->setTarget(jmp);
+				num_critical_edges_instrumented++;
+			}
+			else if (last_instruction_in_source_block->getFallthrough() == first_instruction_in_target_block)
+			{
+				auto jmp=m_IR->addNewInstruction(nullptr,func);	
+				setInstructionAssembly(m_IR, jmp, "jmp 0", nullptr, first_instruction_in_target_block);
+				jmp->setComment("break_critical_edge_fallthrough");
+
+				last_instruction_in_source_block->setFallthrough(jmp);
+				num_critical_edges_instrumented++;
+			}
+		}
+	}
+
+
+	if (m_verbose)
+	{
+		m_IR->assembleRegistry();
+		cout << "Number critical edge instrumented: " << num_critical_edges_instrumented << endl;
+		auto post_cfgp = ControlFlowGraph_t::factory(p_func);
+		auto &post_cfg = *post_cfgp;
+		cout << "Post CFG: " << endl;
+		cout << post_cfg << endl;
+	}
+	return num_critical_edges_instrumented;
+}
+
+
diff --git a/zfuzz/afl_transforms/tools/zax/critical_edge_breaker.hpp b/zfuzz/afl_transforms/tools/zax/critical_edge_breaker.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..bbeeebcdd1e2f5ddb5b29b55ef4651dbbbd1bb7c
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/critical_edge_breaker.hpp
@@ -0,0 +1,33 @@
+#ifndef _LIBTRANSFORM_CRITICAL_EDGE_BREAKER_H
+#define _LIBTRANSFORM_CRITICAL_EDGE_BREAKER_H
+
+#include <irdb-core>
+
+namespace Zafl
+{
+	using namespace IRDB_SDK;
+
+	//
+	// Break critical edges
+	//
+	class CriticalEdgeBreaker_t
+	{
+		public:
+			CriticalEdgeBreaker_t(FileIR_t *p_variantIR, set<string> p_blacklist=set<string>(), const bool p_verbose=false);
+			unsigned getNumberExtraNodes() const;
+
+		protected:
+			void breakCriticalEdges();
+
+		private:
+			unsigned breakCriticalEdges(Function_t*);
+
+		private:
+			FileIR_t*          m_IR;
+			const set<string>  m_blacklist;       
+			const bool         m_verbose;
+			unsigned           m_extra_nodes;
+	};
+} 
+
+#endif
diff --git a/zfuzz/afl_transforms/tools/zax/test/test_context.c b/zfuzz/afl_transforms/tools/zax/test/test_context.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e43960a11c49a0d468c728879f8bb2619e70ca2
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/test/test_context.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+volatile int bar(int a)
+{
+	if (a == 2)
+		return 5;
+	else
+		return 3;
+}
+
+volatile int foo(int a)
+{
+	if (a==3)
+		return bar(a);
+	else
+		return bar(2);
+
+}
+
+volatile int bob(int a)
+{
+	a = bar(7);
+	if (a==2)
+		return 1;
+	else return 2;
+	
+}
+
+int main(int argc, char **argv)
+{
+	int x = foo(argc);
+	int y = bar(argc);
+	int z = bob(argc);
+	printf("out=%d\n", x+y+z);
+}
diff --git a/zfuzz/afl_transforms/tools/zax/test/test_context.sh b/zfuzz/afl_transforms/tools/zax/test/test_context.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7505a722b9b7c82cbbcaadc975e007deb7bea232
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/test/test_context.sh
@@ -0,0 +1,106 @@
+cd $(dirname $(realpath $0) )
+
+PUT=test_context.exe
+ZAFL_PUT="$PUT.zafl $PUT.zafl.context_sensitive"
+MYARG="a"
+
+log_msg()
+{
+	echo "TEST PASS: $1"
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	exit 1
+}
+
+check_afl()
+{
+	which afl-showmap >/dev/null 2>&1
+	if [ ! $? -eq 0 ]; then
+		log_error "AFL doesn't seem to be installed. Try: 'sudo apt install afl' before proceeding or download/build afl directly from source"
+	fi
+}
+
+build_one()
+{
+	local orig=$1
+	local zafl=$2
+	shift
+	shift
+	zafl.sh $orig $zafl $@
+	if [ $? -eq 0 ]; then
+		log_msg "build $zafl" 
+	else
+		log_error "build $zafl" 
+	fi
+}
+
+build_all()
+{
+	g++ test_context.c -o $PUT
+}
+
+zafl_all()
+{
+	for p in $*
+	do
+		build_one $p $p.zafl -v -t $p.analysis 
+		build_one $p $p.zafl.context_sensitive --enable-context-sensitivity function -v -t $p.analysis.context_sensitive
+	done
+}
+
+clean_all()
+{
+	rm -fr ${PUT}* 
+}
+
+verify_output()
+{
+	local arg=$1
+	shift
+	local orig_zafl=$1
+	shift
+	local all_configs=$*
+
+	./$orig_zafl $arg > $orig_zafl.output.orig
+
+	for p in $all_configs 
+	do
+		echo "Program under test: $p"
+		./${p} $arg > $p.output
+		diff $orig_zafl.output.orig $p.output
+		if [ ! $? -eq 0 ]; then
+			log_error "output verification failure: $p.output"
+		fi
+	done
+
+	log_msg "output verified for $orig_zafl"
+}
+
+clean_all
+check_afl
+
+build_all
+
+zafl_all $PUT
+verify_output $MYARG $PUT $ZAFL_PUT
+
+zafl_map=${PUT}.zafl.map
+afl-showmap -o $zafl_map -- ./${PUT}.zafl
+count_zafl=$(wc -l ${zafl_map} | cut -d' ' -f1)
+
+zafl_cs_map=${PUT}.zafl.map
+afl-showmap -o $zafl_cs_map -- ./${PUT}.zafl.context_sensitive
+count_zafl_cs=$(wc -l ${zafl_cs_map} | cut -d' ' -f1)
+
+# difference must be exactly 2
+let diff=$count_zafl_cs-$count_zafl
+if [ $diff -eq 2 ]; then
+	log_msg "context sensitive map has +2 entries over baseline zafl map"
+else
+	log_error "context sensitive map does not have expected number of entries (should be +2): map_size(zafl):$count_zafl map_size(zafl_context_sensitive):$count_zafl_cs"
+fi
+
+clean_all
diff --git a/zfuzz/afl_transforms/tools/zax/test/test_context_recursion.sh b/zfuzz/afl_transforms/tools/zax/test/test_context_recursion.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fd50dc643e03bac5d59dc831cbad7b926e6b6590
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/test/test_context_recursion.sh
@@ -0,0 +1,118 @@
+cd $(dirname $(realpath $0) )
+
+PUT=test_fib.exe
+ZAFL_PUT="$PUT.zafl $PUT.zafl.context_sensitive"
+MYARG=8
+
+log_msg()
+{
+	echo "TEST PASS: $1"
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	exit 1
+}
+
+check_afl()
+{
+	which afl-showmap >/dev/null 2>&1
+	if [ ! $? -eq 0 ]; then
+		log_error "AFL doesn't seem to be installed. Try: 'sudo apt install afl' before proceeding or download/build afl directly from source"
+	fi
+}
+
+build_one()
+{
+	local orig=$1
+	local zafl=$2
+	shift
+	shift
+	zafl.sh $orig $zafl $@
+	if [ $? -eq 0 ]; then
+		log_msg "build $zafl" 
+	else
+		log_error "build $zafl" 
+	fi
+}
+
+build_all()
+{
+	g++ test_fib.c -o $PUT
+}
+
+zafl_all()
+{
+	for p in $*
+	do
+		build_one $p $p.zafl -v -t $p.analysis 
+		build_one $p $p.zafl.context_sensitive --enable-context-sensitivity function -v -t $p.analysis.context_sensitive
+	done
+}
+
+clean_all()
+{
+	rm -fr ${PUT}* 
+}
+
+verify_output()
+{
+	local arg=$1
+	shift
+	local orig_zafl=$1
+	shift
+	local all_configs=$*
+
+	./$orig_zafl $arg > $orig_zafl.output.orig
+
+	for p in $all_configs 
+	do
+		echo "Program under test: $p"
+		./${p} $arg > $p.output
+		diff $orig_zafl.output.orig $p.output
+		if [ ! $? -eq 0 ]; then
+			log_error "output verification failure: $p.output"
+		fi
+	done
+
+	log_msg "output verified for $orig_zafl"
+}
+
+clean_all
+check_afl
+
+build_all
+
+zafl_all $PUT
+verify_output $MYARG $PUT $ZAFL_PUT
+
+zafl_map15=${PUT}.zafl.map
+afl-showmap -o $zafl_map15 -- ./${PUT}.zafl 15
+count_zafl15=$(wc -l ${zafl_map15} | cut -d' ' -f1)
+
+zafl_cs_map8=${PUT}.zafl.cs.map.8
+afl-showmap -o $zafl_cs_map8 -- ./${PUT}.zafl.context_sensitive 8
+count_zafl_cs8=$(wc -l ${zafl_cs_map8} | cut -d' ' -f1)
+
+zafl_cs_map20=${PUT}.zafl.cs.map.20
+afl-showmap -o $zafl_cs_map20 -- ./${PUT}.zafl.context_sensitive 20
+count_zafl_cs20=$(wc -l ${zafl_cs_map20} | cut -d' ' -f1)
+
+# make sure we have more entries with context sensitivity
+let diff=$count_zafl_cs8-$count_zafl15
+if [ $diff -gt 5 ]; then
+	log_msg "vanilla zafl with deep recursion should have fewer entries than context sensitive version"
+else
+	log_error "vanilla zafl with deep recursion should have fewer entries than context sensitive version"
+fi
+
+# make sure we don't blow out the map with deep recursion
+let diff=$count_zafl_cs20-$count_zafl_cs8
+if [ $diff -eq 0 ]; then
+	log_msg "recursion level of 8 or 20 should have same number of entries in the trace map"
+else
+	log_error "recursion level of 8 or 20 should have same number of entries in the trace map"
+fi
+
+clean_all
diff --git a/zfuzz/afl_transforms/tools/zax/test/test_fib.c b/zfuzz/afl_transforms/tools/zax/test/test_fib.c
new file mode 100644
index 0000000000000000000000000000000000000000..0c0e160652b2e2d3b89e8e715f9165f23d80791e
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/test/test_fib.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+volatile int fib(int a)
+{
+	if (a == 0) return 0;
+	if (a == 1) return 1;
+	if (a == 2) return 1;
+	return fib(a-1) + fib(a-2);
+}
+
+int main(int argc, char **argv)
+{
+	if (argc <= 1) return 1;
+	int x = atoi(argv[1]);
+	if (x < 0)
+		return 2;
+	if (x > 50)
+		return 3;
+	int f = fib(x);
+	printf("fibonacci(%d) = %d\n", x, f);
+}
diff --git a/zfuzz/afl_transforms/tools/zax/test/test_graph.sh b/zfuzz/afl_transforms/tools/zax/test/test_graph.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b87836f4ce045a87a7c87e62de011a850b842ab5
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/test/test_graph.sh
@@ -0,0 +1,148 @@
+cd $(dirname $(realpath $0) )
+
+PUT=test_mystrlen.exe
+# make arg 16 chars sharp as it falls on an afl boundary for the hit count
+MYARG="0123456789abcdef"
+
+PUT2=test_mystrlen2.exe
+MYARG2="0123456789abcdefaadsf"
+
+PUT3=test_running.exe
+MYARG3="000aaaaaaaa"
+MYARG3A="000aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+ZAFL_PUT="$PUT.zafl $PUT.zafl.c $PUT.zafl.g $PUT.zafl.d $PUT.zafl.d.g $PUT.zafl.c.d.g"
+ZAFL_PUT2="$PUT2.zafl $PUT2.zafl.c $PUT2.zafl.g $PUT2.zafl.d $PUT2.zafl.d.g $PUT2.zafl.c.d.g"
+ZAFL_PUT3="$PUT3.zafl $PUT3.zafl.c $PUT3.zafl.g $PUT3.zafl.d $PUT3.zafl.d.g $PUT3.zafl.c.d.g"
+
+log_msg()
+{
+	echo "TEST PASS: $1"
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	exit 1
+}
+
+check_afl()
+{
+	which afl-showmap >/dev/null 2>&1
+	if [ ! $? -eq 0 ]; then
+		log_error "AFL doesn't seem to be installed. Try: 'sudo apt install afl' before proceeding or download/build afl directly from source"
+	fi
+}
+
+build_one()
+{
+	local orig=$1
+	local zafl=$2
+	shift
+	shift
+	zafl.sh $orig $zafl $@
+	if [ $? -eq 0 ]; then
+		log_msg "build $zafl" 
+	else
+		log_error "build $zafl" 
+	fi
+}
+
+build_all()
+{
+	g++ test_mystrlen.cpp -o $PUT
+	g++ test_mystrlen2.cpp -o $PUT2
+	g++ test_running.cpp -o $PUT3
+}
+
+zafl_all()
+{
+	for p in $*
+	do
+		build_one $p $p.zafl -v -t $p.analysis 
+		build_one $p $p.zafl.c -c -v -t $p.analysis.c
+		build_one $p $p.zafl.g -g -v -t $p.analysis.g
+		build_one $p $p.zafl.d -d -v -t $p.analysis.d
+		build_one $p $p.zafl.d.g -d -g -v -t $p.analysis.d.g
+		build_one $p $p.zafl.c.d.g -d -g -v -t $p.analysis.c.d.g
+	done
+}
+
+clean_all()
+{
+	rm -fr ${PUT}* ${PUT2}* ${PUT3}*
+}
+
+verify_output()
+{
+	local arg=$1
+	shift
+	local orig_zafl=$1
+	shift
+	local all_configs=$*
+
+	./$orig_zafl $arg > $orig_zafl.output.orig
+
+	for p in $all_configs 
+	do
+		echo "Program under test: $p"
+		./${p} $arg > $p.output
+		diff $orig_zafl.output.orig $p.output
+		if [ ! $? -eq 0 ]; then
+			log_error "output verification failure: $p.output"
+		fi
+	done
+
+	log_msg "output verified for $orig_zafl"
+}
+
+verify_afl_map()
+{
+	local arg=$1
+	shift
+	local orig_zafl=$1
+	shift
+	local all_configs=$*
+	for p in $all_configs
+	do
+		echo "Computing trace maps for input $MYARG"
+		afl-showmap -o $p.map -- ./$p $arg
+		cut -d':' -f2 $p.map | sort -r | head -n 1 > $p.max_count
+	done
+
+	for p in $all_configs
+	do
+		diff $orig_zafl.zafl.max_count $p.max_count >/dev/null 2>&1
+		if [ $? -eq 0 ]; then
+			max=$(cat $orig_zafl.zafl.max_count)
+			log_msg "maximum afl edge value for $orig_zafl.zafl and $p match ($max)"
+		else
+			echo -n "Maximum count for $orig_zafl: "
+			cat $orig_zafl.zafl.max_count
+			echo -n "Maximum count for $p: "
+			cat $p.max_count
+			log_error "maximum afl edge value does not match for $orig_zafl.zafl and $p"
+		fi
+	done
+}
+
+clean_all
+check_afl
+
+build_all
+
+zafl_all $PUT
+verify_output $MYARG $PUT $ZAFL_PUT
+verify_afl_map $MYARG $PUT $ZAFL_PUT
+
+zafl_all $PUT2
+verify_output $MYARG2 $PUT2 $ZAFL_PUT2
+verify_afl_map $MYARG2 $PUT2 $ZAFL_PUT2
+
+zafl_all $PUT3
+verify_output $MYARG3 $PUT3 $ZAFL_PUT3
+verify_afl_map $MYARG3 $PUT3 $ZAFL_PUT3
+verify_output $MYARG3A $PUT3 $ZAFL_PUT3
+verify_afl_map $MYARG3A $PUT3 $ZAFL_PUT3
+
+clean_all
diff --git a/zfuzz/afl_transforms/tools/zax/test/test_mystrlen.cpp b/zfuzz/afl_transforms/tools/zax/test/test_mystrlen.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5bc0f485305ef44047245817145633b28a3b9ace
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/test/test_mystrlen.cpp
@@ -0,0 +1,34 @@
+#include <iostream>
+
+using namespace std;
+
+int x = 0;
+
+volatile int identity(int y)
+{
+	if (y % 39 == 0)
+		x = 1;
+	else
+		x = 2;
+	return y;
+}
+
+size_t my_strlen(char *arg)
+{
+	int count = 0;
+	while (*arg!='\0')
+	{
+		count++;
+		arg++;
+		count = identity(count);
+	}
+
+	return count;
+}
+
+int main(int argc, char **argv)
+{
+	if (argc > 1)
+		cout << "length= " << my_strlen(argv[1]) << endl;
+	cout << "x= " << x << endl;
+}
diff --git a/zfuzz/afl_transforms/tools/zax/test/test_mystrlen2.cpp b/zfuzz/afl_transforms/tools/zax/test/test_mystrlen2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..559b408cc8fa15e8d90327800cb765bdb994d483
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/test/test_mystrlen2.cpp
@@ -0,0 +1,34 @@
+#include <iostream>
+
+using namespace std;
+
+int x = 0;
+
+volatile int identity(int x)
+{
+	return x;
+}
+
+size_t my_strlen(char *arg)
+{
+	int count = 0;
+	while (*arg!='\0')
+	{
+		if (count % 99)
+			x *= count;
+		else if (count % 98)
+			x += count;
+
+		count++;
+		arg++;
+	}
+
+	return count;
+}
+
+int main(int argc, char **argv)
+{
+	if (argc > 1)
+		cout << "length: " << my_strlen(argv[1]) << endl;
+	cout << "x: " << x <<endl;
+}
diff --git a/zfuzz/afl_transforms/tools/zax/test/test_running.cpp b/zfuzz/afl_transforms/tools/zax/test/test_running.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..59d04bd247e560f9777f296925352115434c43d1
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/test/test_running.cpp
@@ -0,0 +1,34 @@
+#include <iostream>
+#include <string.h>
+
+using namespace std;
+
+int num_running_a = 0;
+
+size_t my_strlen(char *arg)
+{
+	int i = 0;
+	bool a_detected = false;
+
+	while(arg[i])
+	{
+		if (arg[i]=='a') {
+				num_running_a++;
+				a_detected = true;
+		}
+		else{
+			if (a_detected)
+				goto out;
+		}
+		i++;
+	}
+out:
+	return i;
+}
+
+int main(int argc, char **argv)
+{
+	if (argc > 1)
+		cout << "length: " << my_strlen(argv[1]) << endl;
+	cout << "num running a: " << num_running_a <<endl;
+}
diff --git a/zfuzz/afl_transforms/tools/zax/zax.cpp b/zfuzz/afl_transforms/tools/zax/zax.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bc1fe097a97691ada8dacc1c020743339303119c
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/zax.cpp
@@ -0,0 +1,410 @@
+/***************************************************************************
+ * Copyright (c)  2018-2019  Zephyr Software LLC. All rights reserved.
+ *
+ * This software is furnished under a license and/or other restrictive
+ * terms and may be used and copied only in accordance with such terms
+ * and the inclusion of the above copyright notice. This software or
+ * any other copies thereof may not be provided or otherwise made
+ * available to any other person without the express written consent
+ * of an authorized representative of Zephyr Software LCC. Title to,
+ * ownership of, and all rights in the software is retained by
+ * Zephyr Software LCC.
+ *
+ * Zephyr Software LLC. Proprietary Information
+ *
+ * Unless otherwise specified, the information contained in this
+ * directory, following this legend, and/or referenced herein is
+ * Zephyr Software LLC. (Zephyr) Proprietary Information.
+ *
+ * CONTACT INFO
+ *
+ * E-mail: jwd@zephyr-software.com
+ **************************************************************************/
+
+#include "zax.hpp"
+
+using namespace std;
+using namespace IRDB_SDK;
+using namespace Zafl;
+
+Zax_t::Zax_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, string p_forkServerEntryPoint, set<string> p_exitPoints, bool p_use_stars, bool p_autozafl) : ZaxBase_t(p_dbinterface, p_variantIR, p_forkServerEntryPoint, p_exitPoints, p_use_stars, p_autozafl)
+{
+}
+
+/*
+ * Return random block id
+ * Try 100x to avoid duplicate ids
+ */
+ZaflBlockId_t Zax_t::getBlockId(const unsigned p_max) 
+{
+       auto counter = 0;
+       auto blockid = 0;
+
+       // only try getting new block id 100 times
+       // avoid returning duplicate if we can help it
+       while (counter++ < 100) {
+               blockid = rand() % p_max; 
+               if (m_used_blockid.find(blockid) == m_used_blockid.end())
+               {
+                       m_used_blockid.insert(blockid);
+                       return blockid;
+               }
+       }
+       return blockid;
+}
+ 
+/*
+	Original afl instrumentation:
+	        block_id = <random>;
+	        zafl_trace_bits[zafl_prev_id ^ block_id]++;
+		zafl_prev_id = block_id >> 1;     
+
+	CollAfl optimization when (#predecessors==1) (goal of CollAfl is to reduce collisions):
+	        block_id = <some unique value for this block>
+	        zafl_trace_bits[block_id]++;
+		zafl_prev_id = block_id >> 1;     
+*/
+void Zax_t::instrumentBasicBlock(BasicBlock_t *p_bb, const bool p_honorRedZone, const bool p_collafl_optimization)
+{
+	char buf[8192];
+	auto live_flags = true;
+	char *reg_temp = NULL;
+	char *reg_temp32 = NULL;
+	char *reg_temp16 = NULL;
+	char *reg_trace_map = NULL;
+	char *reg_prev_id = NULL;
+	char *reg_context = NULL;
+	char *reg_context16 = NULL;
+	auto save_temp = true;
+	auto save_trace_map = true;
+	auto save_prev_id = true;
+	auto save_context = (getContextSensitivity() != ContextSensitivity_None) ? true : false;
+	auto block_record=BBRecord_t();
+
+	// if fixed address, only need 1 register
+	// if not, need up to 4 registers
+	auto num_free_regs_desired = save_context ? 4 : 3;
+	if (useFixedAddresses())
+		num_free_regs_desired = 1; 
+
+	auto instr = getInstructionToInstrument(p_bb, num_free_regs_desired);
+	if (!instr) throw;
+
+	// don't try to reserve the trace_map reg if we aren't using it.
+	if(useFixedAddresses())  
+	{
+		save_trace_map=false;
+		save_prev_id=false;
+		save_context=false;
+	}
+
+	block_record.push_back(instr);
+
+	// If we are using stars, try to assign rax, rcx, and rdx to their 
+	// most desireable position in the instrumentation.
+	if (m_use_stars) 
+	{
+		auto regset = getDeadRegs(instr);
+		live_flags = regset.find(IRDB_SDK::rn_EFLAGS)==regset.end();
+
+		const auto allowed_regs = RegisterSet_t({rn_RAX, rn_RBX, rn_RCX, rn_RDX, rn_R8, rn_R9, rn_R10, rn_R11, rn_R12, rn_R13, rn_R14, rn_R15});
+		auto free_regs = getFreeRegs(regset, allowed_regs);
+
+		for (auto r : regset)
+		{
+			if (r == rn_RAX)
+			{
+				reg_temp = strdup("rax"); reg_temp32 = strdup("eax"); reg_temp16 = strdup("ax");
+				save_temp = false;
+				free_regs.erase(r);
+			}
+			else if (r == rn_RCX && save_trace_map)
+			{
+				reg_trace_map = strdup("rcx");
+				save_trace_map = false;
+				free_regs.erase(r);
+			}
+			else if (r == rn_RDX && save_prev_id)
+			{
+				reg_prev_id = strdup("rdx");
+				save_prev_id = false;
+				free_regs.erase(r);
+			}
+			else if (r == rn_R8 && save_context)
+			{
+				reg_context=strdup("r8");
+				reg_context16=strdup("r8w");
+				save_context = false;
+				free_regs.erase(r);
+			}
+		}
+
+		// if we failed to do the assignment, check for any other register to fill the assignment.
+		if (save_temp && free_regs.size() >= 1) 
+		{
+			auto r = *free_regs.begin(); 
+			auto r32 = convertRegisterTo32bit(r); assert(isValidRegister(r32));
+			auto r16 = convertRegisterTo16bit(r); assert(isValidRegister(r16));
+			reg_temp = strdup(registerToString(r).c_str());
+			reg_temp32 = strdup(registerToString(r32).c_str());
+			reg_temp16 = strdup(registerToString(r16).c_str());
+			save_temp = false;
+			free_regs.erase(r);
+		}
+
+		if (save_trace_map && free_regs.size() >= 1) 
+		{
+			auto r = *free_regs.begin();
+			reg_trace_map = strdup(registerToString(r).c_str());
+			save_trace_map = false;
+			free_regs.erase(r);
+		}
+
+		if (save_prev_id && free_regs.size() >= 1) 
+		{
+			auto r = *free_regs.begin();
+			reg_prev_id = strdup(registerToString(r).c_str());
+			save_prev_id = false;
+			free_regs.erase(r);
+		}
+
+		if (getContextSensitivity() != ContextSensitivity_None)
+		{
+			if (save_context && free_regs.size() >= 1)
+			{
+				auto r = *free_regs.begin();
+				auto r16 = convertRegisterTo16bit(r);
+				reg_context = strdup(registerToString(r).c_str());
+				reg_context16 = strdup(registerToString(r16).c_str());
+				save_context = false;
+				free_regs.erase(r);
+			}
+		}
+	}
+
+	// In the event we couldn't find a free register, or we aren't using stars
+	// to identify free registers, use the default registers.  We will save and
+	// restore these later.
+	if (!reg_temp)      reg_temp      = strdup("rax");
+	if (!reg_temp32)    reg_temp32    = strdup("eax");
+	if (!reg_temp16)    reg_temp16    = strdup("ax");
+	if (!reg_trace_map) reg_trace_map = strdup("rcx");
+	if (!reg_prev_id)   reg_prev_id   = strdup("rdx");
+	if (!reg_context)   reg_context   = strdup("r8");
+	if (!reg_context16) reg_context16   = strdup("r8w");
+
+	if (m_verbose)
+	{
+		cout << "save_temp: " << save_temp << " save_trace_map: " << save_trace_map << " save_prev_id: " << save_prev_id << " live_flags: " << live_flags << endl;
+		cout << "reg_temp: " << reg_temp << " " << reg_temp32 << " " << reg_temp16 
+			<< " reg_trace_map: " << reg_trace_map
+			<< " reg_prev_id: " << reg_prev_id
+			<< " reg_context: " << reg_context << endl;
+	}
+
+	// warning: first instrumentation must use insertAssemblyBefore
+	// others use insertAssemblyAfter.
+	// we declare a macro-like lambda function to do the lifting for us.
+	auto inserted_before = false;
+	auto tmp = instr;
+	const auto do_insert=[&](const string& insn_str) -> void
+		{
+			if (inserted_before)
+			{
+				tmp = insertAssemblyAfter(tmp, insn_str);
+				block_record.push_back(tmp);
+			}
+			else
+			{
+				const auto orig = insertAssemblyBefore(tmp, insn_str);
+				inserted_before = true;
+				block_record.push_back(orig);
+			}
+		};
+
+	// get some IDs which we can use as to generate custom labels
+	const auto blockid = getBlockId();
+	const auto labelid = getLabelId(); 
+
+	if (m_verbose)
+	{
+		cout << "labelid: " << labelid << " baseid: " << instr->getBaseID() << " address: 0x" 
+		     << hex << instr->getAddress()->getVirtualOffset() << dec << " instruction: " 
+		     << instr->getDisassembly();
+	}
+
+	// Emit the instrumentation register-saving phase.
+	// Omit saving any registers we don't need to save because we
+	// were able to locate a free register.
+	if (p_honorRedZone)  do_insert("lea rsp, [rsp-128]");
+	if (save_temp)       do_insert("push rax");
+	if (save_trace_map)  do_insert("push rcx");
+	if (save_prev_id)    do_insert("push rdx");
+	if (save_context)    do_insert("push r8");
+	if (live_flags)      do_insert("pushf");
+
+	const auto live_flags_str = live_flags ? "live" : "dead"; 
+	if (m_verbose) cout << "   flags are "  << live_flags_str << endl;
+
+
+/*
+   0:   mov    rdx,QWORD PTR [rip+0x0]        # load previous block id.
+   7:   mov    rcx,QWORD PTR [rip+0x0]        # load trace map address.
+
+<no collafl optimization>
+   e:   	movzx  eax,WORD PTR [rdx]     # hash prev-block-id with this-block id (0x1234)
+  11:   	xor    ax,0x1234                              
+  15:   	movzx  eax,ax                                
+
+<collafl-style optimization>
+<noaddr>	mov    eax, <blockid>	     # faster hash -- ignore previous id.
+
+  18:   add    rax,QWORD PTR [rcx]           # generate address of trace map to bump 
+  ib:   add    BYTE PTR [rax],0x1            # bump the entr
+  1e:   mov    eax,0x91a                     # write this block ID back to the prev-id variable.  
+  23:   mov    WORD PTR [rdx],ax       
+*/	
+
+	// load the previous block ID.
+	//   0:   mov    rdx,QWORD PTR [rip+0x0]        # 7 <f+0x7>
+// FIXME:  Why are we doing this if we aren't bothering to hash the previous block ID?
+
+	if (!useFixedAddresses())
+	{
+		sprintf(buf, "P%d: mov  %s, QWORD [rel P%d]", labelid, reg_prev_id, labelid); // rdx
+		do_insert(buf);
+		create_got_reloc(getFileIR(), m_prev_id, tmp);
+	}
+
+	if (getContextSensitivity() != ContextSensitivity_None)
+	{
+		if (!useFixedAddresses())
+		{
+			sprintf(buf, "C%d: mov  %s, QWORD [rel C%d]", labelid, reg_context, labelid); 
+			do_insert(buf);
+			create_got_reloc(getFileIR(), m_context_id, tmp);
+
+			sprintf(buf,"mov %s, [%s]", reg_context, reg_context);
+			do_insert(buf);
+		}
+	}
+
+	// if we are using a variable address trace map, generate the address.
+	if(!useFixedAddresses())
+	{
+		//   7:   mov    rcx,QWORD PTR [rip+0x0]        # e <f+0xe>
+		sprintf(buf, "T%d: mov  %s, QWORD [rel T%d]", labelid, reg_trace_map, labelid); 
+		do_insert(buf);
+		create_got_reloc(getFileIR(), m_trace_map, tmp);
+	}
+
+	// compute index into trace map
+	// do the calculation to has the previouus block ID with this block ID
+	// in the faster or slower fashion depending on the requested technique.
+	if (!p_collafl_optimization)
+	{
+		//   e:   movzx  eax,WORD PTR [rdx]                      
+		if (useFixedAddresses())
+		{
+			sprintf(buf,"movzx  %s,WORD [0x%lx]", reg_temp32, getFixedAddressPrevId());
+		}
+		else
+		{
+			sprintf(buf,"movzx  %s,WORD [%s]", reg_temp32, reg_prev_id);
+		}
+		do_insert(buf);
+
+		//  11:   xor    ax,0x1234                              
+		sprintf(buf, "xor   %s,0x%x", reg_temp16, blockid);
+		do_insert(buf);
+	
+		// hash with calling context value
+		if (getContextSensitivity() != ContextSensitivity_None)
+		{
+			if (useFixedAddresses())
+			{
+				sprintf(buf, "xor   %s,WORD [0x%lx]", reg_temp16, getFixedAddressContext());
+				do_insert(buf);
+			}
+			else
+			{
+				// xor ax, <context_id_register>
+				sprintf(buf, "xor   %s,%s", reg_temp16, reg_context16);
+				do_insert(buf);
+			}
+		}
+
+		//  15:   movzx  eax,ax                                
+		sprintf(buf,"movzx  %s,%s", reg_temp32, reg_temp16);
+		do_insert(buf);
+	}
+	else
+	{
+		// <noaddr> mov    rax, <blockid>
+		sprintf(buf,"mov   %s,0x%x", reg_temp, blockid);
+		do_insert(buf);
+	}
+
+	// write into the trace map.
+	if(useFixedAddresses())
+	{
+		// do it the fast way with the fixed-adresss trace map
+		//  1b:   80 00 01                add    BYTE PTR [rax],0x1                  
+		sprintf(buf,"add    BYTE [%s + 0x%lx],0x1", reg_temp, getFixedAddressMap());
+		do_insert(buf);
+	}
+	else
+	{
+		// do it the slow way with the variable-adresss trace map
+		//  18: add    rax,QWORD PTR [rcx]                  
+		sprintf(buf,"add    %s,QWORD [%s]", reg_temp, reg_trace_map);
+		do_insert(buf);
+
+		//  1b: add    BYTE PTR [rax],0x1                  
+		sprintf(buf,"add    BYTE [%s],0x1", reg_temp);
+		do_insert(buf);
+	}
+
+	// write out block id into zafl_prev_id for the next instrumentation.
+	//  1e:   mov    eax,0x91a                          
+	if (!p_collafl_optimization)
+	{
+		if (useFixedAddresses())
+		{
+			sprintf(buf, "mov   WORD [0x%lx], 0x%x", getFixedAddressPrevId(), blockid >> 1);
+			do_insert(buf);
+		}
+		else
+		{
+			sprintf(buf, "mov   %s, 0x%x", reg_temp32, blockid >> 1);
+			do_insert(buf);
+
+			// store prev_id
+			//  23:   mov    WORD PTR [rdx],ax       
+			sprintf(buf, "mov   WORD [%s], %s", reg_prev_id, reg_temp16);
+			do_insert(buf);
+		}
+	}
+
+	// finally, restore any flags/registers so that the program can execute.
+	if (live_flags)       do_insert("popf");
+	if (save_context)     do_insert("pop r8");
+	if (save_prev_id)     do_insert("pop rdx");
+	if (save_trace_map)   do_insert("pop rcx");
+	if (save_temp)        do_insert("pop rax");
+	if (p_honorRedZone)   do_insert("lea rsp, [rsp+128]");
+	
+	m_modifiedBlocks[blockid] = block_record;
+
+
+// FIXME: use strings instead of strdup and buffers everywhere.  
+// there is no chance the mallocs/frees in this function match properly.
+	free(reg_temp); 
+	free(reg_temp32);
+	free(reg_temp16);
+	free(reg_trace_map);
+	free(reg_prev_id);
+	free(reg_context);
+	free(reg_context16);
+}
+
diff --git a/zfuzz/afl_transforms/tools/zax/zax.hpp b/zfuzz/afl_transforms/tools/zax/zax.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9f281bc7faefe436b1f3570b3b653df3415eb836
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/zax.hpp
@@ -0,0 +1,30 @@
+#ifndef _LIBTRANSFORM_ZAX_H
+#define _LIBTRANSFORM_ZAX_H
+
+#include "zax_base.hpp"
+
+namespace Zafl
+{
+	//
+	// Implements afl-style edge coverage instrumentation
+	//
+	class Zax_t : public ZaxBase_t
+	{
+	public:
+		// explicitly disable default and copy constructors
+		Zax_t() = delete;
+		Zax_t(const Zafl::Zax_t&) = delete;
+		Zax_t(pqxxDB_t &p_dbinterface, FileIR_t *p_variantIR, string p_entry, set<string> p_exits, bool p_use_stars=false, bool p_autozafl=false);
+		virtual ~Zax_t() {};
+
+	protected:
+		virtual ZaflBlockId_t getBlockId(const unsigned p_maxid=0xFFFF);
+		virtual void instrumentBasicBlock(BasicBlock_t *p_bb, const bool p_hasLeafAnnotation, const bool p_collafl_optimization=false);
+
+	private:
+		set<ZaflBlockId_t>   m_used_blockid;  // internal bookkeeping to keep track of used block ids
+	};
+
+} 
+
+#endif
diff --git a/zfuzz/afl_transforms/tools/zax/zax_base.cpp b/zfuzz/afl_transforms/tools/zax/zax_base.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8cfb7655619d4977ddaecaea5d812a2885bff7ac
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/zax_base.cpp
@@ -0,0 +1,1299 @@
+/***************************************************************************
+ * Copyright (c)  2018-2019  Zephyr Software LLC. All rights reserved.
+ *
+ * This software is furnished under a license and/or other restrictive
+ * terms and may be used and copied only in accordance with such terms
+ * and the inclusion of the above copyright notice. This software or
+ * any other copies thereof may not be provided or otherwise made
+ * available to any other person without the express written consent
+ * of an authorized representative of Zephyr Software LCC. Title to,
+ * ownership of, and all rights in the software is retained by
+ * Zephyr Software LCC.
+ *
+ * Zephyr Software LLC. Proprietary Information
+ *
+ * Unless otherwise specified, the information contained in this
+ * directory, following this legend, and/or referenced herein is
+ * Zephyr Software LLC. (Zephyr) Proprietary Information.
+ *
+ * CONTACT INFO
+ *
+ * E-mail: jwd@zephyr-software.com
+ **************************************************************************/
+
+#include <stdlib.h>
+#include <string.h> 
+#include <algorithm>
+#include <cctype>
+#include <sstream>
+#include <fstream>
+#include <irdb-cfg>
+#include <irdb-transform>
+#include <irdb-elfdep>
+#include <irdb-deep>
+
+#include "zax_base.hpp"
+#include "critical_edge_breaker.hpp"
+
+using namespace std;
+using namespace IRDB_SDK;
+using namespace Zafl;
+
+#define ALLOF(a) begin(a),end(a)
+#define FIRSTOF(a) (*(begin(a)))
+
+void create_got_reloc(FileIR_t* fir, pair<DataScoop_t*,int> wrt, Instruction_t* i)
+{
+	(void)fir->addNewRelocation(i,wrt.second, "pcrel", wrt.first);
+}
+
+RegisterSet_t ZaxBase_t::getDeadRegs(Instruction_t* insn) const
+{
+	auto it = dead_registers -> find(insn);
+	if(it != dead_registers->end())
+		return it->second;
+	return RegisterSet_t();
+}
+
+// return intersection of candidates and allowed general-purpose registers
+RegisterSet_t ZaxBase_t::getFreeRegs(const RegisterSet_t& candidates, const RegisterSet_t& allowed) const
+{
+	RegisterIDSet_t free_regs;
+	set_intersection(ALLOF(candidates), ALLOF(allowed), std::inserter(free_regs,free_regs.begin()));
+	return free_regs;
+}
+
+bool ZaxBase_t::hasLeafAnnotation(Function_t* fn) const
+{
+	auto it = leaf_functions -> find(fn);
+	return (it != leaf_functions->end());
+}
+
+bool ZaxBase_t::BB_isPaddingNop(const BasicBlock_t *p_bb) const
+{
+	return p_bb->getInstructions().size()==1 && 
+	       p_bb->getPredecessors().size()==0 &&
+	       p_bb->getSuccessors().size()==1 &&
+	       p_bb->getInstructions()[0]->getDisassembly().find("nop")!=string::npos;
+}
+
+bool ZaxBase_t::BB_isPushJmp(const BasicBlock_t *p_bb) const
+{
+	return p_bb->getInstructions().size()==2 && 
+	       p_bb->getInstructions()[0]->getDisassembly().find("push")!=string::npos &&
+	       p_bb->getInstructions()[1]->getDisassembly().find("jmp")!=string::npos;
+}
+
+ZaxBase_t::ZaxBase_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, string p_forkServerEntryPoint, set<string> p_exitPoints, bool p_use_stars, bool p_autozafl)
+	:
+	Transform(p_variantIR),
+	m_dbinterface(p_dbinterface),
+	m_use_stars(p_use_stars),
+	m_autozafl(p_autozafl),
+	m_graph_optimize(false),
+	m_domgraph_optimize(false),
+	m_forkserver_enabled(true),
+	m_breakupCriticalEdges(false),
+	m_fork_server_entry(p_forkServerEntryPoint),
+	m_exitpoints(p_exitPoints)
+{
+	if (m_use_stars) {
+		cout << "Use STARS analysis engine" << endl;
+		auto deep_analysis=DeepAnalysis_t::factory(getFileIR());
+		leaf_functions = deep_analysis -> getLeafFunctions();
+		dead_registers = deep_analysis -> getDeadRegisters();
+	}
+
+	auto ed=ElfDependencies_t::factory(getFileIR());
+	if (p_autozafl)
+	{
+		cout << "autozafl library is on" << endl;
+		(void)ed->prependLibraryDepedencies("libautozafl.so");
+	}
+	else
+	{
+		cout << "autozafl library is off" << endl;
+		(void)ed->prependLibraryDepedencies("libzafl.so");
+	}
+
+	// bind to external symbols declared in libzafl.so
+	m_plt_zafl_initAflForkServer=ed->appendPltEntry("zafl_initAflForkServer");
+	m_trace_map = ed->appendGotEntry("zafl_trace_map");
+	m_prev_id = ed->appendGotEntry("zafl_prev_id");
+	m_context_id = ed->appendGotEntry("zafl_context");
+
+	// let's not instrument these functions ever
+	// see isBlacklisted() for other blacklisted functions
+	m_blacklist.insert("init");
+	m_blacklist.insert("_init");
+	m_blacklist.insert("start");
+	m_blacklist.insert("_start");
+	m_blacklist.insert("fini");
+	m_blacklist.insert("_fini");
+	m_blacklist.insert("register_tm_clones");
+	m_blacklist.insert("deregister_tm_clones");
+	m_blacklist.insert("frame_dummy");
+	m_blacklist.insert("__do_global_ctors_aux");
+	m_blacklist.insert("__do_global_dtors_aux");
+	m_blacklist.insert("__libc_csu_init");
+	m_blacklist.insert("__libc_csu_fini");
+	m_blacklist.insert("__libc_start_main");
+	m_blacklist.insert("__gmon_start__");
+	m_blacklist.insert("__cxa_atexit");
+	m_blacklist.insert("__cxa_finalize");
+	m_blacklist.insert("__assert_fail");
+	m_blacklist.insert("free");
+	m_blacklist.insert("fnmatch");
+	m_blacklist.insert("readlinkat");
+	m_blacklist.insert("malloc");
+	m_blacklist.insert("calloc");
+	m_blacklist.insert("realloc");
+	m_blacklist.insert("argp_failure");
+	m_blacklist.insert("argp_help");
+	m_blacklist.insert("argp_state_help");
+	m_blacklist.insert("argp_error");
+	m_blacklist.insert("argp_parse");
+
+	m_verbose = false;
+	m_bb_float_instrumentation = false;
+
+	setContextSensitivity(ContextSensitivity_None);
+
+	m_entry_point = nullptr;
+
+	m_labelid = 0;
+	m_blockid = 0;
+
+	// stats
+	m_num_bb = 0;
+	m_num_bb_instrumented = 0;
+	m_num_bb_skipped = 0;
+	m_num_bb_skipped_pushjmp = 0;
+	m_num_bb_skipped_nop_padding = 0;
+	m_num_bb_skipped_cbranch = 0;
+	m_num_style_collafl = 0;
+	m_num_bb_float_instrumentation = 0;
+	m_num_bb_float_regs_saved = 0;
+	m_num_domgraph_blocks_elided = 0;
+	m_num_exit_blocks_elided = 0;
+	m_num_entry_blocks_elided = 0;
+	m_num_single_block_function_elided = 0;
+	m_num_contexts = 0;
+
+	// fixed addresses (must match libzafl)
+	const auto trace_map_fixed_addr_s = getenv("ZAFL_TRACE_MAP_FIXED_ADDRESS");
+	m_do_fixed_addr_optimization = (trace_map_fixed_addr_s!=nullptr);
+
+	if (m_do_fixed_addr_optimization) {
+		cout << "fixed address optimization enabled" << endl;
+		m_trace_map_fixed_addr = strtoul(trace_map_fixed_addr_s,nullptr,0);
+		// must match values in libzafl.so
+		// @todo: include libzafl.hpp
+		const auto trace_map_size = 65536; // power of 2 
+		const auto gap = 4096;             // page, multiple of 4K
+		const auto previd_offset = 32;     // word aligned
+		const auto context_offset = 64;    // word aligned (make sure no overlap with previd)
+		m_previd_fixed_addr = m_trace_map_fixed_addr + trace_map_size + gap + previd_offset;
+		m_context_fixed_addr = m_trace_map_fixed_addr + trace_map_size + gap + context_offset;
+		cout << hex;
+		cout << "tracemap fixed at: 0x" << m_trace_map_fixed_addr << endl;
+		cout << "prev_id fixed at : 0x" << m_previd_fixed_addr << endl;
+		cout << "context fixed at : 0x" << m_context_fixed_addr << endl;
+		cout << dec;
+	}
+	else
+	{
+		m_trace_map_fixed_addr = 0;
+		m_previd_fixed_addr = 0;
+		m_context_fixed_addr = 0;
+	}
+}
+
+bool ZaxBase_t::useFixedAddresses() const
+{
+	return m_do_fixed_addr_optimization;
+}
+
+unsigned long ZaxBase_t::getFixedAddressMap() const
+{
+	return m_trace_map_fixed_addr;
+}
+
+unsigned long ZaxBase_t::getFixedAddressPrevId() const
+{
+	return m_previd_fixed_addr;
+}
+
+unsigned long ZaxBase_t::getFixedAddressContext() const
+{
+	return m_context_fixed_addr;
+}
+
+void ZaxBase_t::setVerbose(bool p_verbose)
+{
+	m_verbose = p_verbose;
+}
+
+void ZaxBase_t::setBasicBlockOptimization(bool p_bb_graph_optimize) 
+{
+	m_graph_optimize = p_bb_graph_optimize;
+	const auto enabled = m_graph_optimize ? "enable" : "disable";
+	cout << enabled << " basic block optimization" << endl ;
+}
+
+void ZaxBase_t::setDomgraphOptimization(bool p_domgraph_optimize) 
+{
+	m_domgraph_optimize = p_domgraph_optimize;
+	const auto enabled = m_domgraph_optimize ? "enable" : "disable";
+	cout << enabled << " dominator graph optimization" << endl ;
+}
+
+
+void ZaxBase_t::setEnableForkServer(bool p_forkserver_enabled) 
+{
+	m_forkserver_enabled = p_forkserver_enabled;
+}
+
+void ZaxBase_t::setBreakupCriticalEdges(bool p_breakupEdges)
+{
+	m_breakupCriticalEdges = p_breakupEdges;
+	m_breakupCriticalEdges ?
+		cout << "enable breaking of critical edges" << endl :
+		cout << "disable breaking of critical edges" << endl;
+}
+
+void ZaxBase_t::setBasicBlockFloatingInstrumentation(bool p_float)
+{
+	m_bb_float_instrumentation = p_float;
+	m_bb_float_instrumentation ?
+		cout << "enable floating instrumentation" << endl :
+		cout << "disable floating instrumentation" << endl;
+}
+
+bool ZaxBase_t::getBasicBlockFloatingInstrumentation() const
+{
+	return m_bb_float_instrumentation;
+}
+
+void ZaxBase_t::setContextSensitivity(ContextSensitivity_t p_context_style)
+{
+	m_context_sensitivity = p_context_style;
+	switch (m_context_sensitivity)
+	{
+		case ContextSensitivity_None:
+			cout << "disable context sensitivity" << endl;
+			break;
+		case ContextSensitivity_Function:
+			cout << "enable context sensitivity (style: function)" << endl;
+			break;
+		case ContextSensitivity_Callsite:
+			cout << "enable context sensitivity (style: callsite)" << endl;
+			break;
+	}
+}
+
+ContextSensitivity_t ZaxBase_t::getContextSensitivity() const
+{
+	return m_context_sensitivity;
+}
+
+/*
+ * Only allow instrumentation in whitelisted functions/instructions
+ * Each line in file is either a function name or address
+ */
+void ZaxBase_t::setWhitelist(const string& p_whitelist)
+{
+	std::ifstream whitelistFile(p_whitelist);
+	if (!whitelistFile.is_open())
+		throw std::runtime_error("Could not open file " + p_whitelist);
+	std::string line;
+	while(whitelistFile >> line)
+	{
+		cout <<"Adding " << line << " to white list" << endl;
+		m_whitelist.insert(line);
+	}
+	whitelistFile.close();
+}
+
+/*
+ * Disallow instrumentation in blacklisted functions/instructions
+ * Each line in file is either a function name or address
+ */
+void ZaxBase_t::setBlacklist(const string& p_blackList)
+{
+	std::ifstream blackListFile(p_blackList);
+	if (!blackListFile.is_open())
+		throw;
+	std::string line;
+	while(blackListFile >> line)
+	{
+		cout <<"Adding " << line << " to black list" << endl;
+		m_blacklist.insert(line);
+	}
+	blackListFile.close();
+}
+
+ZaflLabelId_t ZaxBase_t::getLabelId(const unsigned p_max) 
+{
+	return m_labelid++;
+}
+
+ZaflBlockId_t ZaxBase_t::getBlockId(const unsigned p_max)
+{
+	m_blockid = (m_blockid+1) % p_max;
+	return m_blockid;
+}
+
+ZaflContextId_t ZaxBase_t::getContextId(const unsigned p_max)
+{
+       auto counter = 0;
+       auto contextid = 0;
+
+       // only try getting new context id 100 times
+       // avoid returning duplicate if we can help it
+       while (counter++ < 100) {
+               contextid = rand() % p_max; 
+               if (m_used_contextid.find(contextid) == m_used_contextid.end())
+               {
+                       m_used_contextid.insert(contextid);
+                       return contextid;
+               }
+       }
+       return contextid % p_max;
+}
+
+void ZaxBase_t::insertExitPoint(Instruction_t *p_inst)
+{
+	assert(p_inst->getAddress()->getVirtualOffset());
+
+	if (p_inst->getFunction())
+		cout << "in function: " << p_inst->getFunction()->getName() << " ";
+
+	stringstream ss;
+	ss << hex << p_inst->getAddress()->getVirtualOffset();
+	m_blacklist.insert(ss.str());
+
+	cout << "insert exit point at: 0x" << ss.str() << endl;
+	
+	auto tmp = p_inst;
+	     insertAssemblyBefore(tmp, "xor edi, edi"); //  rdi=0
+	tmp = insertAssemblyAfter(tmp, "mov eax, 231"); //  231 = __NR_exit_group   from <asm/unistd_64.h>
+	tmp = insertAssemblyAfter(tmp, "syscall");      //  sys_exit_group(edi)
+}
+
+void ZaxBase_t::insertForkServer(Instruction_t* p_entry)
+{
+	assert(p_entry);
+
+	stringstream ss;
+	ss << "0x" << hex << p_entry->getAddress()->getVirtualOffset();
+	cout << "inserting fork server code at address: " << ss.str() << dec << endl;
+	assert(p_entry->getAddress()->getVirtualOffset());
+
+	if (p_entry->getFunction()) {
+		cout << " function: " << p_entry->getFunction()->getName();
+		cout << " ep instr: " << p_entry->getDisassembly() << endl;
+	}
+	cout << endl;
+
+	// blacklist insertion point
+	cout << "Blacklisting entry point: " << ss.str() << endl;
+	m_blacklist.insert(ss.str());
+
+	m_entry_point = p_entry;
+
+	// insert the instrumentation
+	auto tmp=p_entry;
+	const auto regs = vector<string>({ "rdi", "rsi", "rbp", "rdx", "rcx", "rbx", "rax", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"});
+
+	// red zone
+	(void)insertAssemblyBefore(tmp, "lea rsp, [rsp-128]");
+	// save flags and registrers
+	tmp = insertAssemblyAfter(tmp,  "pushf ") ;
+	for (vector<string>::const_iterator rit = regs.begin(); rit != regs.end(); ++rit)
+		tmp = insertAssemblyAfter(tmp, " push " + *rit);
+	// call fork server initialization routine (in external library)
+	tmp = insertAssemblyAfter(tmp,  "call 0 ", m_plt_zafl_initAflForkServer) ;
+	// restore registers and flags
+	for (vector<string>::const_reverse_iterator rit = regs.rbegin(); rit != regs.rend(); ++rit)
+    		tmp = insertAssemblyAfter(tmp, " pop " + *rit) ;
+	tmp = insertAssemblyAfter(tmp,  "popf ") ;
+	// red zome
+	tmp = insertAssemblyAfter(tmp,  "lea rsp, [rsp+128]");
+}
+
+void ZaxBase_t::insertForkServer(string p_forkServerEntry)
+{
+	assert(p_forkServerEntry.size() > 0);
+
+	cout << "looking for fork server entry point: " << p_forkServerEntry << endl;
+
+	if (std::isdigit(p_forkServerEntry[0]))
+	{
+		// find instruction to insert fork server based on address
+		const auto voffset = (VirtualOffset_t) std::strtoul(p_forkServerEntry.c_str(), NULL, 16);
+		auto instructions=find_if(getFileIR()->getInstructions().begin(), getFileIR()->getInstructions().end(), [&](const Instruction_t* i) {
+				return i->getAddress()->getVirtualOffset()==voffset;
+			});
+
+		if (instructions==getFileIR()->getInstructions().end())
+		{
+			cerr << "Error: could not find address to insert fork server: " << p_forkServerEntry << endl;
+			throw;
+		}
+
+		insertForkServer(*instructions);
+	}
+	else
+	{
+		// find entry point of specified function to insert fork server
+		auto entryfunc=find_if(getFileIR()->getFunctions().begin(), getFileIR()->getFunctions().end(), [&](const Function_t* f) {
+				return f->getName()==p_forkServerEntry;
+			});
+
+		
+		if(entryfunc==getFileIR()->getFunctions().end())
+		{
+			cerr << "Error: could not find function to insert fork server: " << p_forkServerEntry << endl;
+			throw;
+		}
+
+		cout << "inserting fork server code at entry point of function: " << p_forkServerEntry << endl;
+		auto entrypoint = (*entryfunc)->getEntryPoint();
+		
+		if (!entrypoint) 
+		{
+			cerr << "Could not find entry point for: " << p_forkServerEntry << endl;
+			throw;
+		}
+		insertForkServer(entrypoint);
+	}
+}
+
+void ZaxBase_t::setupForkServer()
+{
+	if (m_fork_server_entry.size()>0)
+	{
+		// user has specified entry point
+		insertForkServer(m_fork_server_entry);
+	}
+	else
+	{
+		// try to insert fork server at main
+		const auto &all_funcs=getFileIR()->getFunctions();
+		const auto main_func_it=find_if(all_funcs.begin(), all_funcs.end(), [&](const Function_t* f) { return f->getName()=="main";});
+		if(main_func_it!=all_funcs.end())
+		{
+			insertForkServer("main"); 
+		}
+
+	}
+
+	// it's ok not to have a fork server at all, e.g. libraries
+
+ 	getFileIR()->assembleRegistry();
+ 	getFileIR()->setBaseIDS();
+
+}
+
+void ZaxBase_t::insertExitPoints()
+{
+	for (auto exitp : m_exitpoints)
+	{
+		if (std::isdigit(exitp[0]))
+		{
+			// find instruction to insert fork server based on address
+			const auto voffset = (VirtualOffset_t) std::strtoul(exitp.c_str(), NULL, 16);
+			auto instructions=find_if(getFileIR()->getInstructions().begin(), getFileIR()->getInstructions().end(), [&](const Instruction_t* i) {
+					return i->getAddress()->getVirtualOffset()==voffset;
+				});
+
+			if (instructions==getFileIR()->getInstructions().end())
+			{
+				cerr << "Error: could not find address to insert exit point: " << exitp << endl;
+				throw;
+			}
+
+			insertExitPoint(*instructions);
+		}
+		else
+		{
+			// find function by name
+			auto func_iter=find_if(getFileIR()->getFunctions().begin(), getFileIR()->getFunctions().end(), [&](const Function_t* f) {
+				return f->getName()==exitp;
+			});
+
+		
+			if(func_iter==getFileIR()->getFunctions().end())
+			{
+				cerr << "Error: could not find function to insert exit points: " << exitp << endl;
+				throw;
+			}
+
+			cout << "inserting exit code at return points of function: " << exitp << endl;
+			for (auto i : (*func_iter)->getInstructions())
+			{
+				if (i->getBaseID() >= 0)
+				{
+					const auto d=DecodedInstruction_t::factory(i);
+
+					// if it's a return instruction, add exit point
+					if (d->isReturn())
+					{
+						insertExitPoint(i);
+					}
+				}
+			}
+		}
+	}
+
+ 	getFileIR()->assembleRegistry();
+ 	getFileIR()->setBaseIDS();
+}
+
+// blacklist functions:
+//     - in blacklist
+//     - that start with '.'
+//     - that end with @plt
+bool ZaxBase_t::isBlacklisted(const Function_t *p_func) const
+{
+	return (p_func->getName()[0] == '.' || 
+	        p_func->getName().find("@plt") != string::npos ||
+	        m_blacklist.find(p_func->getName())!=m_blacklist.end());
+}
+
+bool ZaxBase_t::isWhitelisted(const Function_t *p_func) const
+{
+	if (m_whitelist.size() == 0) return true;
+	return (m_whitelist.find(p_func->getName())!=m_whitelist.end());
+}
+
+bool ZaxBase_t::isBlacklisted(const Instruction_t *p_inst) const
+{
+	stringstream ss;
+	ss << "0x" << hex << p_inst->getAddress()->getVirtualOffset();
+	return (m_blacklist.count(ss.str()) > 0 || isBlacklisted(p_inst->getFunction()) || p_inst == m_entry_point);
+}
+
+bool ZaxBase_t::isWhitelisted(const Instruction_t *p_inst) const
+{
+	if (m_whitelist.size() == 0) return true;
+
+	stringstream ss;
+	ss << "0x" << hex << p_inst->getAddress()->getVirtualOffset();
+	return (m_whitelist.count(ss.str()) > 0 || isWhitelisted(p_inst->getFunction()));
+}
+
+void ZaxBase_t::setup()
+{
+	if (m_forkserver_enabled)
+		setupForkServer();
+	else
+		cout << "Fork server has been disabled" << endl;
+
+	insertExitPoints();
+}
+
+void ZaxBase_t::teardown()
+{
+	dumpAttributes();
+	dumpMap();
+}	
+
+// in: control flow graph for a given function
+// out: set of basic blocks to instrument
+BasicBlockSet_t ZaxBase_t::getBlocksToInstrument(const ControlFlowGraph_t &cfg)
+{
+	static int bb_debug_id=-1;
+
+	if (m_verbose)
+		cout << cfg << endl;
+
+	auto keepers = BasicBlockSet_t();
+
+	for (auto &bb : cfg.getBlocks())
+	{
+		assert(bb->getInstructions().size() > 0);
+
+		bb_debug_id++;
+
+		// already marked as a keeper
+		if (keepers.find(bb) != keepers.end())
+			continue;
+ 
+		// if whitelist specified, only allow instrumentation for functions/addresses in whitelist
+		if (!isWhitelisted(bb->getInstructions()[0]))
+			continue;
+
+		if (isBlacklisted(bb->getInstructions()[0]))
+			continue;
+
+		// debugging support
+		if (getenv("ZAFL_LIMIT_BEGIN"))
+		{
+			if (bb_debug_id < atoi(getenv("ZAFL_LIMIT_BEGIN")))
+				continue;	
+		}
+
+		// debugging support
+		if (getenv("ZAFL_LIMIT_END"))
+		{
+			if (bb_debug_id >= atoi(getenv("ZAFL_LIMIT_END"))) 
+				continue;
+		}
+
+		// make sure we're not trying to instrument code we just inserted, e.g., fork server, added exit points
+		if (bb->getInstructions()[0]->getBaseID() < 0)
+		{
+			if (m_verbose)
+				cout << "Base ID < 0" << endl;
+			continue;
+		}
+
+		// push/jmp pair, don't bother instrumenting
+		if (BB_isPushJmp(bb))
+		{
+			m_num_bb_skipped_pushjmp++;
+			continue;
+		}
+
+		keepers.insert(bb);
+	}
+	return keepers;
+}
+
+void ZaxBase_t::filterPaddingNOP(BasicBlockSet_t& p_in_out)
+{
+	auto copy=p_in_out;
+	for(auto block : copy)
+	{
+		if (BB_isPaddingNop(block))
+		{
+			p_in_out.erase(block);
+			m_num_bb_skipped_nop_padding++;
+		}
+	}
+}
+
+void ZaxBase_t::filterEntryBlock(BasicBlockSet_t& p_in_out, BasicBlock_t* p_entry)
+{
+
+	if (!m_graph_optimize)
+		return;
+
+	if (p_entry->getSuccessors().size() != 1)
+		return;
+
+	if (p_in_out.find(p_entry) == p_in_out.end())
+		return;
+
+	if (p_in_out.find(*(p_entry->getSuccessors().begin())) == p_in_out.end())
+		return;
+
+	// both entry and successor are in <p_in_out>
+	// entry block has single successor
+	p_in_out.erase(p_entry);
+	m_num_entry_blocks_elided++;
+	if (m_verbose) {
+		cout << "Eliding entry block" << endl; 
+	}
+}
+
+void ZaxBase_t::filterExitBlocks(BasicBlockSet_t& p_in_out)
+{
+	if (!m_graph_optimize)
+		return;
+	
+	auto copy=p_in_out;
+	for(auto block : copy)
+	{
+		if (!block->getIsExitBlock())
+			continue;
+
+		if (block->getInstructions()[0]->getIndirectBranchTargetAddress())
+			continue;
+
+		if (block->getPredecessors().size() != 1)
+			continue;
+
+		if (copy.find(*block->getPredecessors().begin()) == copy.end())
+			continue;
+
+		const auto last_instruction_index = block->getInstructions().size() - 1;
+		if (block->getInstructions()[last_instruction_index]->getDisassembly().find("ret")==string::npos)
+			continue;
+
+		// must be an exit block (ret)
+		// exit block is not an ibta
+		// only 1 predecessor
+		// predecessor in <p_in_out>
+		p_in_out.erase(block);
+		m_num_exit_blocks_elided++;
+		if (m_verbose) {
+			cout << "Eliding exit block" << endl; 
+		}
+	}
+}
+
+void ZaxBase_t::filterConditionalBranches(BasicBlockSet_t& p_in_out)
+{
+	if (!m_graph_optimize)
+		return;
+	auto copy=p_in_out;
+	for(auto block : copy)
+	{
+		const auto successors_have_unique_preds = 
+			find_if(ALLOF(block->getSuccessors()), [](const BasicBlock_t* s)
+				{
+					return s->getPredecessors().size() > 1;
+				}) == block->getSuccessors().end();
+
+		const auto successor_with_ibta = 
+			find_if(ALLOF(block->getSuccessors()), [](const BasicBlock_t* s)
+				{
+					return s->getInstructions()[0]->getIndirectBranchTargetAddress();
+				}) != block->getSuccessors().end();
+	
+		const auto all_successors_kept = 
+			find_if(ALLOF(block->getSuccessors()), [p_in_out](BasicBlock_t* s)
+				{
+					return p_in_out.find(s) == p_in_out.end();
+				}) == block->getSuccessors().end();
+
+		if (block->endsInConditionalBranch() && 
+		    all_successors_kept &&
+		    successors_have_unique_preds &&
+		    !successor_with_ibta)
+		{
+			// block ends in conditional branch
+			// successors are in <p_in_out>
+			// successors have unique predecessors
+			// no successor is an ibta
+			if (m_verbose)
+				cout << "Eliding conditional branch -- keeping successors" << endl;
+			p_in_out.erase(block);
+			m_num_bb_skipped_cbranch++;
+			continue;
+		}
+	}
+}
+
+void ZaxBase_t::filterBlocksByDomgraph(BasicBlockSet_t& p_in_out,  const DominatorGraph_t* dg)
+{
+	if(!m_domgraph_optimize)
+		return;
+
+	if(m_verbose)
+	{
+		cout<<"And the Dominator graph is:" <<endl;
+		cout<<*dg<<endl;
+	}
+
+	auto copy=p_in_out;
+	for(auto block : copy)
+	{
+		const auto &dominates = dg->getDominated(block);
+
+		const auto is_dg_leaf = dominates.size()==1; // leaf in the dom tree -- we dominate ourselves.
+				// this is leaf of cfg: successors.size() == 0;
+
+		const auto is_dominated=
+			[&](const BasicBlock_t* successor) -> bool
+			{
+				const auto &dominators = dg->getDominators(successor);
+				return dominators.find(block) != end(dominators);
+			};
+		const auto is_non_dominated= [&](const BasicBlock_t* successor) -> bool
+			{
+				return !is_dominated(successor);
+			};
+
+		auto &successors = block->getSuccessors();
+		auto non_dominator_successor_it = find_if(ALLOF(successors), is_non_dominated);
+		const auto has_non_dominator_successor = non_dominator_successor_it != end(successors);
+		const auto keep = (is_dg_leaf || has_non_dominator_successor);
+		if(!keep)
+		{
+			p_in_out.erase(block);
+			m_num_domgraph_blocks_elided++;
+			if(m_verbose)
+			{
+				cout<<"Eliding instrumentation in block id      = " << dec << block->getInstructions()[0]->getBaseID() << endl;
+				cout<<"is_dg_leaf            = " << boolalpha << is_dg_leaf << endl;
+				cout<<"has_non_dom_successor = " << boolalpha << has_non_dominator_successor << endl;
+			}
+		}
+		else
+		{
+			if(m_verbose)
+			{
+				cout<<"Instrumenting block id      = " << dec << block->getInstructions()[0]->getBaseID() << endl;
+				cout<<"is_dg_leaf            = " << boolalpha << is_dg_leaf << endl;
+				cout<<"has_non_dom_successor = " << boolalpha << has_non_dominator_successor << endl;
+			}
+		}
+	}
+}
+
+// by default, return the first instruction in block
+Instruction_t* ZaxBase_t::getInstructionToInstrument(const BasicBlock_t *p_bb, const unsigned p_num_free_regs_desired)
+{
+	if (!p_bb) 
+		return nullptr;
+
+	const auto first_instruction = p_bb->getInstructions()[0];
+
+	// no STARS (i.e., no dead reg annotations)
+	// or floating instrumentation turned off
+	if (!getBasicBlockFloatingInstrumentation() || !m_use_stars)
+	{
+		for (auto i : p_bb->getInstructions())
+		{
+			if (i->getBaseID())
+				return i;
+		}
+
+		// fallback: return the first instruction
+		return first_instruction;
+	}
+
+	// scan basic block looking for instruction with requested number of free regs
+	const auto allowed_regs = RegisterSet_t({rn_RAX, rn_RBX, rn_RCX, rn_RDX, rn_R8, rn_R9, rn_R10, rn_R11, rn_R12, rn_R13, rn_R14, rn_R15});
+	// auto &ap = m_stars_analysis_engine.getAnnotations();
+	auto best_i = first_instruction;
+	auto max_free_regs = 0U;
+	auto num_free_regs_best_i = 0U;
+	auto num_free_regs_first_instruction = 0U;
+
+	for (auto i : p_bb->getInstructions())
+	{
+		if (isBlacklisted(i))
+			continue;
+
+		const auto dead_regs = getDeadRegs(i);
+		const auto num_free_regs = getFreeRegs(dead_regs, allowed_regs).size();
+
+		if (i == first_instruction)
+			num_free_regs_first_instruction = num_free_regs;
+
+		if (num_free_regs >= p_num_free_regs_desired)
+		{
+			// found instruction with requested number of free registers
+			m_num_bb_float_instrumentation++;
+			if (i != first_instruction)
+			{
+				const auto num_saved = std::max(static_cast<long unsigned>(p_num_free_regs_desired), num_free_regs) - num_free_regs_first_instruction;
+				m_num_bb_float_regs_saved += num_saved;
+			}
+			return i;
+		}
+
+		// keep track of the best thus far
+		if (num_free_regs > max_free_regs)
+		{
+			max_free_regs = num_free_regs;
+			best_i = i;
+			num_free_regs_best_i = num_free_regs;
+		}
+	}
+
+	if (best_i != first_instruction) 
+	{
+		const auto num_saved = std::max(p_num_free_regs_desired, num_free_regs_best_i) - num_free_regs_first_instruction;
+		m_num_bb_float_regs_saved += num_saved;
+		m_num_bb_float_instrumentation++;
+	}
+
+	return best_i;
+}
+
+void ZaxBase_t::dumpAttributes()
+{
+	cout << "#ATTRIBUTE num_bb=" << dec << m_num_bb << endl;
+	cout << "#ATTRIBUTE num_bb_instrumented=" << m_num_bb_instrumented << endl;
+	cout << "#ATTRIBUTE num_bb_skipped=" << m_num_bb_skipped << endl;
+	cout << "#ATTRIBUTE num_bb_skipped_pushjmp=" << m_num_bb_skipped_pushjmp << endl;
+	cout << "#ATTRIBUTE num_bb_skipped_nop_padding=" << m_num_bb_skipped_nop_padding << endl;
+	cout << "#ATTRIBUTE num_bb_float_instrumentation=" << m_num_bb_float_instrumentation << endl;
+	cout << "#ATTRIBUTE num_bb_float_register_saved=" << m_num_bb_float_regs_saved << endl;
+	cout << "#ATTRIBUTE graph_optimize=" << boolalpha << m_graph_optimize << endl;
+	cout << "#ATTRIBUTE num_bb_skipped_cond_branch=" << m_num_bb_skipped_cbranch << endl;
+	cout << "#ATTRIBUTE num_style_collafl=" << m_num_style_collafl << endl;
+	cout << "#ATTRIBUTE num_domgraph_blocks_elided=" << m_num_domgraph_blocks_elided << endl;
+	cout << "#ATTRIBUTE num_entry_blocks_elided=" << m_num_entry_blocks_elided << endl;
+	cout << "#ATTRIBUTE num_exit_blocks_elided=" << m_num_exit_blocks_elided << endl;
+	cout << "#ATTRIBUTE num_single_block_function_elided=" << m_num_single_block_function_elided << endl;
+	cout << "#ATTRIBUTE num_contexts=" << m_num_contexts << endl;
+}
+
+// file dump of modified basic block info
+void ZaxBase_t::dumpMap()
+{
+	getFileIR()->setBaseIDS();           // make sure instructions have IDs
+	getFileIR()->assembleRegistry();     // make sure to assemble all instructions
+
+	std::ofstream mapfile("zax.map");
+
+	mapfile << "# BLOCK_ID  ID_EP:size  ID_OLDEP:size (ID_INSTRUMENTATION:size)*" << endl;
+	for (auto &mb : m_modifiedBlocks)
+	{
+		const auto blockid = mb.first;
+		mapfile << dec << blockid << " ";
+		for (auto &entry : mb.second)
+		{
+			mapfile << hex << entry->getBaseID() << ":" << dec << entry->getDataBits().size() << " ";
+		}
+		mapfile << endl;
+	}
+}
+
+void ZaxBase_t::addContextSensitivity_Callsite(const ControlFlowGraph_t& cfg)
+{
+	assert(0);
+}
+
+// update calling context hash at entry point
+// revert calling context hash on exit 
+void ZaxBase_t::addContextSensitivity_Function(const ControlFlowGraph_t& cfg)
+{
+	bool inserted_before = false;
+
+	// don't bother with single block functions
+	if (cfg.getBlocks().size() == 1)
+		return;
+
+	m_num_contexts++;
+
+	//
+	// entry_point
+	//      context = prev_context % RANDOM_CONTEXT_ID
+	//
+	// exit point (returns)
+	//      context = prev_context % RANDOM_CONTEXT_ID
+	//
+	const auto do_insert=[&](Instruction_t* instr, const string& insn_str) -> Instruction_t*
+		{
+			if (inserted_before)
+			{
+				instr = insertAssemblyAfter(instr, insn_str);
+				return instr;
+			}
+			else
+			{
+				insertAssemblyBefore(instr, insn_str);
+				inserted_before = true;
+				return instr;
+			}
+		};
+
+	auto compute_hash_chain = [&](ZaflContextId_t contextid, Instruction_t * instr, string reg_context, string reg_temp) -> Instruction_t*
+		{
+			auto labelid = getLabelId();
+			auto tmp = instr;
+
+			// fast way with fixed addresses:
+			//         xor [regc], <context_id>
+			//
+			// inefficient way:
+			//      E: mov   regc, QWORD[rel E]
+			//         mov   rtmp, [regc]
+			//         xor   rtmp, <context_id>
+			//         mov [regc], rtmp
+			//
+			//         
+			if (useFixedAddresses())
+			{
+				const auto xor_context = string("xor WORD [0x") + to_hex_string(getFixedAddressContext()) + "]" + "," + to_string(contextid);
+				tmp = do_insert(tmp, xor_context);
+			}
+			else
+			{
+				const auto hash_context_reloc = string("E") + to_string(labelid) + ": mov " + reg_context + ", QWORD [rel E" + to_string(labelid) + "]"; 
+				tmp = do_insert(tmp, hash_context_reloc);
+				create_got_reloc(getFileIR(), m_context_id, tmp);
+			
+				const auto deref_context = string("mov ") + reg_temp + ", [" + reg_context + "]";
+				tmp = do_insert(tmp, deref_context);
+
+				const auto hash_chain = string("xor ") + reg_temp + ", " + to_string(contextid);
+				tmp = do_insert(tmp, hash_chain);
+
+				const auto store_context = string("mov [") + reg_context + "]" + "," + reg_temp;
+				tmp = do_insert(tmp, store_context);
+			}
+
+			return tmp;
+		};
+
+	auto add_hash_context_instrumentation = [&](ZaflContextId_t contextid, Instruction_t* i, const bool honor_red_zone)
+		{
+			inserted_before = false;
+
+			// look for instruction in entry block with at least 1 free reg
+			auto reg_context = string("r14");
+			auto reg_temp = string("r15");
+			bool save_context = true;
+			bool save_temp = true;
+
+			if (useFixedAddresses())
+			{
+				save_context = false;
+				save_temp = false;
+			}
+
+			const auto allowed_regs = RegisterSet_t({rn_RAX, rn_RBX, rn_RCX, rn_RDX, rn_R8, rn_R9, rn_R10, rn_R11, rn_R12, rn_R13, rn_R14, rn_R15});
+			const auto dead_regs = getDeadRegs(i);
+			const auto live_flags = dead_regs.find(IRDB_SDK::rn_EFLAGS)==dead_regs.end();
+			auto free_regs = getFreeRegs(dead_regs, allowed_regs);
+
+			if (honor_red_zone)
+				i = do_insert(i, "lea rsp, [rsp-128]");
+
+			if (save_context && free_regs.size() > 0)
+			{
+				reg_context = registerToString(FIRSTOF(free_regs));
+				free_regs.erase(FIRSTOF(free_regs));
+				save_context = false;
+			}
+
+			if (save_temp && free_regs.size() > 0)
+			{
+				reg_temp = registerToString(FIRSTOF(free_regs));
+				free_regs.erase(FIRSTOF(free_regs));
+				save_temp = false;
+			}
+
+			if (save_context)
+				i = do_insert(i, "push " + reg_context);
+
+			if (save_temp)
+				i = do_insert(i, "push " + reg_temp);
+
+			if (live_flags)
+				i = do_insert(i, "pushf");
+
+			// compute new hash chain value
+			i = compute_hash_chain(contextid, i, reg_context, reg_temp);
+
+			if (live_flags)
+				i = do_insert(i, "popf");
+
+			if (save_temp)
+				i = do_insert(i, "pop " + reg_temp);
+
+			if (save_context)
+				i = do_insert(i, "pop " + reg_context);
+
+			if (honor_red_zone)
+				i = do_insert(i, "lea rsp, [rsp+128]");
+		};
+
+	bool honor_red_zone = true;
+	if (m_use_stars) 
+		honor_red_zone = hasLeafAnnotation(cfg.getFunction());
+
+	auto contextid = getContextId();
+	auto entry_block = cfg.getEntry();
+	inserted_before = false;
+	add_hash_context_instrumentation(contextid, entry_block->getInstructions()[0], honor_red_zone);
+
+	// find all exit blocks with returns
+	auto find_exits = BasicBlockSet_t();
+	copy_if(ALLOF(cfg.getBlocks()), inserter(find_exits, find_exits.begin()), [entry_block](BasicBlock_t* bb) {
+			if (bb == entry_block) return false; 			
+			if (!bb->getIsExitBlock()) return false; 			
+			const auto last_instruction_index = bb->getInstructions().size() - 1;
+			return (bb->getInstructions()[last_instruction_index]->getDisassembly().find("ret")!=string::npos);
+		});
+
+	for (const auto &bb: find_exits)
+	{
+		const auto last_instruction_index = bb->getInstructions().size()-1;
+		inserted_before = false;
+		add_hash_context_instrumentation(contextid, bb->getInstructions()[last_instruction_index], honor_red_zone);
+	}
+}
+
+void ZaxBase_t::addContextSensitivity(const ControlFlowGraph_t& cfg)
+{
+	if (m_entry_point && m_entry_point->getFunction())
+	{
+		cout << "cfg.func: " << cfg.getFunction()->getName() << " ep.func: " << m_entry_point->getFunction()->getName() << endl;
+		if (m_entry_point->getFunction()->getName() == cfg.getFunction()->getName())
+		{
+			cout << "Do not setup calling context in same function as entry point for fork server" << endl;
+			return;
+		}
+	}
+
+	if (getContextSensitivity() == ContextSensitivity_Callsite)
+		addContextSensitivity_Callsite(cfg);
+	else if (getContextSensitivity() == ContextSensitivity_Function)
+		addContextSensitivity_Function(cfg);
+	else if (getContextSensitivity() == ContextSensitivity_None)
+		return;
+	else
+		throw;
+}
+
+/*
+ * Execute the transform.
+ *
+ * preconditions: the FileIR is read as from the IRDB. valid file listing functions to auto-initialize
+ * postcondition: instructions added to auto-initialize stack for each specified function
+ *
+ */
+int ZaxBase_t::execute()
+{
+	if (m_breakupCriticalEdges)
+	{
+		CriticalEdgeBreaker_t ceb(getFileIR(), m_blacklist, m_verbose);
+		cout << "#ATTRIBUTE num_bb_extra_blocks=" << ceb.getNumberExtraNodes() << endl;
+
+		getFileIR()->setBaseIDS();
+		getFileIR()->assembleRegistry();
+	}
+
+	setup();
+
+	// for all functions
+	//    build cfg and extract basic blocks
+	//    for all basic blocks, figure out whether should be kept
+	//    for all kept basic blocks
+	//          add afl-compatible instrumentation
+	
+	struct BaseIDSorter
+	{
+		bool operator()( const Function_t* lhs, const Function_t* rhs ) const 
+		{
+			assert(lhs->getBaseID() != BaseObj_t::NOT_IN_DATABASE);
+			assert(rhs->getBaseID() != BaseObj_t::NOT_IN_DATABASE);
+			return lhs->getBaseID() < rhs->getBaseID();
+		}
+	};
+	auto sortedFuncs=set<Function_t*, BaseIDSorter>( ALLOF(getFileIR()->getFunctions()));
+	for(auto f :  sortedFuncs)
+	{
+		if (f == nullptr )       continue;
+		// skip instrumentation for blacklisted functions 
+		if (isBlacklisted(f))    continue;
+		// skip if function has no entry point
+		if (!f->getEntryPoint()) continue;
+
+		bool honorRedZone = true;
+		if (m_use_stars) 
+			honorRedZone = hasLeafAnnotation(f);
+
+		const auto cfgp = ControlFlowGraph_t::factory(f);
+		const auto &cfg = *cfgp;
+		const auto num_blocks_in_func = cfg.getBlocks().size();
+		m_num_bb += num_blocks_in_func;
+
+		if (m_graph_optimize && num_blocks_in_func == 1)
+		{
+			m_num_single_block_function_elided++;
+			m_num_bb_skipped++;
+			continue;
+		}
+
+		const auto dom_graphp=DominatorGraph_t::factory(cfgp.get());
+		const auto has_domgraph_warnings = dom_graphp -> hasWarnings();  
+
+		const auto entry_block = cfg.getEntry();
+		auto keepers = getBlocksToInstrument(cfg);
+
+		if (m_verbose)
+			cout << "num blocks to keep (baseline): " << keepers.size() << endl;
+
+		if(has_domgraph_warnings)
+		{
+			if(m_verbose)
+			{
+				cout << " Domgraph has warnings, eliding domgraph filter" << endl;
+				cout << " And the domgraph is: " << endl;
+				cout << *dom_graphp << endl;
+			}
+		}
+		filterBlocksByDomgraph(keepers,dom_graphp.get());
+
+		if (m_verbose)
+			cout << "num blocks to keep (after filter dom): " << keepers.size() << " / " << cfgp->getBlocks().size() << endl;
+
+		if (m_graph_optimize)
+		{
+			filterConditionalBranches(keepers);
+			if (m_verbose)
+				cout << "num blocks to keep (after filter conditional branches): " << keepers.size() << endl;
+			filterEntryBlock(keepers, entry_block);
+			if (m_verbose)
+				cout << "num blocks to keep (after filter entry): " << keepers.size() << endl;
+
+			filterExitBlocks(keepers);
+			if (m_verbose)
+				cout << "num blocks to keep (after filter exits): " << keepers.size() << endl;
+		}
+
+		filterPaddingNOP(keepers);
+
+		struct BBSorter
+		{
+			bool operator()( const BasicBlock_t* lhs, const BasicBlock_t* rhs ) const 
+			{
+				const auto lhs_insns=lhs->getInstructions();
+				const auto rhs_insns=rhs->getInstructions();
+				assert(lhs_insns[0]->getBaseID() != BaseObj_t::NOT_IN_DATABASE);	
+				assert(rhs_insns[0]->getBaseID() != BaseObj_t::NOT_IN_DATABASE);	
+				return lhs_insns[0]->getBaseID() < rhs_insns[0]->getBaseID();
+			}
+		};
+		auto sortedBasicBlocks = set<BasicBlock_t*, BBSorter> (ALLOF(keepers));
+		for (auto &bb : sortedBasicBlocks)
+		{
+			auto collAflSingleton = false;
+			// for collAfl-style instrumentation, we want #predecessors==1
+			// if the basic block entry point is an IBTA, we don't know the #predecessors
+			if (m_graph_optimize               && 
+			    bb->getPredecessors().size() == 1 && 
+			    !bb->getInstructions()[0]->getIndirectBranchTargetAddress()
+			   )
+			{
+				if (m_verbose) 
+					cout << "Doing collAfl style" << endl;
+				collAflSingleton = true;
+				m_num_style_collafl++;
+			}
+
+			instrumentBasicBlock(bb, honorRedZone, collAflSingleton);
+		}
+
+		m_num_bb_instrumented += keepers.size();
+		m_num_bb_skipped += (num_blocks_in_func - keepers.size());
+
+		if (getContextSensitivity() != ContextSensitivity_None)
+		{
+			// this handles inserting the calling context sensitivity value
+			// at entry and exits of functions (todo: or at call sites a la Angora)
+ 			getFileIR()->assembleRegistry();
+		 	getFileIR()->setBaseIDS();
+			auto cs_cfg=ControlFlowGraph_t::factory(f);	
+			addContextSensitivity(*cs_cfg);
+		}
+
+		if (m_verbose)
+		{
+ 			getFileIR()->assembleRegistry();
+		 	getFileIR()->setBaseIDS();
+			cout << "Post transformation CFG for " << f->getName() << ":" << endl;
+			auto post_cfg=ControlFlowGraph_t::factory(f);	
+			cout << *post_cfg << endl;
+		}
+
+		cout << "Function " << f->getName() << ":  " << dec << keepers.size() << "/" << num_blocks_in_func << " basic blocks instrumented." << endl;
+	};
+
+
+	teardown();
+
+	return 1;
+}
+
diff --git a/zfuzz/afl_transforms/tools/zax/zax_base.hpp b/zfuzz/afl_transforms/tools/zax/zax_base.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..772fc82a025d543cbcf8ffb84191602215a1224a
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/zax_base.hpp
@@ -0,0 +1,152 @@
+#ifndef _LIBTRANSFORM_ZAXBASE_H
+#define _LIBTRANSFORM_ZAXBASE_H
+
+#include <irdb-core>
+#include <irdb-cfg>
+#include <irdb-transform>
+#include <irdb-util>
+#include <irdb-deep>
+
+// utility functions
+// @todo: move these functions into other libs for reuse
+extern void create_got_reloc(IRDB_SDK::FileIR_t* fir, std::pair<IRDB_SDK::DataScoop_t*,int> wrt, IRDB_SDK::Instruction_t* i);
+
+namespace Zafl
+{
+	using namespace IRDB_SDK;
+	using namespace std;
+
+	using ZaflBlockId_t = uint32_t;
+	using ZaflLabelId_t = uint32_t;
+	using ZaflContextId_t = uint32_t;
+	using BBRecord_t = vector<Instruction_t*>;
+	using RegisterSet_t = IRDB_SDK::RegisterIDSet_t;
+	enum ContextSensitivity_t {ContextSensitivity_None, ContextSensitivity_Callsite, ContextSensitivity_Function};
+
+	/*
+	 * Base class for afl-compatible instrumentation:
+	 *   - fork server
+	 *   - trace map 
+	 */
+	class ZaxBase_t : public Transform
+	{
+		public:
+			ZaxBase_t() = delete;
+			ZaxBase_t(const Zafl::ZaxBase_t&) = delete;
+			virtual ~ZaxBase_t() {};
+			virtual int execute();
+			void setWhitelist(const string& p_filename); 
+			void setBlacklist(const string& p_filename); 
+			void setVerbose(bool); 
+			void setBasicBlockOptimization(bool);
+			void setDomgraphOptimization(bool);
+			void setBasicBlockFloatingInstrumentation(bool);
+			void setEnableForkServer(bool);
+			void setBreakupCriticalEdges(bool);
+			void setContextSensitivity(ContextSensitivity_t);
+			void filterPaddingNOP(BasicBlockSet_t& p_in_out);
+			void filterBlocksByDomgraph(BasicBlockSet_t& in_out, const DominatorGraph_t  * dg );
+			void filterConditionalBranches(BasicBlockSet_t& p_in_out);
+			void filterEntryBlock(BasicBlockSet_t& in_out, BasicBlock_t* p_entry);
+			void filterExitBlocks(BasicBlockSet_t& in_out);
+			void addContextSensitivity(const ControlFlowGraph_t&);
+
+		protected:
+			ZaxBase_t(pqxxDB_t &p_dbinterface, FileIR_t *p_variantIR, string p_entry, set<string> p_exits, bool p_use_stars=false, bool p_autozafl=false);
+
+			virtual void instrumentBasicBlock(BasicBlock_t *p_bb, const bool p_hasLeafAnnotation, const bool p_collafl_optimization=false) = 0;
+
+			virtual ZaflLabelId_t getLabelId(const unsigned p_maxid=0xFFFFFF);
+			virtual ZaflBlockId_t getBlockId(const unsigned p_maxid=0xFFFF);
+			virtual ZaflContextId_t getContextId(const unsigned p_maxid=0xFFFF);
+			virtual BasicBlockSet_t getBlocksToInstrument (const ControlFlowGraph_t& cfg);
+			virtual Instruction_t* getInstructionToInstrument(const BasicBlock_t *, const unsigned p_num_free_regs_desired = 0);
+			virtual void setup();
+			virtual void teardown();
+			virtual void dumpAttributes();
+			virtual void dumpMap();
+
+			void insertExitPoint(Instruction_t *inst);
+			void insertForkServer(Instruction_t* p_entry);
+			void insertForkServer(string p_forkServerEntry);
+			void setupForkServer();
+			void insertExitPoints();
+			bool isBlacklisted(const Function_t*) const;
+			bool isWhitelisted(const Function_t*) const;
+			bool isBlacklisted(const Instruction_t*) const;
+			bool isWhitelisted(const Instruction_t*) const;
+			bool BB_isPushJmp(const BasicBlock_t *) const;
+			bool BB_isPaddingNop(const BasicBlock_t *) const;
+			bool getBasicBlockFloatingInstrumentation() const;
+			ContextSensitivity_t getContextSensitivity() const;
+			bool hasLeafAnnotation(Function_t* fn) const;
+			RegisterSet_t getDeadRegs(Instruction_t* insn) const;
+			RegisterSet_t getFreeRegs(const RegisterSet_t& candidates, const RegisterSet_t& allowed) const;
+			void addContextSensitivity_Callsite(const ControlFlowGraph_t&);
+			void addContextSensitivity_Function(const ControlFlowGraph_t&);
+
+			bool useFixedAddresses() const;
+			unsigned long getFixedAddressMap() const;
+			unsigned long getFixedAddressPrevId() const;
+			unsigned long getFixedAddressContext() const;
+
+		protected:
+			pqxxDB_t&                      m_dbinterface;
+			unique_ptr<FunctionSet_t>      leaf_functions;
+			unique_ptr<DeadRegisterMap_t>  dead_registers;
+
+			bool                           m_use_stars;          // use STARS to have access to dead register info
+			bool                           m_autozafl;           // link in library w/ auto fork server
+			bool                           m_graph_optimize;     // skip basic blocks based on graph
+			bool                           m_domgraph_optimize;  // skip basic blocks based on dominator graph
+			bool                           m_forkserver_enabled; // fork server enabled?
+			bool                           m_breakupCriticalEdges;
+			bool                           m_bb_float_instrumentation;  // skip basic blocks based on graph
+			bool                           m_verbose;
+			pair<DataScoop_t*,int>         m_trace_map;  // afl shared memory trace map
+			pair<DataScoop_t*,int>         m_prev_id;    // id of previous block
+			pair<DataScoop_t*,int>         m_context_id;    // calling context variable
+			Instruction_t*                 m_plt_zafl_initAflForkServer; // plt entry for afl fork server initialization routine
+
+			set<ZaflContextId_t>           m_used_contextid;  // internal bookkeeping to keep track of used block ids
+			map<ZaflBlockId_t, BBRecord_t> m_modifiedBlocks;  // keep track of modified blocks
+
+			ContextSensitivity_t           m_context_sensitivity;  // none, @callsite, @function
+
+
+
+			// stats
+			size_t m_num_bb;
+			size_t m_num_bb_instrumented;
+			size_t m_num_bb_skipped;
+			size_t m_num_bb_skipped_pushjmp;
+			size_t m_num_bb_skipped_nop_padding;
+			size_t m_num_bb_skipped_cbranch;
+			size_t m_num_bb_float_instrumentation;
+			size_t m_num_bb_float_regs_saved;
+			size_t m_num_style_collafl;
+			size_t m_num_domgraph_blocks_elided;
+			size_t m_num_entry_blocks_elided;
+			size_t m_num_exit_blocks_elided;
+			size_t m_num_single_block_function_elided;
+			size_t m_num_contexts;
+
+		private:
+			string          m_fork_server_entry;  // string to specify fork server entry point
+			set<string>     m_exitpoints;         // set of strings to specify exit points
+			set<string>     m_whitelist;          // whitelisted functions and/or instructions
+			set<string>     m_blacklist;          // blacklisted functions and/or instructions
+			ZaflLabelId_t   m_labelid;            // internal bookkeeping to generate labels
+			ZaflBlockId_t   m_blockid;            // internal bookkeeping to generate labels
+			Instruction_t*  m_entry_point;        // entry point where fork server was inserted
+
+			// fixed address mode
+			bool            m_do_fixed_addr_optimization;
+			unsigned long   m_trace_map_fixed_addr;
+			unsigned long   m_previd_fixed_addr;
+			unsigned long   m_context_fixed_addr;
+
+	};
+} 
+
+#endif
diff --git a/zfuzz/afl_transforms/tools/zax/zax_driver.cpp b/zfuzz/afl_transforms/tools/zax/zax_driver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7dc32dfdb270129d1d2f2c2d6b56ac4c61289e15
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/zax_driver.cpp
@@ -0,0 +1,295 @@
+/***************************************************************************
+ * Copyright (c)  2018-2019  Zephyr Software LLC. All rights reserved.
+ *
+ * This software is furnished under a license and/or other restrictive
+ * terms and may be used and copied only in accordance with such terms
+ * and the inclusion of the above copyright notice. This software or
+ * any other copies thereof may not be provided or otherwise made
+ * available to any other person without the express written consent
+ * of an authorized representative of Zephyr Software LCC. Title to,
+ * ownership of, and all rights in the software is retained by
+ * Zephyr Software LCC.
+ *
+ * Zephyr Software LLC. Proprietary Information
+ *
+ * Unless otherwise specified, the information contained in this
+ * directory, following this legend, and/or referenced herein is
+ * Zephyr Software LLC. (Zephyr) Proprietary Information.
+ *
+ * CONTACT INFO
+ *
+ * E-mail: jwd@zephyr-software.com
+ **************************************************************************/
+
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include "zax.hpp"
+#include "zuntracer.hpp"
+
+using namespace std;
+using namespace IRDB_SDK;
+using namespace Zafl;
+
+static void usage(char* name)
+{
+	cerr<<"Usage: "<<name<<" <variant_id>\n";
+	cerr<<"\t[--verbose | -v]                               Verbose mode                  "<<endl;
+	cerr<<"\t[--help,--usage,-?,-h]                         Display this message          "<<endl;
+	cerr<<"\t[--entrypoint|-e {<funcName>|<hex_address>}]   Specify where to insert fork server (defaults to main if found)"<<endl;
+	cerr<<"\t[--exitpoint|-E {<funcName>|<hex_address>}]    Specify where to insert exit"<<endl;
+	cerr<<"\t[--whitelist|-w whitelistFile]                 Specify list of functions/addresses to instrument"<<endl;
+	cerr<<"\t[--blacklist|-b blacklistFile]                 Specify list of functions/addresses to omit"<<endl;
+	cerr<<"\t[--stars|-s]                                   Enable STARS optimizations    "<<endl;
+	cerr<<"\t[--enable-bb-graph-optimization|-g]            Elide instrumentation if basic block has 1 successor"<<endl;
+	cerr<<"\t[--disable-bb-graph-optimization|-G]           Elide instrumentation if basic block has 1 successor"<<endl;
+	cerr<<"\t[--autozafl|-a]                                Auto-initialize fork server (incompatible with --entrypoint)"<<endl;
+	cerr<<"\t[--untracer|-u]                                Untracer-style block-coverage instrumentation"<<endl;
+	cerr<<"\t[--enable-critical-edge-breakup|-c]            Breakup critical edges"<<endl;
+	cerr<<"\t[--disable-critical-edge-breakup|-C]           Do not breakup critical edges (default)"<<endl;
+	cerr<<"\t[--enable-floating-instrumentation|-i]         Select best instrumentation within basic block"<<endl;
+	cerr<<"\t[--disable-floating-instrumentation|-I]        Instrument first instruction in basic blocks"<<endl;
+	cerr<<"\t[--enable-context-sensitivity <style>]         Use calling context sensitivity, style={callsite,function}"<<endl;
+	cerr<<"\t[--disable-context-sensitivity]                Disable calling context sensitivity"<<endl;
+	cerr<<"\t[--random-seed|r <value>]                      Specify random seed"<<endl;
+}
+
+int main(int argc, char **argv)
+{
+	if(argc < 2)
+	{
+		usage(argv[0]);
+		exit(1);
+	}
+
+	string programName(argv[0]);
+	auto entry_fork_server = string();
+	auto variantID = atoi(argv[1]);
+	auto verbose=false;
+	auto use_stars=false;
+	auto autozafl=false;
+	auto whitelistFile=string();
+	auto blacklistFile=string();
+	auto bb_graph_optimize=false;
+	auto domgraph_optimize=false;
+	auto forkserver_enabled=true;
+	auto untracer_mode=false;
+	auto breakup_critical_edges=false;
+	auto floating_instrumentation=false;
+	auto context_sensitivity=ContextSensitivity_None;
+	auto random_seed = 0U;
+	set<string> exitpoints;
+
+	srand(getpid()+time(NULL));
+
+	// Parse some options for the transform
+	static struct option long_options[] = {
+		{"verbose", no_argument, 0, 'v'},
+		{"help", no_argument, 0, 'h'},
+		{"usage", no_argument, 0, '?'},
+		{"stars", no_argument, 0, 's'},
+		{"entrypoint", required_argument, 0, 'e'},
+		{"exitpoint", required_argument, 0, 'E'},
+		{"whitelist", required_argument, 0, 'w'},
+		{"blacklist", required_argument, 0, 'b'},
+		{"autozafl", no_argument, 0, 'a'},
+		{"enable-bb-graph-optimization", no_argument, 0, 'g'},
+		{"disable-bb-graph-optimization", no_argument, 0, 'G'},
+		{"enable-domgraph-optimization", no_argument, 0, 'd'},
+		{"disable-domgraph-optimization", no_argument, 0, 'D'},
+		{"enable-forkserver", no_argument, 0, 'f'},
+		{"disable-forkserver", no_argument, 0, 'F'},
+		{"untracer", no_argument, 0, 'u'},
+		{"enable-critical-edge-breakup", no_argument, 0, 'c'},
+		{"disable-critical-edge-breakup", no_argument, 0, 'C'},
+		{"enable-floating-instrumentation", no_argument, 0, 'i'},
+		{"disable-floating-instrumentation", no_argument, 0, 'I'},
+		{"enable-context-sensitivity", required_argument, 0, 'z'},
+		{"random-seed", required_argument, 0, 'r'},
+		{0,0,0,0}
+	};
+	const char* short_opts="r:z:e:E:w:sv?hagGdDfFucCiI";
+
+	while(true)
+	{
+		int index = 0;
+		int c = getopt_long(argc, argv, short_opts, long_options, &index);
+		if(c == -1)
+			break;
+		switch(c)
+		{
+		case 'v':
+			verbose=true;
+			break;
+		case '?':
+		case 'h':
+			usage(argv[0]);
+			exit(1);
+			break;
+		case 's':
+			use_stars=true;
+			cout << "STARS optimization enabled" << endl;
+			break;
+		case 'e':
+			entry_fork_server = optarg;
+			break;
+		case 'E':
+			exitpoints.insert(optarg);
+			break;
+		case 'w':
+			whitelistFile=optarg;
+			break;
+		case 'b':
+			blacklistFile=optarg;
+			break;
+		case 'a':
+			autozafl=true;
+			break;
+		case 'g':
+			bb_graph_optimize=true;
+			break;
+		case 'G':
+			bb_graph_optimize=false;
+			break;
+		case 'd':
+			domgraph_optimize=true;
+			break;
+		case 'D':
+			domgraph_optimize=false;
+			break;
+		case 'f':
+			forkserver_enabled=true;
+			break;
+		case 'F':
+			forkserver_enabled=false;
+			break;
+		case 'u':
+			untracer_mode=true;
+			break;
+		case 'c':
+			breakup_critical_edges=true;
+			break;
+		case 'C':
+			breakup_critical_edges=false;
+			break;
+		case 'i':
+			floating_instrumentation=true;
+			break;
+		case 'I':
+			floating_instrumentation=false;
+			break;
+		case 'z':
+			if (optarg == string("callsite"))
+				context_sensitivity=ContextSensitivity_Callsite; // Angora fuzzer style
+			else if (optarg == string("function"))
+				context_sensitivity=ContextSensitivity_Function;
+			else
+				context_sensitivity=ContextSensitivity_None;
+			break;
+		case 'r':
+			random_seed = strtoul(optarg, NULL, 0);
+			srand(random_seed);
+			cout << "Setting random seed to: " << random_seed << endl;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (entry_fork_server.size() > 0 && autozafl)
+	{
+		cerr << "--entrypoint and --autozafl are incompatible options" << endl;
+		usage(argv[0]);
+		exit(1);
+	}
+
+	if (floating_instrumentation && !use_stars)
+	{
+		cerr << "STARS must be turned on when using floating instrumentation" << endl;
+		usage(argv[0]);
+		exit(1);
+	}
+
+
+	/* setup the interface to the sql server */
+	auto pqxx_interface=pqxxDB_t::factory();
+	BaseObj_t::setInterface(pqxx_interface.get());
+
+	auto pidp=VariantID_t::factory(variantID);
+	assert(pidp->isRegistered()==true);
+
+	bool one_success = false;
+	for(set<File_t*>::iterator it=pidp->getFiles().begin();
+	        it!=pidp->getFiles().end();
+	        ++it)
+	{
+		File_t* this_file = *it;
+		auto firp = FileIR_t::factory(pidp.get(), this_file);
+
+		cout<<"Transforming "<<this_file->getURL()<<endl;
+
+		assert(firp && pidp);
+
+		try
+		{
+			ZaxBase_t* zax_raw;
+			if (untracer_mode)
+				  zax_raw = new ZUntracer_t(*pqxx_interface, firp.get(), entry_fork_server, exitpoints, use_stars, autozafl);
+			else
+				  zax_raw = new Zax_t(*pqxx_interface, firp.get(), entry_fork_server, exitpoints, use_stars, autozafl);
+			auto zax = unique_ptr<ZaxBase_t>(zax_raw);
+
+			if (whitelistFile.size()>0)
+				zax->setWhitelist(whitelistFile);
+			if (blacklistFile.size()>0)
+				zax->setBlacklist(blacklistFile);
+
+			zax->setVerbose(verbose);
+			zax->setBasicBlockOptimization(bb_graph_optimize);
+			zax->setDomgraphOptimization(domgraph_optimize);
+			zax->setBasicBlockFloatingInstrumentation(floating_instrumentation);
+			zax->setEnableForkServer(forkserver_enabled);
+			zax->setBreakupCriticalEdges(breakup_critical_edges);
+			zax->setContextSensitivity(context_sensitivity); 
+
+			int success=zax->execute();
+
+			if (success)
+			{
+				cout<<"Writing changes for "<<this_file->getURL()<<endl;
+				one_success = true;
+				firp->writeToDB();
+			}
+			else
+			{
+				cout<<"Skipping (no changes) "<<this_file->getURL()<<endl;
+			}
+		}
+		catch (const DatabaseError_t pnide)
+		{
+			cerr << programName << ": Unexpected database error: " << pnide << "file url: " << this_file->getURL() << endl;
+			exit(1);
+		}
+		catch (const std::exception &e)
+		{
+			cerr << programName << ": Error: " << e.what() << endl;
+			exit(1);
+		}
+		catch (...)
+		{
+			cerr << programName << ": Unexpected error file url: " << this_file->getURL() << endl;
+			exit(1);
+		}
+	} // end file iterator
+
+	// if any transforms for any files succeeded, we commit
+	if (one_success)
+	{
+		cout<<"Commiting changes...\n";
+		pqxx_interface->commit();
+	}
+
+	return 0;
+}
+
diff --git a/zfuzz/afl_transforms/tools/zax/zuntracer.cpp b/zfuzz/afl_transforms/tools/zax/zuntracer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..82cb301283b458de1c339445b32ed3e5452ff7c8
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/zuntracer.cpp
@@ -0,0 +1,227 @@
+#include "zuntracer.hpp"
+
+using namespace std;
+using namespace IRDB_SDK;
+using namespace Zafl;
+
+ZUntracer_t::ZUntracer_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, string p_forkServerEntryPoint, set<string> p_exitPoints, bool p_use_stars, bool p_autozafl) : ZaxBase_t(p_dbinterface, p_variantIR, p_forkServerEntryPoint, p_exitPoints, p_use_stars, p_autozafl)
+{
+}
+
+void ZUntracer_t::instrumentBasicBlock(BasicBlock_t *p_bb, const bool p_redZoneHint, const bool p_collafl_optimization)
+{
+	if (!p_bb) throw;
+
+	const auto trace_map_fixed_addr       = getenv("ZAFL_TRACE_MAP_FIXED_ADDRESS");
+	const auto do_fixed_addr_optimization = (trace_map_fixed_addr!=nullptr);
+
+	if (do_fixed_addr_optimization)
+		_instrumentBasicBlock_fixed(p_bb, trace_map_fixed_addr);
+	else
+		_instrumentBasicBlock(p_bb, p_redZoneHint);
+}
+
+// Highly efficient instrumentation using known address for tracemap
+void ZUntracer_t::_instrumentBasicBlock_fixed(BasicBlock_t *p_bb, char* p_tracemap_addr)
+{
+	// 1st instruction in block record is the new entry point of the block (instr)
+	// 2nd instruction in block record is where the instruction at the old entry point is now at (orig)
+	auto instr = getInstructionToInstrument(p_bb);
+	if (!instr) throw;
+
+	const auto blockid = getBlockId();
+	BBRecord_t block_record;
+	block_record.push_back(instr);
+
+	// e.g.: mov BYTE [ 0x10000 + blockid ], 0x1
+	const auto s = string("mov BYTE [") + p_tracemap_addr + "+" + to_string(blockid) + "], 0x1";
+	const auto orig = insertAssemblyBefore(instr, s);
+	block_record.push_back(orig);
+
+	m_modifiedBlocks[blockid] = block_record;
+}
+
+void ZUntracer_t::_instrumentBasicBlock(BasicBlock_t *p_bb, const bool p_redZoneHint)
+{
+	/*
+	Original afl instrumentation:
+	        block_id = <random>;
+	        zafl_trace_bits[zafl_prev_id ^ block_id]++;
+		zafl_prev_id = block_id >> 1;     
+
+	Zuntracer instrumentation (simple block coverage)
+		zafl_trace_bits[block_id] = 1;
+	*/
+
+	const auto num_free_regs_desired = 1;
+	auto instr = getInstructionToInstrument(p_bb, num_free_regs_desired);
+	if (!instr) throw;
+
+	auto tmp = instr;
+	auto tracemap_reg = string();
+	auto found_tracemap_free_register = false;
+
+	// 1st instruction in block record is the new entry point of the block (instr)
+	// 2nd instruction in block record is where the instruction at the old entry point is now at (orig)
+	BBRecord_t block_record;
+
+	block_record.push_back(instr);
+	
+	const auto blockid = getBlockId();
+	const auto labelid = getLabelId(); 
+
+	if (m_verbose)
+		cout << "working with blockid: " << blockid << " labelid: " << labelid << endl;
+
+	if (m_use_stars) 
+	{
+		const auto allowed_regs = RegisterSet_t({rn_RAX, rn_RBX, rn_RCX, rn_RDX, rn_R8, rn_R9, rn_R10, rn_R11, rn_R12, rn_R13, rn_R14, rn_R15});
+		const auto dead_regs = getDeadRegs(instr);
+		const auto free_regs = getFreeRegs(dead_regs, allowed_regs);
+		if (free_regs.size() > 0)
+		{
+			auto r = *free_regs.begin();
+			tracemap_reg = registerToString(r);
+			found_tracemap_free_register = true;
+		}
+	}
+
+	auto inserted_before = false;
+	auto honorRedZone = p_redZoneHint;
+
+	const auto do_insert=[&](const string& insn_str) -> void
+		{
+			if (inserted_before)
+			{
+				tmp = insertAssemblyAfter(tmp, insn_str);
+				block_record.push_back(tmp);
+			}
+			else
+			{
+				const auto orig = insertAssemblyBefore(tmp, insn_str);
+				inserted_before = true;
+				block_record.push_back(orig);
+			}
+		};
+
+
+	// if we have a free register, we don't muck with the stack ==> no need to honor red zone
+	if (found_tracemap_free_register)
+	{
+		honorRedZone = false;
+	}
+
+	if (honorRedZone) 
+	{
+		do_insert("lea rsp, [rsp-128]");
+	}
+
+	// we did not find a free register, save rcx and then use it for the tracemap
+	if (!found_tracemap_free_register)
+	{
+		tracemap_reg = "rcx";
+		do_insert("push " + tracemap_reg);
+	}
+
+	assert(tracemap_reg.size()>0);
+
+	// load address trace map into rcx:     T123: mov rcx, QWORD [rel T123]
+	const auto load_trace_map = "T" + to_string(labelid) + ": mov " + tracemap_reg + " , QWORD [ rel T" + to_string(labelid) + "]";
+	do_insert(load_trace_map);
+	create_got_reloc(getFileIR(), m_trace_map, tmp);
+
+	// update trace map: e.g.:              mov rcx, [rcx]
+	do_insert("mov " + tracemap_reg + ", [" + tracemap_reg + "]");
+
+	// set counter to 1:                    mov BYTE [rcx+1234], 1
+	do_insert("mov BYTE [" + tracemap_reg + "+" + to_string(blockid) + "], 1");
+
+	// restore register
+	if (!found_tracemap_free_register)
+	{
+		do_insert("pop " + tracemap_reg);
+	}
+	
+	// red zone
+	if (honorRedZone) 
+	{
+		do_insert("lea rsp, [rsp+128]");
+	}
+
+	m_modifiedBlocks[blockid] = block_record;
+}
+
+set<BasicBlock_t*> ZUntracer_t::getBlocksToInstrument(ControlFlowGraph_t &cfg)
+{
+	static int bb_z_debug_id=-1;
+
+	if (m_verbose)
+		cout << cfg << endl;
+
+	auto keepers = set<BasicBlock_t*>();
+
+	for (auto &bb : cfg.getBlocks())
+	{
+		bb_z_debug_id++;
+
+		// already marked as a keeper
+		if (keepers.find(bb) != keepers.end())
+			continue;
+ 
+		// if whitelist specified, only allow instrumentation for functions/addresses in whitelist
+		if (!isWhitelisted(bb->getInstructions()[0]))
+			continue;
+
+		if (isBlacklisted(bb->getInstructions()[0]))
+			continue;
+
+		// debugging support
+		if (getenv("ZAFL_LIMIT_BEGIN"))
+		{
+			if (bb_z_debug_id < atoi(getenv("ZAFL_LIMIT_BEGIN")))
+				continue;	
+		}
+
+		// debugging support
+		if (getenv("ZAFL_LIMIT_END"))
+		{
+			if (bb_z_debug_id >= atoi(getenv("ZAFL_LIMIT_END"))) 
+				continue;
+		}
+
+		// make sure we're not trying to instrument code we just inserted, e.g., fork server, added exit points
+		if (bb->getInstructions()[0]->getBaseID() < 0)
+			continue;
+
+		// push/jmp pair, don't bother instrumenting
+		if (BB_isPushJmp(bb))
+		{
+			m_num_bb_skipped_pushjmp++;
+			continue;
+		}
+
+		// padding nop, don't bother
+		if (BB_isPaddingNop(bb))
+		{
+			m_num_bb_skipped_nop_padding++;
+			continue;
+		}
+
+		// optimization:
+		//    @warning @todo:
+		//    very experimental!
+		//    elide instrumentation for conditional branches
+		//
+		if (m_graph_optimize)
+		{
+			if (bb->getSuccessors().size() == 2 && bb->endsInConditionalBranch())
+			{
+				m_num_bb_skipped_cbranch++;
+				continue;
+			}
+		}
+
+		keepers.insert(bb);
+	}
+	return keepers;
+}
diff --git a/zfuzz/afl_transforms/tools/zax/zuntracer.hpp b/zfuzz/afl_transforms/tools/zax/zuntracer.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..eba33a8874d490d4fdaefd6f393e0e8676f50ecb
--- /dev/null
+++ b/zfuzz/afl_transforms/tools/zax/zuntracer.hpp
@@ -0,0 +1,31 @@
+#ifndef _LIBTRANSFORM_ZUNTRACER_H
+#define _LIBTRANSFORM_ZUNTRACER_H
+
+#include "zax_base.hpp"
+
+namespace Zafl
+{
+
+	using namespace IRDB_SDK;
+
+	// Block-level instrumentation for Untracer
+	class ZUntracer_t : public ZaxBase_t
+	{
+		public:
+			ZUntracer_t() = delete;
+			ZUntracer_t(const ZUntracer_t&) = delete;
+			ZUntracer_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, string p_entry, set<string> p_exits, bool p_use_stars=false, bool p_autozafl=false);
+			virtual ~ZUntracer_t() {};
+
+		protected:
+			virtual void instrumentBasicBlock(BasicBlock_t*, const bool p_hasLeafAnnotation, const bool p_collafl_optimization=false);
+			virtual set<BasicBlock_t*> getBlocksToInstrument(ControlFlowGraph_t&);
+
+		private:
+			void _instrumentBasicBlock_fixed(BasicBlock_t*, char* p_tracemap_addr);
+			void _instrumentBasicBlock(BasicBlock_t*, const bool p_redZoneHint);
+	};
+
+} 
+
+#endif
diff --git a/zfuzz/bin/zafl.sh b/zfuzz/bin/zafl.sh
new file mode 100755
index 0000000000000000000000000000000000000000..904cf0ad340a4a88726919138edbfc2e14d4d99d
--- /dev/null
+++ b/zfuzz/bin/zafl.sh
@@ -0,0 +1,407 @@
+#!/bin/bash
+
+#
+# Invoke underlying Zipr toolchain with Zafl step and parameters
+#
+
+if [ ! -z $TERM ] && [ "$TERM" != "dumb" ]; then
+	RED=`tput setaf 1`
+	GREEN=`tput setaf 2`
+	YELLOW=`tput setaf 3`
+	ORANGE=`tput setaf 214`
+	MAGENTA=`tput setaf 5`
+	NC=`tput sgr0`
+fi
+
+usage()
+{
+	echo
+	echo "zafl.sh <input_binary> <output_zafl_binary> [options]"
+	echo 
+	echo "options:"
+	echo "     -s, --stars                             Use STARS (default)"
+	echo "     -S, --no-stars                          Do not use STARS"
+	echo "     -g, --graph-optimization                Use control flow graph optimizations"
+	echo "     -G, --no-graph-optimization             Do not use control flow graph optimizations (default)"
+	echo "     -d, --domgraph-optimization             Use Dominator graph optimizations"
+	echo "     -D, --no-domgraph-optimization          Do not use Dominator graph optimizations (default)"
+	echo "     -t, --tempdir <dir>                     Specify location of analysis results directory"
+	echo "     -e, --entry                             Specify fork server entry point"
+	echo "     -E, --exit                              Specify fork server exit point(s)"
+	echo "     -u, --untracer                          Specify untracer instrumentation"
+	echo "     -c, --enable-breakup-critical-edges     Breakup critical edges"
+	echo "     -C, --disable-breakup-critical-edges    Do not breakup critical edges (default)"
+	echo "     -f, --fork-server-only                  Fork server only"
+	echo "     -m, --enable-fixed-map [<address>]      Use fixed address for tracing map (<address> must be hex and page-aligned, e.g., 0x10000)"
+	echo "     -M, --disable-fixed-map                 Disable fixed address tracing map"
+	echo "     -i, --enable-floating-instrumentation   Select best instrumentation point within basic block (default)"
+	echo "     -I, --disable-floating-instrumentation  Use first instruction for instrumentation in basic blocks"
+	echo "     --enable-context-sensitivity <style>    style={callsite,function} only function supported currently (off by default)"
+	echo "     -r, --random-seed <value>               Specify random seed"
+#	echo "     -l, --enable-locality                   Maintain code locality (best effort) when instrumenting binary"
+#	echo "     -L, --disable-locality                  Randomized layout when instrumenting binary"
+	echo "     -w, --whitelist <file>                  Specify function whitelist (one function per line)"
+	echo "     -b, --blacklist <file>                  Specify function blacklist (one function per line)"
+	echo "     --enable-split-compare                  enable laf-intel split compare for integer constants"
+	echo "     --disable-split-compare                 disable laf-intel split compare for integer constants"
+	echo "     --enable-split-branch                   enable laf-intel split branch for integer constants"
+	echo "     --disable-split-branch                  disable laf-intel split branch for integer constants"
+	echo "     -v                                      Verbose mode" 
+	echo 
+}
+
+ida_or_rida_opt=" -c rida "
+stars_opt=" -o zax:--stars "
+zax_opt=""
+other_args=""
+#float_opt=""
+float_opt=" -o zax:--enable-floating-instrumentation "
+context_sensitivity_opt=""
+trace_opt=""
+zipr_opt=""
+random_seed=""
+laf_opt=""
+
+
+me=$(whoami)
+tmp_dir=/tmp/${me}/$$
+mkdir -p $tmp_dir
+
+# by default, use fixed address for map
+trace_map_address="0x10000"
+ZAFL_TM_ENV=""
+
+cleanup()
+{
+	if [ ! -z "$tmp_dir" ]; then
+		rm -fr $tmp_dir
+	fi
+}
+
+log_msg()
+{
+	echo -e "${GREEN}Zafl: $1 ${NC}"
+}
+
+log_warning()
+{
+	echo -e "${ORANGE}Zafl: $1 ${NC}"
+}
+
+log_error()
+{
+	echo -e "${RED}Zafl: $1 ${NC}"
+}
+
+log_error_exit()
+{
+	log_error "$1"
+	cleanup
+	exit 1
+}
+
+parse_args()
+{
+	PARAMS=""
+	while (( "$#" )); do
+		key="$1"
+
+		case $key in
+			-h|--help)
+				usage
+				exit 0
+				;;
+			--ida)
+				ida_or_rida_opt=" -c meds_static=on -s rida=off "
+				shift
+				;;
+			--rida)
+				ida_or_rida_opt=" -s meds_static=off -c rida=on "
+				shift
+				;;
+			-s | --stars)
+				stars_opt=" -o zax:--stars "
+				shift
+				;;
+			-S | --no-stars)
+				stars_opt=" "
+				float_opt=" -o zax:--disable-floating-instrumentation "
+				shift
+				;;
+			-g | --graph-optimization)
+				zax_opt=" $zax_opt -o zax:-g "
+				shift
+				;;
+			-G | --no-graph-optimization)
+				zax_opt=" $zax_opt -o zax:-G "
+				shift
+				;;
+			-d | --domgraph-optimization)
+				zax_opt=" $zax_opt -o zax:-d "
+				shift
+				;;
+			-D | --no-domgraph-optimization)
+				zax_opt=" $zax_opt -o zax:-D "
+				shift
+				;;
+			-e | --entry)
+				shift
+				entry_opt=" -o zax:\"-e $1\" "
+				shift
+				;;
+			-E | --exit)
+				shift
+				exit_opt=" $exit_opt -o zax:\"-E $1\" "
+				shift
+				;;
+			-v | --verbose)
+				verbose_opt=" -o zax:-v "
+				shift
+				;;
+			-t | --tempdir)
+				shift
+				other_args=" --tempdir $1"
+				shift
+				;;
+			-w | --whitelist)
+				shift
+				zax_opt=" $zax_opt -o zax:\"--whitelist $(realpath $1) \""
+				shift
+				;;
+			-b | --blacklist)
+				shift
+				zax_opt=" $zax_opt -o zax:\"--blacklist $(realpath $1) \""
+				shift
+				;;
+			-u | --untracer)
+				zax_opt=" $zax_opt -o zax:--untracer "
+				shift
+				;;
+			-c | --enable-breakup-critical-edges)
+				zax_opt=" $zax_opt -o zax:-c "
+				shift
+				;;
+			-C | --disable-breakup-critical-edges)
+				zax_opt=" $zax_opt -o zax:-C "
+				shift
+				;;
+			-f | --fork-server-only)
+				ZAFL_LIMIT_END=0
+				export ZAFL_LIMIT_END
+				log_warning "Fork Server Only mode: no block-level instrumentation will be performed"
+				shift
+				;;
+			-m | --enable-fixed-map)
+				shift
+				case $1 in
+					0x*)
+						trace_map_address="$1"
+						shift
+					;;
+				esac
+				ZAFL_TM_ENV="ZAFL_TRACE_MAP_FIXED_ADDRESS=$trace_map_address"
+				;;
+			-M | --disable-fixed-map)
+				unset ZAFL_TRACE_MAP_FIXED_ADDRESS
+				ZAFL_TM_ENV=""
+				shift
+				;;
+			-i | --enable-floating-instrumentation)
+				float_opt=" -o zax:--enable-floating-instrumentation "
+				shift
+				;;
+			-I | --disable-floating-instrumentation)
+				float_opt=" -o zax:--disable-floating-instrumentation "
+				shift
+				;;
+			--enable-context-sensitivity)
+				shift
+				case $1 in
+					function)
+						zax_opt=" -o zax:\"--enable-context-sensitivity function\" "
+						shift
+					;;
+					callsite)
+						zax_opt=" -o zax:\"--enable-context-sensitivity callsite\" "
+						echo "Error: context sensitivity <callsite> currently unsupported"
+						exit 1
+					;;
+					*)
+						echo "Error: must specify function or callsite for context sensitivity"
+						exit 1
+					;;
+				esac
+				;;
+			-r | --random-seed)
+				shift
+				random_seed="$1"
+				zax_opt=" $zax_opt -o zax:\"--random-seed $random_seed\" "
+				zipr_opt=" $zipr_opt --step-option zipr:\"--zipr:seed $random_seed\" "
+				shift
+				;;
+			-l | --enable-locality)
+				trace_opt=" --step-option zipr:--traceplacement:on --step-option zipr:true "
+				shift
+				;;
+			-L | --disable-locality)
+				trace_opt=""
+				shift
+				;;
+			--enable-split-compare)
+				laf_opt=" $laf_opt -o laf:--enable-split-compare "
+				shift
+				;;
+			--disable-split-compare)
+				laf_opt=" $laf_opt -o laf:--disable-split-compare "
+				shift
+				;;
+			--enable-split-branch)
+				laf_opt=" $laf_opt -o laf:--enable-split-branch "
+				shift
+				;;
+			--disable-split-branch)
+				laf_opt=" $laf_opt -o laf:--disable-split-branch "
+				shift
+				;;
+			-*|--*=) # unsupported flags
+				echo "Error: Unsupported flag $1" >&2
+				exit 1
+				;;
+    			*) # preserve positional arguments
+				PARAMS="$PARAMS $1"
+				shift
+				;;
+		esac
+	done
+
+	eval set -- "$PARAMS"
+	positional=($PARAMS)
+	input_binary=${positional[0]}
+	output_zafl_binary=${positional[1]}
+
+	if [ -z $input_binary ]; then
+		usage
+		log_error_exit "You must specify an input binary to be protected"
+	fi
+
+	if [ -z $output_zafl_binary ]; then
+		usage
+		log_error_exit "You must specify the name of the output binary"
+	fi
+
+	input_binary=$(realpath $input_binary)
+}
+
+find_main()
+{
+	main_addr=""
+	tmp_objdump=$tmp_dir/tmp.objdump
+	tmp_main=$tmp_dir/tmp.main
+
+	objdump -d $input_binary > $tmp_objdump
+
+	grep "<main>:" $tmp_objdump > $tmp_main
+
+	if [  $? -eq 0 ]; then
+		main_addr=$(cut -d' ' -f1 $tmp_main)
+		log_msg "Detected main at: 0x$main_addr"
+		options=" $options -o zax:'-e 0x$main_addr'"
+	else
+		grep -B1 "libc_start_main@" $tmp_objdump >/dev/null 2>&1
+		if [ $? -eq 0 ]; then
+			grep -B1 start_main $tmp_objdump | grep rdi | grep rip >/dev/null 2>&1
+			if [ $? -eq 0 ]; then
+				ep=$(readelf -h $input_binary | grep -i "entry point" | cut -d'x' -f2)
+				if [ ! -z $ep ]; then
+					log_msg "main exec is PIE... use entry point address (0x$ep) for fork server"
+					options=" $options -o zax:'-e 0x$ep'"
+				else
+					log_error_exit "error finding entry point address"
+				fi
+			else
+				grep "libc_start_main" $tmp_objdump | grep ">:" | grep -v -e "@plt" -e "jmp" >/dev/null 2>&1
+				if [ $? -eq 0 ]; then
+					log_msg "Detected libc: no main"
+					rm $tmp_objdump
+					return
+				fi
+
+				main_addr=$(grep -B1 libc_start_main@plt $tmp_objdump | grep mov | grep rdi | cut -d':' -f2 | cut -d'm' -f2 | cut -d',' -f1 | cut -d'x' -f2)
+				if [ "$main_addr" = "" ]; then 
+					log_error_exit "error inferring main"
+				fi
+
+				log_msg "inferring main to be at: 0x$main_addr"
+				options=" $options -o zax:'-e 0x$main_addr'"
+			fi
+		else
+			log_warning "no main() detected, probably a library ==> no automated insertion of fork server"
+		fi
+	fi
+	rm $tmp_objdump >/dev/null 2>&1
+}
+
+verify_zafl_symbols()
+{
+	# verify library dependency set
+	ldd $1 | grep -e libzafl -e libautozafl >/dev/null 2>&1
+	if [ $? -eq 0 ]; then
+		log_msg "success. Output file is: $1"
+	else
+		ldd $1
+		log_error_exit "output binary does not show a dependence on the Zafl support library"
+	fi
+
+	# sanity check symbols in zafl library resolve
+	ldd -d $1 | grep symbol | grep 'not defined' >/dev/null 2>&1
+	if [ $? -eq 0 ]; then
+		log_error_exit "something went wrong in resolving Zafl symbols"
+	fi
+}
+
+parse_args $*
+if [ -z "$entry_opt" ]; then
+	find_main
+else
+	options=" $options $entry_opt "
+fi
+
+if [ ! -z "$exit_opt" ]; then
+	options=" $options $exit_opt "
+fi
+
+#
+# Execute Zipr toolchain with Zafl options
+#
+log_msg "Transforming input binary $input_binary into $output_zafl_binary"
+
+optional_step=""
+if [ ! -z "$laf_opt" ];
+then
+	optional_step=" -c laf=on $laf_opt "
+fi
+
+zax_opt=" $zax_opt $float_opt "
+cmd="$ZAFL_TM_ENV $PSZ $input_binary $output_zafl_binary $ida_or_rida_opt -c move_globals=on $optional_step -c zax=on -o move_globals:--elftables-only $stars_opt $zax_opt $verbose_opt $options $other_args $trace_opt $zipr_opt"
+
+
+if [ ! -z "$ZAFL_TM_ENV" ]; then
+	log_msg "Trace map will be expected at fixed address"
+	if [ -z $ZAFL_TRACE_MAP_FIXED_ADDRESS ]; then
+		log_warning "When running afl-fuzz, make sure that the environment variable ZAFL_TRACE_MAP_FIXED_ADDRESS is exported and set properly to (otherwise the instrumented binary will crash):"
+		log_warning "export $ZAFL_TM_ENV"
+	fi
+else
+	if [ ! -z $ZAFL_TRACE_MAP_FIXED_ADDRESS ]; then
+		log_msg "Trace map will be at fixed address: $ZAFL_TRACE_MAP_FIXED_ADDRESS"
+	fi
+fi
+
+log_msg "Issuing command: $cmd"
+eval $cmd
+if [ $? -eq 0 ]; then
+	verify_zafl_symbols $output_zafl_binary
+else
+	log_error_exit "error transforming input program"
+fi
+
diff --git a/zfuzz/build-all.sh b/zfuzz/build-all.sh
new file mode 100755
index 0000000000000000000000000000000000000000..845b062ca636439d6abe848729c82b77c7263e07
--- /dev/null
+++ b/zfuzz/build-all.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+echo
+echo "Building Fuzzing Support"
+echo
+
+SCONSDEBUG=""
+if [[ "$*" =~ "--debug" ]]; then
+	SCONSDEBUG=" debug=1 "
+fi
+
+cd $AFL_TRANSFORMS
+scons $SCONSDEBUG -j 3 || exit
+
+cd $ZFUZZ_HOME/libzafl
+scons
+cp lib/* $ZEST_RUNTIME/lib64/
+
+
diff --git a/zfuzz/clean-all.sh b/zfuzz/clean-all.sh
new file mode 100755
index 0000000000000000000000000000000000000000..54fcb50cef3afeff6d75ab354d56a1cfe4dc75b9
--- /dev/null
+++ b/zfuzz/clean-all.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+cd $AFL_TRANSFORMS
+scons -c || exit
+
+cd $ZFUZZ_HOME/libzafl/src
+scons -c || exit
+scons autozafl=1 -c || exit
+
+cd $ZFUZZ_HOME
+rm -fr afl
diff --git a/zfuzz/get-packages.sh b/zfuzz/get-packages.sh
new file mode 100755
index 0000000000000000000000000000000000000000..42bc16e296de1bb6e01686f4e0dd033f3e587945
--- /dev/null
+++ b/zfuzz/get-packages.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+args="$@"
+if [[ "$args" == "" ]]; then
+        args="all"
+fi
+
+for arg in $args; do
+	case $arg in
+		build)
+			# do nothing
+		;;
+
+		all | deploy | test)
+		        which apt-get 1> /dev/null 2> /dev/null
+			if [ $? -eq 0 ]; then
+				sudo apt-get install -y --ignore-missing afl
+			else
+				sudo yum install -y --skip-broken afl
+			fi
+		;;
+
+		*)
+			echo "arg not recognized. Recognized args: all, build, test, deploy"
+			exit 1
+		;;
+	esac
+done
diff --git a/zfuzz/libzafl b/zfuzz/libzafl
new file mode 160000
index 0000000000000000000000000000000000000000..5bcb4a8dbae1af977384ceda3b92e402f3c7f67d
--- /dev/null
+++ b/zfuzz/libzafl
@@ -0,0 +1 @@
+Subproject commit 5bcb4a8dbae1af977384ceda3b92e402f3c7f67d
diff --git a/zfuzz/manifest.txt b/zfuzz/manifest.txt
new file mode 100644
index 0000000000000000000000000000000000000000..445b1c8c73767510674eda1da672a40d879a6eea
--- /dev/null
+++ b/zfuzz/manifest.txt
@@ -0,0 +1,5 @@
+# env vars.
+file set_env_vars zfuzz
+file get-packages.sh zfuzz
+directory bin zfuzz
+directory test zfuzz
diff --git a/zfuzz/set_env_vars b/zfuzz/set_env_vars
new file mode 100644
index 0000000000000000000000000000000000000000..7f210602174452a34543d9343e9c835e587189d8
--- /dev/null
+++ b/zfuzz/set_env_vars
@@ -0,0 +1,5 @@
+export ZFUZZ_HOME=`pwd`
+export AFL_TRANSFORMS=$ZFUZZ_HOME/afl_transforms
+export PATH=$PATH:$ZFUZZ_HOME/bin
+export AFL_SKIP_BIN_CHECK=1
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib
diff --git a/zfuzz/test/bc.fixed_map/test_bc.sh b/zfuzz/test/bc.fixed_map/test_bc.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c62e0e0618c49341198d381479c0c9759bc933ca
--- /dev/null
+++ b/zfuzz/test/bc.fixed_map/test_bc.sh
@@ -0,0 +1,107 @@
+export AFL_TIMEOUT=15
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/:. 
+
+user=$(whoami)
+session=/tmp/tmp.${user}.zafl.bc.fixed_map.$$
+
+cleanup()
+{
+	rm -fr $session
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	cleanup
+	exit 1
+}
+
+log_message()
+{
+	echo "TEST  MSG: $1"
+}
+
+log_success()
+{
+	echo "TEST PASS: $1"
+}
+
+fuzz_with_zafl()
+{
+	bc_zafl=$1
+
+	env | grep ZAFL
+
+	# setup AFL directories
+	mkdir zafl_in
+	echo "1" > zafl_in/1
+
+	if [ -d zafl_out ]; then
+		rm -fr zafl_out
+	fi
+
+	# run for 30 seconds
+	timeout $AFL_TIMEOUT afl-fuzz -i zafl_in -o zafl_out -- $bc_zafl 
+	if [ $? -eq 124 ]; then
+		if [ ! -e zafl_out/fuzzer_stats ]; then
+			log_error "$bc_zafl: something went wrong with afl -- no fuzzer stats file"
+		fi
+
+		cat zafl_out/fuzzer_stats
+		execs_per_sec=$( grep execs_per_sec zafl_out/fuzzer_stats )
+		log_success "$bc_zafl: $execs_per_sec"
+	else
+		log_error "$bc_zafl: unable to run with afl"
+	fi
+
+}
+
+mkdir -p $session
+pushd $session
+
+# Fix map at 0x10000
+# Should match value in env. var ZAFL_TRACE_MAP_FIXED_ADDRESS
+trace_map_address="0x10000"
+
+# build ZAFL version of bc executable with fixed map
+
+zafl.sh `which bc` bc.fixed.zafl -m $trace_map_address --tempdir analysis.bc.fixed.zafl
+if [ $? -eq 0 ]; then
+	log_success "build bc.fixed.zafl"
+else
+	log_error "build bc.fixed.zafl"
+fi
+grep ATTR analysis.bc.fixed.zafl/logs/zax.log
+log_message "Fuzz for $AFL_TIMEOUT secs"
+fuzz_with_zafl $(realpath ./bc.fixed.zafl)
+
+# build ZAFL version of readline shared library
+readline=$( ldd `which bc` | grep libreadline | cut -d'>' -f2 | cut -d'(' -f1 )
+readline_basename=$( basename $readline )
+readline_realpath=$( realpath $readline )
+echo "basename: $readline_basename  realpath: $readline_realpath"
+zafl.sh $readline_realpath $readline_basename -m $trace_map_address
+if [ $? -eq 0 ]; then
+	log_success "build zafl version of $readline_basename at $readline_realpath"
+else
+	log_error "build zafl version of $readline_basename at $readline_realpath"
+fi
+
+ldd bc.fixed.zafl
+
+log_message "Fuzz for $AFL_TIMEOUT secs (with readline library zafl'ed)"
+fuzz_with_zafl $(realpath ./bc.fixed.zafl)
+
+# test functionality
+echo "2+3" | `which bc` > out.bc.orig
+echo "2+3" | ./bc.fixed.zafl > out.bc.fixed.zafl
+diff out.bc.orig out.bc.fixed.zafl >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+	log_success "bc.fixed.zafl basic functionality"
+else
+	log_error "bc.fixed.zafl basic functionality"
+fi
+
+popd
+
+cleanup
diff --git a/zfuzz/test/bc/test_bc.sh b/zfuzz/test/bc/test_bc.sh
new file mode 100755
index 0000000000000000000000000000000000000000..09358674e59976ed25915e76c4ff002d6dab0774
--- /dev/null
+++ b/zfuzz/test/bc/test_bc.sh
@@ -0,0 +1,95 @@
+export AFL_TIMEOUT=15
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/:. 
+
+user=$(whoami)
+session=/tmp/tmp.${user}.zafl.bc.$$
+
+cleanup()
+{
+	rm -fr $session
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	cleanup
+	exit 1
+}
+
+log_message()
+{
+	echo "TEST  MSG: $1"
+}
+
+log_success()
+{
+	echo "TEST PASS: $1"
+}
+
+fuzz_with_zafl()
+{
+	bc_zafl=$1
+
+	# setup AFL directories
+	mkdir zafl_in
+	echo "1" > zafl_in/1
+
+	if [ -d zafl_out ]; then
+		rm -fr zafl_out
+	fi
+
+	# run for 30 seconds
+	timeout $AFL_TIMEOUT afl-fuzz -i zafl_in -o zafl_out -- $bc_zafl 
+	if [ $? -eq 124 ]; then
+		if [ ! -e zafl_out/fuzzer_stats ]; then
+			log_error "$bc_zafl: something went wrong with afl -- no fuzzer stats file"
+		fi
+
+		cat zafl_out/fuzzer_stats
+		execs_per_sec=$( grep execs_per_sec zafl_out/fuzzer_stats )
+		log_success "$bc_zafl: $execs_per_sec"
+	else
+		log_error "$bc_zafl: unable to run with afl"
+	fi
+
+}
+
+mkdir -p $session
+pushd $session
+
+# build with graph optimization
+zafl.sh `which bc` bc.stars.zafl.d.g.r.cs -d -g --tempdir analysis.bc.stars.zafl.d.g.r.cs -r 123 --enable-context-sensitivity function
+if [ $? -eq 0 ]; then
+	log_success "build bc.stars.zafl.d.g.r.cs"
+else
+	log_error "build bc.stars.zafl.d.g.r.cs"
+fi
+log_message "Fuzz for $AFL_TIMEOUT secs"
+fuzz_with_zafl $(realpath ./bc.stars.zafl.d.g.r.cs)
+
+# build ZAFL version of readline shared library
+readline=$( ldd `which bc` | grep libreadline | cut -d'>' -f2 | cut -d'(' -f1 )
+readline_basename=$( basename $readline )
+readline_realpath=$( realpath $readline )
+echo "basename: $readline_basename  realpath: $readline_realpath"
+#$PSZ $readline_realpath $readline_basename -c move_globals=on -c zafl=on -o move_globals:--elftables -o zipr:--traceplacement:on -o zipr:true -o zafl:--stars 
+zafl.sh $readline_realpath $readline_basename --random-seed 42 -d
+if [ $? -eq 0 ]; then
+	log_success "build zafl version of $readline_basename at $readline_realpath"
+else
+	log_error "build zafl version of $readline_basename at $readline_realpath"
+fi
+
+# test functionality
+echo "2+3" | `which bc` > out.bc.orig
+echo "2+3" | ./bc.stars.zafl.d.g.r.cs > out.bc.stars.zafl.d.g.r.cs
+diff out.bc.orig out.bc.stars.zafl.d.g.r.cs >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+	log_success "bc.stars.zafl.d.g.r.cs basic functionality"
+else
+	log_error "bc.stars.zafl.d.g.r.cs basic functionality"
+fi
+
+popd
+
+cleanup
diff --git a/zfuzz/test/bench/binutils.spec b/zfuzz/test/bench/binutils.spec
new file mode 100755
index 0000000000000000000000000000000000000000..26ef326726a0aa003317098dfb21064f18eb6c69
--- /dev/null
+++ b/zfuzz/test/bench/binutils.spec
@@ -0,0 +1,20 @@
+#tools can be aflgcc zafl qemu dyninst
+tools="aflgcc zafl qemu"
+
+#binutils_binaries="objdump size readelf strings cxxfilt nm-new strip-new ar"
+binutils_binaries="objdump readelf nm-new"
+
+# specify how to run under afl
+declare -A fuzz_map
+fuzz_map["size"]="@@"
+fuzz_map["objdump"]="-d @@"
+fuzz_map["readelf"]="-a @@"
+fuzz_map["strings"]=""
+fuzz_map["cxxfilt"]=""
+fuzz_map["nm-new"]="-a @@"
+fuzz_map["strip-new"]="@@"
+fuzz_map["gzip"]="-f"
+
+# additional afl params to pass in
+declare -A afl_args
+afl_args["objdump"]=" -m 150 "
diff --git a/zfuzz/test/bench/build_aflgcc.sh b/zfuzz/test/bench/build_aflgcc.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2dfd7254ab47a51c9c12ed91bd121bba3aa00ac8
--- /dev/null
+++ b/zfuzz/test/bench/build_aflgcc.sh
@@ -0,0 +1,17 @@
+SCRIPT=$(readlink -f $0)                                                                            
+
+cd $(dirname $SCRIPT)
+source binutils.spec
+
+echo "Build afl-gcc version of $binutils_binaries"
+
+for b in $binutils_binaries
+do
+	aflgcc_dir="${b}_aflgcc"
+	if [ ! -d $aflgcc_dir ];
+	then
+		mkdir ${b}_aflgcc
+	fi
+
+	cp binutils-2.30/binutils/$b ${b}_aflgcc/${b}.aflgcc
+done
diff --git a/zfuzz/test/bench/build_dyninst.sh b/zfuzz/test/bench/build_dyninst.sh
new file mode 100755
index 0000000000000000000000000000000000000000..e7454ed340c937df62c3cbc84ca72ef63608f2cf
--- /dev/null
+++ b/zfuzz/test/bench/build_dyninst.sh
@@ -0,0 +1,24 @@
+source binutils.spec
+echo "Build dyninst version of $binutils_binaries"
+
+AFL_DYNINST_DIR=/home/an7s/aware/zfuzz/afl-dyninst/
+AFL_DYNINST=$AFL_DYNINST_DIR/afl-dyninst
+
+for b in $binutils_binaries
+do
+	dyninst_dir="${b}_dyninst"
+	if [ ! -d $dyninst_dir ];
+	then
+		mkdir ${b}_dyninst
+	fi
+
+	cp binutils-2.30/binutils/$b ${b}_dyninst
+
+	pushd $dyninst_dir
+	echo "Building Zafl version of $b"
+	ln -s $AFL_DYNINST_DIR/libAflDyninst.so .
+	$AFL_DYNINST -f -i $b -o ${b}.dyninst
+	mkdir in
+	echo "1" > in/1
+	popd
+done
diff --git a/zfuzz/test/bench/build_qemu.sh b/zfuzz/test/bench/build_qemu.sh
new file mode 100755
index 0000000000000000000000000000000000000000..05defdba7aafea96d9079f6ecaa0ece50ff528bf
--- /dev/null
+++ b/zfuzz/test/bench/build_qemu.sh
@@ -0,0 +1,13 @@
+source binutils.spec
+echo "Build qemu version of $binutils_binaries"
+
+for b in $binutils_binaries
+do
+	qemu_dir="${b}_qemu"
+	if [ ! -d $qemu_dir ];
+	then
+		mkdir ${b}_qemu
+	fi
+
+	cp binutils-2.30/binutils/$b ${b}_qemu/${b}.qemu
+done
diff --git a/zfuzz/test/bench/build_zafl.sh b/zfuzz/test/bench/build_zafl.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f7499d9f334a50cf650b5f317a06f3c61b062641
--- /dev/null
+++ b/zfuzz/test/bench/build_zafl.sh
@@ -0,0 +1,29 @@
+SCRIPT=$(readlink -f $0)                                                                            
+
+cd $(dirname $SCRIPT)
+source binutils.spec
+
+echo "Zafl $binutils_binaries"
+
+for b in $binutils_binaries
+do
+	zafl_dir="${b}_zafl"
+	if [ ! -d $zafl_dir ];
+	then
+		mkdir ${b}_zafl
+	fi
+
+	cp binutils-2.30/binutils/$b ${b}_zafl/
+
+	pushd $zafl_dir
+	echo "Remove any remnants of previous analysis runs"
+	rm -fr peasoup_exec*
+	echo "Building Zafl version of $b"
+	zafl.sh ./$b ${b}.zafl 
+
+	if [ ! -d in ]; then
+		mkdir in
+	fi
+	echo "1" > in/1
+	popd
+done
diff --git a/zfuzz/test/bench/download.sh b/zfuzz/test/bench/download.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8583614f0e5dfc4617a59a479abb5f88202e2df0
--- /dev/null
+++ b/zfuzz/test/bench/download.sh
@@ -0,0 +1,9 @@
+wget http://ftp.gnu.org/gnu/gzip/gzip-1.9.tar.gz
+tar -zxf gzip*.tar.gz
+
+wget http://ftp.gnu.org/gnu/bc/bc-1.07.tar.gz
+tar -zxf bc*.tar.gz 
+
+wget http://ftp.gnu.org/gnu/binutils/binutils-2.30.tar.gz
+tar -zxf binut*.tar.gz 
+
diff --git a/zfuzz/test/bench/run-all.sh b/zfuzz/test/bench/run-all.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9974a28d240eaff798fb368d90ff9500277c32cd
--- /dev/null
+++ b/zfuzz/test/bench/run-all.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+SCRIPT=$(readlink -f $0)
+MYDIR=$(dirname $SCRIPT)
+
+cd $MYDIR
+
+source binutils.spec
+
+echo "Evaluate $binutils_binaries"
+AFL_TIMEOUT=3600
+EPOCH_TIMEOUT=3800
+
+./setup_afl.sh
+
+for b in $binutils_binaries
+do
+	echo "fuzz_map for $b: ${fuzz_map[$b]}"
+
+	cd $MYDIR/${b}_aflgcc
+	nohup timeout $AFL_TIMEOUT afl-fuzz ${afl_args[$b]} -i in -o out -- ./${b}.aflgcc ${fuzz_map[$b]} &
+
+	cd $MYDIR/${b}_zafl
+	nohup timeout $AFL_TIMEOUT afl-fuzz ${afl_args[$b]} -i in -o out -- ./${b}.zafl ${fuzz_map[$b]} &
+
+	cd $MYDIR/${b}_dyninst
+	nohup timeout $AFL_TIMEOUT afl-fuzz ${afl_args[$b]} -i in -o out -- ./${b}.dyninst ${fuzz_map[$b]} &
+
+	cd $MYDIR/${b}_qemu
+	nohup timeout $AFL_TIMEOUT afl-fuzz ${afl_args[$b]} -i in -o out -Q -- ./${b}.qemu ${fuzz_map[$b]} &
+
+	sleep $EPOCH_TIMEOUT
+
+	pkill afl-fuzz >/dev/null 2>&1
+	pkill afl-qemu-trace >/dev/null 2>&1
+
+	grep execs ${b}_*/out/fuzzer_stats
+done
diff --git a/zfuzz/test/bench/run-zafl-all.sh b/zfuzz/test/bench/run-zafl-all.sh
new file mode 100755
index 0000000000000000000000000000000000000000..27a8a11e22f20f5c0f2e99655352611592c4ec8a
--- /dev/null
+++ b/zfuzz/test/bench/run-zafl-all.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+AFL_TIMEOUT=3600
+EPOCH_TIMEOUT=3800
+
+SCRIPT=$(readlink -f $0)
+MYDIR=$(dirname $SCRIPT)
+
+cd $MYDIR
+
+source binutils.spec
+
+echo
+echo "Build and compare different Zafl configurations"
+echo
+
+binaries=$binutils_binaries
+trials="a b c"
+
+# build all the zafl configurations we care about
+for b in $binaries
+do
+	cd $MYDIR/${b}_zafl
+	echo building in $PWD
+	if [ ! -e $b.zafl ]; then
+		$PSZ $b $b.zafl -c move_globals=on -c zax=on -o move_globals:--elftables -o zipr:'--zipr:seed 123'
+	fi
+#	if [ ! -e $b.zafl.stars ]; then
+#		$PSZ $b $b.zafl.stars -c move_globals=on -c zax=on -o move_globals:--elftables -o zafl:--stars -o zipr:'--zipr:seed 123'
+#	fi
+#	if [ ! -e $b.zafl.trace ]; then
+#		$PSZ $b $b.zafl.trace -c move_globals=on -c zax=on -o move_globals:--elftables -o zipr:--traceplacement:on -o zipr:'--zipr:seed 123'
+#	fi
+#	if [ ! -e $b.zafl.stars.trace ]; then
+#		$PSZ $b $b.zafl.stars.trace -c move_globals=on -c zax=on -o move_globals:--elftables -o zipr:--traceplacement:on -o zipr:true -o zafl:--stars -o zipr:'--zipr:seed 123'
+#	fi
+#	if [ ! -e $b.zafl.stars.relax ]; then
+#		$PSZ $b $b.zafl.stars.relax -c move_globals=on -c zax=on -o move_globals:--elftables -o zipr:--relax:on -o zafl:--stars -o zipr:'--zipr:seed 123'
+#	fi
+done
+
+for t in $trials
+do
+	for b in $binaries
+	do
+		cd $MYDIR/${b}_zafl
+
+		echo "fuzz_map for $b: ${fuzz_map[$b]}"
+
+		# create input seed directory
+		mkdir in >/dev/null 2>&1
+		echo "1" > in/1
+
+		rm -fr out.$t.zafl
+		nohup timeout $AFL_TIMEOUT afl-fuzz -i in -o out.$t.zafl -- ./$b.zafl ${fuzz_map[$b]} &
+#		nohup timeout $AFL_TIMEOUT afl-fuzz -i in -o out.$t.zafl.stars -- ./$b.zafl.stars ${fuzz_map[$b]} &
+#		nohup timeout $AFL_TIMEOUT afl-fuzz -i in -o out.$t.zafl.trace -- ./$b.zafl.trace ${fuzz_map[$b]} &
+#		nohup timeout $AFL_TIMEOUT afl-fuzz -i in -o out.$t.zafl.stars.trace -- ./$b.zafl.stars.trace ${fuzz_map[$b]} &
+#		nohup timeout $AFL_TIMEOUT afl-fuzz -i in -o out.$t.zafl.stars.relax -- ./$b.zafl.stars.relax ${fuzz_map[$b]} &
+
+		sleep $EPOCH_TIMEOUT
+
+		pkill afl-fuzz >/dev/null 2>&1
+	done
+done
diff --git a/zfuzz/test/bench/setup_afl.sh b/zfuzz/test/bench/setup_afl.sh
new file mode 100755
index 0000000000000000000000000000000000000000..95a41ff712e6662c1b352c6b4c09b6265f8a47a7
--- /dev/null
+++ b/zfuzz/test/bench/setup_afl.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+SCRIPT=$(readlink -f $0)
+MYDIR=$(dirname $SCRIPT)
+
+cd $MYDIR
+
+source binutils.spec
+
+for b in $binutils_binaries
+do
+	for t in $tools
+	do
+		pushd ${b}_${t}
+		if [ ! -d in ]; then
+			mkdir in
+		fi
+		echo "1" > in/1
+
+		if [ -d out ]; then
+			rm -fr out
+		fi
+		popd
+	done
+done
diff --git a/zfuzz/test/bench/setup_aflgcc.sh b/zfuzz/test/bench/setup_aflgcc.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4429cf27503efab167fab22c993420e1880797f2
--- /dev/null
+++ b/zfuzz/test/bench/setup_aflgcc.sh
@@ -0,0 +1,8 @@
+pushd binutils-2.30
+make clean distclean
+rm -fr config.cache
+rm -fr */config.cache
+rm -fr */*/config.cache
+CC=afl-gcc ./configure
+make clean all
+popd
diff --git a/zfuzz/test/bench/setup_binutils.sh b/zfuzz/test/bench/setup_binutils.sh
new file mode 100755
index 0000000000000000000000000000000000000000..74adaff01b65bb63a557183d233b8a5e7e8969d5
--- /dev/null
+++ b/zfuzz/test/bench/setup_binutils.sh
@@ -0,0 +1,8 @@
+pushd binutils-2.30
+make clean distclean
+rm -fr config.cache
+rm -fr */config.cache
+rm -fr */*/config.cache
+./configure
+make clean all
+popd
diff --git a/zfuzz/test/gzip/test_gzip.sh b/zfuzz/test/gzip/test_gzip.sh
new file mode 100755
index 0000000000000000000000000000000000000000..28b661595e7e4d9737c53a1e1b6a370da3540e46
--- /dev/null
+++ b/zfuzz/test/gzip/test_gzip.sh
@@ -0,0 +1,134 @@
+AFL_TIMEOUT=30
+session=/tmp/tmp.gzip.$$
+TMP_FILE_1="${session}/gzip.tmp.$$"
+TMP_FILE_2="${session}/gzip.tmp.$$"
+
+mkdir -p $session
+
+cleanup()
+{
+	rm -fr /tmp/gzip.tmp* gzip*.zafl peasoup_exec*.gzip* zafl_in zafl_out ${session}
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	exit 1
+}
+
+log_message()
+{
+	echo "TEST  MSG: $1"
+}
+
+log_success()
+{
+	echo "TEST PASS: $1"
+}
+
+setup()
+{
+	echo "hello" > $TMP_FILE_1
+	echo "hello" > $TMP_FILE_2
+}
+
+build_zafl()
+{
+	gzip_zafl=$1
+	shift
+	$PSZ `which gzip` $gzip_zafl -c move_globals=on -c zax=on -o move_globals:--elftables -o zipr:--traceplacement:on -o zipr:true $* --tempdir analysis.${gzip_zafl}
+	if [ ! $? -eq 0 ]; then
+		log_error "$gzip_zafl: unable to generate zafl version"	
+	else
+		log_message "$gzip_zafl: built successfully"
+	fi
+
+	grep ATTR analysis.${gzip_zafl}/logs/zax.log
+}
+
+test_zafl()
+{
+	gzip_zafl=$( realpath $1 )
+	shift
+
+	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/ $gzip_zafl $* $TMP_FILE_1
+	if [ ! $? -eq 0 ]; then
+		log_error "$gzip_zafl $*: unable to gzip file using zafl version"
+	fi
+
+	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/ $gzip_zafl -d ${TMP_FILE_1}.gz
+	diff $TMP_FILE_1 $TMP_FILE_2
+	if [ $? -eq 0 ]; then
+		log_success "$gzip_zafl $*: after zipping and unzipping, we get the same file back. yeah!"
+	else
+		log_error "$gzip_zafl $*: after zipping and unzipping, we get a diferent file"
+	fi
+}
+
+fuzz_with_zafl()
+{
+	gzip_zafl=$1
+
+	# setup AFL directories
+	mkdir zafl_in
+	echo "1" > zafl_in/1
+
+	if [ -d zafl_out ]; then
+		rm -fr zafl_out
+	fi
+
+	# run for 30 seconds
+	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/ timeout $AFL_TIMEOUT afl-fuzz -i zafl_in -o zafl_out -- $gzip_zafl -f
+	if [ $? -eq 124 ]; then
+		if [ ! -e zafl_out/fuzzer_stats ]; then
+			log_error "$gzip_zafl: something went wrong with afl -- no fuzzer stats file"
+		fi
+
+		cat zafl_out/fuzzer_stats
+		execs_per_sec=$( grep execs_per_sec zafl_out/fuzzer_stats )
+		log_success "$gzip_zafl: ran zafl binary: $execs_per_sec"
+	else
+		log_error "$gzip_zafl: unable to run with afl"
+	fi
+
+}
+
+pushd ${session}
+setup
+
+
+file /bin/gzip | grep "shared object" >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+	echo "PIE detected -- this test only designed for non-PIE"
+	exit 1
+fi
+
+# test setting of entry point via address
+ep=$( objdump -Mintel -d /bin/gzip | grep text | grep -v -i disassembly | cut -d' ' -f1 | sed 's/^00000000//g' )
+build_zafl gzip.stars.entrypoint.${ep}.zafl -o zax:--stars -o "zax:--entrypoint=$ep"
+test_zafl ./gzip.stars.entrypoint.${ep}.zafl --fast
+
+# test setting of entry point via function name
+build_zafl gzip.entrypoint.zafl -o "zax:--entrypoint=main"
+test_zafl ./gzip.entrypoint.zafl --best
+
+# test non-STARS version
+build_zafl gzip.nostars.zafl
+test_zafl ./gzip.nostars.zafl
+test_zafl ./gzip.nostars.zafl --fast
+test_zafl ./gzip.nostars.zafl --best
+
+# test STARS version
+build_zafl gzip.stars.zafl -o zax:--stars
+test_zafl ./gzip.stars.zafl
+test_zafl ./gzip.stars.zafl --fast
+test_zafl ./gzip.stars.zafl --best
+
+# test STARS version on AFL
+log_message "Fuzz for $AFL_TIMEOUT seconds"
+fuzz_with_zafl ./gzip.stars.zafl
+
+log_success "all tests passed: zafl instrumentation operational on gzip"
+
+cleanup
+popd
diff --git a/zfuzz/test/ls.zuntracer/test_ls.sh b/zfuzz/test/ls.zuntracer/test_ls.sh
new file mode 100755
index 0000000000000000000000000000000000000000..eb4b6ef93844b18061a1014f12a57df1d64a50b0
--- /dev/null
+++ b/zfuzz/test/ls.zuntracer/test_ls.sh
@@ -0,0 +1,127 @@
+AFL_TIMEOUT=15
+session=/tmp/tmp.ls.$$
+TMP_FILE_1="${session}/ls.tmp.$$"
+
+mkdir -p $session
+
+cleanup()
+{
+	rm -fr /tmp/ls.tmp* ls*.zafl peasoup_exec*.ls* zafl_in zafl_out ${session}
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	exit 1
+}
+
+log_message()
+{
+	echo "TEST  MSG: $1"
+}
+
+log_success()
+{
+	echo "TEST PASS: $1"
+}
+
+setup()
+{
+	echo "hello" > $TMP_FILE_1
+}
+
+build_zuntracer()
+{
+	ls_zafl=$1
+	shift
+	zafl.sh `which ls` $ls_zafl --untracer --tempdir analysis.${ls_zafl} $*
+	if [ ! $? -eq 0 ]; then
+		log_error "$ls_zafl: unable to generate zafl version"	
+	else
+		log_message "$ls_zafl: built successfully"
+	fi
+
+	grep ATTR analysis.${ls_zafl}/logs/zax.log
+	if [ ! $? -eq 0 ]; then
+		log_error "$ls_zafl: no attributes or zax.log file produced"
+	fi
+
+	if [ ! -f analysis.${ls_zafl}/zax.map ]; then
+		log_error "$ls_zafl: zax.map file not found"
+	fi
+}
+
+test_zuntracer()
+{
+	ls_zafl=$( realpath $1 )
+	shift
+	$ls_zafl $* $TMP_FILE_1
+	if [ ! $? -eq 0 ]; then
+		log_error "$ls_zafl $*: unable to ls file using zafl version"
+	fi
+}
+
+fuzz_with_zafl()
+{
+	ls_zafl=$1
+	shift
+
+	# setup AFL directories
+	mkdir zafl_in
+	echo "1" > zafl_in/1
+
+	if [ -d zafl_out ]; then
+		rm -fr zafl_out
+	fi
+
+	# run for 30 seconds
+	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/ timeout $AFL_TIMEOUT afl-fuzz -i zafl_in -o zafl_out -- $ls_zafl $*
+	if [ $? -eq 124 ]; then
+		if [ ! -e zafl_out/fuzzer_stats ]; then
+			log_error "$ls_zafl: something went wrong with afl -- no fuzzer stats file"
+		fi
+
+		cat zafl_out/fuzzer_stats
+		execs_per_sec=$( grep execs_per_sec zafl_out/fuzzer_stats )
+		log_success "$ls_zafl $*: ran zafl binary: $execs_per_sec"
+	else
+		log_error "$ls_zafl $*: unable to run with afl"
+	fi
+
+}
+
+pushd ${session}
+setup
+
+# zuntracer, don't break critical edges
+build_zuntracer ls.untracer.no_critical_edge -C
+test_zuntracer ./ls.untracer.no_critical_edge -lt
+
+# zuntracer, do break critical edges
+build_zuntracer ls.untracer.critical_edge -c
+test_zuntracer ./ls.untracer.critical_edge -lt
+
+# zuntracer, do break critical edges, optimize graph
+build_zuntracer ls.untracer.critical_edge.graph -c -g -M
+test_zuntracer ./ls.untracer.critical_edge.graph -lt
+
+log_message "Fuzz zuntracer (basic block coverage) for $AFL_TIMEOUT seconds"
+fuzz_with_zafl ./ls.untracer.no_critical_edge -lt
+
+log_message "Fuzz zuntracer (break critical edges) for $AFL_TIMEOUT seconds"
+fuzz_with_zafl ./ls.untracer.critical_edge -lt 
+
+log_message "Fuzz zuntracer (break critical edges + graph optimization) for $AFL_TIMEOUT seconds"
+fuzz_with_zafl ./ls.untracer.critical_edge.graph -lt
+
+build_zuntracer ls.untracer.fixed -m 
+test_zuntracer ./ls.untracer.fixed -lt
+build_zuntracer ls.untracer.fixed.0x10000 -m 0x10000
+test_zuntracer ./ls.untracer.fixed.0x10000 -lt
+
+fuzz_with_zafl ./ls.untracer.fixed.0x10000 -lt
+
+log_success "all tests passed: zafl/zuntracer instrumentation operational on ls"
+
+cleanup
+popd
diff --git a/zfuzz/test/od/test_od.sh b/zfuzz/test/od/test_od.sh
new file mode 100755
index 0000000000000000000000000000000000000000..67d2f75d0aceabbb799d8cf356ab845b75fbb1d5
--- /dev/null
+++ b/zfuzz/test/od/test_od.sh
@@ -0,0 +1,71 @@
+export AFL_TIMEOUT=15
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/:. 
+
+session=/tmp/tmp.od.$$
+
+cleanup()
+{
+	rm -fr /tmp/od.tmp* od*.zafl peasoup_exec*.od* zafl_in zafl_out $session
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	exit 1
+}
+
+log_message()
+{
+	echo "TEST  MSG: $1"
+}
+
+log_success()
+{
+	echo "TEST PASS: $1"
+}
+
+fuzz_with_zafl()
+{
+	od_zafl=$1
+
+	# setup AFL directories
+	mkdir zafl_in
+	echo "1" > zafl_in/1
+
+	if [ -d zafl_out ]; then
+		rm -fr zafl_out
+	fi
+
+	# run for 30 seconds
+	timeout $AFL_TIMEOUT afl-fuzz -i zafl_in -o zafl_out -- $od_zafl @@
+	if [ $? -eq 124 ]; then
+		if [ ! -e zafl_out/fuzzer_stats ]; then
+			log_error "$od_zafl: something went wrong with afl -- no fuzzer stats file"
+		fi
+
+		cat zafl_out/fuzzer_stats
+		execs_per_sec=$( grep execs_per_sec zafl_out/fuzzer_stats )
+		log_success "$od_zafl: $execs_per_sec"
+	else
+		log_error "$od_zafl: unable to run with afl"
+	fi
+
+}
+
+mkdir $session
+pushd $session
+
+# build ZAFL (with graph optimizations) version of od executable
+zafl.sh `which od` od.zafl.d.g -d -g --tempdir analysis.od.zafl.d.g
+if [ $? -eq 0 ]; then
+	log_success "build od.zafl.d.g"
+else
+	log_error "build od.zafl.d.g"
+fi
+grep ATTR analysis.od.zafl.d.g/logs/zax.log
+
+log_message "Fuzz rida.zafl for $AFL_TIMEOUT secs"
+fuzz_with_zafl $(realpath ./od.zafl.d.g)
+
+cleanup
+popd
diff --git a/zfuzz/test/sha256sum/test_sha256sum.sh b/zfuzz/test/sha256sum/test_sha256sum.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5fccb52600cd9b3f7bcaa05c275a91e8b075d9c5
--- /dev/null
+++ b/zfuzz/test/sha256sum/test_sha256sum.sh
@@ -0,0 +1,89 @@
+export AFL_TIMEOUT=15
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/:. 
+
+session=/tmp/tmp.sha256sum.$$
+
+cleanup()
+{
+	rm -fr /tmp/sha256sum.tmp* sha256sum*.zafl peasoup_exec*.sha256sum* zafl_in zafl_out $session
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	exit 1
+}
+
+log_message()
+{
+	echo "TEST  MSG: $1"
+}
+
+log_success()
+{
+	echo "TEST PASS: $1"
+}
+
+fuzz_with_zafl()
+{
+	sha256sum_zafl=$1
+
+	# setup AFL directories
+	mkdir zafl_in
+	echo "1" > zafl_in/1
+
+	if [ -d zafl_out ]; then
+		rm -fr zafl_out
+	fi
+
+	# run for 30 seconds
+	timeout $AFL_TIMEOUT afl-fuzz -i zafl_in -o zafl_out -- $sha256sum_zafl 
+	if [ $? -eq 124 ]; then
+		if [ ! -e zafl_out/fuzzer_stats ]; then
+			log_error "$sha256sum_zafl: something went wrong with afl -- no fuzzer stats file"
+		fi
+
+		cat zafl_out/fuzzer_stats
+		execs_per_sec=$( grep execs_per_sec zafl_out/fuzzer_stats )
+		log_success "$sha256sum_zafl: $execs_per_sec"
+	else
+		log_error "$sha256sum_zafl: unable to run with afl"
+	fi
+
+}
+
+mkdir $session
+pushd $session
+
+# build ZAFL (no Ida) version of sha256sum executable
+zafl.sh `which sha256sum` sha256sum.rida.zafl --tempdir analysis.sha256sum
+if [ $? -eq 0 ]; then
+	log_success "build sha256sum.rida.zafl"
+else
+	log_error "build sha256sum.rida.zafl"
+fi
+grep ATTR analysis.sha256sum/logs/zax.log
+if [ ! $? -eq 0 ]; then
+	log_error "zax transform did not run"
+fi
+
+log_message "Fuzz rida.zafl for $AFL_TIMEOUT secs"
+fuzz_with_zafl $(realpath ./sha256sum.rida.zafl)
+
+# build ZAFL (with Ida) version of sha256sum executable
+zafl.sh `which sha256sum` sha256sum.ida.zafl --tempdir analysis.sha256sum.ida
+if [ $? -eq 0 ]; then
+	log_success "build sha256sum.ida.zafl"
+else
+	log_error "build sha256sum.ida.zafl"
+fi
+grep ATTR analysis.sha256sum.ida/logs/zax.log
+if [ ! $? -eq 0 ]; then
+	log_error "zax transform did not run"
+fi
+
+log_message "Fuzz ida.zafl for $AFL_TIMEOUT secs"
+fuzz_with_zafl $(realpath ./sha256sum.ida.zafl)
+
+cleanup
+popd
diff --git a/zfuzz/test/spec2006/test_spec.sh b/zfuzz/test/spec2006/test_spec.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b792652d3a49d0f4a3c8c233ba168d222af190a2
--- /dev/null
+++ b/zfuzz/test/spec2006/test_spec.sh
@@ -0,0 +1,240 @@
+#!/bin/bash
+
+# the bad boys
+#benchmarks="
+#	400.perlbench
+#	403.gcc
+#	445.gobmk
+#	450.soplex
+#	453.povray
+#	458.sjeng
+#	464.h264ref
+#	465.tonto
+#	471.omnetpp
+#	481.wrf
+#	482.sphinx3
+#	483.xalancbmk
+#	"
+
+# all
+all_benchmarks="400.perlbench 401.bzip2 403.gcc 410.bwaves 416.gamess 429.mcf 433.milc 434.zeusmp 435.gromacs 436.cactusADM 437.leslie3d 444.namd 445.gobmk 450.soplex 453.povray 454.calculix 456.hmmer 458.sjeng 459.GemsFDTD 462.libquantum 464.h264ref 465.tonto 470.lbm 471.omnetpp 473.astar 481.wrf 482.sphinx3 483.xalancbmk"
+#all_benchmarks=" 403.gcc "
+#all_benchmarks=" 401.bzip2 "
+
+
+# should be 3 for reportable run
+number=1
+
+setup()
+{
+
+	if [ ! -d spec2006 ]; then
+		#svn co ^/spec2006/trunk spec2006
+		git clone --depth 1 http://git.zephyr-software.com/allzp/spec2006.git spec2006
+	fi
+
+	if [[ ! -f /usr/bin/gfortran ]]; then
+		sudo apt-get install gfortran -y
+	fi
+
+	cd spec2006/
+	if [ ! -L bin ]; then
+		ln -s bin.power/ bin
+	fi
+	source shrc
+	bin/relocate
+}
+
+
+run_test()
+{
+	config_name=$1
+	config=$2
+	benchmarks="$3"
+	cd $SPEC
+	if [ ! -d result.$config_name ]; then
+		dropdb $PGDATABASE
+		createdb $PGDATABASE
+		$PEASOUP_HOME/tools/db/pdb_setup.sh
+		rm -Rf result/*
+		runspec  --action scrub --config $config $benchmarks
+
+		echo
+		echo "**************************************************************************"
+		echo "Starting test of $config_name"
+		echo "**************************************************************************"
+		echo
+		runspec  --action validate --config $config -n $number $benchmarks 
+		cp benchspec/CPU2006/*/exe/* result
+		mv result result.$config_name
+		for bench in $benchmarks
+		do
+			mv benchspec/CPU2006/$bench/run/build*/peasoup*/logs result.$config_name/$bench.log
+		done
+	fi
+
+}
+
+get_size_result()
+{
+	bench=$1
+	if [ -e $bench ]; then
+		size=$(stat --printf="%s" $bench)
+		#echo -n "$size"
+		#LC_ALL= numfmt --grouping $size
+		#LC_ALL= printf "%'d" $size
+		#LC_NUMERIC=en_US printf "%'d" $size
+		#LC_NUMERIC=en_US printf "%'f" $size
+		#LC_NUMERIC=en_US printf "%'.f" $size
+		#LC_NUMERIC=en_US printf "%'10.10f" $size
+		#LC_NUMERIC=en_US /usr/bin/printf "%'d" $size
+		echo $size
+	else
+		echo -n "0"
+	fi
+}
+
+get_result()
+{
+	bench=$1
+	config=$2
+
+	results=$(cat $SPEC/result.$config/CPU2006.002.log|grep Success|grep $bench|grep ratio=|sed 's/.*ratio=//'|sed 's/,.*//')
+
+	sum=0
+	count=0
+	for res in $results
+	do
+		sum=$(echo $sum + $res | bc)
+		count=$(echo $count + 1  | bc)
+	done
+	#echo sum=$sum
+	#echo count=$count
+	res=$(echo  "scale=2; $sum / $count" | bc 2> /dev/null )
+
+	count=$(echo $res|wc -w)
+
+	if [ $count = 1 ];  then
+		echo -n $res
+	else
+		echo -n "0"
+	fi
+
+}
+
+
+get_raw_results()
+{
+	get_raw_perf_results "$@"
+	get_raw_size_results "$@"
+	#get_raw_fde_results "$@"
+}
+
+get_raw_perf_results()
+{
+	configs=$*
+	first_config=$1
+	echo "--------------------------------------------------------------"
+	echo "Performance results are:"
+	echo "--------------------------------------------------------------"
+	echo benchmark $configs
+	for bench in $benchmarks
+	do
+		echo -n "$bench 	"
+		for config in $*
+		do
+			get_result $bench $config
+			echo -n "	"
+		done
+		echo
+	done
+}
+
+get_raw_size_results()
+{
+	echo "--------------------------------------------------------------"
+	echo "Size results are:"
+	echo "--------------------------------------------------------------"
+	configs=$*
+	echo benchmark $configs
+	for bench in $SPEC/result.$first_config/*_base.amd64-m64-gcc42-nn
+	do
+		echo -n "$(basename $bench _base.amd64-m64-gcc42-nn)	"
+		for config in $*
+		do
+			if [[ $config == "baseline" ]]; then
+				file="$SPEC/result.$config/$(basename $bench)"
+				cp $file /tmp/foo.exe
+				strip /tmp/foo.exe
+				file="/tmp/foo.exe"
+			else
+				file="$SPEC/result.$config/$(basename $bench)"
+			fi
+			res=$(get_size_result $file)
+
+			#printf "%15s" $res
+			echo -n "	$res"
+		done
+		echo
+	done
+
+}
+
+get_raw_fde_results()
+{
+	echo "--------------------------------------------------------------"
+	echo "FDE results are:"
+	echo "--------------------------------------------------------------"
+	configs=$*
+	echo benchmark $configs
+	for bench in $SPEC/result.$first_config/*_base.amd64-m64-gcc42-nn
+	do
+		#printf "%-20s"  $(basename $bench _base.amd64-m64-gcc42-nn)
+		echo -n $(basename $bench _base.amd64-m64-gcc42-nn)
+		for config in $*
+		do
+			file="$SPEC/result.$config/$(basename $bench)"
+			res=$(readelf -w $file |grep FDE|wc -l )
+			#if [[ $config == "baseline" ]]; then
+			#else
+			#fi
+
+			#printf "%15s" $res
+			echo -n "	$res"
+		done
+		echo
+	done
+
+}
+
+main()
+{
+	zipr_flags="	--backend zipr --step-option zipr:--add-sections --step-option zipr:true"
+	trace_flags="   --step-option zipr:--traceplacement:on --step-option zipr:true"
+	relax_flags="   --step-option zipr:--relax:on --step-option zipr:true --step-option zipr:--unpin:on --step-option zipr:false"
+	nounpin_flags=" --step-option zipr:--unpin:on --step-option zipr:false"
+	split_flags="   --step-option fill_in_indtargs:--split-eh-frame "
+	icall_flags="   --step-option fix_calls:--no-fix-icalls "
+	p1flags=" 	-c p1transform=on " 
+	zafl_flags="    --backend zipr -s meds_static=off -s rida=on -c move_globals=on -c zax=on -o move_globals:--elftables-only "
+	zafl_opt_flags="--backend zipr -s meds_static=off -s rida=on -c move_globals=on -c zax=on -o move_globals:--elftables-only -o zipr:--traceplacement:on -o zax:--stars "
+	start_dir=$(pwd)
+	setup
+
+	# baseline 
+	run_test baseline $SPEC/config/ubuntu14.04lts-64bit.cfg "$all_benchmarks"
+
+	# should be 100% success, tested by jdh on 4/11/18 as 100% success.
+	PSOPTS="$zipr_flags "  run_test zipr     $SPEC/config/ubuntu14.04lts-64bit-withps.cfg "$all_benchmarks"
+
+	PSOPTS="$zafl_flags "  run_test zafl   $SPEC/config/ubuntu14.04lts-64bit-withps.cfg "$all_benchmarks"
+
+#	PSOPTS="$zafl_opt_flags "  run_test zafl   $SPEC/config/ubuntu14.04lts-64bit-withps.cfg "$all_benchmarks"
+
+	get_raw_results baseline zipr zafl
+}
+
+main "$@"
+
+
+
diff --git a/zfuzz/test/spec2017/test_spec17.sh b/zfuzz/test/spec2017/test_spec17.sh
new file mode 100755
index 0000000000000000000000000000000000000000..97a4daf85965ae910704779ada7a3a2548d3b869
--- /dev/null
+++ b/zfuzz/test/spec2017/test_spec17.sh
@@ -0,0 +1,234 @@
+#!/bin/bash
+
+run_size="test"
+
+all_benchmarks=" 
+600.perlbench_s 602.gcc_s 603.bwaves_s 605.mcf_s 607.cactuBSSN_s 619.lbm_s 620.omnetpp_s 621.wrf_s 623.xalancbmk_s 625.x264_s 627.cam4_s 628.pop2_s 631.deepsjeng_s 638.imagick_s 641.leela_s 644.nab_s 648.exchange2_s 649.fotonik3d_s 654.roms_s 657.xz_s 996.specrand_fs 998.specrand_is 
+"
+
+all_benchmarks="
+502.gcc_s 625.x264_s
+"
+
+
+
+number=1
+
+setup()
+{
+
+	if [ ! -d spec2017 ]; then
+		#svn co ^/spec2017/trunk spec2017
+		git clone --depth 1 git@git.zephyr-software.com:allzp/spec2017.git spec2017
+	fi
+
+	if [[ ! -f /usr/bin/gfortran ]]; then
+		sudo apt-get install gfortran gcc g++ -y
+	fi
+
+	cd spec2017/
+	source shrc
+}
+
+
+run_test()
+{
+	local config_name="$1"
+	local config="$2"
+	local benchmarks="$3"
+
+	tests_that_ran="$tests_that_ran $config_name"
+
+	cd $SPEC
+	if [ ! -d result.$config_name ]; then
+		bash -x $PEASOUP_UMBRELLA_DIR/postgres_reset.sh
+		rm -Rf result/*
+		runcpu  --action scrub --config $config $benchmarks
+
+		echo
+		echo "**************************************************************************"
+		echo "Starting test of $config_name"
+		echo "**************************************************************************"
+		echo
+		#runspec  --action validate --config $config -n $number $benchmarks 
+                runcpu  --config $config --iterations $number --size $run_size --copies=8 --parallel_test_workload $run_size --noreportable $benchmarks
+
+ 		cp benchspec/CPU/*/exe/* result
+		mv result result.$config_name
+		for bench in $benchmarks
+		do
+                        mv benchspec/CPU/$bench/build/build*/peasoup*/logs result.$config_name/$bench.log
+		done
+	fi
+
+}
+
+get_size_result()
+{
+	bench=$1
+	if [ -e $bench ]; then
+		size=$(stat --printf="%s" $bench)
+		#echo -n "$size"
+		#LC_ALL= numfmt --grouping $size
+		#LC_ALL= printf "%'d" $size
+		#LC_NUMERIC=en_US printf "%'d" $size
+		#LC_NUMERIC=en_US printf "%'f" $size
+		#LC_NUMERIC=en_US printf "%'.f" $size
+		#LC_NUMERIC=en_US printf "%'10.10f" $size
+		#LC_NUMERIC=en_US /usr/bin/printf "%'d" $size
+		echo $size
+	else
+		echo -n "0"
+	fi
+}
+
+get_result()
+{
+	bench=$1
+	config=$2
+
+	results=$(cat $SPEC/result.$config/CPU2017.002.log|grep Success|grep $bench|grep ratio=|sed 's/.*ratio=//'|sed 's/,.*//')
+
+	sum=0
+	count=0
+	for res in $results
+	do
+		sum=$(echo $sum + $res | bc)
+		count=$(echo $count + 1  | bc)
+	done
+	#echo sum=$sum
+	#echo count=$count
+	res=$(echo  "scale=2; $sum / $count" | bc 2> /dev/null )
+
+	count=$(echo $res|wc -w)
+
+	if [ $count = 1 ];  then
+		echo -n $res
+	else
+		echo -n "0"
+	fi
+
+}
+
+
+get_raw_results()
+{
+	get_raw_perf_results $tests_that_ran
+	get_raw_size_results $tests_that_ran
+	#get_raw_fde_results $tests_that_ran
+}
+
+get_raw_perf_results()
+{
+	configs="$*"
+	first_config=$1
+
+
+	echo "--------------------------------------------------------------"
+	echo "Performance results are:"
+	echo "--------------------------------------------------------------"
+	echo benchmark $configs
+	for bench in $all_benchmarks
+	do
+		echo -n "$bench 	"
+		for config in $*
+		do
+			get_result $bench $config
+			echo -n "	"
+		done
+		echo
+	done
+}
+
+get_raw_size_results()
+{
+	echo "--------------------------------------------------------------"
+	echo "Size results are:"
+	echo "--------------------------------------------------------------"
+	configs=$*
+	echo benchmark $configs
+	for bench in $SPEC/result.$first_config/*mytest-m64
+	do
+		echo -n "$(basename $bench _base.mytest-m64)	"
+		for config in $*
+		do
+			if [[ $config == "baseline" ]]; then
+				file="$SPEC/result.$config/$(basename $bench)"
+				cp $file /tmp/foo.exe
+				strip /tmp/foo.exe
+				file="/tmp/foo.exe"
+			else
+				file="$SPEC/result.$config/$(basename $bench)"
+			fi
+			res=$(get_size_result $file)
+
+			#printf "%15s" $res
+			echo -n "	$res"
+		done
+		echo
+	done
+
+}
+
+get_raw_fde_results()
+{
+	echo "--------------------------------------------------------------"
+	echo "FDE results are:"
+	echo "--------------------------------------------------------------"
+	configs=$*
+	echo benchmark $configs
+	for bench in $SPEC/result.$first_config/*mytest-m64
+	do
+		#printf "%-20s"  $(basename $bench _base.amd64-m64-gcc42-nn)
+		echo -n $(basename $bench _base.amd64-m64-gcc42-nn)
+		for config in $*
+		do
+			file="$SPEC/result.$config/$(basename $bench)"
+			res=$(readelf -w $file |grep FDE|wc -l )
+			#if [[ $config == "baseline" ]]; then
+			#else
+			#fi
+
+			#printf "%15s" $res
+			echo -n "	$res"
+		done
+		echo
+	done
+
+}
+
+main()
+{
+	local zipr_flags="	--backend zipr --step-option zipr:--add-sections --step-option zipr:true"
+	local rida_flags="	-c rida "
+	local trace_flags="   --step-option zipr:--traceplacement:on --step-option zipr:true"
+	local relax_flags="   --step-option zipr:--relax:on --step-option zipr:true --step-option zipr:--unpin:on --step-option zipr:false"
+	local nounpin_flags=" --step-option zipr:--unpin:on --step-option zipr:false"
+	local split_flags="   --step-option fill_in_indtargs:--split-eh-frame "
+	local icall_flags="   --step-option fix_calls:--no-fix-icalls "
+	local p1flags=" 	-c p1transform=on " 
+	local zafl_flags="     "
+	local zafl_domgraphflags=" -d    "
+
+	# sets $SPEC
+	setup
+
+	local nops_config=$SPEC/config/ubuntu14.cfg
+	local withps_config=$SPEC/config/ubuntu14_withps.cfg
+	
+
+	# baseline 
+	run_test baseline $SPEC/config/ubuntu14.cfg "$all_benchmarks"
+
+	PSOPTS="$zipr_flags $rida_flags "  run_test zipr.rida  $withps_config "$all_benchmarks"
+
+	PS="zafl.sh" PSOPTS="$zafl_flags "           run_test zafl.vanilla   $withps_config "$all_benchmarks"
+	PS="zafl.sh" PSOPTS="$zafl_domgraph_flags "  run_test zafl.domgraph  $withps_config "$all_benchmarks"
+
+	get_raw_results 
+}
+
+main "$@"
+
+
+
diff --git a/zfuzz/test/strings/test_strings.sh b/zfuzz/test/strings/test_strings.sh
new file mode 100755
index 0000000000000000000000000000000000000000..513e8b3fa6d0f30431db2dbbf9c55876c0e9ad9f
--- /dev/null
+++ b/zfuzz/test/strings/test_strings.sh
@@ -0,0 +1,78 @@
+export AFL_TIMEOUT=15
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SECURITY_TRANSFORMS_HOME/lib/:. 
+
+session=/tmp/tmp.$(whoami).zafl.strings.$$
+
+cleanup()
+{
+	rm -fr $session
+}
+
+log_error()
+{
+	echo "TEST FAIL: $1"
+	cleanup
+	exit 1
+}
+
+log_message()
+{
+	echo "TEST  MSG: $1"
+}
+
+log_success()
+{
+	echo "TEST PASS: $1"
+}
+
+fuzz_with_zafl()
+{
+	strings_zafl=$1
+
+	# setup AFL directories
+	mkdir zafl_in
+	echo "1" > zafl_in/1
+
+	if [ -d zafl_out ]; then
+		rm -fr zafl_out
+	fi
+
+	# run for 30 seconds
+	timeout $AFL_TIMEOUT afl-fuzz -i zafl_in -o zafl_out -- $strings_zafl 
+	if [ $? -eq 124 ]; then
+		if [ ! -e zafl_out/fuzzer_stats ]; then
+			log_error "$strings_zafl: something went wrong with afl -- no fuzzer stats file"
+		fi
+
+		cat zafl_out/fuzzer_stats
+		execs_per_sec=$( grep execs_per_sec zafl_out/fuzzer_stats )
+		log_success "$strings_zafl: $execs_per_sec"
+	else
+		log_error "$strings_zafl: unable to run with afl"
+	fi
+
+}
+
+loc_afl=$(which afl-fuzz)
+if [ -z "$loc_afl" ]; then
+	which afl-fuzz
+	log_error "afl-fuzz not found"
+fi
+
+mkdir $session
+pushd $session
+
+# build ZAFL version of strings executable
+zafl.sh `which strings` strings.zafl.d.g -d -g --tempdir analysis.strings.zafl
+if [ $? -eq 0 ]; then
+	log_success "build strings.zafl.d.g"
+else
+	log_error "build strings.zafl.d.g"
+fi
+grep ATTR analysis.strings.zafl.d.g/logs/zax.log
+
+log_message "Fuzz for $AFL_TIMEOUT secs"
+fuzz_with_zafl $(realpath ./strings.zafl.d.g)
+
+cleanup
+popd
diff --git a/zfuzz/util/afl_setup_core_pattern.sh b/zfuzz/util/afl_setup_core_pattern.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7b0ddd6d6002ba2db467d46dcdaf76e5f183d0c2
--- /dev/null
+++ b/zfuzz/util/afl_setup_core_pattern.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo core >/proc/sys/kernel/core_pattern
diff --git a/zfuzz/util/setup-afl.sh b/zfuzz/util/setup-afl.sh
new file mode 100755
index 0000000000000000000000000000000000000000..67393044df7a2282b2c5f293da47a02ee4bf0304
--- /dev/null
+++ b/zfuzz/util/setup-afl.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+echo
+echo "Building Fuzzing Support ($ZFUZZ_HOME)"
+echo
+
+if [ -z "$ZFUZZ_HOME" ]; then
+	echo "error: environment var $ZFUZZ_HOME is undefined"
+	exit 1
+fi
+
+cd $ZFUZZ_HOME
+
+afl_loc=$(which afl-fuzz)
+if [ -z "$afl_loc" ]; then
+	echo
+	echo Setup AFL
+	echo 
+	wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz
+	tar -xzvf afl-latest.tgz && rm afl-latest.tgz
+	if [ -d afl ]; then
+		rm -fr afl
+	fi
+	mv afl-* afl
+	cd afl
+	make
+	sudo make install
+#	cd qemu_mode && ./build_qemu_support.sh
+
+	# afl wants this
+	sudo $ZFUZZ_HOME/util/afl_setup_core_pattern.sh
+fi