From bb2e98a91845d77ed655a0c187b870e93f9f8de8 Mon Sep 17 00:00:00 2001
From: jdh8d <jdh8d@git.zephyr-software.com>
Date: Mon, 3 Apr 2017 14:58:33 +0000
Subject: [PATCH] First, working version of the EH-iR.  enable with
 --step-option fill_in_indtargs:--split-eh-frame.

---
 .gitattributes      |   2 +
 include/ehwrite.h   | 131 ++++++++
 include/elfwrite.h  |   4 +-
 include/zipr_all.h  |   1 +
 include/zipr_impl.h |   4 +
 src/SConscript      |   3 +-
 src/ehwrite.cpp     | 797 ++++++++++++++++++++++++++++++++++++++++++++
 src/elfwrite.cpp    |  41 ---
 src/zipr.cpp        |  41 ++-
 9 files changed, 976 insertions(+), 48 deletions(-)
 create mode 100644 include/ehwrite.h
 create mode 100644 src/ehwrite.cpp

diff --git a/.gitattributes b/.gitattributes
index 1c77dee..1f1c316 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,6 +8,7 @@
 /config.sub -text
 /configure -text
 /configure.in -text
+include/ehwrite.h -text
 include/elfwrite.h -text
 include/plugin_man.h -text
 include/sled.h -text
@@ -24,6 +25,7 @@ src/Makefile.in -text
 src/SConscript -text
 src/SConstruct -text
 src/dollop.cpp -text
+src/ehwrite.cpp -text
 src/elfwrite.cpp -text
 src/main.cpp -text
 src/memory_space.cpp -text
diff --git a/include/ehwrite.h b/include/ehwrite.h
new file mode 100644
index 0000000..8a87636
--- /dev/null
+++ b/include/ehwrite.h
@@ -0,0 +1,131 @@
+#ifndef ElfWriter_h
+#define ElfWriter_h
+
+#include <iostream>
+
+class EhWriter_t 
+{	 
+	public: 
+	virtual void GenerateNewEhInfo() =0;
+};
+
+
+static const std::string ehframe_s_filename="ehframe.s";
+static const std::string ehframe_exe_filename="ehframe.exe";
+
+template <int ptrsize> 
+class EhWriterImpl_t : public EhWriter_t
+{
+	private:
+
+	class EhProgramListingManip_t : public libIRDB::EhProgramListing_t
+	{
+		public:
+		EhProgramListingManip_t(){}
+		EhProgramListingManip_t(const libIRDB::EhProgramListing_t &pgm) : libIRDB::EhProgramListing_t(pgm) { }
+		bool canExtend(const EhProgramListingManip_t &other);
+		void extend(const uint64_t inc_amt, const EhProgramListingManip_t &other);
+		private:
+		int getMergeIndex(const EhProgramListingManip_t &other);
+		bool isAdvanceDirective(const std::string &s);
+
+		static const int DW_CFA_advance_loc1 = 0x02;
+		static const int DW_CFA_advance_loc2 = 0x03;
+		static const int DW_CFA_advance_loc4 = 0x04;
+
+	};
+
+	class FDErepresentation_t;	// forward decl
+	class CIErepresentation_t
+	{
+		public:
+		CIErepresentation_t(libIRDB::Instruction_t*, EhWriterImpl_t<ptrsize>* ehw);
+		void emitAssembly(std::ostream& out) {}
+		bool canSupport(libIRDB::Instruction_t* insn) const;
+
+		private:
+			// need nothing?
+
+		EhProgramListingManip_t pgm;
+		uint64_t code_alignment_factor;
+		int64_t data_alignment_factor;
+		uint64_t return_reg;
+		libIRDB::Relocation_t* personality_reloc;
+
+		mutable bool has_been_output;
+
+		friend class FDErepresentation_t;
+		friend EhWriterImpl_t<ptrsize>;	
+	};
+
+
+	class FDErepresentation_t
+	{
+		private:
+
+		class LSDArepresentation_t
+		{
+			public:
+			LSDArepresentation_t(libIRDB::Instruction_t* insn);
+			void extend(libIRDB::Instruction_t* insn);
+			bool canExtend(libIRDB::Instruction_t* insn) const { (void)insn; return true; }
+			bool exists()  const  { return callsite_table.size() > 0; }
+
+			struct call_site_t
+			{
+				libIRDB::Instruction_t* cs_insn_start;
+				libIRDB::Instruction_t* cs_insn_end;
+				libIRDB::Instruction_t* landing_pad;
+				int action_table_index;
+				std::set<libIRDB::Relocation_t*> actions;
+			};
+			std::vector<call_site_t> callsite_table;
+			std::vector<std::set<libIRDB::Relocation_t*> > action_table;
+			std::vector<libIRDB::Relocation_t*> type_table;
+
+		};
+
+		LSDArepresentation_t lsda;
+		CIErepresentation_t* cie;
+		libIRDB::virtual_offset_t start_addr;
+		libIRDB::virtual_offset_t end_addr;
+		libIRDB::virtual_offset_t last_advance_addr;
+		// the pgm for the fde
+		EhProgramListingManip_t pgm;
+
+		public:
+		FDErepresentation_t(libIRDB::Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw);
+		void extend(libIRDB::Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw);
+		void emitAssembly(std::ostream& out);
+		bool canExtend(libIRDB::Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw);
+		bool hasLsda() const { return lsda.exists(); }
+
+		friend EhWriterImpl_t<ptrsize>;	
+	};
+
+	friend class FDErepresentation_t;
+	friend class CIErepresentation_t;
+
+	ZiprImpl_t& zipr_obj;
+	std::vector<FDErepresentation_t*> all_fdes;
+	std::vector<CIErepresentation_t*> all_cies;
+
+        void BuildFDEs();
+        void GenerateEhOutput();
+        void CompileEhOutput();
+        void ScoopifyEhOutput();
+
+	public:
+	EhWriterImpl_t(ZiprImpl_t& p_zipr_obj) 
+		: zipr_obj(p_zipr_obj)
+	
+	{ 
+	}
+
+	virtual ~EhWriterImpl_t();
+
+	void GenerateNewEhInfo();
+
+};
+
+#endif
diff --git a/include/elfwrite.h b/include/elfwrite.h
index d984fab..0c412bb 100644
--- a/include/elfwrite.h
+++ b/include/elfwrite.h
@@ -1,6 +1,6 @@
 
-#ifndef ElfWriter_h
-#define ElfWriter_h
+#ifndef EhWriter_h
+#define EhWriter_h
 
 #include <vector>
 #include <map>
diff --git a/include/zipr_all.h b/include/zipr_all.h
index 3d53ca6..8fdbe56 100644
--- a/include/zipr_all.h
+++ b/include/zipr_all.h
@@ -59,6 +59,7 @@ using namespace Zipr_SDK;
 #include <zipr_optimizations.h>
 #include <zipr_stats.h>
 #include <elfwrite.h>
+#include <ehwrite.h>
 };
 
 #endif
diff --git a/include/zipr_impl.h b/include/zipr_impl.h
index c4194c3..8406fbd 100644
--- a/include/zipr_impl.h
+++ b/include/zipr_impl.h
@@ -398,6 +398,8 @@ class ZiprImpl_t : public Zipr_t
 
 		void dump_map();
 
+	public: 
+
                 virtual Zipr_SDK::MemorySpace_t *GetMemorySpace() { return &memory_space; }
 		virtual Zipr_SDK::DollopManager_t *GetDollopManager() { return &m_dollop_mgr; }
                 virtual ELFIO::elfio *GetELFIO() { return elfiop; }
@@ -405,6 +407,8 @@ class ZiprImpl_t : public Zipr_t
                 virtual Zipr_SDK::InstructionLocationMap_t *GetLocationMap() { return &final_insn_locations; }
 		virtual Zipr_SDK::PlacementQueue_t* GetPlacementQueue() { return &placement_queue; }  
 		virtual Zipr_SDK::RangeAddress_t PlaceUnplacedScoops(Zipr_SDK::RangeAddress_t max);
+ 		virtual void RelayoutEhInfo();
+
 
 
 	private:
diff --git a/src/SConscript b/src/SConscript
index 50a81a7..a13f761 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -4,7 +4,7 @@ import os
 
 
 Import('env')
-myenv=env
+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'])
@@ -22,6 +22,7 @@ files=  '''
 	dollop.cpp
 	zipr_dollop_man.cpp
 	elfwrite.cpp
+	ehwrite.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.
diff --git a/src/ehwrite.cpp b/src/ehwrite.cpp
new file mode 100644
index 0000000..542c23a
--- /dev/null
+++ b/src/ehwrite.cpp
@@ -0,0 +1,797 @@
+
+#include <zipr_all.h>
+#include <libIRDB-core.hpp>
+#include <Rewrite_Utility.hpp>
+#include <iostream>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <sys/mman.h>
+#include <ctype.h>
+#include <iostream>   // std::cout
+#include <string>     // std::string, std::to_string
+#include <fstream>
+#include <elf.h>
+
+#include "elfio/elfio.hpp"
+#include "elfio/elfio_dump.hpp"
+#include "targ-config.h"
+#include "beaengine/BeaEngine.h"
+
+using namespace libIRDB;
+using namespace std;
+using namespace zipr;
+using namespace ELFIO;
+
+template < typename T > std::string to_hex_string( const T& n )
+{
+        std::ostringstream stm ;
+        stm << std::hex<< "0x"<< n ;
+        return stm.str() ;
+}
+
+template<int ptrsize>
+void EhWriterImpl_t<ptrsize>::GenerateNewEhInfo()
+{
+	
+	BuildFDEs();
+	GenerateEhOutput();
+	CompileEhOutput();
+	ScoopifyEhOutput();
+
+}
+
+template <int ptrsize>
+bool EhWriterImpl_t<ptrsize>::CIErepresentation_t::canSupport(Instruction_t* insn) const
+{
+	// if the insn is missing info, we can support it.
+	if(insn==NULL)
+		return true;
+	if(insn->GetEhProgram()==NULL)
+		return true;
+
+	// all info here.
+
+
+	// check that the program,CAF, DAF and RR match.  if not, can't support
+	if(insn->GetEhProgram()->GetCIEProgram() != pgm || 
+	   insn->GetEhProgram()->GetCodeAlignmentFactor() != code_alignment_factor || 
+	   insn->GetEhProgram()->GetDataAlignmentFactor() != data_alignment_factor || 
+	   insn->GetEhProgram()->GetReturnRegNumber() != return_reg 
+	  )
+		return false;
+
+	auto personality_it=find_if(
+		insn->GetEhProgram()->GetRelocations().begin(), 
+		insn->GetEhProgram()->GetRelocations().end(),
+		[](const Relocation_t* r) { return r->GetType()=="personality"; });
+
+	// lastly, check for a compatible personality reloc.
+	// if incoming has no personality, we better have no personality to match.
+	if(personality_it==insn->GetEhProgram()->GetRelocations().end())
+	{
+		return personality_reloc==NULL;
+	}
+
+	// incomming has personality, but do we?
+	if(personality_reloc==NULL) return false;
+
+	// compare personalities.
+	if(personality_reloc->GetWRT() != (*personality_it)->GetWRT()) return false;
+	if(personality_reloc->GetAddend() != (*personality_it)->GetAddend()) return false;
+
+	return true;
+}
+
+template <int ptrsize>
+EhWriterImpl_t<ptrsize>::CIErepresentation_t::CIErepresentation_t(Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw)
+	: has_been_output(false)
+{
+	assert(insn && ehw && insn->GetEhProgram());
+
+	pgm = insn->GetEhProgram()->GetCIEProgram();
+	code_alignment_factor = insn->GetEhProgram()->GetCodeAlignmentFactor();
+	data_alignment_factor = insn->GetEhProgram()->GetDataAlignmentFactor();
+	return_reg = insn->GetEhProgram()->GetReturnRegNumber();
+
+	auto personality_it=find_if(
+		insn->GetEhProgram()->GetRelocations().begin(), 
+		insn->GetEhProgram()->GetRelocations().end(),
+		[](const Relocation_t* r) { return r->GetType()=="personality";});
+
+	personality_reloc = (personality_it==insn->GetEhProgram()->GetRelocations().end())
+		? (Relocation_t*)NULL
+		: *personality_it;
+}
+
+
+template <int ptrsize>
+EhWriterImpl_t<ptrsize>::FDErepresentation_t::FDErepresentation_t(Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw)
+	: 
+		lsda(insn),
+		cie(NULL)
+{
+	auto cie_it=find_if( ehw->all_cies.begin(), ehw->all_cies.end(), [&](const CIErepresentation_t* candidate)
+	{
+		return candidate->canSupport(insn);
+	});
+
+	if(cie_it==ehw->all_cies.end())
+	{
+		cie=new CIErepresentation_t(insn,ehw);
+		ehw->all_cies.push_back(cie);
+	}
+	else
+		cie=*cie_it;
+
+	start_addr=ehw->zipr_obj.GetLocationMap()->at(insn);
+	last_advance_addr=start_addr;
+	end_addr=start_addr+insn->GetDataBits().size();
+	pgm=EhProgramListingManip_t(insn->GetEhProgram()->GetFDEProgram());
+}
+
+
+template <int ptrsize>
+int EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getMergeIndex(const EhProgramListingManip_t &other)
+{
+	auto other_index=(size_t)0;
+	for(const auto &this_ele : *this)
+	{
+		if(isAdvanceDirective(this_ele))
+			continue;
+
+		if(other_index >= other.size())
+			return -1;
+
+		if( this_ele!=other.at(other_index))
+			return -1;
+		other_index++;
+	}
+
+	return other_index;
+}
+template <int ptrsize>
+bool EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::canExtend(const EhProgramListingManip_t &other)
+{
+	return getMergeIndex(other) != -1;
+}
+
+template <int ptrsize>
+void EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::extend(const uint64_t inc_amt, const EhProgramListingManip_t &other)
+{
+
+	// make an advance directive
+	string ehinsn;
+	ehinsn.resize(5);
+	ehinsn[0]=DW_CFA_advance_loc4;
+	for(auto i=0;i<4;i++)
+		ehinsn[i+1]=((const char*)(&inc_amt))[i];
+
+	// add it with this->push_back()
+	this->push_back(ehinsn);
+
+	// add elements from other[merge_index]-other[other.size()]
+	auto merge_index=getMergeIndex(other);
+	assert(merge_index>=0);
+	for_each(other.begin()+merge_index,other.end(), [&](const string& s)
+	{
+		this->push_back(s);
+	});
+
+	
+}
+
+template <int ptrsize>
+bool EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::isAdvanceDirective(const string &s)
+{
+	// make sure uint8_t is an unsigned char.       
+	static_assert(std::is_same<unsigned char, uint8_t>::value, "uint8_t is not unsigned char");
+
+	auto data=s.data();
+	auto opcode=data[0];
+	auto opcode_upper2=(uint8_t)(opcode >> 6);
+	auto opcode_lower6=(uint8_t)(opcode & (0x3f));
+
+	switch(opcode_upper2)
+	{
+		case 1:
+		{
+			return true;
+		}
+		case 0:
+		{
+			switch(opcode_lower6)
+			{
+				case DW_CFA_advance_loc1:
+				case DW_CFA_advance_loc2:
+				case DW_CFA_advance_loc4:
+					return true;
+
+			}
+		}
+	}
+	return false;
+
+}
+
+template <int ptrsize>
+EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::LSDArepresentation_t(Instruction_t* insn)
+{
+	extend(insn);
+}
+
+template <int ptrsize>
+void EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::extend(Instruction_t* insn)
+{
+	// if there's no call site info, the LSDA doesn't need an extension.
+	if(insn->GetEhCallSite() == NULL)
+		return;
+
+	// FIXME: optimization possibilty:  see if the last call site in the table
+	// has the same set of catch-types + landing_pad and is "close enough" to this insn.
+	// if so, combine.  
+
+	cout<<"Creating call sites in LSDA for "<<hex<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl;
+
+	// just create a new entry in the CS table.. 
+	auto cs=(call_site_t){0}; 
+
+	cs.cs_insn_start=insn;
+	cs.cs_insn_end=insn;
+	cs.landing_pad=insn->GetEhCallSite()->GetLandingPad();
+
+
+	// go through the relocations on the eh call site and 
+	// resolve each one by putting it into a set.
+	// the set will be (non-duplicating) inserted as a "entry" (really multiple entries) 
+	// into the action table,
+	// Each reloc will also get a non-duplicating insert into the type table.
+	for(const auto &reloc : insn->GetEhCallSite()->GetRelocations())
+	{
+		const auto wrt_scoop=dynamic_cast<DataScoop_t*>(reloc->GetWRT());
+		if(reloc->GetWRT()==NULL)
+			cout<<"\tFound reloc: NULL (catch all)"<<endl;
+		else if(wrt_scoop)
+			cout<<"\tFound reloc: scoop "<<wrt_scoop->GetName()<<"+0x"<<hex<<reloc->GetAddend()<<endl;
+		else
+			cout<<"\tFound reloc: unexpected type? "<<endl;
+
+		// for now, this is the only supported reloc type on a EhCallSite 
+		assert(reloc->GetType()=="type_table_entry");
+		cs.actions.insert(reloc);
+		auto tt_it=find(type_table.begin(),type_table.end(), reloc);
+		if(tt_it==type_table.end())
+			type_table.push_back(reloc);	
+	}
+
+	// non-duplciating insert into the action table
+	auto at_it=find(action_table.begin(),action_table.end(), cs.actions);
+	if(at_it==action_table.end())
+	{
+		// actions will be at the end of the action table.
+		cs.action_table_index=action_table.size();
+
+		// add to the action table
+		action_table.push_back(cs.actions);
+	}
+	else
+	{
+		// calc which entry in the action table for the call site.
+		cs.action_table_index=at_it-action_table.begin();
+	}
+
+	// the call site will index the action table at the end of the action table.
+	callsite_table.push_back(cs);
+}
+
+template <int ptrsize>
+bool EhWriterImpl_t<ptrsize>::FDErepresentation_t::canExtend(Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw)
+{
+	const auto insn_addr=ehw->zipr_obj.GetLocationMap()->at(insn);
+	const auto new_fde_thresh=100;
+
+	if(insn_addr<start_addr)
+		return false;
+
+	if(end_addr + new_fde_thresh < insn_addr)
+		return false;
+
+	return pgm.canExtend(insn->GetEhProgram()->GetFDEProgram()) && 
+		lsda.canExtend(insn);
+
+
+}
+
+template <int ptrsize>
+void EhWriterImpl_t<ptrsize>::FDErepresentation_t::extend(Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw)
+{
+	const auto insn_addr=ehw->zipr_obj.GetLocationMap()->at(insn);
+	const auto new_end_addr=insn_addr+insn->GetDataBits().size();
+	const auto incr_amnt=insn_addr-last_advance_addr;
+	last_advance_addr=insn_addr;
+
+	// add appropriate instructions to the pgm.
+	pgm.extend((incr_amnt)/cie->code_alignment_factor, insn->GetEhProgram()->GetFDEProgram());
+
+	lsda.extend(insn);
+
+	// extend the end 
+	end_addr=new_end_addr;
+	
+}
+
+template <int ptrsize>
+void EhWriterImpl_t<ptrsize>::FDErepresentation_t::emitAssembly(ostream& out)
+{
+	out<<"Hello"<<endl;
+}
+
+template<int ptrsize>
+void EhWriterImpl_t<ptrsize>::BuildFDEs()
+{
+	// build a map of the instructions in program order
+	map<virtual_offset_t,Instruction_t*> insn_in_order;
+	for(const auto& this_pair : *zipr_obj.GetLocationMap())
+		insn_in_order[this_pair.second]=this_pair.first;
+
+
+	// build the fdes (and cies/lsdas for this insn, starting with a null fde in case none exist
+	auto current_fde=(FDErepresentation_t*)NULL;
+	auto insns_with_frame=0;
+
+//	for_each instruction in program order
+	for(const auto& this_pair : insn_in_order)
+	{
+		const auto &this_insn=this_pair.second;
+		const auto &this_addr=this_pair.first;
+
+		// no eh pgm or call site?  no worries, just ignore this insn
+		if(this_insn->GetEhProgram()==NULL && this_insn->GetEhCallSite()==NULL)
+			continue;
+
+		insns_with_frame++;
+
+		// if it has an unwinder and/or a call site, we will need an fde.
+
+		// end this fde
+		if(current_fde && !current_fde->canExtend(this_insn, this))
+		{
+			if(getenv("EH_VERBOSE")!=NULL)
+				cout<<"Ending FDE because insn "<<hex<<this_insn->GetBaseID()<<":"<<this_insn->getDisassembly()<<" doesn't fit at " << this_addr<< endl;
+			current_fde=NULL;
+		}
+
+
+		// if we need to start a new fde, create one.
+		if(current_fde==NULL)
+		{
+			if(getenv("EH_VERBOSE")!=NULL)
+				cout<<"Creating new FDE for "<<hex<<this_insn->GetBaseID()<<":"<<this_insn->getDisassembly()<< " at " << this_addr<<endl;
+			current_fde=new FDErepresentation_t(this_insn,this);
+			all_fdes.push_back(current_fde);
+		}
+		else
+		{
+			if(getenv("EH_VERBOSE")!=NULL)
+				cout<<"Extending new FDE for "<<hex<<this_insn->GetBaseID()<<":"<<this_insn->getDisassembly()<<" at " << this_addr <<endl;
+			current_fde->extend(this_insn,this);
+		}
+	}
+	cout<<"#ATTRIBUTE fdes_calculated="<<dec<<all_fdes.size()<<endl;
+	cout<<"#ATTRIBUTE cies_calculated="<<dec<<all_cies.size()<<endl;
+	cout<<"#ATTRIBUTE insns_with_eh_info="<<dec<<insns_with_frame<<endl;
+	cout<<"#ATTRIBUTE avg_insns_per_fde="<<dec<<insns_with_frame/(float)all_fdes.size()<<endl;
+}
+
+template<int ptrsize>
+void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
+{
+
+	auto output_program=[&](const EhProgramListingManip_t& p, ostream & out) 
+	{
+		auto flags=out.flags();//save flags
+		for(const auto &s : p)
+		{		
+			out<<"       .byte ";
+			auto first=true;
+			for(const auto &c : s)
+			{
+				if(!first)
+				{
+					out<<", ";
+				}
+				else
+					first=false;
+				out<<"0x"<<hex<<setfill('0')<<setw(2)<<((int)c&0xff);
+			}
+			out << endl;
+		}
+		out.flags(flags); // restore flags
+	};
+	const auto output_lsda=[&](const FDErepresentation_t* fde, ostream& out, const uint32_t lsda_num) -> void
+	{
+		const auto lsda=&fde->lsda;
+
+		const auto output_action=[&](const set<Relocation_t*> acts, const uint32_t act_num) -> void
+		{
+			const auto zero_it=find_if(acts.begin(), acts.end(), [](const Relocation_t* act) { return act->GetWRT()==NULL; });
+			const auto has_zero=(zero_it!=acts.end());
+
+			// counter for the element in this action table entry.
+			auto act_entry_num=acts.size()-1;
+
+			if(has_zero)
+			{
+				const auto zero_reloc=*zero_it;
+				const auto tt_it=find(lsda->type_table.begin(), lsda->type_table.end(), zero_reloc);
+				assert(tt_it != lsda->type_table.end());
+				const auto tt_index=tt_it-lsda->type_table.begin();
+				out<<"LSDA"<<dec<<lsda_num<<"_act"<<act_num<<"_start_entry"<<act_entry_num<<":"<<endl;
+				out<<"	.uleb128 "<<dec<<1+tt_index<<endl;        
+				out<<"	.uleb128 0 "<<endl;
+				act_entry_num--;
+
+			}
+
+			for(const auto& act : acts)
+			{
+				// do nothing for a 
+				if(act->GetWRT()==NULL)	continue;
+
+				const auto tt_it=find(lsda->type_table.begin(), lsda->type_table.end(), act);
+				assert(tt_it != lsda->type_table.end());
+				const auto tt_index=tt_it-lsda->type_table.begin();
+				out<<"LSDA"<<dec<<lsda_num<<"_act"<<act_num<<"_start_entry"<<act_entry_num<<""<<":"<<endl;
+				out<<"	.uleb128 "<<dec<<1+tt_index<<endl;        
+				if(act_entry_num==acts.size()-1)
+					out<<"	.uleb128 0 "<<endl;
+				else
+					out<<"	.uleb128  LSDA"<<lsda_num<<"_act"<<act_num<<"_start_entry"<<act_entry_num+1<<" - . "<<endl;
+				act_entry_num--;
+			}
+        		//out<<"	.equ  LSDA"<<lsda_num<<"_act"<<act_num<<"_start,  LSDA"<<lsda_num<<"_act"<<act_num<<"_start_entry0"<<endl;
+		};
+
+
+		const auto output_callsite=[&](const typename FDErepresentation_t::LSDArepresentation_t::call_site_t &cs, const uint32_t cs_num) -> void
+		{
+			const auto cs_start_addr=zipr_obj.GetLocationMap()->at(cs.cs_insn_start);
+			const auto cs_end_addr=zipr_obj.GetLocationMap()->at(cs.cs_insn_start)+cs.cs_insn_start->GetDataBits().size();
+			const auto cs_len=cs_end_addr-cs_start_addr;
+			out<<"LSDA"<<dec<<lsda_num<<"_cs_tab_entry"<<cs_num<<"_start:"<<endl;
+        		out<<"	# 1) start of call site relative to FDE start addr"<<endl;
+        		out<<"	.uleb128 0x"<<hex<<cs_start_addr<<" - 0x"<<hex<<fde->start_addr<<endl;
+        		out<<"	# 2) length of call site"<<endl;
+        		out<<"	.uleb128 "<<dec<<cs_len<<endl;
+			if(cs.landing_pad)
+			{
+				const auto lp_addr=zipr_obj.GetLocationMap()->at(cs.landing_pad);
+				out<<"	# 3) the landing pad, or 0 if none exists."<<endl;
+				out<<"	.uleb128 0x"<<hex<<lp_addr<<" - 0x"<<hex<<fde->start_addr<<endl;
+			}
+			else
+			{
+				out<<"	# 3) the landing pad, or 0 if none exists."<<endl;
+				out<<"	.uleb128 0"<<endl;
+			}
+			if(cs.actions.size() > 0 )
+			{
+				out<<"	# 4) index into action table + 1 -- 0 indicates unwind only"<<endl;
+				out<<"	.uleb128 1 + LSDA"<<dec<<lsda_num<<"_act"<<cs.action_table_index<<"_start_entry0 - LSDA"<<dec<<lsda_num<<"_action_tab_start"<<endl;
+			}
+			else
+			{
+				out<<"	# 4) index into action table + 1 -- 0 indicates unwind only"<<endl;
+				out<<"	.uleb128 0 # no actions!" << endl;
+			}
+			out<<"LSDA"<<dec<<lsda_num<<"_cs_tab_entry"<<cs_num<<"_end:"<<endl;
+
+		};
+
+		out<<"LSDA"<<dec<<lsda_num<<":"<<endl;
+		if(!lsda->exists())
+		{
+			return;
+		}
+		out<<""<<endl;
+		out<<"        # 1) encoding of next field "<<endl;
+		out<<"        .byte 0xff # DW_EH_PE_omit (0xff)"<<endl;
+		out<<""<<endl;
+		out<<"        # 2) landing pad base, if omitted, use FDE start addr"<<endl;
+		out<<"        # .<fdebasetype> <fdebase> -- omitted.  "<<endl;
+		out<<""<<endl;
+		out<<"        # 3) encoding of type table entries"<<endl;
+		out<<"        .byte 0x3  # DW_EH_PE_udata4"<<endl;
+		out<<""<<endl;
+		out<<"        # 4) type table pointer -- always a uleb128"<<endl;
+		out<<"        .uleb128 LSDA"<<lsda_num<<"_type_table_end - LSDA"<<lsda_num<<"_tt_ptr_end"<<endl;
+		out<<"LSDA"<<lsda_num<<"_tt_ptr_end:"<<endl;
+		out<<""<<endl;
+		out<<"        # 5) call site table encoding"<<endl;
+		out<<"        .byte 0x1 # DW_EH_PE_uleb128 "<<endl;
+		out<<""<<endl;
+		out<<"        # 6) the length of the call site table"<<endl;
+		out<<"        .uleb128 LSDA"<<lsda_num<<"_cs_tab_end-LSDA"<<lsda_num<<"_cs_tab_start"<<endl;
+		out<<"LSDA"<<lsda_num<<"_cs_tab_start:"<<endl;
+
+
+		// output call site table
+		auto cs_num=0;
+		for(const auto & cs : lsda->callsite_table)
+		{
+			output_callsite(cs,cs_num++);
+		}
+		out<<"LSDA"<<dec<<lsda_num<<"_cs_tab_end:"<<endl;
+
+		// output action table
+		out<<"LSDA"<<dec<<lsda_num<<"_action_tab_start:"<<endl;
+		auto act_num=0;
+		for(const auto & act : lsda->action_table)
+		{
+			output_action(act,act_num++);
+		}
+		out<<"LSDA"<<dec<<lsda_num<<"_action_tab_end:"<<endl;
+
+
+		out<<"LSDA"<<dec<<lsda_num<<"_type_table_start:"<<endl;
+		for_each( lsda->type_table.rbegin(), lsda->type_table.rend(),  [&](const Relocation_t* reloc)
+		{
+			if(reloc->GetWRT()==NULL)
+			{
+				out<<"	.int 0x0"<<endl;
+			}
+			else
+			{
+				const auto scoop=dynamic_cast<DataScoop_t*>(reloc->GetWRT());
+				assert(scoop);
+				const auto final_addr=scoop->GetStart()->GetVirtualOffset() + reloc->GetAddend();
+				out<<"	.int 0x"<<hex<<final_addr<<endl;
+				
+			}
+		});
+		out<<"LSDA"<<dec<<lsda_num<<"_type_table_end:"<<endl;
+	};
+	const auto output_cie=[&](const CIErepresentation_t* cie, ostream& out) -> void
+	{
+		assert(cie);
+		if(cie->has_been_output)
+			return;
+
+		const auto cie_pos_it=std::find(all_cies.begin(), all_cies.end(), cie);
+		assert(cie_pos_it!=all_cies.end());
+
+		const auto personality_scoop=cie->personality_reloc ? dynamic_cast<DataScoop_t*>  (cie->personality_reloc->GetWRT()) : (DataScoop_t*)NULL;
+		const auto personality_insn =cie->personality_reloc ? dynamic_cast<Instruction_t*>(cie->personality_reloc->GetWRT()) : (Instruction_t*)NULL;
+		const auto personality_addend=cie->personality_reloc ? cie->personality_reloc->GetAddend() : 0;
+
+		const auto cie_pos=cie_pos_it-all_cies.begin();
+
+		cie->has_been_output=true;
+		out<<"# cie "<<dec<<cie_pos<<""<<endl;
+		out<<"Lcie"<<cie_pos<<":"<<endl;
+		out<<"	 .int Lcie"<<cie_pos<<"_end - Lcie"<<cie_pos<<" - 4 # length of this record. -4 because length doesn't include this field"<<endl;
+		out<<"        .int 0                  # cie (not fde)"<<endl;
+		out<<"        .byte 3                 # version"<<endl;
+		out<<"        .asciz \"zPLR\"           # aug string."<<endl;
+		out<<"        .uleb128 "<<dec<<cie->code_alignment_factor<<"              # code alignment factor"<<endl;
+		out<<"        .sleb128 "<<dec<<cie->data_alignment_factor<<"             # data alignment factor"<<endl;
+		out<<"        .uleb128 "<<dec<<cie->return_reg<<"             # return address reg."<<endl;
+		out<<"        # encode the Z (length)"<<endl;
+		out<<"        .sleb128 Lcie"<<cie_pos<<"_aug_data_end-Lcie"<<cie_pos<<"_aug_data_start # Z -- handle length field"<<endl;
+		out<<"Lcie"<<cie_pos<<"_aug_data_start:"<<endl;
+		out<<""<<endl;
+		if(personality_scoop)
+		{
+			auto personality_value=personality_scoop->GetStart()->GetVirtualOffset()+personality_addend;
+			out<<"        #encode the P (personality encoding + personality routine)"<<endl;
+			out<<"        .byte 0x80 | 0x10 | 0x0B        #  personality pointer encoding DH_EH_PE_indirect (0x80) | pcrel | sdata4"<<endl;
+			out<<"        .int "<<personality_value<<" - .               # actual personality routine, encoded as noted in prev line."<<endl;
+		}
+		else if(personality_insn)
+		{
+			const auto personality_insn_addr=zipr_obj.GetLocationMap()->at(personality_insn);
+			const auto personality_value=personality_insn_addr+personality_addend;
+			out<<"        #encode the P (personality encoding + personality routine)"<<endl;
+			out<<"        .byte 0x10 | 0x0B        #  personality pointer encoding pcrel | sdata4"<<endl;
+			out<<"        .int "<<personality_value<<" - .               # actual personality routine, encoded as noted in prev line."<<endl;
+		}
+		else
+		{
+			assert(cie->personality_reloc==NULL || cie->personality_reloc->GetWRT()==NULL);
+			out<<"        #encode the P (personality encoding + personality routine)"<<endl;
+			out<<"        .byte  0x0B        #  personality pointer encoding sdata4"<<endl;
+			out<<"        .int 0               # actual personality routine, encoded as noted in prev line."<<endl;
+		}
+		out<<""<<endl;
+		out<<"        # encode L (lsda encoding) "<<endl;
+		out<<"        .byte  0x03     # LSDA encoding (udata4 -- or maybe later pcrel|sdata4 ? )"<<endl;
+		out<<""<<endl;
+		out<<"        # encode R (FDE encoding) "<<endl;
+		out<<"        .byte  0x10 | 0x0B      # FDE encoding (pcrel | sdata4)"<<endl;
+		out<<"Lcie"<<cie_pos<<"_aug_data_end:"<<endl;
+		out<<"       # CIE program"<<endl;
+		output_program(cie->pgm,out);
+		out<<""<<endl;
+		out<<"       # pad with nops"<<endl;
+		out<<"       .align 4, 0"<<endl;
+		out<<"Lcie"<<cie_pos<<"_end:"<<endl;
+
+	};
+	auto output_fde=[&](const FDErepresentation_t* fde, ostream& out, const uint32_t fde_num) -> void
+	{
+		assert(fde && fde->cie);
+		output_cie(fde->cie,out);
+
+
+		auto cie_pos_it=std::find(all_cies.begin(), all_cies.end(), fde->cie);
+		assert(cie_pos_it!=all_cies.end());
+		auto cie_pos=cie_pos_it-all_cies.begin();
+
+		out<<"#fde "<<dec<<fde_num<<""<<endl;
+		out<<"Lfde"<<fde_num<<":"<<endl;
+		out<<"        .int Lfde"<<fde_num<<"_end - Lfde"<<fde_num<<" - 4      # length of this record. -4 because "
+		     "length doesn't include this field."<<endl;
+		out<<"        .int . - Lcie"<<cie_pos<<"                  # this is an FDE (not a "
+		     "cie), and it's cie is CIE"<<cie_pos<<".  byte offset from start of field."<<endl;
+		out<<"        .int 0x"<<hex<<fde->start_addr<<dec<<" - .               # FDE start addr"<<endl;
+		out<<"        .int "<<dec<<fde->end_addr-fde->start_addr<<"                     # fde range length (i.e., can calc the "
+		     "fde_end_addr from this -- note that pcrel is ignored here!)"<<endl;
+		out<<"        #encode Z (length)"<<endl;
+		out<<"        .uleb128 Lfde"<<fde_num<<"_aug_data_end-Lfde"<<fde_num<<"_aug_data_start"<<endl;
+		out<<"Lfde"<<fde_num<<"_aug_data_start:"<<endl;
+		out<<"        #encode L (LSDA) "<<endl;
+		if(fde->hasLsda())
+			out<<"        .int LSDA"<<fde_num<<"      # LSDA hard coded here"<<endl;	 
+		else
+			out<<"        .int 0      # no LSDA "<<endl;	 
+		out<<"Lfde"<<fde_num<<"_aug_data_end:"<<endl;
+		out<<""<<endl;
+		out<<"        # FDE"<<fde_num<<" program"<<endl;
+		output_program(fde->pgm,out);
+		out<<"        .align 4, 0"<<endl;
+		out<<"        Lfde"<<fde_num<<"_end:"<<endl;
+
+	};
+	auto generate_eh_frame_hdr=[&](ostream& out) -> void	
+	{
+		out<<".section eh_frame_hdr, \"a\", @progbits"<<endl;
+		out<<"eh_frame_hdr_start:"<<endl;
+		out<<"        .byte 1                 # version"<<endl;
+		out<<"        .byte 0x10 | 0x0B       # encoding for pointer to eh-frame -- DH_EH_PE_pcrel (0x10) | DH_EH_PE_sdata4 (0x0B)"<<endl;
+		out<<"        .byte 0x03              # encoding for ; of entries in eh-frame-hdr  -- BDH_EH_PE_udata4 (0x03)"<<endl;
+		out<<"        .byte 0x30 | 0x0B       # encoding for pointers (to fdes) held in the eh-frame-hdr header  "
+		     "-- DH_EH_PE_datarel (0x30) | DH_EH_PE_sdata4 (0x0b) " <<endl;
+
+		out<<"        .int Lfde_table - .     # pointer to fde_table, encoded as an sdata4, pcrel"<<endl;
+		out<<"        .int (eh_frame_table_end-eh_frame_table)/8     # number of FDEs in the header."<<endl;
+		out<<"        .align 4"<<endl;
+		out<<"eh_frame_table:"<<endl;
+		out<<"        # fde pointers"<<endl;
+
+		for(auto fde_num=0; fde_num < all_fdes.size(); fde_num++)
+		{
+			const auto& fde=all_fdes[fde_num];
+			out<<"        .int 0x"<<hex<<fde->start_addr<<" - eh_frame_hdr_start"<<endl;
+			out<<"        .int Lfde"<<dec<<fde_num<<" - eh_frame_hdr_start"<<endl;
+		}
+
+		out<<"eh_frame_table_end:"<<endl;
+
+	};
+	auto generate_eh_frame=[&](ostream& out) -> void	
+	{
+		out<<".section eh_frame, \"a\", @progbits"<<endl;
+		out<<"Lfde_table: # needed for xref to eh_frame_hdr" <<endl;
+
+		auto fde_num=0;
+		for(const auto& fde: all_fdes)
+		{
+			output_fde(fde,out, fde_num++);
+		}
+	};
+	auto generate_gcc_except_table=[&](ostream& out) -> void	
+	{
+		out<<".section gcc_except_table, \"a\", @progbits"<<endl;
+		auto lsda_num=0;
+		for(const auto& fde: all_fdes)
+		{
+			output_lsda(fde,out,lsda_num++);
+		}
+	};
+
+	ofstream fout(ehframe_s_filename, std::ofstream::out);
+	if(!fout)
+	{
+		cerr<<"Fatal: cannot open "<<ehframe_s_filename<<"."<<endl;
+		exit(2);
+	}
+
+	generate_eh_frame_hdr(fout);
+	generate_eh_frame(fout);
+	generate_gcc_except_table(fout);
+}
+
+template<int ptrsize>
+void EhWriterImpl_t<ptrsize>::CompileEhOutput()
+{
+	auto page_round_up=[](const uintptr_t x) -> uintptr_t 
+	{
+		auto page_size=(uintptr_t)PAGE_SIZE;
+		return  ( (((uintptr_t)(x)) + page_size-1)  & (~(page_size-1)) );
+	};
+
+	// find maximum used scoop address.
+	const auto max_used_addr=std::max_element(
+		zipr_obj.GetFileIR()->GetDataScoops().begin(),
+		zipr_obj.GetFileIR()->GetDataScoops().end(),
+		[&](const DataScoop_t* a, const DataScoop_t* b)
+		{
+			assert(a && b && a->GetEnd() && b->GetEnd()) ;
+			return a->GetEnd()->GetVirtualOffset() < b->GetEnd()->GetVirtualOffset();
+		}
+		);
+
+	// round it up and stringify it.
+	const auto eh_frame_hdr_addr=page_round_up((*max_used_addr)->GetEnd()->GetVirtualOffset());
+	const auto eh_frame_hdr_addr_str=to_hex_string(eh_frame_hdr_addr);
+
+	// create and execute the command to build the ehframe.
+	auto cmd=(string)"$PEASOUP_HOME/tools/eh_frame_tools/eh_to_bin.sh "+ehframe_s_filename+" "+eh_frame_hdr_addr_str+" "+ehframe_exe_filename;
+	auto res=system(cmd.c_str());
+
+	// err check.
+	if( res==-1 || WEXITSTATUS(res)!=0 )
+	{
+		cerr<<"Cannot compile eh_frame."<<endl;
+		exit(2);
+	}
+}
+
+template<int ptrsize>
+void EhWriterImpl_t<ptrsize>::ScoopifyEhOutput()
+{
+        ELFIO::elfio ehframe_exe_elfio;
+	ehframe_exe_elfio.load(ehframe_exe_filename);
+
+	auto to_scoop=[&](const string &secname)->void
+	{
+		auto sec=ehframe_exe_elfio.sections[secname];
+
+		// if sec is missing, don't scoopify.
+
+		if(sec==NULL) return;
+		auto data=string(sec->get_data(), sec->get_size());
+		auto start_vo=sec->get_address();
+		auto start_addr=new AddressID_t(BaseObj_t::NOT_IN_DATABASE, BaseObj_t::NOT_IN_DATABASE, start_vo);
+		auto end_vo=sec->get_address()+sec->get_size()-1;
+		auto end_addr=new AddressID_t(BaseObj_t::NOT_IN_DATABASE, BaseObj_t::NOT_IN_DATABASE, end_vo);
+		auto new_scoop=new DataScoop_t(BaseObj_t::NOT_IN_DATABASE, secname, start_addr,end_addr,NULL,4,false,data);
+
+		zipr_obj.GetFileIR()->GetAddresses().insert(start_addr);
+		zipr_obj.GetFileIR()->GetAddresses().insert(end_addr);
+		zipr_obj.GetFileIR()->GetDataScoops().insert(new_scoop);
+	};
+
+	to_scoop(".eh_frame_hdr");	
+	to_scoop(".eh_frame");	
+	to_scoop(".gcc_except_table");	
+
+
+}
+
+template<int ptrsize>
+EhWriterImpl_t<ptrsize>::~EhWriterImpl_t()
+{
+	for(const auto &i : all_fdes) delete i;
+	for(const auto &i : all_cies) delete i;
+}
+
+
+/* make sure these get compiled */
+namespace zipr
+{
+template class EhWriterImpl_t<8>;
+template class EhWriterImpl_t<4>;
+};
diff --git a/src/elfwrite.cpp b/src/elfwrite.cpp
index 2b2efad..b75babd 100644
--- a/src/elfwrite.cpp
+++ b/src/elfwrite.cpp
@@ -663,47 +663,6 @@ bool ElfWriterImpl<T_Elf_Ehdr,T_Elf_Phdr,T_Elf_Addr,T_Elf_Shdr,T_Elf_Sym, T_Elf_
 
 
 	std::vector<T_Elf_Phdr> relro_phdrs;
-#if 0
-	for_each(new_phdrs.begin(), new_phdrs.end(), [&](const T_Elf_Phdr& phdr)
-	{
-		if(phdr.p_type==PT_LOAD)
-		{
-			//auto do_relro=[&this,phdr,&relro_phdrs](const virtual_offset_t start, const virtual_offset_t end)
-			auto do_relro=[&](virtual_offset_t start, virtual_offset_t end)
-			{
-				if(! (pagemap.at(start)).is_relro)
-					return;
-
-				cout<<"Creating relro for "<<hex<<start<<"-"<<end<<endl;
-
-				T_Elf_Phdr relro_phdr=phdr;
-				relro_phdr.p_type=PT_GNU_RELRO;
-				relro_phdr.p_memsz=end-start+1;
-				relro_phdr.p_filesz=end-start+1;
-				relro_phdr.p_vaddr=start;
-				relro_phdr.p_paddr=start;
-				relro_phdr.p_offset= phdr.p_offset+start-phdr.p_vaddr;
-				relro_phdr.p_flags=4;
-
-				relro_phdrs.push_back(relro_phdr);
-			};
-
-			bool prev_relro=pagemap[phdr.p_vaddr].is_relro;
-			virtual_offset_t prev_i=phdr.p_vaddr, i=0;
-			for(i=phdr.p_vaddr; i<phdr.p_vaddr+phdr.p_memsz;i+=PAGE_SIZE)
-			{
-				if(prev_relro != pagemap.at(i).is_relro)
-				{
-					do_relro(prev_i, i-1);
-					prev_i=i;
-					prev_relro=pagemap.at(i).is_relro;
-					
-				}
-			}
-			do_relro(prev_i, i-1);
-		}
-	});
-#endif
 	new_phdrs.insert(new_phdrs.end(), relro_phdrs.begin(), relro_phdrs.end());
 
 #ifdef CGC
diff --git a/src/zipr.cpp b/src/zipr.cpp
index c55873d..041e99d 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -927,7 +927,7 @@ void ZiprImpl_t::PreReserve2ByteJumpTargets()
 				 *    b. If i has prereserved space associated with it, we
 				 *       we clear that space.
 				 */
-				printf("Warning: No location for near jump reserved at 0x%x.\n", addr);
+				cout<<"Warning: No location for near jump reserved at 0x"<<hex<<addr<<"."<<endl;
 
 				/*
 				 * The first thing that we have to do is to tell
@@ -948,7 +948,8 @@ void ZiprImpl_t::PreReserve2ByteJumpTargets()
 				for (RangeAddress_t i = addr; i<end_of_sled; i++)
 				{
 					Instruction_t *found_pinned_insn = NULL;
-					if (found_pinned_insn = FindPinnedInsnAtAddr(i))
+					found_pinned_insn = FindPinnedInsnAtAddr(i);
+					if (found_pinned_insn)
 					{
 						/*
 						 * TODO: Continue from here. Continue implementing the above
@@ -1286,7 +1287,7 @@ RangeAddress_t ZiprImpl_t::Do68Sled(RangeAddress_t addr)
 	/*
 	 * Put down the sled.
 	 */
-	for(size_t i=0;i<sled_size;i++)
+	for(auto i=0;i<sled_size;i++)
 	{
 		if (m_verbose)
 			cout << "Adding 68 at "
@@ -1428,7 +1429,7 @@ int ZiprImpl_t::Calc68SledSize(RangeAddress_t addr, size_t sled_overhead)
 	int sled_size=0;
 	while(true)
 	{
-		int i=0;
+		auto i=(size_t)0;
 		for(i=0;i<sled_overhead;i++)
 		{
 			if (FindPinnedInsnAtAddr(addr+sled_size+i))
@@ -3765,6 +3766,11 @@ void ZiprImpl_t::OutputBinaryFile(const string &name)
 #endif
 
 
+	// now that the textra scoop has been crated and setup, we have the info we need to 
+	// re-generate the eh information.
+	RelayoutEhInfo(); 
+
+
 	// create the output file in a totally different way using elfwriter. later we may 
 	// use this instead of the old way.
 
@@ -4255,3 +4261,30 @@ void  ZiprImpl_t::FixMultipleFallthroughs()
 
 	cout<<"#ATTRIBUTE zipr::jumps_inserted_for_multiple_fallthroughs="<<dec<<count<<endl;
 }
+
+
+void  ZiprImpl_t::RelayoutEhInfo()
+{
+	const auto found_eh_ir_it = find_if( 
+		m_firp->GetInstructions().begin(), 
+		m_firp->GetInstructions().end(),
+	 	[](const Instruction_t* i)
+			{ 
+				return (i->GetEhProgram()!=NULL || i->GetEhCallSite()!=NULL);
+			} 
+		);
+
+	// do nothing if we didn't find any IR.
+	if(found_eh_ir_it==m_firp->GetInstructions().end())
+		return;
+		
+	auto eh = (EhWriter_t *)NULL;
+	if(m_firp->GetArchitectureBitWidth()==64)
+		eh=new EhWriterImpl_t<8>(*this);
+	else if(m_firp->GetArchitectureBitWidth()==32)
+		eh=new EhWriterImpl_t<4>(*this);
+	else
+		assert(0);
+
+	eh->GenerateNewEhInfo();
+}
-- 
GitLab