diff --git a/zipr_xeon_plugin/README.md b/zipr_xeon_plugin/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2d22d3137141c091512b10f9612fd5b597b9295f
--- /dev/null
+++ b/zipr_xeon_plugin/README.md
@@ -0,0 +1 @@
+M. McGill to provide.
\ No newline at end of file
diff --git a/zipr_xeon_plugin/SConscript b/zipr_xeon_plugin/SConscript
new file mode 100644
index 0000000000000000000000000000000000000000..1b275c8a82fa5d3d3756fab35f79456f9c12ca3a
--- /dev/null
+++ b/zipr_xeon_plugin/SConscript
@@ -0,0 +1,61 @@
+import shutil
+import os
+import tarfile
+
+Import('env')
+
+
+#print 'env='
+#print env.Dump()
+
+
+
+myenv=env.Clone()
+myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME'])
+myenv.Replace(ZIPR_HOME=os.environ['ZIPR_HOME'])
+myenv.Replace(ZIPR_SDK=os.environ['ZIPR_SDK'])
+myenv.Replace(IRDB_SDK=os.environ['IRDB_SDK'])
+myenv.Replace(ZIPR_INSTALL=os.environ['ZIPR_INSTALL'])
+
+
+
+files=  '''
+	Xeon_relocs.cpp
+	'''
+
+# ELFIO needs to be first so we get the zipr version instead of the sectrans version.  the zipr version is modified to include get_offset.
+cpppath=''' 
+	.
+	$IRDB_SDK/include/
+	$ZIPR_SDK/include/
+	$SECURITY_TRANSFORMS_HOME/libtransform/include
+	$SECURITY_TRANSFORMS_HOME/third_party/elfio-code
+	'''
+'''
+	$SECURITY_TRANSFORMS_HOME/include/
+	$SECURITY_TRANSFORMS_HOME/libIRDB/include/
+	$SECURITY_TRANSFORMS_HOME/beaengine/include
+	$SECURITY_TRANSFORMS_HOME/beaengine/beaengineSources/Includes/
+	$ZIPR_HOME/include/
+	$ZIPR_SDK/include/
+	'''
+
+libs='''
+	'''
+
+libpath='''
+	$SECURITY_TRANSFORMS_HOME/lib
+	'''
+
+myenv.Append(CCFLAGS=" -Wall -Werror -std=c++11 -fmax-errors=2 ")
+myenv=myenv.Clone(CPPPATH=Split(cpppath), LIBPATH=Split(libpath), SHLIBSUFFIX=".zpi", SHLIBPREFIX="")
+lib=myenv.SharedLibrary("Xeon_relocs", Split(files))
+
+install=myenv.Install("$ZIPR_INSTALL/plugins/", lib)
+Default(install)
+
+pedi = Command( target = "./testoutput",
+                source = "./SConscript",
+                action = "cd "+os.environ['ZIPR_INSTALL']+" ; " +os.environ['PEDI_HOME']+"/pedi -m manifest.txt ; cd -" )
+Default( pedi )
+
diff --git a/zipr_xeon_plugin/SConstruct b/zipr_xeon_plugin/SConstruct
new file mode 100644
index 0000000000000000000000000000000000000000..66f12e3d96c0decea989b3c27b466247b865978d
--- /dev/null
+++ b/zipr_xeon_plugin/SConstruct
@@ -0,0 +1,37 @@
+import os
+import sys
+
+
+env=Environment()
+
+# default build options
+env.Replace(CFLAGS="-fPIC  -w ")
+env.Replace(CXXFLAGS="-fPIC  -w ")
+env.Replace(LINKFLAGS="-fPIC  ")
+
+# parse arguments
+env.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME'])
+env.Replace(ZIPR_HOME=os.environ['ZIPR_HOME'])
+env.Replace(ZIPR_INSTALL=os.environ['ZIPR_INSTALL'])
+env.Replace(ZIPR_SDK=os.environ['ZIPR_SDK'])
+env.Replace(debug=ARGUMENTS.get("debug",0))
+env.Replace(do_64bit_build=ARGUMENTS.get("do_64bit_build",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")
+
+env['build_appfw']=0
+env['build_tools']=0
+
+Export('env')
+SConscript("SConscript", variant_dir='build')
+
diff --git a/zipr_xeon_plugin/Xeon_relocs.cpp b/zipr_xeon_plugin/Xeon_relocs.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b0cc7307ad6b0409066cc46c7be870893f7085bf
--- /dev/null
+++ b/zipr_xeon_plugin/Xeon_relocs.cpp
@@ -0,0 +1,493 @@
+#include "Xeon_relocs.hpp"
+#include <algorithm>
+
+using namespace IRDB_SDK;
+using namespace Zipr_SDK;
+using namespace std;
+
+
+// use this to determine whether a scoop has a given name.
+static struct ScoopFinder : binary_function<const DataScoop_t*,const string,bool>
+{
+        // declare a simple scoop finder function that finds scoops by name
+        bool operator()(const DataScoop_t* scoop, const string& name) const
+        {
+                return (scoop->getName() == name);
+        };
+} scoop_finder;
+
+
+static DataScoop_t* find_scoop(FileIR_t *firp,const string &name)
+{
+        auto it=find_if(firp->getDataScoops().begin(), firp->getDataScoops().end(), bind2nd(scoop_finder, name)) ;
+        if( it != firp->getDataScoops().end() )
+                return *it;
+        return NULL;
+};
+
+
+static void extract_fields(const string &reloc_string, int &sz, int &pos, string &val)
+{
+	sz=pos=0;
+        val="";
+        
+	size_t loc=reloc_string.find('=');
+	string nonce_value=reloc_string.substr(loc+1,reloc_string.size()-loc-1);
+        
+	// trying to parse a triple of form (a,b,c) into strings a,b,c
+	// cfi_nonce=(pos=2,nv=0,sz=1)
+
+	// find first comma
+	size_t comma_pos=nonce_value.find(',');
+	
+        // parse out A
+	string first=nonce_value.substr(5,comma_pos-1-4); // 1== strlen(","), 5==strlen("(pos=")
+
+	//  parse out "b,c)"
+	string rest=nonce_value.substr(comma_pos+1, string::npos); 	// 1 == strlen(",")
+
+	// find next comma
+	comma_pos=rest.find(',');
+
+	// parse out B
+	string second=rest.substr(3,comma_pos-3); // 3=strlen("nv=")
+
+	// parse out "c)"
+	rest=rest.substr(comma_pos+1, string::npos);	// 1==sizeof(",")
+
+	// find closing paren.
+	size_t paren_pos=rest.find(')');
+
+	// pares out C
+	string third=rest.substr(3,paren_pos-3); // 3==strlen("sz=")
+
+
+	pos=(int)strtol(first.c_str(),0,10);	
+	val=second;
+	sz=(int)strtol(third.c_str(),0,10);
+}
+
+static string GetNonceValue(Relocation_t& reloc)
+{
+	int sz, pos;
+	string val;
+	extract_fields(reloc.getType(), sz, pos, val);
+	return val;
+}
+
+static int GetNonceSize(Relocation_t& reloc)
+{
+	int sz, pos;
+	string val;
+	extract_fields(reloc.getType(), sz, pos, val);
+	return sz;
+}
+
+static int GetNonceOffset(Relocation_t& reloc)
+{
+	int sz, pos;
+	string val;
+	extract_fields(reloc.getType(), sz, pos, val);
+	return pos;
+}
+
+
+// TODO: BAD COUPLING, SHOULD PASS REG WITH RELOC
+void Xeon_relocs::AddDynLibCheckCode()
+{
+    // Decide what register to use
+    string reg="ecx";	// 32-bit reg 
+    if(firp->getArchitectureBitWidth()==64)
+	reg="r11";	// 64-bit reg.
+    
+    for( auto it=firp->getInstructions().begin(); it!=firp->getInstructions().end(); ++it)
+    {
+        const auto insn=*it;
+        if(FindRelocation(insn, "insert_dynlib_check"))
+        {
+            Instruction_t* old_target = insn->getTarget();
+            insn->setTarget(GetDynLibCheckCode(reg, old_target));
+        }	
+    }
+    firp->assembleRegistry();	// resolve all assembly into actual bits.
+    firp->setBaseIDS();		// assign a unique ID to each insn.
+}
+
+
+void Xeon_relocs::UpdateAddrRanges()
+{
+    RangeAddress_t  min_addr=m_memory_space->getMinPlopped();
+    RangeAddress_t  max_addr=m_memory_space->getMaxPlopped();
+
+    int offset=0;	// deal with REX prefix for 64-bit mode.
+    if(firp->getArchitectureBitWidth()==64)
+	offset=1;
+
+    InstructionSet_t::iterator it;
+    for(it=min_addr_update.begin(); it!=min_addr_update.end(); ++it)
+    {
+	Instruction_t& insn=*(*it);
+	RangeAddress_t insn_addr=(*final_insn_locations)[&insn];
+	if(insn_addr)
+	{
+            // if(m_elfio->get_type() == ET_EXEC)
+	    if(firp->getArchitecture()->getFileType()==adftELFEXE)
+            {
+                cout<<"Updating min_addr for cmp at "<<hex<<insn_addr<<" to compare to "<<min_addr<<endl;
+		m_memory_space->plopBytes(insn_addr+2+offset,(const char*)&min_addr,4); // cmp insn has a 4 byte immed.
+            }
+            // else if(m_elfio->get_type() == ET_DYN)
+	    else if(firp->getArchitecture()->getFileType()==adftELFSO)
+            {
+            	// pcrel addressing is always trick.
+		// effective address == instruction address + instruction size + offset
+		// so we need offset=effective_addr-instruction_address-insn_size;
+		RangeAddress_t offset=min_addr-insn_addr-insn.getDataBits().size();
+		// lea trick doesn't work on 32-bit.
+		assert(firp->getArchitectureBitWidth()==64);
+		cout<<"Updating min_addr for "<<hex<<insn.getBaseID()<<":lea at "<<hex<<insn_addr<<" to compare to "<<min_addr<<", offset="<<offset<<endl;
+		m_memory_space->plopBytes(insn_addr+3,(const char*)&offset,4); // cmp insn has a 4 byte immed.
+            }
+            else
+		assert(0);
+        }
+        else
+        {
+            cout<<"No addr for  min_addr at "<<hex<<insn_addr<<" to compare to "<<min_addr<<endl;
+	}
+    }
+
+    for(it=max_addr_update.begin(); it!=max_addr_update.end(); ++it)
+    {
+	Instruction_t& insn=*(*it);
+	RangeAddress_t insn_addr=(*final_insn_locations)[&insn];
+	assert(insn_addr);
+	if(insn_addr)
+	{
+            // if(m_elfio->get_type() == ET_EXEC)
+	    if(firp->getArchitecture()->getFileType()==adftELFEXE)
+            {
+            	cout<<"Updating max_addr at "<<hex<<insn_addr<<" to compare to "<<max_addr<<endl;
+		m_memory_space->plopBytes(insn_addr+2+offset,(const char*)&max_addr,4);	// cmp insn with a 4-byte immed
+            }
+	    else if(firp->getArchitecture()->getFileType()==adftELFSO)
+            // else if(m_elfio->get_type() == ET_DYN)
+            {
+		// pcrel addressing is always trick.
+		// effective address == instruction address + instruction size + offset
+		// so we need offset=effective_addr-instruction_address-insn_size;
+		RangeAddress_t offset=max_addr-insn_addr-insn.getDataBits().size();
+		// lea trick doesn't work on 32-bit.
+		assert(firp->getArchitectureBitWidth()==64);
+		cout<<"Updating max_addr for "<<hex<<insn.getBaseID()<<":lea at "<<hex<<insn_addr<<" to compare to "<<max_addr<<", offset="<<offset<<endl;
+		m_memory_space->plopBytes(insn_addr+3,(const char*)&offset,4); // cmp insn has a 4 byte immed.
+            }
+            else
+		assert(0);
+	}
+	else
+	{
+            cout<<"No addr for  max_addr at "<<hex<<insn_addr<<" to compare to "<<max_addr<<endl;
+	}
+    }
+}
+
+#if 0
+ZiprOptionsNamespace_t *Xeon_relocs::registerOptions(Zipr_SDK::ZiprOptionsNamespace_t *global) 
+{
+	global->addOption(&m_verbose);
+	return NULL;
+}
+#endif
+
+
+bool Xeon_relocs::willPluginPlop(IRDB_SDK::Instruction_t* insn)
+{
+	if(!m_on)
+            return false;
+        
+	bool will_plop = false;
+        
+	if(FindExeNonceRelocation(insn))
+            will_plop = true;
+
+	if (*m_verbose)
+	{
+	
+		cout << "Xeon_relocs::WillPluginPlop:WillPlop=" <<std::boolalpha <<will_plop<<" for "
+		     << hex << insn->getBaseID()<<":"<<insn->getDisassembly()<<endl;
+	}
+	return will_plop;
+}
+
+
+size_t Xeon_relocs::getDollopEntryOpeningSize(DollopEntry_t* entry)
+{
+	return 0;
+}
+
+
+size_t Xeon_relocs::getDollopEntryClosingSize(DollopEntry_t* entry)
+{
+
+	if(!m_on)
+		return 0;
+
+	Instruction_t* insn=entry->getInstruction();	
+        int exeNonceSize = 0;
+	for(
+                RelocationSet_t::iterator rit=insn->getRelocations().begin();
+                rit!=insn->getRelocations().end();
+                rit++
+	   )
+        {
+            Relocation_t& reloc=*(*rit);
+            if(IsExeNonceRelocation(reloc))
+            {
+		exeNonceSize += GetNonceSize(reloc);		
+            }
+        }
+	
+	return exeNonceSize;
+}
+
+
+RangeAddress_t Xeon_relocs::plopDollopEntry(Zipr_SDK::DollopEntry_t *de,
+	RangeAddress_t & placed_addr,
+	RangeAddress_t & target_addr,
+	size_t instruction_size,
+	bool &instruction_placed)
+{
+	
+	//placed_addr=de->Place();
+	RangeAddress_t ret=placed_addr; // relocs currently account for instruction size in offset
+	// TODO: Need to update ret to =instruction size + placed addr for calls if plopping on calls
+	Instruction_t* insn=de->getInstruction();
+	if(DecodedInstruction_t::factory(insn)->isCall())
+	{
+		ret += instruction_size;
+	}
+
+	if (*m_verbose)
+	{
+		cout << "Xeon_relocs::Plopping Instruction  : " << hex 
+		     << de->getInstruction()->getBaseID() <<":"<<de->getInstruction()->getDisassembly()<<endl;
+		cout << "placed_address  : " << std::hex << placed_addr << endl;
+		cout << "de->Place()     : " << std::hex << de->getPlace() << endl;
+		cout << "instruction_size: " << std::dec << instruction_size << endl;
+	}
+
+	cout<<"Xeon_relocs::plopping "<<de->getInstruction()->getDisassembly()<<" at "<<hex<<placed_addr<<endl;
+        
+        RangeAddress_t baseOffset = ret;
+        for(
+                RelocationSet_t::iterator rit=insn->getRelocations().begin();
+                rit!=insn->getRelocations().end();
+                rit++
+	   )
+        {
+            Relocation_t& reloc=*(*rit);
+            if(IsExeNonceRelocation(reloc))
+            {
+		int offset=GetNonceOffset(reloc);
+                int size=GetNonceSize(reloc);
+		if(offset+size+baseOffset > ret)
+                {
+                    ret = offset+size+baseOffset;
+                }
+                
+                string value=GetNonceValue(reloc);
+                
+                cout<<"Xeon_relocs::Placing nonce:"<<std::hex<<value<<" at "<<hex<<ret<<endl;
+                // Places in big endian order (it assumes the reloc has value in little-endian where appropriate)
+                for(int i = 0; i < size; ++i)
+                {
+		    (*m_memory_space)[baseOffset+offset]=value.at(i);
+		    ++offset;
+                }
+            }
+        }
+        
+	return ret;	
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+// minor helpers
+
+Relocation_t* Xeon_relocs::FindRelocation(Instruction_t* insn, string type)
+{
+	RelocationSet_t::iterator rit;
+	for( rit=insn->getRelocations().begin(); rit!=insn->getRelocations().end(); ++rit)
+	{
+		Relocation_t& reloc=*(*rit);
+		if(reloc.getType()==type)
+		{
+			return &reloc;
+		}
+	}
+	return NULL;
+}
+
+
+Relocation_t* Xeon_relocs::FindExeNonceRelocation(Instruction_t* insn)
+{
+        RelocationSet_t::iterator rit;
+	for( rit=insn->getRelocations().begin(); rit!=insn->getRelocations().end(); ++rit)
+	{
+		Relocation_t* reloc=*rit;
+                if(strstr(reloc->getType().c_str(),"cfi_exe_nonce=")!=NULL)                    
+                    return reloc;
+	}
+        return NULL;
+}
+
+
+bool Xeon_relocs::IsExeNonceRelocation(Relocation_t& reloc)
+{
+	if(strstr(reloc.getType().c_str(),"cfi_exe_nonce=")==NULL)
+		return false;
+	return true;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+// main workers
+
+Instruction_t* Xeon_relocs::GetDynLibCheckCode(string reg, Instruction_t* target)
+{
+	string rspreg="esp";	// 32-bit reg 
+        if(firp->getArchitectureBitWidth()==64)
+	    rspreg="rsp";	// 64-bit reg.
+	
+	static Instruction_t* bounds_start=NULL;
+	Instruction_t* bounds_end=NULL;
+        
+        if(bounds_start != NULL)
+            return bounds_start;
+
+	// we need a dispatch handler in case the range check fails
+	// this range check should be working with multimodule support enabled.
+	Instruction_t* out_of_range_handler=NULL;
+	out_of_range_handler = GenerateOutOfRangeHandler();
+
+	// before the individual checks on the slow path
+	// we want to insert a range check.
+	//	cmp ecx/r11, start_segement_addr
+	//	jlt out_of_range_handler
+	//	cmp ecx/r11, end_segment_addr
+	//	jgt out_of_range_handler
+
+	// statically loaded exe.
+	// if(m_elfio->get_type() == ET_EXEC)
+	if(firp->getArchitecture()->getFileType()==adftELFEXE)
+	{
+		Instruction_t* tmp=NULL;
+		bounds_start =
+		tmp = addNewAssembly(firp,NULL,"cmp "+reg+", 0x12345678");
+		min_addr_update.insert(tmp);
+		// cross library jump detected
+		tmp = insertAssemblyAfter(firp,tmp,"jl 0",out_of_range_handler);        
+		// cross library jump detected
+		tmp = insertAssemblyAfter(firp,tmp,"cmp "+reg+", 0x87654321");
+		max_addr_update.insert(tmp);
+		tmp = insertAssemblyAfter(firp,tmp,"jg 0",out_of_range_handler);        // cross library jump detected
+		bounds_end=tmp;
+	}
+	// dynamically loaded object (pie exec or pic)
+	// else if(m_elfio->get_type() == ET_DYN)
+	else if(firp->getArchitecture()->getFileType()==adftELFSO)
+	{
+		Instruction_t* tmp=NULL;
+		Instruction_t* oor_pop=addNewAssembly(firp, NULL, "pop "+reg);		// SYS_exit
+		oor_pop->setFallthrough(out_of_range_handler);
+
+		string leastring1("\x4c\x8d\x1d\x78\x56\x34\x12",7);
+		string leastring2("\x4c\x8d\x1d\x12\x34\x56\x78",7);
+
+		bounds_start=
+		tmp = addNewAssembly(firp,NULL,"push "+reg);	// save target on stack
+		tmp = insertDataBitsAfter(firp,tmp, leastring1);        	// load lower bound
+                min_addr_update.insert(tmp);
+		tmp = insertAssemblyAfter(firp,tmp,"cmp [rsp], "+reg);        	// cmp to lower bound to target.
+		tmp = insertAssemblyAfter(firp,tmp,"jl 0", oor_pop);        		// cross library jump detected
+		tmp = insertDataBitsAfter(firp,tmp, leastring2);       	// load upper bound
+                max_addr_update.insert(tmp);
+		tmp = insertAssemblyAfter(firp,tmp,"cmp [rsp], "+reg);        	// compare upper bound to target.
+		tmp = insertAssemblyAfter(firp,tmp,"jg 0", oor_pop);        		// cross lib jmp detected.
+		tmp = insertAssemblyAfter(firp,tmp,"pop "+reg);        		// restore ecx/r11.
+		bounds_end=tmp;
+	}
+	else
+		assert(0); // what?
+
+	assert(bounds_start && bounds_end);
+        Instruction_t* jmp = addNewAssembly(firp, NULL, "jmp 0");
+        jmp->setTarget(target);
+	bounds_end->setFallthrough(jmp);
+	return bounds_start;
+}
+
+
+Instruction_t* Xeon_relocs::GenerateOutOfRangeHandler(void)
+{
+	string reg="ecx";
+	if(firp->getArchitectureBitWidth()==64)
+		reg="r11";
+	unsigned ptrsize=firp->getArchitectureBitWidth()/8;
+
+	// find some scoops we'll need
+	DataScoop_t* dynstr_scoop=find_scoop(firp, ".dynstr");
+	DataScoop_t* dispatch_scoop =find_scoop(firp, "zest_cfi_dispatch");
+
+	// if we can't find the cfi multimodule support, don't do multimodule protection
+	if(!dynstr_scoop || dynstr_scoop->getContents().find("zestcfi") == string::npos)
+	{
+		Instruction_t *jmp=addNewAssembly(firp, NULL, "jmp "+reg);	// jmp ecx/r11 
+		return jmp;
+	}
+
+	// if it was transformed with multimodule support, all these scoops better exist.
+	assert(dispatch_scoop);
+
+
+	// for now, just do the simple thing of calling zest_cfi_dispatch to check if the transfer is allowed.
+	// if the function returns, then the transfer is OK, and we should cache it.
+	// again, for now, just allow the xfer.
+	if(ptrsize==8)
+	{
+		// call <pc-6> is "call 0" in pcrel-ness.  we'll hang a reloc off this to indicate 
+		// which scoop it should really go to.		
+		char jmp_neg6[]="\xff\x25\xfa\xff\xff\xff";	 
+		string jmp_neg6_str(jmp_neg6,sizeof(jmp_neg6)-1);
+
+		auto dispatchjmp=addNewDataBits(firp, NULL, jmp_neg6_str);	// jmp zest_cfi_dispatch with r11==target
+		auto dispatchjmp_reloc=firp->addNewRelocation(dispatchjmp,  0, "pcrel", dispatch_scoop);
+		(void)dispatchjmp_reloc; // just giving to the IR 
+
+
+		// need to update the calls to use pcrel addressing
+		return dispatchjmp;
+	}
+	else if(ptrsize==4)
+	{
+		// fixme later.
+		assert(0);
+	}
+	else
+		assert(0);
+}
+
+
+extern "C"
+Zipr_SDK::ZiprPluginInterface_t* GetPluginInterface(
+        Zipr_SDK::Zipr_t* zipr_object)
+{
+        Zipr_SDK::MemorySpace_t *p_ms=zipr_object->getMemorySpace();
+        IRDB_SDK::FileIR_t *p_firp=zipr_object->getFileIR();
+        Zipr_SDK::InstructionLocationMap_t *p_fil=zipr_object->getLocationMap();
+
+	return new Xeon_relocs(p_ms,p_firp,p_fil,zipr_object);
+}
diff --git a/zipr_xeon_plugin/Xeon_relocs.hpp b/zipr_xeon_plugin/Xeon_relocs.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccb233353a122f997a87e1ccba0325d008d8df08
--- /dev/null
+++ b/zipr_xeon_plugin/Xeon_relocs.hpp
@@ -0,0 +1,97 @@
+#ifndef Xeon_relocs_hpp
+#define Xeon_relocs_hpp
+
+#include <irdb-core>
+#include <irdb-transform>
+#include <zipr-sdk>
+#include <dlfcn.h>
+
+using namespace Zipr_SDK;
+using namespace IRDB_SDK;
+
+class Xeon_relocs : public ZiprPluginInterface_t
+{
+    public:
+        // The plugin constructor
+        Xeon_relocs(MemorySpace_t *p_ms,
+		              FileIR_t *p_firp,
+		              InstructionLocationMap_t *p_fil,
+		              Zipr_t *p_zipr) :
+                        firp(p_firp),
+			m_memory_space(p_ms), 
+			final_insn_locations(p_fil),
+			m_zipr(p_zipr),
+			m_on(false)
+		{
+			if(p_firp==NULL)
+				return;
+			// optimization
+			// find out if slow path insns are even needed!
+			if(p_firp!=NULL)
+			{
+                            for( auto it=firp->getInstructions().begin(); it!=firp->getInstructions().end(); ++it)
+				{
+					const auto insn=*it;
+					if(FindRelocation(insn, "nonce_miscomp_path"))
+					{
+						m_on=true;
+						break;
+					}	
+				}
+			}
+			if(m_on)
+				cout<<"Xeon_relocs plugin: Turning plugin on."<<endl;
+
+			auto global=p_zipr->getOptionsManager()->getNamespace("global");
+			m_verbose=global->getBooleanOption("verbose");
+			
+
+		}
+        
+		virtual void doPinningEnd() override
+				{ 
+					if(!m_on) return; 
+					cout<<"Xeon_relocs: Inserting bounds check."<<endl;
+					AddDynLibCheckCode(); 
+				}
+		virtual void doCallbackLinkingEnd() override
+				{
+					if(!m_on) return; 
+					cout<<"Xeon_relocs: Updating bounds check"  <<endl;
+					UpdateAddrRanges(); 
+				}
+		// virtual ZiprOptionsNamespace_t *registerOptions(ZiprOptionsNamespace_t *);
+		virtual bool willPluginPlop(Instruction_t*);
+                virtual RangeAddress_t plopDollopEntry(DollopEntry_t *,
+                        RangeAddress_t &,
+                        RangeAddress_t &,
+			size_t,
+			bool &)override ;
+
+		size_t getDollopEntryOpeningSize(DollopEntry_t*)override ;
+		size_t getDollopEntryClosingSize(DollopEntry_t*)override ;
+                virtual string toString() override { return "Xeon_relocs"; }
+        
+    private: //methods
+        bool IsExeNonceRelocation(Relocation_t& reloc);
+        Relocation_t* FindExeNonceRelocation(Instruction_t* insn);
+        Relocation_t* FindRelocation(Instruction_t* insn, std::string type);
+        Instruction_t* GenerateOutOfRangeHandler(void);
+        void UpdateAddrRanges();
+        void AddDynLibCheckCode();
+        Instruction_t* GetDynLibCheckCode(std::string reg, Instruction_t* fall_through);
+        
+    private: //data
+        FileIR_t* firp;
+        MemorySpace_t *m_memory_space;	
+	InstructionLocationMap_t *final_insn_locations;
+	Zipr_t *m_zipr;
+        ZiprBooleanOption_t *m_verbose;
+	bool m_on;
+        // bounds check updates
+	InstructionSet_t max_addr_update;
+        InstructionSet_t min_addr_update;
+};
+
+#endif
+