diff --git a/callbacks/lib/crt.s b/callbacks/lib/crt.s
index ef26ea327b5130b9b560f75898f58ee35920f62e..7e085eecc8e5adc970eea850b14e5693ec1841f8 100644
--- a/callbacks/lib/crt.s
+++ b/callbacks/lib/crt.s
@@ -1,4 +1,4 @@
-bits 64
+bits 32
 global _start
 section .text
 _start: 
diff --git a/include/memory_space.h b/include/memory_space.h
index 33e52025e43faf37515d0ecf85482e6a3bf29c12..38f6b827ca3c5fe2e487b3998c4a6ae7efaac633 100644
--- a/include/memory_space.h
+++ b/include/memory_space.h
@@ -46,7 +46,6 @@ struct Range_tCompare
 class MemorySpace_t : public std::map<RangeAddress_t,char>
 {
 	public:
-//		MemorySpace_t():m_opts(NULL) { }
 		MemorySpace_t(Options_t *opts) :
 			m_opts(opts)
 		{ 
@@ -78,6 +77,8 @@ class MemorySpace_t : public std::map<RangeAddress_t,char>
 		
 		void PlopByte(RangeAddress_t addr, char the_byte)
 		{
+			min_plopped=std::min(addr,min_plopped);
+			max_plopped=std::max(addr,max_plopped);
         		if(this->find(addr) == this->end() )
                 		this->SplitFreeRange(addr);
         		(*this)[addr]=the_byte;
@@ -87,11 +88,16 @@ class MemorySpace_t : public std::map<RangeAddress_t,char>
         		char bytes[]={(char)0xe9,(char)0,(char)0,(char)0,(char)0}; // jmp rel8
                 	this->PlopBytes(addr,bytes,sizeof(bytes));
 		}
+		RangeAddress_t GetMinPlopped() const { return min_plopped; }
+		RangeAddress_t GetMaxPlopped() const { return max_plopped; }
+
 	protected:
 		std::set<Range_t, Range_tCompare> free_ranges;   // keep ordered
 		Options_t *m_opts;
 
 	private:
+		RangeAddress_t min_plopped;
+		RangeAddress_t max_plopped;
 };
 
 #endif
diff --git a/include/nonce_relocs.h b/include/nonce_relocs.h
index fce63f05bfc0a9cc577e01356dcd917408ef4bee..ad36b89433b199fc2aad80f7b07bfec2b1473358 100644
--- a/include/nonce_relocs.h
+++ b/include/nonce_relocs.h
@@ -47,19 +47,21 @@ class NonceRelocs_t
 
 		// main workhorse
 		void HandleNonceRelocs();
+		void UpdateAddrRanges(std::map<libIRDB::Instruction_t*,RangeAddress_t> &final_insn_locations);
 
 	private:
 
 		// helpers
-		bool IsNonceRelocation(libIRDB::Relocation_t& reloc);
 		int GetNonceValue(libIRDB::Relocation_t& reloc);
 		int GetNonceSize(libIRDB::Relocation_t& reloc);
-		void HandleNonceRelocation(libIRDB::Instruction_t& insn, libIRDB::Relocation_t& reloc);
+		bool IsNonceRelocation(libIRDB::Relocation_t& reloc);
+		libIRDB::Relocation_t* FindRelocation(libIRDB::Instruction_t* insn, std::string type);
 		libIRDB::Relocation_t* FindNonceRelocation(libIRDB::Instruction_t* insn);
-		void AddSlowPathInstructions();
 		libIRDB::Relocation_t* FindSlowpathRelocation(libIRDB::Instruction_t* insn);
 
-
+		// major workhorses
+		void HandleNonceRelocation(libIRDB::Instruction_t& insn, libIRDB::Relocation_t& reloc);
+		void AddSlowPathInstructions();
 
 		// references to input
 		MemorySpace_t &m_memory_space;	
@@ -73,7 +75,11 @@ class NonceRelocs_t
 		// couldn't.  This will be necessary when we need to emit code for the slow path 
 		libIRDB::InstructionSet_t slow_path_nonces;
 
-		
+
+		// max_addr_updates
+		libIRDB::InstructionSet_t max_addr_update;
+		libIRDB::InstructionSet_t min_addr_update;
+
 };
 
 #endif
diff --git a/include/zipr.h b/include/zipr.h
index b124b82f74d69cdad3c2cf00c6a25f599d534468..dde5478793b34ab3afd85134123f13cec6af2674 100644
--- a/include/zipr.h
+++ b/include/zipr.h
@@ -72,19 +72,11 @@ class Zipr_t
 		void UpdateCallbacks();
 		void PrintStats();
 
-		//  emitting bytes.
-// moved to memory_space.Plop*
-//		void PlopByte(RangeAddress_t addr, char the_byte);
-//		void PlopBytes(RangeAddress_t addr, const char the_byte[], int num);
-//		void PlopJump(RangeAddress_t addr);
-
 		// emiting instructions
-		RangeAddress_t PlopInstruction(libIRDB::Instruction_t* insn,RangeAddress_t addr);
+		RangeAddress_t PlopInstruction(libIRDB::Instruction_t* insn, RangeAddress_t addr);
 		RangeAddress_t PlopWithTarget(libIRDB::Instruction_t* insn, RangeAddress_t at);
 		RangeAddress_t PlopWithCallback(libIRDB::Instruction_t* insn, RangeAddress_t at);
 
-
-
 		// patching
 		void PatchJump(RangeAddress_t at_addr, RangeAddress_t to_addr);
 		void ApplyPatches(libIRDB::Instruction_t* insn);
diff --git a/include/zipr_all.h b/include/zipr_all.h
index d10a9e51ea2b9cc1663128cb0e4a261c7ee1b9ff..96e58395140699f08d5b99303644bf8ae6d9aadf 100644
--- a/include/zipr_all.h
+++ b/include/zipr_all.h
@@ -37,6 +37,7 @@
 #include <list>
 #include <map>
 #include <libIRDB-core.hpp>
+#include <algorithm>
 
 #include "elfio/elfio.hpp"
 #include "elfio/elfio_dump.hpp"
diff --git a/src/nonce_relocs.cpp b/src/nonce_relocs.cpp
index ec5e1d5aed2bf34247e99101f09a8954f41d4d9c..7764a987f2ac293de8c9aa3ff11491039c54f6cf 100644
--- a/src/nonce_relocs.cpp
+++ b/src/nonce_relocs.cpp
@@ -1,6 +1,7 @@
 
 #include <zipr_all.h>
 #include <string>
+#include <algorithm>
 #include "utils.hpp"
 #include "Rewrite_Utility.hpp"
 
@@ -10,6 +11,7 @@ using namespace std;
 using namespace zipr;
 using namespace ELFIO;
 
+
 static Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, string p_asm)
 {
         Instruction_t* newinstr;
@@ -90,33 +92,76 @@ void NonceRelocs_t::HandleNonceRelocation(Instruction_t &insn, Relocation_t& rel
 void NonceRelocs_t::AddSlowPathInstructions()
 {
 
-	Instruction_t* slow_path=NULL, *tmp=NULL;
+	InstructionSet_t::iterator it;
+        for( it=m_firp.GetInstructions().begin(); it!=m_firp.GetInstructions().end(); ++it)
+        {
+                Instruction_t* insn=*it;
+                Relocation_t* reloc=FindSlowpathRelocation(insn);
+                if(reloc)
+                        break;
+        }
+	// exited loop normally, or hit the break statement?
+	if(it==m_firp.GetInstructions().end())
+	{
+		cout<<"Found no slow paths to link, skipping slow-path code."<<endl;
+		return;
+	}
+	
+
+// optimization
+// find out if slow path insns are even needed!
+
+	Instruction_t* slow_path=NULL, *exit_node=NULL, *tmp=NULL;
+	string reg="ecx";
+	if(m_firp.GetArchitectureBitWidth()==64)
+		reg="rcx";
 
+	// call exit.
+	exit_node=
 	slow_path=tmp = addNewAssembly(&m_firp, NULL, "mov eax, 1");
 	          tmp = insertAssemblyAfter(&m_firp,tmp,"int 0x80",NULL);
 
-	for(InstructionSet_t::iterator it=slow_path_nonces.begin();
-		it!=slow_path_nonces.end();
-		++it
-	   )
+	for(it=slow_path_nonces.begin(); it!=slow_path_nonces.end(); ++it)
 	{
 		Instruction_t* insn=*it;
 		Relocation_t* reloc=FindNonceRelocation(insn);
 		assert(reloc);
 
-		string reg="ecx";
-		if(m_firp.GetArchitectureBitWidth()==64)
-			reg="rcx";
 
 		string assembly="cmp "+reg+", "+to_string(insn->GetIndirectBranchTargetAddress()->GetVirtualOffset());
+		// insert before acts weird, and really does enough bookkeeping to insert-after in a way to mimic insert before.
         	Instruction_t* after = insertAssemblyBefore(&m_firp,slow_path,assembly);
 		Instruction_t* jne   = insertAssemblyAfter(&m_firp, slow_path, "je 0", insn);
+		exit_node=after;
 	}
 
-	for(InstructionSet_t::iterator it=m_firp.GetInstructions().begin();
-		it!=m_firp.GetInstructions().end();
-		++it
-	   )
+#ifdef CGC
+	// CGC  needs to keep from faulting, so we have to check to make sure the IB is an intra-module IB.
+	// if not, we terminate immediately.
+	// so, we emit this sequence before we try the slow path:
+	// 	pop rcx (get ret addr)
+	//	cmp rcx, start_segement_addr
+	//	jlt terminate
+	//	cmp rcx, end_segment_addr
+	//	jgt terminate
+	// After we're sure it's in this segment, we can 
+	// go ahead and check for a nonce that we layed down previously.
+	// 	cmp byte [rcx-1], 0xf4
+	// 	jeq slow_path
+
+	Instruction_t* after = insertAssemblyBefore(&m_firp,slow_path,"pop "+reg);
+	tmp = insertAssemblyAfter(&m_firp,slow_path,"cmp "+reg+", 0x12345678");
+	min_addr_update.insert(tmp);
+        tmp = insertAssemblyAfter(&m_firp,tmp,"jl 0",exit_node);        // terminate
+	tmp = insertAssemblyAfter(&m_firp,tmp,"cmp "+reg+", 0x87654321");
+	max_addr_update.insert(tmp);
+        tmp = insertAssemblyAfter(&m_firp,tmp,"jg 0",exit_node);        // terminate
+        tmp = insertAssemblyAfter(&m_firp,tmp,"cmp byte ["+reg+"-1], 0xf4");
+        tmp = insertAssemblyAfter(&m_firp,tmp,"jne 0",after);       // finally, go to the slow path checks when a nonce didn't work.
+        tmp = insertAssemblyAfter(&m_firp,tmp,"jmp "+reg);
+#endif // CGC
+
+	for( it=m_firp.GetInstructions().begin(); it!=m_firp.GetInstructions().end(); ++it)
 	{
 		Instruction_t* insn=*it;
 		Relocation_t* reloc=FindSlowpathRelocation(insn);
@@ -124,17 +169,18 @@ void NonceRelocs_t::AddSlowPathInstructions()
 			insn->SetTarget(slow_path);	
 	}
 
+	m_firp.SetBaseIDS();		// assign a unique ID to each insn.
 	m_firp.AssembleRegistry();	// resolve all assembly into actual bits.
 }
 
-Relocation_t* NonceRelocs_t::FindSlowpathRelocation(Instruction_t* insn)
+Relocation_t* NonceRelocs_t::FindRelocation(Instruction_t* insn, string type)
 {
 	Instruction_t* first_slow_path_insn=NULL;
 	RelocationSet_t::iterator rit;
 	for( rit=insn->GetRelocations().begin(); rit!=insn->GetRelocations().end(); ++rit)
 	{
 		Relocation_t& reloc=*(*rit);
-		if(reloc.GetType()=="slow_cfi_path")
+		if(reloc.GetType()==type)
 		{
 			return &reloc;
 		}
@@ -142,6 +188,11 @@ Relocation_t* NonceRelocs_t::FindSlowpathRelocation(Instruction_t* insn)
 	return NULL;
 }
 
+Relocation_t* NonceRelocs_t::FindSlowpathRelocation(Instruction_t* insn)
+{
+	return FindRelocation(insn,"slow_cfi_path");
+}
+
 Relocation_t* NonceRelocs_t::FindNonceRelocation(Instruction_t* insn)
 {
 	Instruction_t* first_slow_path_insn=NULL;
@@ -174,6 +225,9 @@ void NonceRelocs_t::HandleNonceRelocs()
 		{
 			HandleNonceRelocation(insn,*reloc);
 			handled++;
+
+			assert(insn.GetIndirectBranchTargetAddress());
+			
 		}
 	}
 
@@ -185,3 +239,44 @@ void NonceRelocs_t::HandleNonceRelocs()
 
 }
 
+
+void NonceRelocs_t::UpdateAddrRanges(std::map<libIRDB::Instruction_t*,RangeAddress_t> &final_insn_locations)
+{
+	RangeAddress_t  min_addr=m_memory_space.GetMinPlopped();
+	RangeAddress_t  max_addr=m_memory_space.GetMaxPlopped();
+
+	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)
+		{
+			cout<<"Updating min_addr at "<<hex<<insn_addr<<" to compare to "<<min_addr<<endl;
+			m_memory_space.PlopBytes(insn_addr+2,(const char*)&min_addr,sizeof(RangeAddress_t));
+		}
+		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)
+		{
+			cout<<"Updating max_addr at "<<hex<<insn_addr<<" to compare to "<<max_addr<<endl;
+			m_memory_space.PlopBytes(insn_addr+2,(const char*)&max_addr,sizeof(RangeAddress_t));
+		}
+		else
+		{
+			cout<<"No addr for  max_addr at "<<hex<<insn_addr<<" to compare to "<<max_addr<<endl;
+		}
+	}
+
+
+	
+}
diff --git a/src/zipr.cpp b/src/zipr.cpp
index d6da1f11e38bc54a9ed83b76bfe8dcadb0e01cdc..111b7146660a823f00326f6387c1fbd61b5758e8 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -147,6 +147,9 @@ void Zipr_t::CreateBinaryFile(const std::string &name)
 	// go ahead and update any callback sites with the new locations 
 	UpdateCallbacks();
 
+	// tell the Nonce class to update it's range of high/low addrs if it used any.
+	nr.UpdateAddrRanges(final_insn_locations);
+
 	m_stats->total_free_ranges = memory_space.GetRangeCount();
 
 	// write binary file to disk