From 7dd13a74121ee1c44b6fa35d639b8ff2e3a6a2ae Mon Sep 17 00:00:00 2001
From: Jason Hiser <jdhiser@gmail.com>
Date: Mon, 22 Apr 2019 14:20:35 -0400
Subject: [PATCH] code cleanups, and no longer forcing unpinned ibt
 instructions into the placement queue.  we should put them in on demand if we
 find they aren't being placed.

---
 include/ehwrite.h  | 342 ++++++++++++++++-------
 src/ehwrite.cpp    | 674 +++++++++++++++++++++++++++++----------------
 src/pewrite.cpp    |  14 +
 src/pinner_x86.cpp |  89 +++---
 src/zipr.cpp       |  27 +-
 5 files changed, 732 insertions(+), 414 deletions(-)

diff --git a/include/ehwrite.h b/include/ehwrite.h
index 63e4b0ef2..4ea9e8b70 100644
--- a/include/ehwrite.h
+++ b/include/ehwrite.h
@@ -2,141 +2,289 @@
 #define EhWriter_h
 
 #include <iostream>
+#include <irdb-core>
 
-class EhWriter_t 
-{	 
-	public: 
-	virtual void GenerateNewEhInfo() =0;
-};
+namespace EhWriter
+{
 
+	using namespace std;
+	using namespace IRDB_SDK;
 
-static const std::string ehframe_s_filename="ehframe.s";
-static const std::string ehframe_exe_filename="ehframe.exe";
+	class EhWriter_t 
+	{	 
+		protected:
+			ZiprImpl_t& zipr_obj;
+			VirtualOffset_t eh_addr=0;
 
-template <int ptrsize> 
-class EhWriterImpl_t : public EhWriter_t
-{
-	private:
+			EhWriter_t(ZiprImpl_t& p_zipr_obj)
+				: 
+					zipr_obj(p_zipr_obj)
+			{
 
+			}
 
+			void SetEhAddr()
+			{
+
+				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=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.
+				eh_addr=page_round_up((*max_used_addr)->getEnd()->getVirtualOffset());
+			}
+
+
+		public: 
+			virtual ~EhWriter_t() {}
+			virtual void GenerateNewEhInfo() =0;
+
+		static unique_ptr<EhWriter_t> factory(ZiprImpl_t& p_zipr_obj);
+	};
 
-	class EhProgramListingManip_t : public IRDB_SDK::EhProgramListing_t
+	class PE_unwind_info_t
 	{
-		public:
-		EhProgramListingManip_t(){}
-		EhProgramListingManip_t(const IRDB_SDK::EhProgramListing_t &pgm) : IRDB_SDK::EhProgramListing_t(pgm) { }
-		bool canExtend(const EhProgramListingManip_t &other);
-		void extend(const uint64_t inc_amt, const EhProgramListingManip_t &other);
-		bool isAdvanceDirective(const std::string &s) const;
-		std::string getPrintableString(const std::string &s) const;
 		private:
-		int getMergeIndex(const EhProgramListingManip_t &other);
+			VirtualOffset_t start_rva = 0;
+			VirtualOffset_t end_rva   = 0;
+			union
+			{
+				struct
+				{
+					uint8_t	version:3;
+					uint8_t	flags:5;
+				} parts;
+				uint8_t whole;
+			} ver_and_flags = {};
+			uint8_t	prolog_sz = 0;
+			union
+			{
+				struct
+				{
+					uint8_t	frame_reg:4;
+					uint8_t	frame_reg_offset:4;
+				} parts;
+				uint8_t whole;
+			} frame_reg_and_offset = {};
+			vector<uint16_t> unwind_array;
+
+			struct 
+			{
+				uint32_t         handler_rva;
+				vector<uint8_t>  user_data;
+			} handle = {};
+
+			ZiprImpl_t& zipr_obj;
+
+		public:
+			PE_unwind_info_t(Instruction_t* insns, ZiprImpl_t& zipr_obj);
+
+			bool canExtend(Instruction_t* insn) const
+			{
+				const auto o = PE_unwind_info_t(insn, zipr_obj);
+				return tie(  ver_and_flags.whole,   prolog_sz,   frame_reg_and_offset.whole,   unwind_array,   handle.handler_rva,   handle.user_data) ==
+				       tie(o.ver_and_flags.whole, o.prolog_sz, o.frame_reg_and_offset.whole, o.unwind_array, o.handle.handler_rva, o.handle.user_data) ;
+			}
+
+			void extend(Instruction_t* insn)
+			{
+				const auto &loc_map = *zipr_obj.getLocationMap();
+				end_rva             = loc_map.at(insn) - zipr_obj.getFileIR()->getArchitecture()->getFileBase() + insn->getDataBits().size();
+			}
+
+			void extend(const VirtualOffset_t to_addr)
+			{
+				end_rva = to_addr - zipr_obj.getFileIR()->getArchitecture()->getFileBase();
+			}
+
+			string get_raw_bytes() const
+			{
+				const auto unwind_sz = static_cast<uint8_t>(unwind_array.size());
+
+				auto ret = string();
+				ret += string(reinterpret_cast<const char*>(&ver_and_flags.whole)       , 1) ; 
+				ret += string(reinterpret_cast<const char*>(&prolog_sz)                 , 1) ;
+				ret += string(reinterpret_cast<const char*>(&unwind_sz)                 , 1) ; 
+				ret += string(reinterpret_cast<const char*>(&frame_reg_and_offset.whole), 1) ;
+				ret += string(reinterpret_cast<const char*>(unwind_array.data())        , 2*unwind_array.size());
+
+				// may need to pad the unwind array.
+				if( (unwind_sz & 0b1) == 0xb1 )
+					ret += string(2, '\0');
+
+
+				ret += string(reinterpret_cast<const char*>(&handle.handler_rva)    , 4);
+				ret += string(reinterpret_cast<const char*>(handle.user_data.data()), handle.user_data.size());
+
+				return move(ret);
+
+			}
+
+			VirtualOffset_t getStartRVA() const { return start_rva; }
+			VirtualOffset_t getEndRVA()   const { return end_rva; }
 
-		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
+	template <int ptrsize> 
+	class PEEhWriter_t : public EhWriter_t
 	{
-		public:
-		CIErepresentation_t(IRDB_SDK::Instruction_t*, EhWriterImpl_t<ptrsize>* ehw);
-		void emitAssembly(std::ostream& out) {}
-		bool canSupport(IRDB_SDK::Instruction_t* insn) const;
-		IRDB_SDK::Relocation_t* GetPersonalityReloc() const { return personality_reloc;}
-
 		private:
-			// need nothing?
+			using SehVector_t = vector<unique_ptr<PE_unwind_info_t> > ;
 
-		EhProgramListingManip_t pgm;
-		uint64_t code_alignment_factor;
-		int64_t data_alignment_factor;
-		uint64_t return_reg;
-		IRDB_SDK::Relocation_t* personality_reloc;
+			SehVector_t BuildSehVector();
+			void LayoutSehVector (const SehVector_t& seh_vector);
 
-		mutable bool has_been_output;
+		public:
+			PEEhWriter_t(ZiprImpl_t& p_zipr_obj) 
+				: EhWriter_t(p_zipr_obj)
+			
+			{ 
+			}
 
-		friend class FDErepresentation_t;
-		friend EhWriterImpl_t<ptrsize>;	
-	};
+			virtual ~PEEhWriter_t() {}
 
-	static void print_pers(IRDB_SDK::Instruction_t* insn, CIErepresentation_t *cie);
+			void GenerateNewEhInfo();
 
+	};
 
-	class FDErepresentation_t
+	template <int ptrsize> 
+	class ElfEhWriter_t : public EhWriter_t
 	{
+
 		private:
 
-		class LSDArepresentation_t
-		{
-			public:
-			LSDArepresentation_t(IRDB_SDK::Instruction_t* insn);
-			void extend(IRDB_SDK::Instruction_t* insn);
-			bool canExtend(IRDB_SDK::Instruction_t* insn) const;
-			bool exists()  const  { return callsite_table.size() > 0; }
+			const string ehframe_s_filename="ehframe.s";
+			const string ehframe_exe_filename="ehframe.exe";
 
-			struct call_site_t
+			class EhProgramListingManip_t : public EhProgramListing_t
 			{
-				IRDB_SDK::Instruction_t* cs_insn_start;
-				IRDB_SDK::Instruction_t* cs_insn_end;
-				IRDB_SDK::Instruction_t* landing_pad;
-				int action_table_index;
-				IRDB_SDK::TTOrderVector_t actions;
+				public:
+				EhProgramListingManip_t(){}
+				EhProgramListingManip_t(const EhProgramListing_t &pgm) : EhProgramListing_t(pgm) { }
+				bool canExtend(const EhProgramListingManip_t &other);
+				void extend(const uint64_t inc_amt, const EhProgramListingManip_t &other);
+				bool isAdvanceDirective(const string &s) const;
+				string getPrintableString(const string &s) const;
+				private:
+				int getMergeIndex(const EhProgramListingManip_t &other);
+
+				static const int DW_CFA_advance_loc1 = 0x02;
+				static const int DW_CFA_advance_loc2 = 0x03;
+				static const int DW_CFA_advance_loc4 = 0x04;
+
 			};
-			std::vector<call_site_t> callsite_table;
-			std::vector<IRDB_SDK::TTOrderVector_t> action_table;
-			std::vector<IRDB_SDK::Relocation_t*> type_table;
-			uint64_t tt_encoding;
 
-		};
+			class FDErepresentation_t;	// forward decl
+			class CIErepresentation_t
+			{
+				public:
+				CIErepresentation_t(Instruction_t*, ElfEhWriter_t<ptrsize>* ehw);
+				bool canSupport(Instruction_t* insn) const;
+				Relocation_t* GetPersonalityReloc() const { return personality_reloc;}
 
-		LSDArepresentation_t lsda;
-		CIErepresentation_t* cie;
-		IRDB_SDK::VirtualOffset_t start_addr;
-		IRDB_SDK::VirtualOffset_t end_addr;
-		IRDB_SDK::VirtualOffset_t last_advance_addr;
-		// the pgm for the fde
-		EhProgramListingManip_t pgm;
+				private:
+					// need nothing?
 
-		public:
-		FDErepresentation_t(IRDB_SDK::Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw);
-		void extend(IRDB_SDK::Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw);
-		void emitAssembly(std::ostream& out);
-		bool canExtend(IRDB_SDK::Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw);
-		bool hasLsda() const { return lsda.exists(); }
+				EhProgramListingManip_t pgm;
+				uint64_t code_alignment_factor;
+				int64_t data_alignment_factor;
+				uint64_t return_reg;
+				Relocation_t* personality_reloc;
 
-		friend EhWriterImpl_t<ptrsize>;	
-	};
+				mutable bool has_been_output;
+
+				friend class FDErepresentation_t;
+				friend ElfEhWriter_t<ptrsize>;	
+			};
 
-	friend class FDErepresentation_t;
-	friend class CIErepresentation_t;
+			static void print_pers(Instruction_t* insn, CIErepresentation_t *cie);
 
-	ZiprImpl_t& zipr_obj;
-	std::vector<FDErepresentation_t*> all_fdes;
-	std::vector<CIErepresentation_t*> all_cies;
 
-	VirtualOffset_t eh_frame_hdr_addr; // where the eh frame hdr will land.
-	string asm_comment;
+			class FDErepresentation_t
+			{
+				private:
+
+				class LSDArepresentation_t
+				{
+					public:
+					LSDArepresentation_t(Instruction_t* insn);
+					void extend(Instruction_t* insn);
+					bool canExtend(Instruction_t* insn) const;
+					bool exists()  const  { return callsite_table.size() > 0; }
+
+					struct call_site_t
+					{
+						Instruction_t* cs_insn_start;
+						Instruction_t* cs_insn_end;
+						Instruction_t* landing_pad;
+						int action_table_index;
+						TTOrderVector_t actions;
+					};
+					vector<call_site_t> callsite_table;
+					vector<TTOrderVector_t> action_table;
+					vector<Relocation_t*> type_table;
+					uint64_t tt_encoding;
+
+				};
+
+				LSDArepresentation_t lsda;
+				CIErepresentation_t* cie;
+				VirtualOffset_t start_addr;
+				VirtualOffset_t end_addr;
+				VirtualOffset_t last_advance_addr;
+				// the pgm for the fde
+				EhProgramListingManip_t pgm;
+
+				public:
+				FDErepresentation_t(Instruction_t* insn, ElfEhWriter_t<ptrsize>* ehw);
+				void extend(Instruction_t* insn, ElfEhWriter_t<ptrsize>* ehw);
+				bool canExtend(Instruction_t* insn, ElfEhWriter_t<ptrsize>* ehw);
+				bool hasLsda() const { return lsda.exists(); }
+
+				friend ElfEhWriter_t<ptrsize>;	
+			};
 
-        void BuildFDEs();
-        void GenerateEhOutput();
-        void CompileEhOutput();
-        void ScoopifyEhOutput();
+			friend class FDErepresentation_t;
+			friend class CIErepresentation_t;
 
-	public:
-	EhWriterImpl_t(ZiprImpl_t& p_zipr_obj) 
-		: zipr_obj(p_zipr_obj)
-	
-	{ 
-		asm_comment = p_zipr_obj.getFileIR()->getArchitecture()->getMachineType()==admtAarch64 ?  " // " : " # " ;
-	}
+			vector<FDErepresentation_t*> all_fdes;
+			vector<CIErepresentation_t*> all_cies;
 
-	virtual ~EhWriterImpl_t();
+			VirtualOffset_t eh_frame_hdr_addr; // where the eh frame hdr will land.
+			string asm_comment;
 
-	void GenerateNewEhInfo();
+			void BuildFDEs();
+			void GenerateEhOutput();
+			void CompileEhOutput();
+			void ScoopifyEhOutput();
 
-};
+		public:
+			ElfEhWriter_t(ZiprImpl_t& p_zipr_obj) 
+				: EhWriter_t(p_zipr_obj)
+			
+			{ 
+				asm_comment = p_zipr_obj.getFileIR()->getArchitecture()->getMachineType()==admtAarch64 ?  " // " : " # " ;
+			}
+
+			virtual ~ElfEhWriter_t();
+
+			void GenerateNewEhInfo();
+
+	};
+}
 
 #endif
diff --git a/src/ehwrite.cpp b/src/ehwrite.cpp
index 65b82543c..ffaf300e1 100644
--- a/src/ehwrite.cpp
+++ b/src/ehwrite.cpp
@@ -9,8 +9,8 @@
 #include <assert.h>
 #include <sys/mman.h>
 #include <ctype.h>
-#include <iostream>   // std::cout
-#include <string>     // std::string, std::to_string
+#include <iostream>   // cout
+#include <string>     // string, to_string
 #include <fstream>
 #include <elf.h>
 
@@ -22,38 +22,211 @@ using namespace IRDB_SDK;
 using namespace std;
 using namespace zipr;
 using namespace EXEIO;
+using namespace EhWriter;
 
-template < typename T > std::string to_hex_string( const T& n )
+#define ALLOF(a) begin(a),end(a)
+
+template < typename T > string to_hex_string( const T& n )
 {
-        std::ostringstream stm ;
-        stm << std::hex<< "0x"<< n ;
+        ostringstream stm ;
+        stm << hex <<  "0x" <<  n ;
         return stm.str() ;
 }
 
+
+
+PE_unwind_info_t::PE_unwind_info_t(Instruction_t* insn, ZiprImpl_t& p_zipr_obj)
+	: zipr_obj(p_zipr_obj)
+{
+	// extract bits from IR into this structure.
+	const auto  ehpgm        = insn->getEhProgram();
+	const auto  cie_pgm      = ehpgm ->getCIEProgram();
+	const auto  fde_pgm      = ehpgm ->getFDEProgram();
+	const auto &ehcs         = insn->getEhCallSite();
+	const auto  handler_insn = ehcs->getLandingPad();
+	const auto &loc_map      = *zipr_obj.getLocationMap();
+
+	// constants
+	ver_and_flags.parts.version                 = *reinterpret_cast<const uint8_t*>(cie_pgm[0].c_str());
+	ver_and_flags.parts.flags                   = *reinterpret_cast<const uint8_t*>(cie_pgm[1].c_str());
+	prolog_sz                                   = 0; // don't do prologues for now.
+	frame_reg_and_offset.parts.frame_reg        = *reinterpret_cast<const uint8_t*>(cie_pgm[2].c_str());
+	frame_reg_and_offset.parts.frame_reg_offset = *reinterpret_cast<const uint8_t*>(cie_pgm[3].c_str());
+
+	// extract unwind array
+	for(const auto &s : fde_pgm) 	
+		unwind_array.push_back({*reinterpret_cast<const uint16_t*>(s.c_str())});
+
+	// extract the handler
+	if(handler_insn != nullptr)
+		handle.handler_rva = loc_map.at(handler_insn) - zipr_obj.getFileIR()->getArchitecture()->getFileBase();
+
+	start_rva = loc_map.at(insn) - zipr_obj.getFileIR()->getArchitecture()->getFileBase();
+	end_rva   = loc_map.at(insn) - zipr_obj.getFileIR()->getArchitecture()->getFileBase() + insn->getDataBits().size();
+	
+	// extract user data
+	if(cie_pgm.size() > 4) 
+		handle.user_data.insert(handle.user_data.end(), ALLOF(cie_pgm[4]));
+
+}
+
 template<int ptrsize>
-void EhWriterImpl_t<ptrsize>::GenerateNewEhInfo()
+typename PEEhWriter_t<ptrsize>::SehVector_t  PEEhWriter_t<ptrsize>::BuildSehVector()
 {
-	auto page_round_up=[](const uintptr_t x) -> uintptr_t 
+	// build a map of the instructions in program order
+	auto insn_in_order = map<VirtualOffset_t,Instruction_t*>();
+	for(const auto& this_pair : *zipr_obj.GetLocationMap())
+		insn_in_order[this_pair.second]=this_pair.first;
+
+	// build the unwind directory and unwind info
+	auto insns_with_frame      = 0u;
+	auto current_unwind_info   = unique_ptr<PE_unwind_info_t>();
+	auto all_unwind_infos      = vector<unique_ptr<PE_unwind_info_t> >();
+
+
+	// generate an unwind info struct for each chunk of code in the output program.
+	// record in all_unwind_infos
+	// for_each instruction in program order
+	for(const auto& this_pair : insn_in_order)
 	{
-		auto page_size=(uintptr_t)PAGE_SIZE;
-		return  ( (((uintptr_t)(x)) + page_size-1)  & (~(page_size-1)) );
-	};
+		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()==nullptr && this_insn->getEhCallSite()==nullptr)
+			continue;
 
-	// 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)
+		insns_with_frame++;
+
+		// if it has an unwinder and/or a call site, we will need an fde.
+
+		// end this fde
+		if(current_unwind_info && !current_unwind_info->canExtend(this_insn))
 		{
-			assert(a && b && a->getEnd() && b->getEnd()) ;
-			return a->getEnd()->getVirtualOffset() < b->getEnd()->getVirtualOffset();
+			if(getenv("EH_VERBOSE")!=nullptr)
+				cout << "Ending unwind_info because insn " << hex << this_insn->getBaseID() << ":" << this_insn->getDisassembly() << " doesn't fit at "  <<  this_addr << endl;
+
+			current_unwind_info->extend(this_addr);  // extend all the way up to this instruction, but then end this unwind info.
+			all_unwind_infos.push_back(move(current_unwind_info));
 		}
-		);
 
-	// round it up and stringify it.
-	eh_frame_hdr_addr=page_round_up((*max_used_addr)->getEnd()->getVirtualOffset());
 
-	
+		// if we need to start a new fde, create one.
+		if(current_unwind_info == nullptr)
+		{
+			if(getenv("EH_VERBOSE")!=nullptr)
+				cout << "Creating new unwind_info for " << hex << this_insn->getBaseID() << ":" << this_insn->getDisassembly() <<  " at "  <<  this_addr << endl;
+			current_unwind_info.reset(new PE_unwind_info_t(this_insn, zipr_obj));
+		}
+		else
+		{
+			if(getenv("EH_VERBOSE")!=nullptr)
+				cout << "Extending unwind info for " << hex << this_insn->getBaseID() << ":" << this_insn->getDisassembly() << " at "  <<  this_addr  << endl;
+
+			current_unwind_info->extend(this_insn);
+		}
+	}
+	const auto unwind_infos        = all_unwind_infos.size();
+	const auto avg_insn_per_unwind = insns_with_frame/(float)unwind_infos;
+
+	cout << "# ATTRIBUTE ExceptionHandlerWrite::unwinds_calculated=" << dec << unwind_infos        << endl;
+	cout << "# ATTRIBUTE ExceptionHandlerWrite::insns_with_eh_info=" << dec << insns_with_frame    << endl;
+	cout << "# ATTRIBUTE ExceptionHandlerWrite::avg_insns_per_fde =" << dec << avg_insn_per_unwind << endl;
+	return move(all_unwind_infos);
+}
+
+template<int ptrsize>
+void PEEhWriter_t<ptrsize>::LayoutSehVector(const PEEhWriter_t<ptrsize>::SehVector_t& seh_vector)
+{
+	const auto exc_dir_entry_sz = (sizeof(uint32_t)*3);
+	const auto exc_dir_sz       = seh_vector.size() * exc_dir_entry_sz;
+	const auto unwind_info_addr = eh_addr + exc_dir_sz;
+	const auto firp             = zipr_obj.getFileIR();
+	const auto file_base        = firp->getArchitecture()->getFileBase();
+
+
+
+	// assign addresses to the unwind infos.
+	// and record the bytes that go into the unwind area
+	auto cur_uia      = unwind_info_addr;
+	auto ui_rvas      = map<PE_unwind_info_t*, VirtualOffset_t>();
+	auto all_ui_bytes = string();
+
+	for(auto & ui : seh_vector)
+	{
+		// record address
+		ui_rvas[ui.get()] = cur_uia - file_base;
+
+		// get the raw bytes
+		auto raw_bytes = ui->get_raw_bytes();
+
+		// update the address of the next thing to be at the right place
+		cur_uia += raw_bytes.length();
+
+		// record the raw bytes for output in a moment.
+		all_ui_bytes += raw_bytes;
+ 
+	}
+
+	// now, record the exception directory entries
+	auto except_dir_str = string();
+	for(auto &ui : seh_vector)
+	{
+		// create the entry
+		struct 
+		{
+			uint32_t start_rva;
+			uint32_t end_rva;
+			uint32_t unwind_rva;
+
+		} entry = 
+		{
+			static_cast<uint32_t>(ui->getStartRVA()),
+			static_cast<uint32_t>(ui->getEndRVA()),
+			static_cast<uint32_t>(ui_rvas[ui.get()])
+		};
+
+		// record the bytes as a string;
+		except_dir_str += string (reinterpret_cast<const char*>(&entry), sizeof(entry));
+	}
+
+
+	// how to create a scoop
+	auto to_scoop=[&](const string& name, const string& contents, const VirtualOffset_t start_rva) -> DataScoop_t*
+		{
+			// create exception directory
+			const auto start_vo   = start_rva;
+			const auto start_addr = firp->addNewAddress(BaseObj_t::NOT_IN_DATABASE, start_vo);
+			const auto end_vo     = start_vo + contents.size();
+			const auto end_addr   = firp->addNewAddress(BaseObj_t::NOT_IN_DATABASE, end_vo);
+			return firp->addNewDataScoop(name, start_addr,end_addr,nullptr,4,false,contents);
+		};
+
+	// create a scoop in the IR for the new SEH data
+	to_scoop(".zipr_sehd" , except_dir_str, eh_addr);
+	to_scoop(".zipr_sehui", all_ui_bytes  , eh_addr+except_dir_str.size());
+
+}
+
+template<int ptrsize>
+void PEEhWriter_t<ptrsize>::GenerateNewEhInfo()
+{
+	// find the location of the eh infos.
+	SetEhAddr(); 
+
+	// build the basic structure.
+	const auto seh_vec = BuildSehVector();
+	LayoutSehVector(seh_vec);
+}
+
+template<int ptrsize>
+void ElfEhWriter_t<ptrsize>::GenerateNewEhInfo()
+{
+
+	// find and record the max scoop addr, round it up 
+	SetEhAddr(); 
+	eh_frame_hdr_addr=eh_addr;
+
 	BuildFDEs();
 	GenerateEhOutput();
 	CompileEhOutput();
@@ -62,7 +235,7 @@ void EhWriterImpl_t<ptrsize>::GenerateNewEhInfo()
 }
 
 template <int ptrsize>
-bool EhWriterImpl_t<ptrsize>::CIErepresentation_t::canSupport(Instruction_t* insn) const
+bool ElfEhWriter_t<ptrsize>::CIErepresentation_t::canSupport(Instruction_t* insn) const
 {
 	// if the insn is missing info, we can support it.
 	if(insn==nullptr)
@@ -104,7 +277,7 @@ bool EhWriterImpl_t<ptrsize>::CIErepresentation_t::canSupport(Instruction_t* ins
 }
 
 template <int ptrsize>
-EhWriterImpl_t<ptrsize>::CIErepresentation_t::CIErepresentation_t(Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw)
+ElfEhWriter_t<ptrsize>::CIErepresentation_t::CIErepresentation_t(Instruction_t* insn, ElfEhWriter_t<ptrsize>* ehw)
 	: has_been_output(false)
 {
 	assert(insn && ehw && insn->getEhProgram());
@@ -126,29 +299,29 @@ EhWriterImpl_t<ptrsize>::CIErepresentation_t::CIErepresentation_t(Instruction_t*
 
 
 template <int ptrsize>
-void EhWriterImpl_t<ptrsize>::print_pers(Instruction_t* insn, EhWriterImpl_t<ptrsize>::CIErepresentation_t *cie)
+void ElfEhWriter_t<ptrsize>::print_pers(Instruction_t* insn, ElfEhWriter_t<ptrsize>::CIErepresentation_t *cie)
 {
 	const auto pretty_print= [&](Relocation_t* pr)
 		{
 			if(pr==nullptr)
 			{
-				cout<<"Found no personality reloc"<<endl;
+				cout << "Found no personality reloc" << endl;
 				return;
 			}
 			const auto personality_scoop=dynamic_cast<DataScoop_t*>(pr->getWRT());
 			const auto personality_insn=dynamic_cast<Instruction_t*>(pr->getWRT());
 
 			if(pr->getWRT()==nullptr)
-				cout<<"\tFound null personality"<<endl;
+				cout << "\tFound null personality" << endl;
 			else if(personality_scoop)
-				cout<<"\tFound personlity scoop "<<personality_scoop->getName()<<"+0x"<<hex<<pr->getAddend()<<endl;
+				cout << "\tFound personlity scoop " << personality_scoop->getName() << "+0x" << hex << pr->getAddend() << endl;
 			else if(personality_insn)
-				cout<<"\tFound personlity instruction "<<hex<<personality_insn->getBaseID()<<dec<<":"<<hex<<personality_insn->getDisassembly()<<endl;
+				cout << "\tFound personlity instruction " << hex << personality_insn->getBaseID() << dec << ":" << hex << personality_insn->getDisassembly() << endl;
 			else
-				cout<<"\tFound reloc: unexpected type? "<<endl;
+				cout << "\tFound reloc: unexpected type? " << endl;
 		};
 
-	cout<<"  CIE-Personality addr= "<<hex<<cie->personality_reloc<<dec<<endl;
+	cout << "  CIE-Personality addr= " << hex << cie->personality_reloc << dec << endl;
 	pretty_print(cie->GetPersonalityReloc());
 	const auto personality_it=find_if(
 		insn->getEhProgram()->getRelocations().begin(), 
@@ -158,7 +331,7 @@ void EhWriterImpl_t<ptrsize>::print_pers(Instruction_t* insn, EhWriterImpl_t<ptr
 	const auto pr = (personality_it==insn->getEhProgram()->getRelocations().end())
 		? (Relocation_t*)nullptr
 		: *personality_it;
-	cout<<"  insn personality addr= "<<hex<<pr<<dec<<endl;
+	cout << "  insn personality addr= " << hex << pr << dec << endl;
 	pretty_print(pr);
 
 
@@ -166,7 +339,7 @@ void EhWriterImpl_t<ptrsize>::print_pers(Instruction_t* insn, EhWriterImpl_t<ptr
 
 
 template <int ptrsize>
-EhWriterImpl_t<ptrsize>::FDErepresentation_t::FDErepresentation_t(Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw)
+ElfEhWriter_t<ptrsize>::FDErepresentation_t::FDErepresentation_t(Instruction_t* insn, ElfEhWriter_t<ptrsize>* ehw)
 	: 
 		lsda(insn),
 		cie(nullptr)
@@ -182,14 +355,14 @@ EhWriterImpl_t<ptrsize>::FDErepresentation_t::FDErepresentation_t(Instruction_t*
 		ehw->all_cies.push_back(cie);
 
 		if(getenv("EH_VERBOSE")!=nullptr)
-			cout<<"Creating new CIE representation"<<endl;
+			cout << "Creating new CIE representation" << endl;
 	}
 	else
 	{
 		cie=*cie_it;
 		if(getenv("EH_VERBOSE")!=nullptr)
 		{
-			cout<<"Re-using CIE representation"<<endl;
+			cout << "Re-using CIE representation" << endl;
 			print_pers(insn, cie);
 		}
 	}
@@ -202,7 +375,7 @@ EhWriterImpl_t<ptrsize>::FDErepresentation_t::FDErepresentation_t(Instruction_t*
 
 
 template <int ptrsize>
-int EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getMergeIndex(const EhProgramListingManip_t &other)
+int ElfEhWriter_t<ptrsize>::EhProgramListingManip_t::getMergeIndex(const EhProgramListingManip_t &other)
 {
 	auto other_index=(size_t)0;
 	for(const auto &this_ele : *this)
@@ -221,13 +394,13 @@ int EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getMergeIndex(const EhProg
 	return other_index;
 }
 template <int ptrsize>
-bool EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::canExtend(const EhProgramListingManip_t &other)
+bool ElfEhWriter_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)
+void ElfEhWriter_t<ptrsize>::EhProgramListingManip_t::extend(const uint64_t inc_amt, const EhProgramListingManip_t &other)
 {
 	if(size() > 0 && isAdvanceDirective(at(size()-1)))
 	{
@@ -308,10 +481,10 @@ void EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::extend(const uint64_t inc
 }
 
 template <int ptrsize>
-bool EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::isAdvanceDirective(const string &s) const
+bool ElfEhWriter_t<ptrsize>::EhProgramListingManip_t::isAdvanceDirective(const string &s) const
 {
 	// make sure uint8_t is an unsigned char.       
-	static_assert(std::is_same<unsigned char, uint8_t>::value, "uint8_t is not unsigned char");
+	static_assert(is_same<unsigned char, uint8_t>::value, "uint8_t is not unsigned char");
 
 	auto data=s.data();
 	auto opcode=data[0];
@@ -379,7 +552,7 @@ static bool read_sleb128 (
         {
                 byte = data [position];
                 position++;
-                result |= ((byte & 0x7f)<< shift);
+                result |= ((byte & 0x7f) << shift);
                 shift += 7;
         } while( (byte & 0x80) != 0);
 
@@ -403,7 +576,7 @@ static void print_uleb_operand(
 {
         auto uleb=uint64_t(0xdeadbeef);
         read_uleb128<ptrsize>(uleb, pos, data, max);
-        sout<<" "<<dec<<uleb;
+        sout << " " << dec << uleb;
 }
 
 template <int ptrsize>
@@ -415,18 +588,18 @@ static void print_sleb_operand(
 {
         auto leb=int64_t(0xdeadbeef);
         read_sleb128<ptrsize>(leb, pos, data, max);
-        sout<<" "<<dec<<leb;
+        sout << " " << dec << leb;
 }
 
 
 
 template <int ptrsize>
-string EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getPrintableString(const string &s) const
+string ElfEhWriter_t<ptrsize>::EhProgramListingManip_t::getPrintableString(const string &s) const
 {
 
 	stringstream sout;
 	// make sure uint8_t is an unsigned char.	
-	static_assert(std::is_same<unsigned char, uint8_t>::value, "uint8_t is not unsigned char");
+	static_assert(is_same<unsigned char, uint8_t>::value, "uint8_t is not unsigned char");
 
 	auto data=s;
 	auto opcode=(uint8_t)data[0];
@@ -440,23 +613,23 @@ string EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getPrintableString(cons
 		case 1:
 		{
 			// case DW_CFA_advance_loc:
-			sout<<"				cfa_advance_loc "<<dec<<+opcode_lower6<<" * caf";
+			sout << "				cfa_advance_loc " << dec << +opcode_lower6 << " * caf";
 			break;
 		}
 		case 2:
 		{
 			uint64_t uleb=0;
-			sout<<"				cfa_offset "; 
+			sout << "				cfa_offset "; 
 			if(read_uleb128<ptrsize>(uleb, pos, (const uint8_t* const)data.data(), max))
 				break;
 			// case DW_CFA_offset:
-			sout <<dec<<uleb;
+			sout  << dec << uleb;
 			break;
 		}
 		case 3:
 		{
 			// case DW_CFA_restore (register #):
-			sout<<"				cfa_restore";
+			sout << "				cfa_restore";
 			break;
 		}
 		case 0:
@@ -465,39 +638,39 @@ string EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getPrintableString(cons
 			{
 			
 				case DW_CFA_nop:
-					sout<<"				nop" ;
+					sout << "				nop" ;
 					break;
 				case DW_CFA_remember_state:
-					sout<<"				remember_state" ;
+					sout << "				remember_state" ;
 					break;
 				case DW_CFA_restore_state:
-					sout<<"				restore_state" ;
+					sout << "				restore_state" ;
 					break;
 
 				// takes single uleb128
 				case DW_CFA_undefined:
-					sout<<"				undefined" ;
+					sout << "				undefined" ;
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max); 
 					break;
 		
 				case DW_CFA_same_value:
-					sout<<"				same_value ";
+					sout << "				same_value ";
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max); 
 					break;
 				case DW_CFA_restore_extended:
-					sout<<"				restore_extended ";
+					sout << "				restore_extended ";
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max); 
 					break;
 				case DW_CFA_def_cfa_register:
-					sout<<"				def_cfa_register ";
+					sout << "				def_cfa_register ";
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max); 
 					break;
 				case DW_CFA_GNU_args_size:
-					sout<<"				GNU_arg_size ";
+					sout << "				GNU_arg_size ";
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max); 
 					break;
 				case DW_CFA_def_cfa_offset:
-					sout<<"				def_cfa_offset "; 
+					sout << "				def_cfa_offset "; 
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max); 
 					break;
 
@@ -513,46 +686,46 @@ string EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getPrintableString(cons
 						default: 
 							assert(0);
 					}
-					sout<<"				set_loc "<<hex<<arg;
+					sout << "				set_loc " << hex << arg;
 					break;
 				}
 				case DW_CFA_advance_loc1:
 				{
 					auto loc=*(uint8_t*)(&data.data()[pos]);
-					sout<<"				advance_loc1 "<<+loc<<" * caf " ;
+					sout << "				advance_loc1 " << +loc << " * caf " ;
 					break;
 				}
 
 				case DW_CFA_advance_loc2:
 				{
 					auto loc=*(uint16_t*)(&data.data()[pos]);
-					sout<<"				advance_loc2 "<<+loc<<" * caf " ;
+					sout << "				advance_loc2 " << +loc << " * caf " ;
 					break;
 				}
 
 				case DW_CFA_advance_loc4:
 				{
 					auto loc=*(uint32_t*)(&data.data()[pos]);
-					sout<<"				advance_loc4 "<<+loc<<" * caf " ;
+					sout << "				advance_loc4 " << +loc << " * caf " ;
 					break;
 				}
 				case DW_CFA_offset_extended:
-					sout<<"				offset_extended ";
+					sout << "				offset_extended ";
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max);
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max);
 					break;
 				case DW_CFA_register:
-					sout<<"				register ";
+					sout << "				register ";
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max);
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max);
 					break;
 				case DW_CFA_def_cfa:
-					sout<<"				def_cfa ";
+					sout << "				def_cfa ";
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max);
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max);
 					break;
 				case DW_CFA_def_cfa_sf:
-					sout<<"				def_cfa_sf ";
+					sout << "				def_cfa_sf ";
 					print_uleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max);
 					print_sleb_operand<ptrsize>(sout,pos,(const uint8_t* const)data.data(),max);
 					break;
@@ -560,24 +733,24 @@ string EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getPrintableString(cons
 				case DW_CFA_def_cfa_expression:
 				{
 					auto uleb=uint64_t(0);
-					sout<<"				def_cfa_expression "; 
+					sout << "				def_cfa_expression "; 
 					if(read_uleb128<ptrsize>(uleb, pos, (const uint8_t* const)data.data(), max))
 						break;
-					sout <<dec<<uleb;
+					sout  << dec << uleb;
 					pos+=uleb;		// doing this old school for now, as we aren't printing the expression.
-					sout <<" (not printing expression)";
+					sout  << " (not printing expression)";
 					break;
 				}
 				case DW_CFA_expression:
 				{
 					auto uleb1=uint64_t(0);
 					auto uleb2=uint64_t(0);
-					sout<<"                              expression "; 
+					sout << "                              expression "; 
 					if(read_uleb128<ptrsize>(uleb1, pos, (const uint8_t* const)data.data(), max))
 						break;
 					if(read_uleb128<ptrsize>(uleb2, pos, (const uint8_t* const)data.data(), max))
 						break;
-					sout<<dec<<uleb1<<" "<<uleb2;
+					sout << dec << uleb1 << " " << uleb2;
 					pos+=uleb2;
 					break;
 				}
@@ -585,34 +758,34 @@ string EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getPrintableString(cons
 				{
 					auto uleb1=uint64_t(0);
 					auto uleb2=uint64_t(0);
-					sout<<"                              val_expression "; 
+					sout << "                              val_expression "; 
 					if(read_uleb128<ptrsize>(uleb1, pos, (const uint8_t* const)data.data(), max))
 						break;
 					if(read_uleb128<ptrsize>(uleb2, pos, (const uint8_t* const)data.data(), max))
 						break;
-					sout <<dec<<uleb1<<" "<<uleb2;
+					sout  << dec << uleb1 << " " << uleb2;
 					pos+=uleb2;
 					break;
 				}
 				case DW_CFA_def_cfa_offset_sf:
 				{
 					auto leb=int64_t(0);
-					sout<<"					def_cfa_offset_sf "; 
+					sout << "					def_cfa_offset_sf "; 
 					if(read_sleb128<ptrsize>(leb, pos, (const uint8_t* const)data.data(), max))
 						break;
-					sout <<dec<<leb;
+					sout  << dec << leb;
 					break;
 				}
 				case DW_CFA_offset_extended_sf:
 				{
 					auto uleb1=uint64_t(0);
 					auto sleb2=int64_t(0);
-					sout<<"                              offset_extended_sf "; 
+					sout << "                              offset_extended_sf "; 
 					if(read_uleb128<ptrsize>(uleb1, pos, (const uint8_t* const)data.data(), max))
 						break;
 					if(read_sleb128<ptrsize>(sleb2, pos, (const uint8_t* const)data.data(), max))
 						break;
-					sout <<dec<<uleb1<<" "<<sleb2;
+					sout  << dec << uleb1 << " " << sleb2;
 					break;
 				}
 
@@ -624,7 +797,7 @@ string EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getPrintableString(cons
 				case DW_CFA_GNU_window_save:
 				case DW_CFA_GNU_negative_offset_extended:
 				default:
-					sout<<"Unhandled opcode cannot print. opcode="<<opcode;
+					sout << "Unhandled opcode cannot print. opcode=" << opcode;
 			}
 			break;
 		}
@@ -636,7 +809,7 @@ string EhWriterImpl_t<ptrsize>::EhProgramListingManip_t::getPrintableString(cons
 }
 
 template <int ptrsize>
-EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::LSDArepresentation_t(Instruction_t* insn)
+ElfEhWriter_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::LSDArepresentation_t(Instruction_t* insn)
 	// if there are call sites, use the call site encoding.  if not, set to omit for initializer.
 	//  extend/canExtend should be able to extend an omit to a non-omit.
 	: tt_encoding( insn->getEhCallSite() ? insn->getEhCallSite()->getTTEncoding() : 0xff)
@@ -659,7 +832,7 @@ static const auto RelocsEqual=[](const Relocation_t* a, const Relocation_t* b) -
 };
 
 template <int ptrsize>
-bool EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::canExtend(Instruction_t* insn) const
+bool ElfEhWriter_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::canExtend(Instruction_t* insn) const
 {
 	if(insn->getEhCallSite() == nullptr)
 		return true;
@@ -702,7 +875,7 @@ bool EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::canExte
 }
 
 template <int ptrsize>
-void EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::extend(Instruction_t* insn)
+void ElfEhWriter_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() == nullptr)
@@ -714,7 +887,7 @@ void EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::extend(
 	// 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;
+	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}; 
@@ -751,11 +924,11 @@ void EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::extend(
 	{
 		const auto wrt_scoop=dynamic_cast<DataScoop_t*>(reloc->getWRT());
 		if(reloc->getWRT()==nullptr)
-			cout<<"\tFound reloc: nullptr (catch all)"<<endl;
+			cout << "\tFound reloc: nullptr (catch all)" << endl;
 		else if(wrt_scoop)
-			cout<<"\tFound reloc: scoop "<<wrt_scoop->getName()<<"+0x"<<hex<<reloc->getAddend()<<endl;
+			cout << "\tFound reloc: scoop " << wrt_scoop->getName() << "+0x" << hex << reloc->getAddend() << endl;
 		else
-			cout<<"\tFound reloc: unexpected type? "<<endl;
+			cout << "\tFound reloc: unexpected type? " << endl;
 
 		// for now, this is the only supported reloc type on a EhCallSite 
 		assert(reloc->getType()=="type_table_entry");
@@ -800,7 +973,7 @@ void EhWriterImpl_t<ptrsize>::FDErepresentation_t::LSDArepresentation_t::extend(
 }
 
 template <int ptrsize>
-bool EhWriterImpl_t<ptrsize>::FDErepresentation_t::canExtend(Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw)
+bool ElfEhWriter_t<ptrsize>::FDErepresentation_t::canExtend(Instruction_t* insn, ElfEhWriter_t<ptrsize>* ehw)
 {
 	const auto insn_addr=ehw->zipr_obj.GetLocationMap()->at(insn);
 	const auto new_fde_thresh=100;
@@ -822,7 +995,7 @@ bool EhWriterImpl_t<ptrsize>::FDErepresentation_t::canExtend(Instruction_t* insn
 }
 
 template <int ptrsize>
-void EhWriterImpl_t<ptrsize>::FDErepresentation_t::extend(Instruction_t* insn, EhWriterImpl_t<ptrsize>* ehw)
+void ElfEhWriter_t<ptrsize>::FDErepresentation_t::extend(Instruction_t* insn, ElfEhWriter_t<ptrsize>* ehw)
 {
 	const auto insn_addr=ehw->zipr_obj.GetLocationMap()->at(insn);
 	const auto new_end_addr=insn_addr+insn->getDataBits().size();
@@ -839,21 +1012,14 @@ void EhWriterImpl_t<ptrsize>::FDErepresentation_t::extend(Instruction_t* insn, E
 	
 }
 
-template <int ptrsize>
-void EhWriterImpl_t<ptrsize>::FDErepresentation_t::emitAssembly(ostream& out)
-{
-	out<<"Hello"<<endl;
-}
-
 template<int ptrsize>
-void EhWriterImpl_t<ptrsize>::BuildFDEs()
+void ElfEhWriter_t<ptrsize>::BuildFDEs()
 {
 	// build a map of the instructions in program order
-	map<VirtualOffset_t,Instruction_t*> insn_in_order;
+	auto insn_in_order = map<VirtualOffset_t,Instruction_t*>();
 	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*)nullptr;
 	auto insns_with_frame=0;
@@ -876,7 +1042,7 @@ void EhWriterImpl_t<ptrsize>::BuildFDEs()
 		if(current_fde && !current_fde->canExtend(this_insn, this))
 		{
 			if(getenv("EH_VERBOSE")!=nullptr)
-				cout<<"Ending FDE because insn "<<hex<<this_insn->getBaseID()<<":"<<this_insn->getDisassembly()<<" doesn't fit at " << this_addr<< endl;
+				cout << "Ending FDE because insn " << hex << this_insn->getBaseID() << ":" << this_insn->getDisassembly() << " doesn't fit at "  <<  this_addr <<  endl;
 			current_fde=nullptr;
 		}
 
@@ -885,7 +1051,7 @@ void EhWriterImpl_t<ptrsize>::BuildFDEs()
 		if(current_fde==nullptr)
 		{
 			if(getenv("EH_VERBOSE")!=nullptr)
-				cout<<"Creating new FDE for "<<hex<<this_insn->getBaseID()<<":"<<this_insn->getDisassembly()<< " at " << this_addr<<endl;
+				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);
 		}
@@ -893,7 +1059,7 @@ void EhWriterImpl_t<ptrsize>::BuildFDEs()
 		{
 			if(getenv("EH_VERBOSE")!=nullptr)
 			{
-				cout<<"Extending new FDE for "<<hex<<this_insn->getBaseID()<<":"<<this_insn->getDisassembly()<<" at " << this_addr <<endl;
+				cout << "Extending new FDE for " << hex << this_insn->getBaseID() << ":" << this_insn->getDisassembly() << " at "  <<  this_addr  << endl;
 				print_pers(this_insn,current_fde->cie);
 
 			}
@@ -909,14 +1075,14 @@ void EhWriterImpl_t<ptrsize>::BuildFDEs()
         assert(getenv("SELF_VALIDATE")==nullptr || insns_with_frame > 10 );
         assert(getenv("SELF_VALIDATE")==nullptr ||  avg_insn_per_fde > 1 ) ;
 
-	cout<<"# ATTRIBUTE ExceptionHandlerWrite::fdes_calculated="<<dec<<all_fdes.size()<<endl;
-	cout<<"# ATTRIBUTE ExceptionHandlerWrite::cies_calculated="<<dec<<all_cies.size()<<endl;
-	cout<<"# ATTRIBUTE ExceptionHandlerWrite::insns_with_eh_info="<<dec<<insns_with_frame<<endl;
-	cout<<"# ATTRIBUTE ExceptionHandlerWrite::avg_insns_per_fde="<<dec<<avg_insn_per_fde<<endl;
+	cout << "# ATTRIBUTE ExceptionHandlerWrite::fdes_calculated=" << dec << all_fdes.size() << endl;
+	cout << "# ATTRIBUTE ExceptionHandlerWrite::cies_calculated=" << dec << all_cies.size() << endl;
+	cout << "# ATTRIBUTE ExceptionHandlerWrite::insns_with_eh_info=" << dec << insns_with_frame << endl;
+	cout << "# ATTRIBUTE ExceptionHandlerWrite::avg_insns_per_fde=" << dec << avg_insn_per_fde << endl;
 }
 
 template<int ptrsize>
-void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
+void ElfEhWriter_t<ptrsize>::GenerateEhOutput()
 {
 
 	auto output_program=[&](const EhProgramListingManip_t& p, ostream & out) 
@@ -927,26 +1093,26 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 			const auto &s = p[i];
 			if(i==p.size()-1 && p.isAdvanceDirective(s))	/* no need to output last insn if it's an advance */
 				break;
-			out<<"       .byte ";
+			out << "       .byte ";
 			auto first=true;
 			for(const auto &c : s)
 			{
 				if(!first)
 				{
-					out<<", ";
+					out << ", ";
 				}
 				else
 					first=false;
-				out<<"0x"<<hex<<setfill('0')<<setw(2)<<((int)c&0xff);
+				out << "0x" << hex << setfill('0') << setw(2) << ((int)c&0xff);
 			}
-			out << asm_comment << p.getPrintableString(s)<<endl;
+			out  <<  asm_comment  <<  p.getPrintableString(s) << 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;
-		out<<"LSDA"<<dec<<lsda_num<<":"<<endl;
+		out << "LSDA" << dec << lsda_num << ":" << endl;
 		if(!lsda->exists())
 		{
 			return;
@@ -1018,12 +1184,12 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 
 			for(int i=act_entry_num; i>=0; i--)
 			{
-				out<<"LSDA"<<dec<<lsda_num<<"_act"<<act_num<<"_start_entry"<<act_entry_num<<""<<":"<<endl;
-				out<<"	.sleb128 "<<dec<<ttov.at(act_entry_num)<<endl;        
+				out << "LSDA" << dec << lsda_num << "_act" << act_num << "_start_entry" << act_entry_num << "" << ":" << endl;
+				out << "	.sleb128 " << dec << ttov.at(act_entry_num) << endl;        
 				if(act_entry_num==biggest_ttov_index)
-					out<<"	.sleb128 0 "<<endl;
+					out << "	.sleb128 0 " << endl;
 				else
-					out<<"	.sleb128  LSDA"<<lsda_num<<"_act"<<act_num<<"_start_entry"<<act_entry_num+1<<" - . "<<endl;
+					out << "	.sleb128  LSDA" << lsda_num << "_act" << act_num << "_start_entry" << act_entry_num+1 << " - . " << endl;
 				act_entry_num--;
 			}
 		};
@@ -1034,34 +1200,34 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 			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<< asm_comment << "	1) start of call site relative to FDE start addr (call site encoding)"<<endl;
-        		out<<"	.sleb128 0x"<<hex<<cs_start_addr<<" - 0x"<<hex<<fde->start_addr<<endl;
-        		out<<asm_comment << "   2) length of call site (call site encoding)"<<endl;
-        		out<<"	.sleb128 "<<dec<<cs_len<<endl;
+			out << "LSDA" << dec << lsda_num << "_cs_tab_entry" << cs_num << "_start:" << endl;
+        		out <<  asm_comment  <<  "	1) start of call site relative to FDE start addr (call site encoding)" << endl;
+        		out << "	.sleb128 0x" << hex << cs_start_addr << " - 0x" << hex << fde->start_addr << endl;
+        		out << asm_comment  <<  "   2) length of call site (call site encoding)" << endl;
+        		out << "	.sleb128 " << dec << cs_len << endl;
 			if(cs.landing_pad)
 			{
 				const auto lp_addr=zipr_obj.GetLocationMap()->at(cs.landing_pad);
-				out<<asm_comment<<"   3) the landing pad, or 0 if none exists. (call site encoding)"<<endl;
-				out<<"	.sleb128 0x"<<hex<<lp_addr<<" - 0x"<<hex<<landing_pad_base<<endl;
+				out << asm_comment << "   3) the landing pad, or 0 if none exists. (call site encoding)" << endl;
+				out << "	.sleb128 0x" << hex << lp_addr << " - 0x" << hex << landing_pad_base << endl;
 			}
 			else
 			{
-				out<<asm_comment<<"   3) the landing pad, or 0 if none exists. (call site encoding)"<<endl;
-				out<<"	.sleb128 0"<<endl;
+				out << asm_comment << "   3) the landing pad, or 0 if none exists. (call site encoding)" << endl;
+				out << "	.sleb128 0" << endl;
 			}
 			if(cs.actions.size() > 0 )
 			{
-				out<<asm_comment<<"   4) index into action table + 1 -- 0 indicates unwind only (call site encoding)"<<endl;
-				out<<"	.sleb128 1 + LSDA"<<dec<<lsda_num<<"_act"
-				   <<cs.action_table_index<<"_start_entry0 - LSDA"<<dec<<lsda_num<<"_action_tab_start"<<endl;
+				out << asm_comment << "   4) index into action table + 1 -- 0 indicates unwind only (call site encoding)" << endl;
+				out << "	.sleb128 1 + LSDA" << dec << lsda_num << "_act"
+				    << cs.action_table_index << "_start_entry0 - LSDA" << dec << lsda_num << "_action_tab_start" << endl;
 			}
 			else
 			{
-				out<<asm_comment<<"   4) index into action table + 1 -- 0 indicates unwind only (always uleb)"<<endl;
-				out<<"	.uleb128 0 // no actions!" << endl;
+				out << asm_comment << "   4) index into action table + 1 -- 0 indicates unwind only (always uleb)" << endl;
+				out << "	.uleb128 0 // no actions!"  <<  endl;
 			}
-			out<<"LSDA"<<dec<<lsda_num<<"_cs_tab_entry"<<cs_num<<"_end:"<<endl;
+			out << "LSDA" << dec << lsda_num << "_cs_tab_entry" << cs_num << "_end:" << endl;
 
 		};
 
@@ -1069,41 +1235,41 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 		{
 			if(landing_pad_base==fde->start_addr)
 			{
-				out<<asm_comment<<"   1) encoding of next field "<<endl;
-				out<<"        .byte 0xff "<<asm_comment<<" DW_EH_PE_omit (0xff)"<<endl;
-				out<<""<<endl;
-				out<<asm_comment<<"   2) landing pad base, if omitted, use FDE start addr"<<endl;
-				out<<asm_comment<<"   .<fdebasetype> <fdebase> -- omitted.  "<<endl;
+				out << asm_comment << "   1) encoding of next field " << endl;
+				out << "        .byte 0xff " << asm_comment << " DW_EH_PE_omit (0xff)" << endl;
+				out << "" << endl;
+				out << asm_comment << "   2) landing pad base, if omitted, use FDE start addr" << endl;
+				out << asm_comment << "   .<fdebasetype> <fdebase> -- omitted.  " << endl;
 			}
 			else
 			{
-				out<<asm_comment<<"   1) encoding of next field "<<endl;
-				out<<"        .byte 0x1b "<<asm_comment<<" DW_EH_PE_pcrel (0x10) |sdata4 (0xb)"<<endl;
-				out<<""<<endl;
-				out<<"        "<<asm_comment<<" 2) landing pad base, if omitted, use FDE start addr"<<endl;
-				out<<"        .int  0x"<<hex<<landing_pad_base<<" + eh_frame_hdr_start - . - "<<dec<<eh_frame_hdr_addr<<" "<<asm_comment<<" as pcrel|sdata4 .  "<<endl;
+				out << asm_comment << "   1) encoding of next field " << endl;
+				out << "        .byte 0x1b " << asm_comment << " DW_EH_PE_pcrel (0x10) |sdata4 (0xb)" << endl;
+				out << "" << endl;
+				out << "        " << asm_comment << " 2) landing pad base, if omitted, use FDE start addr" << endl;
+				out << "        .int  0x" << hex << landing_pad_base << " + eh_frame_hdr_start - . - " << dec << eh_frame_hdr_addr << " " << asm_comment << " as pcrel|sdata4 .  " << endl;
 			}
-			out<<""<<endl;
-			out<<asm_comment<<"   3) encoding of type table entries"<<endl;
-			out<<"        .byte 0x"<<hex<<lsda->tt_encoding<<"  "<<asm_comment<<" DW_EH_PE_udata4"<<endl;
-			out<<""<<endl;
-			out<<asm_comment<<"   4) type table pointer -- always a uleb128"<<endl;
+			out << "" << endl;
+			out << asm_comment << "   3) encoding of type table entries" << endl;
+			out << "        .byte 0x" << hex << lsda->tt_encoding << "  " << asm_comment << " DW_EH_PE_udata4" << endl;
+			out << "" << endl;
+			out << asm_comment << "   4) type table pointer -- always a uleb128" << endl;
 			if(lsda->tt_encoding==0xff) /* omit */
 			{
-				out<<asm_comment<<"   .uleb128 LSDAptr omitted"<< endl;
+				out << asm_comment << "   .uleb128 LSDAptr omitted" <<  endl;
 			}
 			else
 			{
-				out<<"        .uleb128 LSDA"<<dec<<lsda_num<<"_type_table_end - LSDA"<<lsda_num<<"_tt_ptr_end"<<endl;
+				out << "        .uleb128 LSDA" << dec << lsda_num << "_type_table_end - LSDA" << lsda_num << "_tt_ptr_end" << endl;
 			}
-			out<<"LSDA"<<dec<<lsda_num<<"_tt_ptr_end:"<<endl;
-			out<<""<<endl;
-			out<<asm_comment<<"   5) call site table encoding"<<endl;
-			out<<"        .byte 0x9 "<<asm_comment<<" DW_EH_PE_sleb128 "<<endl;
-			out<<""<<endl;
-			out<<asm_comment<<"   6) the length of the call site table"<<endl;
-			out<<"        .uleb128 LSDA"<<dec<<lsda_num<<"_cs_tab_end-LSDA"<<dec<<lsda_num<<"_cs_tab_start"<<endl;
-			out<<"LSDA"<<dec<<lsda_num<<"_cs_tab_start:"<<endl;
+			out << "LSDA" << dec << lsda_num << "_tt_ptr_end:" << endl;
+			out << "" << endl;
+			out << asm_comment << "   5) call site table encoding" << endl;
+			out << "        .byte 0x9 " << asm_comment << " DW_EH_PE_sleb128 " << endl;
+			out << "" << endl;
+			out << asm_comment << "   6) the length of the call site table" << endl;
+			out << "        .uleb128 LSDA" << dec << lsda_num << "_cs_tab_end-LSDA" << dec << lsda_num << "_cs_tab_start" << endl;
+			out << "LSDA" << dec << lsda_num << "_cs_tab_start:" << endl;
 		};
 
 		const auto output_call_site_table=[&]()
@@ -1114,34 +1280,34 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 			{
 				output_callsite(cs,cs_num++);
 			}
-			out<<"LSDA"<<dec<<lsda_num<<"_cs_tab_end:"<<endl;
+			out << "LSDA" << dec << lsda_num << "_cs_tab_end:" << endl;
 		};
 		const auto output_action_table=[&]()
 		{
 			// output action table
-			out<<"LSDA"<<dec<<lsda_num<<"_action_tab_start:"<<endl;
+			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 << "_action_tab_end:" << endl;
 		};
 
 		const auto output_type_table=[&]()
 		{
-			out<<"LSDA"<<dec<<lsda_num<<"_type_table_start:"<<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==nullptr)
 				{
 					// indicates a catch all or empty type table entry
-					out<<"	.int 0x0 "<<asm_comment<<" not used!"<<endl;
+					out << "	.int 0x0 " << asm_comment << " not used!" << endl;
 				}
 				else if(reloc->getWRT()==nullptr)
 				{
 					// indicates a catch all or empty type table entry
-					out<<"	.int 0x0 "<<asm_comment<<" catch all "<<endl;
+					out << "	.int 0x0 " << asm_comment << " catch all " << endl;
 				}
 				else
 				{
@@ -1150,13 +1316,13 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 					assert(scoop);
 					const auto final_addr=scoop->getStart()->getVirtualOffset() + reloc->getAddend();
 					if(((lsda->tt_encoding)&0x10) == 0x10) // if encoding contains pcrel (0x10).
-						out<<"	.int 0x"<<hex<<final_addr<<" + eh_frame_hdr_start - . -  "<<dec<<eh_frame_hdr_addr<<endl;
+						out << "	.int 0x" << hex << final_addr << " + eh_frame_hdr_start - . -  " << dec << eh_frame_hdr_addr << endl;
 					else
-						out<<"	.int 0x"<<hex<<final_addr<<endl;
+						out << "	.int 0x" << hex << final_addr << endl;
 					
 				}
 			});
-			out<<"LSDA"<<dec<<lsda_num<<"_type_table_end:"<<endl;
+			out << "LSDA" << dec << lsda_num << "_type_table_end:" << endl;
 		};
 
 		output_lsda_header();
@@ -1171,7 +1337,7 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 		if(cie->has_been_output)
 			return;
 
-		const auto cie_pos_it=std::find(all_cies.begin(), all_cies.end(), cie);
+		const auto cie_pos_it=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*)nullptr;
@@ -1181,54 +1347,54 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 		const auto cie_pos=cie_pos_it-all_cies.begin();
 
 		cie->has_been_output=true;
-		out<<asm_comment<<" cie "<<dec<<cie_pos<<""<<endl;
-		out<<"Lcie"<<cie_pos<<":"<<endl;
-		out<<"	 .int Lcie"<<cie_pos<<"_end - Lcie"<<cie_pos<<" - 4 "<<asm_comment<<" length of this record. -4 because length doesn't include this field"<<endl;
-		out<<"        .int 0                  "<<asm_comment<<" cie (not fde)"<<endl;
-		out<<"        .byte 3                 "<<asm_comment<<" version"<<endl;
-		out<<"        .asciz \"zPLR\"           "<<asm_comment<<" aug string."<<endl;
-		out<<"        .uleb128 "<<dec<<cie->code_alignment_factor<<"              "<<asm_comment<<" code alignment factor"<<endl;
-		out<<"        .sleb128 "<<dec<<cie->data_alignment_factor<<"             "<<asm_comment<<" data alignment factor"<<endl;
-		out<<"        .uleb128 "<<dec<<cie->return_reg<<"             "<<asm_comment<<" return address reg."<<endl;
-		out<<"        "<<asm_comment<<" encode the Z (length)"<<endl;
-		out<<"        .sleb128 Lcie"<<cie_pos<<"_aug_data_end-Lcie"<<cie_pos<<"_aug_data_start "<<asm_comment<<" Z -- handle length field"<<endl;
-		out<<"Lcie"<<cie_pos<<"_aug_data_start:"<<endl;
-		out<<""<<endl;
+		out << asm_comment << " cie " << dec << cie_pos << "" << endl;
+		out << "Lcie" << cie_pos << ":" << endl;
+		out << "	 .int Lcie" << cie_pos << "_end - Lcie" << cie_pos << " - 4 " << asm_comment << " length of this record. -4 because length doesn't include this field" << endl;
+		out << "        .int 0                  " << asm_comment << " cie (not fde)" << endl;
+		out << "        .byte 3                 " << asm_comment << " version" << endl;
+		out << "        .asciz \"zPLR\"           " << asm_comment << " aug string." << endl;
+		out << "        .uleb128 " << dec << cie->code_alignment_factor << "              " << asm_comment << " code alignment factor" << endl;
+		out << "        .sleb128 " << dec << cie->data_alignment_factor << "             " << asm_comment << " data alignment factor" << endl;
+		out << "        .uleb128 " << dec << cie->return_reg << "             " << asm_comment << " return address reg." << endl;
+		out << "        " << asm_comment << " encode the Z (length)" << endl;
+		out << "        .sleb128 Lcie" << cie_pos << "_aug_data_end-Lcie" << cie_pos << "_aug_data_start " << asm_comment << " 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<<"        "<<asm_comment<<"encode the P (personality encoding + personality routine)"<<endl;
-			out<<"        .byte 0x80 | 0x10 | 0x0B        "<<asm_comment<<"  personality pointer encoding DH_EH_PE_indirect (0x80) | pcrel | sdata4"<<endl;
-			out<<"        .int "<<personality_value<<" + eh_frame_hdr_start - . - "<<dec<<eh_frame_hdr_addr<<" "<<asm_comment<<" actual personality routine, encoded as noted in prev line."<<endl;
+			out << "        " << asm_comment << "encode the P (personality encoding + personality routine)" << endl;
+			out << "        .byte 0x80 | 0x10 | 0x0B        " << asm_comment << "  personality pointer encoding DH_EH_PE_indirect (0x80) | pcrel | sdata4" << endl;
+			out << "        .int " << personality_value << " + eh_frame_hdr_start - . - " << dec << eh_frame_hdr_addr << " " << asm_comment << " 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<<"        "<<asm_comment<<"encode the P (personality encoding + personality routine)"<<endl;
-			out<<"        .byte 0x10 | 0x0B        "<<asm_comment<<"  personality pointer encoding pcrel | sdata4"<<endl;
-			out<<"        .int "<<personality_value<<" + eh_frame_hdr_start - . - "<<dec<<eh_frame_hdr_addr<<" "<<asm_comment<<" actual personality routine, encoded as noted in prev line."<<endl;
+			out << "        " << asm_comment << "encode the P (personality encoding + personality routine)" << endl;
+			out << "        .byte 0x10 | 0x0B        " << asm_comment << "  personality pointer encoding pcrel | sdata4" << endl;
+			out << "        .int " << personality_value << " + eh_frame_hdr_start - . - " << dec << eh_frame_hdr_addr << " " << asm_comment << " actual personality routine, encoded as noted in prev line." << endl;
 		}
 		else
 		{
 			assert(cie->personality_reloc==nullptr || cie->personality_reloc->getWRT()==nullptr);
-			out<<"        "<<asm_comment<<"encode the P (personality encoding + personality routine)"<<endl;
-			out<<"        .byte  0x0B        "<<asm_comment<<"  personality pointer encoding sdata4"<<endl;
-			out<<"        .int 0               "<<asm_comment<<" actual personality routine, encoded as noted in prev line."<<endl;
+			out << "        " << asm_comment << "encode the P (personality encoding + personality routine)" << endl;
+			out << "        .byte  0x0B        " << asm_comment << "  personality pointer encoding sdata4" << endl;
+			out << "        .int 0               " << asm_comment << " actual personality routine, encoded as noted in prev line." << endl;
 		}
-		out<<""<<endl;
-		out<<"        "<<asm_comment<<" encode L (lsda encoding) "<<endl;
-		out<<"        .byte  0x1b     "<<asm_comment<<" LSDA encoding (pcrel|sdata4)"<<endl;
-		out<<""<<endl;
-		out<<"        "<<asm_comment<<" encode R (FDE encoding) "<<endl;
-		out<<"        .byte  0x10 | 0x0B      "<<asm_comment<<" FDE encoding (pcrel | sdata4)"<<endl;
-		out<<"Lcie"<<cie_pos<<"_aug_data_end:"<<endl;
-		out<<"       "<<asm_comment<<" CIE program"<<endl;
+		out << "" << endl;
+		out << "        " << asm_comment << " encode L (lsda encoding) " << endl;
+		out << "        .byte  0x1b     " << asm_comment << " LSDA encoding (pcrel|sdata4)" << endl;
+		out << "" << endl;
+		out << "        " << asm_comment << " encode R (FDE encoding) " << endl;
+		out << "        .byte  0x10 | 0x0B      " << asm_comment << " FDE encoding (pcrel | sdata4)" << endl;
+		out << "Lcie" << cie_pos << "_aug_data_end:" << endl;
+		out << "       " << asm_comment << " CIE program" << endl;
 		output_program(cie->pgm,out);
-		out<<""<<endl;
-		out<<"       "<<asm_comment<<" pad with nops"<<endl;
-		out<<"       .align 4, 0"<<endl;
-		out<<"Lcie"<<cie_pos<<"_end:"<<endl;
+		out << "" << endl;
+		out << "       " << asm_comment << " 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
@@ -1237,69 +1403,69 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 		output_cie(fde->cie,out);
 
 
-		auto cie_pos_it=std::find(all_cies.begin(), all_cies.end(), fde->cie);
+		auto cie_pos_it=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<<""<<asm_comment<<"fde "<<dec<<fde_num<<""<<endl;
-		out<<"Lfde"<<fde_num<<":"<<endl;
-		out<<"        .int Lfde"<<fde_num<<"_end - Lfde"<<fde_num<<" - 4      "<<asm_comment<<" length of this record. -4 because "
-		     "length doesn't include this field."<<endl;
-		out<<"        .int . - Lcie"<<cie_pos<<"                  "<<asm_comment<<" 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<<" + eh_frame_hdr_start - . - "<<dec<<eh_frame_hdr_addr<<" "<<asm_comment<<" FDE start addr"<<endl;
-		out<<"        .int "<<dec<<fde->end_addr-fde->start_addr<<"                     "<<asm_comment<<" fde range length (i.e., can calc the "
-		     "fde_end_addr from this -- note that pcrel is ignored here!)"<<endl;
-		out<<"        "<<asm_comment<<"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<<"        "<<asm_comment<<"encode L (LSDA) "<<endl;
+		out << "" << asm_comment << "fde " << dec << fde_num << "" << endl;
+		out << "Lfde" << fde_num << ":" << endl;
+		out << "        .int Lfde" << fde_num << "_end - Lfde" << fde_num << " - 4      " << asm_comment << " length of this record. -4 because "
+		     "length doesn't include this field." << endl;
+		out << "        .int . - Lcie" << cie_pos << "                  " << asm_comment << " 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 << " + eh_frame_hdr_start - . - " << dec << eh_frame_hdr_addr << " " << asm_comment << " FDE start addr" << endl;
+		out << "        .int " << dec << fde->end_addr-fde->start_addr << "                     " << asm_comment << " fde range length (i.e., can calc the "
+		     "fde_end_addr from this -- note that pcrel is ignored here!)" << endl;
+		out << "        " << asm_comment << "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 << "        " << asm_comment << "encode L (LSDA) " << endl;
 		if(fde->hasLsda())
-			out<<"        .int LSDA"<<fde_num<<" - .    "<<asm_comment<<" LSDA hard coded here (as pcrel+sdata4)"<<endl;	 
+			out << "        .int LSDA" << fde_num << " - .    " << asm_comment << " LSDA hard coded here (as pcrel+sdata4)" << endl;	 
 		else
-			out<<"        .int 0 + eh_frame_hdr_start - . - "<<dec<<eh_frame_hdr_addr<<"      "<<asm_comment<<" no LSDA, encoded with pcrel "<<endl;	 
-		out<<"Lfde"<<fde_num<<"_aug_data_end:"<<endl;
-		out<<""<<endl;
-		out<<"        "<<asm_comment<<" FDE"<<fde_num<<" program"<<endl;
+			out << "        .int 0 + eh_frame_hdr_start - . - " << dec << eh_frame_hdr_addr << "      " << asm_comment << " no LSDA, encoded with pcrel " << endl;	 
+		out << "Lfde" << fde_num << "_aug_data_end:" << endl;
+		out << "" << endl;
+		out << "        " << asm_comment << " FDE" << fde_num << " program" << endl;
 		output_program(fde->pgm,out);
-		out<<"        .align 4, 0"<<endl;
-		out<<"        Lfde"<<fde_num<<"_end:"<<endl;
+		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                 "<<asm_comment<<" version"<<endl;
-		out<<"        .byte 0x10 | 0x0B       "<<asm_comment<<" encoding for pointer to eh-frame -- DH_EH_PE_pcrel (0x10) | DH_EH_PE_sdata4 (0x0B)"<<endl;
-		out<<"        .byte 0x03              "<<asm_comment<<" encoding for ; of entries in eh-frame-hdr  -- BDH_EH_PE_udata4 (0x03)"<<endl;
-		out<<"        .byte 0x30 | 0x0B       "<<asm_comment<<" encoding for pointers (to fdes) held in the eh-frame-hdr header  "
-		     "-- DH_EH_PE_datarel (0x30) | DH_EH_PE_sdata4 (0x0b) " <<endl;
+		out << ".section eh_frame_hdr, \"a\", @progbits" << endl;
+		out << "eh_frame_hdr_start:" << endl;
+		out << "        .byte 1                 " << asm_comment << " version" << endl;
+		out << "        .byte 0x10 | 0x0B       " << asm_comment << " encoding for pointer to eh-frame -- DH_EH_PE_pcrel (0x10) | DH_EH_PE_sdata4 (0x0B)" << endl;
+		out << "        .byte 0x03              " << asm_comment << " encoding for ; of entries in eh-frame-hdr  -- BDH_EH_PE_udata4 (0x03)" << endl;
+		out << "        .byte 0x30 | 0x0B       " << asm_comment << " 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 - .     "<<asm_comment<<" pointer to fde_table, encoded as an sdata4, pcrel"<<endl;
-		out<<"        .int (eh_frame_table_end-eh_frame_table)/8     "<<asm_comment<<" number of FDEs in the header."<<endl;
+		out << "        .int Lfde_table - .     " << asm_comment << " pointer to fde_table, encoded as an sdata4, pcrel" << endl;
+		out << "        .int (eh_frame_table_end-eh_frame_table)/8     " << asm_comment << " number of FDEs in the header." << endl;
 
 // on some archs, this line causes an additional alignment, as the assembler feels free to align as much as you want.
 // but the eh-parser is expecting the table _right here_, so we do the alignment manually by making sure the above part
 // has a multiple-of-4 bytes.
-//		out<<"        .align 4"<<endl;
-		out<<"eh_frame_table:"<<endl;
-		out<<"        "<<asm_comment<<" fde pointers"<<endl;
+//		out << "        .align 4" << endl;
+		out << "eh_frame_table:" << endl;
+		out << "        " << asm_comment << " fde pointers" << endl;
 
 		for(auto fde_num=0U; fde_num < all_fdes.size(); fde_num++)
 		{
 			const auto& fde=all_fdes[fde_num];
-			out<<"        .int 0x"<<hex<<fde->start_addr<<" - "<<dec<<eh_frame_hdr_addr<<endl;
-			out<<"        .int Lfde"<<dec<<fde_num<<" - eh_frame_hdr_start"<<endl;
+			out << "        .int 0x" << hex << fde->start_addr<<" - " << dec << eh_frame_hdr_addr << endl;
+			out << "        .int Lfde" << dec << fde_num << " - eh_frame_hdr_start" << endl;
 		}
 
-		out<<"eh_frame_table_end:"<<endl;
+		out << "eh_frame_table_end:" << endl;
 
 	};
 	auto generate_eh_frame=[&](ostream& out) -> void	
 	{
-		out<<".section eh_frame, \"a\", @progbits"<<endl;
-		out<<"Lfde_table: "<<asm_comment<<" needed for xref to eh_frame_hdr" <<endl;
+		out << ".section eh_frame, \"a\", @progbits" << endl;
+		out << "Lfde_table: " << asm_comment << " needed for xref to eh_frame_hdr"  << endl;
 
 		auto fde_num=0;
 		for(const auto& fde: all_fdes)
@@ -1309,7 +1475,7 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 	};
 	auto generate_gcc_except_table=[&](ostream& out) -> void	
 	{
-		out<<".section gcc_except_table, \"a\", @progbits"<<endl;
+		out << ".section gcc_except_table, \"a\", @progbits" << endl;
 		auto lsda_num=0;
 		for(const auto& fde: all_fdes)
 		{
@@ -1317,10 +1483,10 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 		}
 	};
 
-	ofstream fout(ehframe_s_filename, std::ofstream::out);
+	ofstream fout(ehframe_s_filename, ofstream::out);
 	if(!fout)
 	{
-		cerr<<"Fatal: cannot open "<<ehframe_s_filename<<"."<<endl;
+		cerr << "Fatal: cannot open " << ehframe_s_filename << "." << endl;
 		exit(2);
 	}
 
@@ -1330,28 +1496,28 @@ void EhWriterImpl_t<ptrsize>::GenerateEhOutput()
 }
 
 template<int ptrsize>
-void EhWriterImpl_t<ptrsize>::CompileEhOutput()
+void ElfEhWriter_t<ptrsize>::CompileEhOutput()
 {
 
 	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;
-	cout<<"Running: "<<cmd<<endl;
+	cout << "Running: " << cmd << endl;
 	auto res=system(cmd.c_str());
 
 	// err check.
 	if( res==-1 || WEXITSTATUS(res)!=0 )
 	{
 		perror("Cannot compile eh_frame.");
-		cerr<<"Exit code="<<res<<endl;
-		cerr<<" for command="<<cmd<<endl;
+		cerr << "Exit code=" << res << endl;
+		cerr << " for command=" << cmd << endl;
 		exit(2);
 	}
 }
 
 template<int ptrsize>
-void EhWriterImpl_t<ptrsize>::ScoopifyEhOutput()
+void ElfEhWriter_t<ptrsize>::ScoopifyEhOutput()
 {
         EXEIO::exeio ehframe_exe_rep;
 	ehframe_exe_rep.load(ehframe_exe_filename);
@@ -1384,16 +1550,34 @@ void EhWriterImpl_t<ptrsize>::ScoopifyEhOutput()
 }
 
 template<int ptrsize>
-EhWriterImpl_t<ptrsize>::~EhWriterImpl_t()
+ElfEhWriter_t<ptrsize>::~ElfEhWriter_t()
 {
 	for(const auto &i : all_fdes) delete i;
 	for(const auto &i : all_cies) delete i;
 }
 
 
+unique_ptr<EhWriter_t> EhWriter_t::factory(ZiprImpl_t& zipr_obj)
+{
+	auto firp=zipr_obj.getFileIR();
+	const auto is_pe  = firp->getArchitecture()->getFileType() == adftPE;
+	const auto is_elf = firp->getArchitecture()->getFileType() == adftELFEXE ||
+	              firp->getArchitecture()->getFileType() == adftELFSO;
+	const auto is_64  = firp->getArchitectureBitWidth()==64;
+	const auto is_32  = firp->getArchitectureBitWidth()==32;
+
+	auto eh = (is_elf && is_64) ? static_cast<EhWriter_t*>(new ElfEhWriter_t<8>(zipr_obj)) :
+		  (is_elf && is_32) ? static_cast<EhWriter_t*>(new ElfEhWriter_t<4>(zipr_obj)) :
+		  (is_pe  && is_64) ? static_cast<EhWriter_t*>(new PEEhWriter_t <8>(zipr_obj)) :
+		  throw invalid_argument("Cannot create eh factory for unknown file type/ptr size combo");
+
+	return unique_ptr<EhWriter_t>(eh);
+}
+
+
 /* make sure these get compiled */
 namespace zipr
 {
-template class EhWriterImpl_t<8>;
-template class EhWriterImpl_t<4>;
+	template class ElfEhWriter_t<8>;
+	template class ElfEhWriter_t<4>;
 };
diff --git a/src/pewrite.cpp b/src/pewrite.cpp
index 484dc7f4f..55fd0358a 100644
--- a/src/pewrite.cpp
+++ b/src/pewrite.cpp
@@ -18,6 +18,8 @@
 #pragma GCC diagnostic pop
 
 
+#define ALLOF(a) begin(a),end(a)
+
 
 using namespace IRDB_SDK;
 using namespace std;
@@ -162,6 +164,18 @@ void PeWriter<width>::InitHeaders()
 	}
 
 
+	auto exc_dir_it = find_if(ALLOF(m_firp->getDataScoops()), 
+		[](const DataScoop_t* s)
+		{
+			return s->getName() == ".zipr_sehd";
+		});
+	if(exc_dir_it != end(m_firp->getDataScoops()))
+	{
+		const auto sehd_scoop=*exc_dir_it;
+		image_data_dir_hdrs[pe_bliss::pe_win::image_directory_entry_exception].virtual_address = sehd_scoop->getStart()->getVirtualOffset() - m_firp->getArchitecture()->getFileBase();
+		image_data_dir_hdrs[pe_bliss::pe_win::image_directory_entry_exception].size            = sehd_scoop->getSize();
+	}
+
 	CreateSectionHeaders();
 }
 
diff --git a/src/pinner_x86.cpp b/src/pinner_x86.cpp
index 23ad72580..bf31e6e74 100644
--- a/src/pinner_x86.cpp
+++ b/src/pinner_x86.cpp
@@ -112,7 +112,11 @@ void ZiprPinnerX86_t::AddPinnedInstructions()
                         // Unpinned IBT. Create dollop and add it to placement
                         // queue straight away--there are no pinning considerations.
                         auto newDoll=m_dollop_mgr.addNewDollops(insn);
-			placement_queue.insert({newDoll, 0});
+#if 1
+			(void)newDoll;
+#else
+// 			placement_queue.insert({newDoll, 0});
+#endif
 			continue;
                 }
 
@@ -129,14 +133,8 @@ void ZiprPinnerX86_t::AddPinnedInstructions()
 
 void ZiprPinnerX86_t::RecordPinnedInsnAddrs()
 {
-	for(
-		set<Instruction_t*>::const_iterator it=m_firp->getInstructions().begin();
-		it!=m_firp->getInstructions().end();
-		++it
-		)
+	for(auto insn : m_firp->getInstructions())
 	{
-		RangeAddress_t ibta_addr;
-		Instruction_t* insn=*it;
 		assert(insn);
 
 		if(!insn->getIndirectBranchTargetAddress()
@@ -144,9 +142,8 @@ void ZiprPinnerX86_t::RecordPinnedInsnAddrs()
 		{
 			continue;
 		}
-		ibta_addr=(RangeAddress_t)insn->
-		                          getIndirectBranchTargetAddress()->
-		                          getVirtualOffset();
+		const auto ibta_addr=(RangeAddress_t)insn-> getIndirectBranchTargetAddress()-> getVirtualOffset();
+
 		/*
 		* Record the size of thing that we are pinning.
 		* We are going to use this information for doing
@@ -169,35 +166,29 @@ void ZiprPinnerX86_t::RecordPinnedInsnAddrs()
 		* record the size of the instruction itself.
 		*/
 		if (ShouldPinImmediately(insn))
-			m_InsnSizeAtAddrs[ibta_addr]=std::pair<Instruction_t*, size_t>(insn,insn->getDataBits().length());
+			m_InsnSizeAtAddrs[ibta_addr]={insn,insn->getDataBits().length()};
 		else					 
-			m_InsnSizeAtAddrs[ibta_addr]=std::pair<Instruction_t*, size_t>(insn,2);
+			m_InsnSizeAtAddrs[ibta_addr]={insn,2};
 	}
 }
 
 
 bool ZiprPinnerX86_t::ShouldPinImmediately(Instruction_t *upinsn)
 {
-	auto d=DecodedInstruction_t::factory (upinsn);
-	Instruction_t *pin_at_next_byte = nullptr;
-	AddressID_t *upinsn_ibta = nullptr, *ft_ibta = nullptr;
-
+	const auto d=DecodedInstruction_t::factory (upinsn);
 	if(d->isReturn() )
 		return true;
 
-	upinsn_ibta=upinsn->getIndirectBranchTargetAddress();
+	const auto upinsn_ibta = upinsn->getIndirectBranchTargetAddress();
+	const auto ft_ibta     = upinsn->getFallthrough() != nullptr ? upinsn->getFallthrough()->getIndirectBranchTargetAddress() : (AddressID_t*)nullptr;
 	assert(upinsn_ibta!=nullptr && upinsn_ibta->getVirtualOffset()!=0);
 
-	if (upinsn->getFallthrough() != nullptr)
-		ft_ibta=upinsn->getFallthrough()->getIndirectBranchTargetAddress();
-
 	/* careful with 1 byte instructions that have a pinned fallthrough */ 
 	const auto len=upinsn->getDataBits().length();
 	if(len==1)
 	{
 		if(upinsn->getFallthrough()==nullptr)
 			return true;
-		ft_ibta=upinsn->getFallthrough()->getIndirectBranchTargetAddress();
 		if((ft_ibta && ft_ibta->getVirtualOffset()!=0) && (upinsn_ibta->getVirtualOffset()+1) == ft_ibta->getVirtualOffset())
 			return true;
 	}
@@ -225,28 +216,29 @@ bool ZiprPinnerX86_t::ShouldPinImmediately(Instruction_t *upinsn)
 
 
 	// find the insn pinned at the next byte.
-	pin_at_next_byte = FindPinnedInsnAtAddr(upinsn_ibta->getVirtualOffset() + 1);
-	if ( pin_at_next_byte && 
+	auto pin_at_next_byte = FindPinnedInsnAtAddr(upinsn_ibta->getVirtualOffset() + 1);
+	if (    pin_at_next_byte && 
 
-	/* upinsn has lock prefix */
+		/* upinsn has lock prefix */
 		upinsn->getDataBits()[0]==(char)(0xF0) 	&&
-	/*
-	 * upinsn:  lock cmpxchange op1 op2 [pinned at x]
-	 *          x    x+1        x+2 x+3
-	 * 
-	 * AND pin_at_next_byte (x+1) is:
-	 */
+		/*
+		 * upinsn:  lock cmpxchange op1 op2 [pinned at x]
+		 *          x    x+1        x+2 x+3
+		 * 
+		 * AND pin_at_next_byte (x+1) is:
+		 */
 		pin_at_next_byte->getDataBits() == upinsn->getDataBits().substr(1,upinsn->getDataBits().length()-1) &&  
-	/*
-         *               cmpxchange op1 op2 [pinned at x+1]
-	 *               x+1        x+2 x+3
-	 * AND  pin_at_next_byte->fallthrough() == upinsn->Fallthrough()
-	 */
-		pin_at_next_byte->getFallthrough() == upinsn->getFallthrough() ) 
-	/*
-	 * x should become nop, put down immediately
-	 * x+1 should become the entire lock command.
-	 */
+		/*
+		 *               cmpxchange op1 op2 [pinned at x+1]
+		 *               x+1        x+2 x+3
+		 * AND  pin_at_next_byte->fallthrough() == upinsn->Fallthrough()
+		 */
+		pin_at_next_byte->getFallthrough() == upinsn->getFallthrough() 
+		/*
+		 * x should become nop, put down immediately
+		 * x+1 should become the entire lock command.
+		 */
+	  )
 	{
 		if (m_verbose)
 			cout<<"Using pin_at_next_byte special case, addrs="<<
@@ -286,9 +278,7 @@ void ZiprPinnerX86_t::PreReserve2ByteJumpTargets()
 	do
 	{
 		repeat = false;
-		for(set<UnresolvedPinned_t>::const_iterator it=two_byte_pins.begin();
-			it!=two_byte_pins.end();
-			)
+		for(auto  it=two_byte_pins.begin(); it!=two_byte_pins.end(); /* empty */)
 		{
 			UnresolvedPinned_t up=*it;
 			bool found_close_target = false;
@@ -364,17 +354,18 @@ void ZiprPinnerX86_t::PreReserve2ByteJumpTargets()
 						 * addr: place of prereserved memory
 						 * size: size of the amount of prereserved memory
 						 */
-						UnresolvedUnpinned_t uu(up);
-						Patch_t patch(up.GetRange().getStart(),
-						              UnresolvedType_t::UncondJump_rel32);
+						auto uu = UnresolvedUnpinned_t(up);
+						auto patch = Patch_t(up.GetRange().getStart(), UnresolvedType_t::UncondJump_rel32);
+
 						if (size == 2)
 							patch.setType(UnresolvedType_t::UncondJump_rel8);
-						UnresolvedUnpinnedPatch_t uup(uu, patch);
+
+						auto uup = UnresolvedUnpinnedPatch_t(uu, patch);
 
 						if (m_verbose)
 							cout << "Adding a chain entry at address "
 							     << std::hex << up.GetRange().getStart() << endl;
-						m_parent->RecordNewPatch(std::pair<RangeAddress_t, UnresolvedUnpinnedPatch_t>(up.GetRange().getStart(),uup));
+						m_parent->RecordNewPatch({up.GetRange().getStart(),uup});
 
 						found_close_target = true;
 						break;
diff --git a/src/zipr.cpp b/src/zipr.cpp
index f4266f8a1..7c636fa2f 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -799,8 +799,7 @@ void ZiprImpl_t::PlaceDollops()
 	auto count_pins=0u;
 
 	/*
-	 * Build up initial placement q with destinations of
-	 * pins.
+	 * Build up initial placement q with destinations of pins.
 	 */
 	for (auto p : patch_list)
 	{
@@ -844,7 +843,7 @@ void ZiprImpl_t::PlaceDollops()
 
 	// Make sure each instruction referenced in a relocation (regardless
 	// of if that relocation is on an instruction or a scoop) gets placed.
-	for(auto &reloc : m_firp->getRelocations())
+	for(const auto &reloc : m_firp->getRelocations())
         	handle_reloc(reloc);	
 
 	while (!placement_queue.empty())
@@ -2244,28 +2243,10 @@ void  ZiprImpl_t::FixMultipleFallthroughs()
 
 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()!=nullptr || i->getEhCallSite()!=nullptr);
-			} 
-		);
-
-	// do nothing if we didn't find any IR.
-	if(found_eh_ir_it==m_firp->getInstructions().end())
+	if(m_firp->getAllEhPrograms().size()  ==  0 && m_firp->getAllEhCallSites().size() ==0)
 		return;
-		
-	auto eh = (EhWriter_t *)nullptr;
-	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();
+	EhWriter::EhWriter_t::factory(*this) -> GenerateNewEhInfo();
 }
 
 
-- 
GitLab