diff --git a/.gitignore b/.gitignore
index 10e73a2ebadb95fd18ad8d87a261f8ae912832ef..5477298a9e8d3cde38e9cb08901f47aad93af0c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,4 @@ lib/
 manifest.txt.config
 tools/meds2pdb/meds2pdb
 plugins_install/*.exe
-
+*.swp
diff --git a/.gitmodules b/.gitmodules
index 48c10c452cbd48639f7c314b5f4236d5d5ff12fc..4b0edb3474f64adf4a81b678bdca648e9f85ae45 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,3 +2,6 @@
 	shallow = true
 	path = libcapstone
 	url = https://github.com/aquynh/capstone.git
+[submodule "libehp"]
+	path = libehp
+	url = git@git.zephyr-software.com:allnp/libehp.git
diff --git a/SConscript b/SConscript
index e903bf20629827340f5e024865c3eb698722688f..9c5aa68797f7a92111313a2c47d01e76c51c8a64 100644
--- a/SConscript
+++ b/SConscript
@@ -58,10 +58,15 @@ else:
 
 env['BASE_IRDB_LIBS']="IRDB-core", "pqxx", "pq", "EXEIO"
 
+pedi = Command( target = "./testoutput",
+		source = "./SConscript",
+                action = os.environ['PEDI_HOME']+"/pedi -m manifest.txt " )
+
 if sysname != "SunOS":
 	libPEBLISS=SConscript("pebliss/trunk/pe_lib/SConscript", variant_dir='scons_build/libPEBLISS')
 	# setup libraries needed for linking
 	env['BASE_IRDB_LIBS']="IRDB-core", "pqxx", "pq", "EXEIO", "pebliss"
+	Depends(pedi,libPEBLISS)
 
 # pebliss requires iconv, which needs to be explicit on cygwin.
 if "CYGWIN" in sysname:
@@ -70,6 +75,9 @@ if "CYGWIN" in sysname:
 
 Export('env')
 
+libehp=env.SConscript("libehp/SConscript", variant_dir='scons_build/libehp')
+libehp=env.Install("$SECURITY_TRANSFORMS_HOME/lib", libehp);
+
 libtransform=SConscript("libtransform/SConscript", variant_dir='scons_build/libtransform')
 libEXEIO=SConscript("libEXEIO/SConscript", variant_dir='scons_build/libEXEIO')
 libbea=SConscript("beaengine/SConscript", variant_dir='scons_build/beaengine')
@@ -79,10 +87,8 @@ libIRDB=SConscript("libIRDB/SConscript", variant_dir='scons_build/libIRDB')
 libStructDiv=SConscript("libStructDiv/SConscript", variant_dir='scons_build/libStructDiv')
 libElfDep=SConscript("libElfDep/SConscript", variant_dir='scons_build/libElfDep')
 
-pedi = Command( target = "./testoutput",
-		source = "./SConscript",
-                action = os.environ['PEDI_HOME']+"/pedi -m manifest.txt " )
-Depends(pedi, (libEXEIO, libbea, libMEDSannotation,libxform,libtransform,libIRDB,libStructDiv, libElfDep))
+
+Depends(pedi, (libehp,libtransform,libEXEIO,libbea,libMEDSannotation,libxform,libIRDB,libStructDiv,libElfDep))
 
 tools=None
 if 'build_tools' not in env or env['build_tools'] is None or int(env['build_tools']) == 1:
diff --git a/SConstruct b/SConstruct
index 2eb231368d1cbcf75e96cd03583b8de36c92be82..0180dbc4a74c660677d100a709a741b2dc842698 100644
--- a/SConstruct
+++ b/SConstruct
@@ -9,9 +9,9 @@ env=Environment()
 
 
 # default build options
-env.Replace(CFLAGS="-fPIC  -Wall -Werror ")
-env.Replace(CXXFLAGS="-fPIC  -Wall -Werror ")
-env.Replace(LINKFLAGS="-fPIC -Wall -Werror ")
+env.Replace(CFLAGS="-fPIC  -Wall -Werror -fmax-errors=2")
+env.Replace(CXXFLAGS="-fPIC  -Wall -Werror -fmax-errors=2 ")
+env.Replace(LINKFLAGS="-fPIC -Wall -Werror -fmax-errors=2 ")
 
 # parse arguments
 env.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME'])
diff --git a/libIRDB/include/cfg/BasicBlock.hpp b/libIRDB/include/cfg/BasicBlock.hpp
index 340c9d697dc1e8ce801c5e5641ae2bcedb9b9cb8..42a9a4bf81d79e6ed5d487deedeab81c3103f691 100644
--- a/libIRDB/include/cfg/BasicBlock.hpp
+++ b/libIRDB/include/cfg/BasicBlock.hpp
@@ -49,6 +49,9 @@ class BasicBlock_t
 		bool EndsInIndirectBranch();
 		bool EndsInConditionalBranch();
 		Instruction_t* GetBranchInstruction();
+		void dump(std::ostream &os=std::cout) const { os<<*this; }
+
+	protected:
 
 		void BuildBlock(Function_t* func,
                 		Instruction_t* insn,
@@ -65,6 +68,7 @@ class BasicBlock_t
 		bool is_exit_block;
 
 	friend std::ostream& operator<<(std::ostream& os, const BasicBlock_t& block);
+	friend class ControlFlowGraph_t;
 };
 
 std::ostream& operator<<(std::ostream& os, const BasicBlock_t& block);
diff --git a/libIRDB/include/cfg/CFG.hpp b/libIRDB/include/cfg/CFG.hpp
index 532570be5ed3343adc29f77c7ea56f431f163736..647f916aa1017393cd5428dc9bdf73ad34845e8d 100644
--- a/libIRDB/include/cfg/CFG.hpp
+++ b/libIRDB/include/cfg/CFG.hpp
@@ -29,6 +29,7 @@ class ControlFlowGraph_t
 
 		BasicBlock_t* GetEntry() const { return entry; }
 		Function_t* GetFunction() const { return function; }
+		void dump(std::ostream &os=std::cout) const { os<<*this; }
 
 	protected:
 		void Build(Function_t *func);
diff --git a/libIRDB/include/core/eh.hpp b/libIRDB/include/core/eh.hpp
index 3f52768f2afc528834a7c91f48dc3fd61586d5ac..6c3da494cb6278f0a36cdb981b29eb167436236f 100644
--- a/libIRDB/include/core/eh.hpp
+++ b/libIRDB/include/core/eh.hpp
@@ -79,6 +79,8 @@ class EhProgram_t : public BaseObj_t
 
         std::vector<std::string> WriteToDB(File_t* fid);    // writes to DB, ID is not -1.
 
+        uint8_t GetPointerSize() const { return ptrsize; }
+
 
 	friend bool operator<(const EhProgram_t&a, const EhProgram_t&b);
 
diff --git a/libIRDB/test/SConscript b/libIRDB/test/SConscript
index 24c10568e47edf1e6dda13f3c6e4ac6bfac57a29..6610373ca87f8118af7c3311e4f132196b61714b 100644
--- a/libIRDB/test/SConscript
+++ b/libIRDB/test/SConscript
@@ -15,10 +15,11 @@ if 'build_tools' not in myenv or myenv['build_tools'] is None or int(myenv['buil
 		 $SECURITY_TRANSFORMS_HOME/libIRDB/include 
 		 $SECURITY_TRANSFORMS_HOME/libMEDSannotation/include 
 		 $SECURITY_TRANSFORMS_HOME/libEXEIO/include 
+		 $SECURITY_TRANSFORMS_HOME/libehp/include 
 		'''
 
 	LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
-	LIBS=Split( 'IRDB-cfg IRDB-util ' + env.subst('$BASE_IRDB_LIBS')+ " MEDSannotation")
+	LIBS=Split( 'IRDB-cfg IRDB-util ' + env.subst('$BASE_IRDB_LIBS')+ " MEDSannotation ehp")
 
 	myenv=myenv.Clone(CPPPATH=Split(cpppath))
 
diff --git a/libIRDB/test/dwarf2.h b/libIRDB/test/dwarf2.h
deleted file mode 100644
index 6917b1457496310a34a8d33508e9ff89f062e56c..0000000000000000000000000000000000000000
--- a/libIRDB/test/dwarf2.h
+++ /dev/null
@@ -1,595 +0,0 @@
-/* Declarations and definitions of codes relating to the DWARF2 symbolic
-   debugging information format.
-   Copyright (C) 1992-2014 Free Software Foundation, Inc.
-   Contributed by Gary Funck (gary@intrepid.com).  Derived from the
-   DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.com).
-
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifndef _DWARF2_H
-#define _DWARF2_H	1
-
-/* This file is derived from the DWARF specification (a public document)
-   Revision 2.0.0 (July 27, 1993) developed by the UNIX International
-   Programming Languages Special Interest Group (UI/PLSIG) and distributed
-   by UNIX International.  Copies of this specification are available from
-   UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.  */
-
-/* This file is shared between GCC and GDB, and should not contain
-   prototypes.  */
-
-#ifndef __ASSEMBLER__
-/* Tag names and codes.  */
-
-enum dwarf_tag
-  {
-    DW_TAG_padding = 0x00,
-    DW_TAG_array_type = 0x01,
-    DW_TAG_class_type = 0x02,
-    DW_TAG_entry_point = 0x03,
-    DW_TAG_enumeration_type = 0x04,
-    DW_TAG_formal_parameter = 0x05,
-    DW_TAG_imported_declaration = 0x08,
-    DW_TAG_label = 0x0a,
-    DW_TAG_lexical_block = 0x0b,
-    DW_TAG_member = 0x0d,
-    DW_TAG_pointer_type = 0x0f,
-    DW_TAG_reference_type = 0x10,
-    DW_TAG_compile_unit = 0x11,
-    DW_TAG_string_type = 0x12,
-    DW_TAG_structure_type = 0x13,
-    DW_TAG_subroutine_type = 0x15,
-    DW_TAG_typedef = 0x16,
-    DW_TAG_union_type = 0x17,
-    DW_TAG_unspecified_parameters = 0x18,
-    DW_TAG_variant = 0x19,
-    DW_TAG_common_block = 0x1a,
-    DW_TAG_common_inclusion = 0x1b,
-    DW_TAG_inheritance = 0x1c,
-    DW_TAG_inlined_subroutine = 0x1d,
-    DW_TAG_module = 0x1e,
-    DW_TAG_ptr_to_member_type = 0x1f,
-    DW_TAG_set_type = 0x20,
-    DW_TAG_subrange_type = 0x21,
-    DW_TAG_with_stmt = 0x22,
-    DW_TAG_access_declaration = 0x23,
-    DW_TAG_base_type = 0x24,
-    DW_TAG_catch_block = 0x25,
-    DW_TAG_const_type = 0x26,
-    DW_TAG_constant = 0x27,
-    DW_TAG_enumerator = 0x28,
-    DW_TAG_file_type = 0x29,
-    DW_TAG_friend = 0x2a,
-    DW_TAG_namelist = 0x2b,
-    DW_TAG_namelist_item = 0x2c,
-    DW_TAG_packed_type = 0x2d,
-    DW_TAG_subprogram = 0x2e,
-    DW_TAG_template_type_param = 0x2f,
-    DW_TAG_template_value_param = 0x30,
-    DW_TAG_thrown_type = 0x31,
-    DW_TAG_try_block = 0x32,
-    DW_TAG_variant_part = 0x33,
-    DW_TAG_variable = 0x34,
-    DW_TAG_volatile_type = 0x35,
-    /* SGI/MIPS Extensions */
-    DW_TAG_MIPS_loop = 0x4081,
-    /* GNU extensions */
-    DW_TAG_format_label = 0x4101,	/* for FORTRAN 77 and Fortran 90 */
-    DW_TAG_function_template = 0x4102,	/* for C++ */
-    DW_TAG_class_template = 0x4103,	/* for C++ */
-    DW_TAG_GNU_BINCL = 0x4104,
-    DW_TAG_GNU_EINCL = 0x4105
-  };
-
-#define DW_TAG_lo_user	0x4080
-#define DW_TAG_hi_user	0xffff
-
-/* flag that tells whether entry has a child or not */
-#define DW_children_no   0
-#define	DW_children_yes  1
-
-/* Form names and codes.  */
-enum dwarf_form
-  {
-    DW_FORM_addr = 0x01,
-    DW_FORM_block2 = 0x03,
-    DW_FORM_block4 = 0x04,
-    DW_FORM_data2 = 0x05,
-    DW_FORM_data4 = 0x06,
-    DW_FORM_data8 = 0x07,
-    DW_FORM_string = 0x08,
-    DW_FORM_block = 0x09,
-    DW_FORM_block1 = 0x0a,
-    DW_FORM_data1 = 0x0b,
-    DW_FORM_flag = 0x0c,
-    DW_FORM_sdata = 0x0d,
-    DW_FORM_strp = 0x0e,
-    DW_FORM_udata = 0x0f,
-    DW_FORM_ref_addr = 0x10,
-    DW_FORM_ref1 = 0x11,
-    DW_FORM_ref2 = 0x12,
-    DW_FORM_ref4 = 0x13,
-    DW_FORM_ref8 = 0x14,
-    DW_FORM_ref_udata = 0x15,
-    DW_FORM_indirect = 0x16
-  };
-
-/* Attribute names and codes.  */
-
-enum dwarf_attribute
-  {
-    DW_AT_sibling = 0x01,
-    DW_AT_location = 0x02,
-    DW_AT_name = 0x03,
-    DW_AT_ordering = 0x09,
-    DW_AT_subscr_data = 0x0a,
-    DW_AT_byte_size = 0x0b,
-    DW_AT_bit_offset = 0x0c,
-    DW_AT_bit_size = 0x0d,
-    DW_AT_element_list = 0x0f,
-    DW_AT_stmt_list = 0x10,
-    DW_AT_low_pc = 0x11,
-    DW_AT_high_pc = 0x12,
-    DW_AT_language = 0x13,
-    DW_AT_member = 0x14,
-    DW_AT_discr = 0x15,
-    DW_AT_discr_value = 0x16,
-    DW_AT_visibility = 0x17,
-    DW_AT_import = 0x18,
-    DW_AT_string_length = 0x19,
-    DW_AT_common_reference = 0x1a,
-    DW_AT_comp_dir = 0x1b,
-    DW_AT_const_value = 0x1c,
-    DW_AT_containing_type = 0x1d,
-    DW_AT_default_value = 0x1e,
-    DW_AT_inline = 0x20,
-    DW_AT_is_optional = 0x21,
-    DW_AT_lower_bound = 0x22,
-    DW_AT_producer = 0x25,
-    DW_AT_prototyped = 0x27,
-    DW_AT_return_addr = 0x2a,
-    DW_AT_start_scope = 0x2c,
-    DW_AT_stride_size = 0x2e,
-    DW_AT_upper_bound = 0x2f,
-    DW_AT_abstract_origin = 0x31,
-    DW_AT_accessibility = 0x32,
-    DW_AT_address_class = 0x33,
-    DW_AT_artificial = 0x34,
-    DW_AT_base_types = 0x35,
-    DW_AT_calling_convention = 0x36,
-    DW_AT_count = 0x37,
-    DW_AT_data_member_location = 0x38,
-    DW_AT_decl_column = 0x39,
-    DW_AT_decl_file = 0x3a,
-    DW_AT_decl_line = 0x3b,
-    DW_AT_declaration = 0x3c,
-    DW_AT_discr_list = 0x3d,
-    DW_AT_encoding = 0x3e,
-    DW_AT_external = 0x3f,
-    DW_AT_frame_base = 0x40,
-    DW_AT_friend = 0x41,
-    DW_AT_identifier_case = 0x42,
-    DW_AT_macro_info = 0x43,
-    DW_AT_namelist_items = 0x44,
-    DW_AT_priority = 0x45,
-    DW_AT_segment = 0x46,
-    DW_AT_specification = 0x47,
-    DW_AT_static_link = 0x48,
-    DW_AT_type = 0x49,
-    DW_AT_use_location = 0x4a,
-    DW_AT_variable_parameter = 0x4b,
-    DW_AT_virtuality = 0x4c,
-    DW_AT_vtable_elem_location = 0x4d,
-    /* SGI/MIPS Extensions */
-    DW_AT_MIPS_fde = 0x2001,
-    DW_AT_MIPS_loop_begin = 0x2002,
-    DW_AT_MIPS_tail_loop_begin = 0x2003,
-    DW_AT_MIPS_epilog_begin = 0x2004,
-    DW_AT_MIPS_loop_unroll_factor = 0x2005,
-    DW_AT_MIPS_software_pipeline_depth = 0x2006,
-    DW_AT_MIPS_linkage_name = 0x2007,
-    DW_AT_MIPS_stride = 0x2008,
-    DW_AT_MIPS_abstract_name = 0x2009,
-    DW_AT_MIPS_clone_origin = 0x200a,
-    DW_AT_MIPS_has_inlines = 0x200b,
-    /* GNU extensions.  */
-    DW_AT_sf_names = 0x2101,
-    DW_AT_src_info = 0x2102,
-    DW_AT_mac_info = 0x2103,
-    DW_AT_src_coords = 0x2104,
-    DW_AT_body_begin = 0x2105,
-    DW_AT_body_end = 0x2106
-  };
-
-#define DW_AT_lo_user	0x2000	/* implementation-defined range start */
-#define DW_AT_hi_user	0x3ff0	/* implementation-defined range end */
-
-/* Location atom names and codes.  */
-
-enum dwarf_location_atom
-  {
-    DW_OP_addr = 0x03,
-    DW_OP_deref = 0x06,
-    DW_OP_const1u = 0x08,
-    DW_OP_const1s = 0x09,
-    DW_OP_const2u = 0x0a,
-    DW_OP_const2s = 0x0b,
-    DW_OP_const4u = 0x0c,
-    DW_OP_const4s = 0x0d,
-    DW_OP_const8u = 0x0e,
-    DW_OP_const8s = 0x0f,
-    DW_OP_constu = 0x10,
-    DW_OP_consts = 0x11,
-    DW_OP_dup = 0x12,
-    DW_OP_drop = 0x13,
-    DW_OP_over = 0x14,
-    DW_OP_pick = 0x15,
-    DW_OP_swap = 0x16,
-    DW_OP_rot = 0x17,
-    DW_OP_xderef = 0x18,
-    DW_OP_abs = 0x19,
-    DW_OP_and = 0x1a,
-    DW_OP_div = 0x1b,
-    DW_OP_minus = 0x1c,
-    DW_OP_mod = 0x1d,
-    DW_OP_mul = 0x1e,
-    DW_OP_neg = 0x1f,
-    DW_OP_not = 0x20,
-    DW_OP_or = 0x21,
-    DW_OP_plus = 0x22,
-    DW_OP_plus_uconst = 0x23,
-    DW_OP_shl = 0x24,
-    DW_OP_shr = 0x25,
-    DW_OP_shra = 0x26,
-    DW_OP_xor = 0x27,
-    DW_OP_bra = 0x28,
-    DW_OP_eq = 0x29,
-    DW_OP_ge = 0x2a,
-    DW_OP_gt = 0x2b,
-    DW_OP_le = 0x2c,
-    DW_OP_lt = 0x2d,
-    DW_OP_ne = 0x2e,
-    DW_OP_skip = 0x2f,
-    DW_OP_lit0 = 0x30,
-    DW_OP_lit1 = 0x31,
-    DW_OP_lit2 = 0x32,
-    DW_OP_lit3 = 0x33,
-    DW_OP_lit4 = 0x34,
-    DW_OP_lit5 = 0x35,
-    DW_OP_lit6 = 0x36,
-    DW_OP_lit7 = 0x37,
-    DW_OP_lit8 = 0x38,
-    DW_OP_lit9 = 0x39,
-    DW_OP_lit10 = 0x3a,
-    DW_OP_lit11 = 0x3b,
-    DW_OP_lit12 = 0x3c,
-    DW_OP_lit13 = 0x3d,
-    DW_OP_lit14 = 0x3e,
-    DW_OP_lit15 = 0x3f,
-    DW_OP_lit16 = 0x40,
-    DW_OP_lit17 = 0x41,
-    DW_OP_lit18 = 0x42,
-    DW_OP_lit19 = 0x43,
-    DW_OP_lit20 = 0x44,
-    DW_OP_lit21 = 0x45,
-    DW_OP_lit22 = 0x46,
-    DW_OP_lit23 = 0x47,
-    DW_OP_lit24 = 0x48,
-    DW_OP_lit25 = 0x49,
-    DW_OP_lit26 = 0x4a,
-    DW_OP_lit27 = 0x4b,
-    DW_OP_lit28 = 0x4c,
-    DW_OP_lit29 = 0x4d,
-    DW_OP_lit30 = 0x4e,
-    DW_OP_lit31 = 0x4f,
-    DW_OP_reg0 = 0x50,
-    DW_OP_reg1 = 0x51,
-    DW_OP_reg2 = 0x52,
-    DW_OP_reg3 = 0x53,
-    DW_OP_reg4 = 0x54,
-    DW_OP_reg5 = 0x55,
-    DW_OP_reg6 = 0x56,
-    DW_OP_reg7 = 0x57,
-    DW_OP_reg8 = 0x58,
-    DW_OP_reg9 = 0x59,
-    DW_OP_reg10 = 0x5a,
-    DW_OP_reg11 = 0x5b,
-    DW_OP_reg12 = 0x5c,
-    DW_OP_reg13 = 0x5d,
-    DW_OP_reg14 = 0x5e,
-    DW_OP_reg15 = 0x5f,
-    DW_OP_reg16 = 0x60,
-    DW_OP_reg17 = 0x61,
-    DW_OP_reg18 = 0x62,
-    DW_OP_reg19 = 0x63,
-    DW_OP_reg20 = 0x64,
-    DW_OP_reg21 = 0x65,
-    DW_OP_reg22 = 0x66,
-    DW_OP_reg23 = 0x67,
-    DW_OP_reg24 = 0x68,
-    DW_OP_reg25 = 0x69,
-    DW_OP_reg26 = 0x6a,
-    DW_OP_reg27 = 0x6b,
-    DW_OP_reg28 = 0x6c,
-    DW_OP_reg29 = 0x6d,
-    DW_OP_reg30 = 0x6e,
-    DW_OP_reg31 = 0x6f,
-    DW_OP_breg0 = 0x70,
-    DW_OP_breg1 = 0x71,
-    DW_OP_breg2 = 0x72,
-    DW_OP_breg3 = 0x73,
-    DW_OP_breg4 = 0x74,
-    DW_OP_breg5 = 0x75,
-    DW_OP_breg6 = 0x76,
-    DW_OP_breg7 = 0x77,
-    DW_OP_breg8 = 0x78,
-    DW_OP_breg9 = 0x79,
-    DW_OP_breg10 = 0x7a,
-    DW_OP_breg11 = 0x7b,
-    DW_OP_breg12 = 0x7c,
-    DW_OP_breg13 = 0x7d,
-    DW_OP_breg14 = 0x7e,
-    DW_OP_breg15 = 0x7f,
-    DW_OP_breg16 = 0x80,
-    DW_OP_breg17 = 0x81,
-    DW_OP_breg18 = 0x82,
-    DW_OP_breg19 = 0x83,
-    DW_OP_breg20 = 0x84,
-    DW_OP_breg21 = 0x85,
-    DW_OP_breg22 = 0x86,
-    DW_OP_breg23 = 0x87,
-    DW_OP_breg24 = 0x88,
-    DW_OP_breg25 = 0x89,
-    DW_OP_breg26 = 0x8a,
-    DW_OP_breg27 = 0x8b,
-    DW_OP_breg28 = 0x8c,
-    DW_OP_breg29 = 0x8d,
-    DW_OP_breg30 = 0x8e,
-    DW_OP_breg31 = 0x8f,
-    DW_OP_regx = 0x90,
-    DW_OP_fbreg = 0x91,
-    DW_OP_bregx = 0x92,
-    DW_OP_piece = 0x93,
-    DW_OP_deref_size = 0x94,
-    DW_OP_xderef_size = 0x95,
-    DW_OP_nop = 0x96
-  };
-
-#define DW_OP_lo_user	0x80	/* implementation-defined range start */
-#define DW_OP_hi_user	0xff	/* implementation-defined range end */
-
-/* Type encodings.  */
-
-enum dwarf_type
-  {
-    DW_ATE_void = 0x0,
-    DW_ATE_address = 0x1,
-    DW_ATE_boolean = 0x2,
-    DW_ATE_complex_float = 0x3,
-    DW_ATE_float = 0x4,
-    DW_ATE_signed = 0x5,
-    DW_ATE_signed_char = 0x6,
-    DW_ATE_unsigned = 0x7,
-    DW_ATE_unsigned_char = 0x8
-  };
-
-#define	DW_ATE_lo_user 0x80
-#define	DW_ATE_hi_user 0xff
-
-/* Array ordering names and codes.  */
-enum dwarf_array_dim_ordering
-  {
-    DW_ORD_row_major = 0,
-    DW_ORD_col_major = 1
-  };
-
-/* access attribute */
-enum dwarf_access_attribute
-  {
-    DW_ACCESS_public = 1,
-    DW_ACCESS_protected = 2,
-    DW_ACCESS_private = 3
-  };
-
-/* visibility */
-enum dwarf_visibility_attribute
-  {
-    DW_VIS_local = 1,
-    DW_VIS_exported = 2,
-    DW_VIS_qualified = 3
-  };
-
-/* virtuality */
-enum dwarf_virtuality_attribute
-  {
-    DW_VIRTUALITY_none = 0,
-    DW_VIRTUALITY_virtual = 1,
-    DW_VIRTUALITY_pure_virtual = 2
-  };
-
-/* case sensitivity */
-enum dwarf_id_case
-  {
-    DW_ID_case_sensitive = 0,
-    DW_ID_up_case = 1,
-    DW_ID_down_case = 2,
-    DW_ID_case_insensitive = 3
-  };
-
-/* calling convention */
-enum dwarf_calling_convention
-  {
-    DW_CC_normal = 0x1,
-    DW_CC_program = 0x2,
-    DW_CC_nocall = 0x3
-  };
-
-#define DW_CC_lo_user 0x40
-#define DW_CC_hi_user 0xff
-
-/* inline attribute */
-enum dwarf_inline_attribute
-  {
-    DW_INL_not_inlined = 0,
-    DW_INL_inlined = 1,
-    DW_INL_declared_not_inlined = 2,
-    DW_INL_declared_inlined = 3
-  };
-
-/* discriminant lists */
-enum dwarf_discrim_list
-  {
-    DW_DSC_label = 0,
-    DW_DSC_range = 1
-  };
-
-/* line number opcodes */
-enum dwarf_line_number_ops
-  {
-    DW_LNS_extended_op = 0,
-    DW_LNS_copy = 1,
-    DW_LNS_advance_pc = 2,
-    DW_LNS_advance_line = 3,
-    DW_LNS_set_file = 4,
-    DW_LNS_set_column = 5,
-    DW_LNS_negate_stmt = 6,
-    DW_LNS_set_basic_block = 7,
-    DW_LNS_const_add_pc = 8,
-    DW_LNS_fixed_advance_pc = 9
-  };
-
-/* line number extended opcodes */
-enum dwarf_line_number_x_ops
-  {
-    DW_LNE_end_sequence = 1,
-    DW_LNE_set_address = 2,
-    DW_LNE_define_file = 3
-  };
-
-/* call frame information */
-enum dwarf_call_frame_info
-  {
-    DW_CFA_advance_loc = 0x40,
-    DW_CFA_offset = 0x80,
-    DW_CFA_restore = 0xc0,
-    DW_CFA_nop = 0x00,
-    DW_CFA_set_loc = 0x01,
-    DW_CFA_advance_loc1 = 0x02,
-    DW_CFA_advance_loc2 = 0x03,
-    DW_CFA_advance_loc4 = 0x04,
-    DW_CFA_offset_extended = 0x05,
-    DW_CFA_restore_extended = 0x06,
-    DW_CFA_undefined = 0x07,
-    DW_CFA_same_value = 0x08,
-    DW_CFA_register = 0x09,
-    DW_CFA_remember_state = 0x0a,
-    DW_CFA_restore_state = 0x0b,
-    DW_CFA_def_cfa = 0x0c,
-    DW_CFA_def_cfa_register = 0x0d,
-    DW_CFA_def_cfa_offset = 0x0e,
-    DW_CFA_def_cfa_expression = 0x0f,
-    DW_CFA_expression = 0x10,
-    /* Dwarf 2.1 */
-    DW_CFA_offset_extended_sf = 0x11,
-    DW_CFA_def_cfa_sf = 0x12,
-    DW_CFA_def_cfa_offset_sf = 0x13,
-    /* added by jdh for newer version of dwarf?  libc uses this in ubuntu 14.04 */
-    DW_CFA_val_offset = 0x14,
-    DW_CFA_val_offset_sf = 0x15,
-    DW_CFA_val_expression = 0x16,
-  
-
-    /* SGI/MIPS specific */
-    DW_CFA_MIPS_advance_loc8 = 0x1d,
-
-    /* GNU extensions */
-    DW_CFA_GNU_window_save = 0x2d,
-    DW_CFA_GNU_args_size = 0x2e,
-    DW_CFA_GNU_negative_offset_extended = 0x2f
-  };
-
-#define DW_CIE_ID	  0xffffffff
-#define DW_CIE_VERSION	  1
-
-#define DW_CFA_extended   0
-#define DW_CFA_low_user   0x1c
-#define DW_CFA_high_user  0x3f
-
-#define DW_CHILDREN_no		     0x00
-#define DW_CHILDREN_yes		     0x01
-
-#define DW_ADDR_none		0
-
-/* Source language names and codes.  */
-
-enum dwarf_source_language
-  {
-    DW_LANG_C89 = 0x0001,
-    DW_LANG_C = 0x0002,
-    DW_LANG_Ada83 = 0x0003,
-    DW_LANG_C_plus_plus = 0x0004,
-    DW_LANG_Cobol74 = 0x0005,
-    DW_LANG_Cobol85 = 0x0006,
-    DW_LANG_Fortran77 = 0x0007,
-    DW_LANG_Fortran90 = 0x0008,
-    DW_LANG_Pascal83 = 0x0009,
-    DW_LANG_Modula2 = 0x000a,
-    DW_LANG_Java = 0x000b,
-    DW_LANG_Mips_Assembler = 0x8001
-  };
-
-
-#define DW_LANG_lo_user 0x8000	/* implementation-defined range start */
-#define DW_LANG_hi_user 0xffff	/* implementation-defined range start */
-
-/* Names and codes for macro information.  */
-
-enum dwarf_macinfo_record_type
-  {
-    DW_MACINFO_define = 1,
-    DW_MACINFO_undef = 2,
-    DW_MACINFO_start_file = 3,
-    DW_MACINFO_end_file = 4,
-    DW_MACINFO_vendor_ext = 255
-  };
-
-#endif /* !ASSEMBLER */
-
-/* @@@ For use with GNU frame unwind information.  */
-
-#define DW_EH_PE_absptr		0x00
-#define DW_EH_PE_omit		0xff
-
-#define DW_EH_PE_uleb128	0x01
-#define DW_EH_PE_udata2		0x02
-#define DW_EH_PE_udata4		0x03
-#define DW_EH_PE_udata8		0x04
-#define DW_EH_PE_sleb128	0x09
-#define DW_EH_PE_sdata2		0x0A
-#define DW_EH_PE_sdata4		0x0B
-#define DW_EH_PE_sdata8		0x0C
-#define DW_EH_PE_signed		0x08
-
-#define DW_EH_PE_pcrel		0x10
-#define DW_EH_PE_textrel	0x20
-#define DW_EH_PE_datarel	0x30
-#define DW_EH_PE_funcrel	0x40
-#define DW_EH_PE_aligned	0x50
-
-#define DW_EH_PE_indirect	0x80
-
-#endif /* dwarf2.h */
diff --git a/libIRDB/test/eh_frame.hpp b/libIRDB/test/eh_frame.hpp
deleted file mode 100644
index d5826f1eb9483f67b058da877b07ebcada86d696..0000000000000000000000000000000000000000
--- a/libIRDB/test/eh_frame.hpp
+++ /dev/null
@@ -1,402 +0,0 @@
-#ifndef eh_frame_hpp
-#define eh_frame_hpp
-
-#include <libIRDB-core.hpp>
-#include <iostream>
-#include <iomanip>
-#include <fstream>
-#include <limits>
-#include <stdlib.h>
-#include <string.h>
-#include <map>
-#include <assert.h>
-#include <elf.h>
-#include <algorithm>
-#include <memory>
-
-#include <exeio.h>
-#include "dwarf2.h"
-
-
-
-
-typedef std::map<libIRDB::virtual_offset_t, libIRDB::Instruction_t*> OffsetMap_t;
-
-template <int ptrsize>
-class eh_frame_util_t
-{
-	public: 
-	template <class T> 
-	static bool read_type(T &value, uint32_t &position, const uint8_t* const data, const uint32_t max);
-	template <class T> 
-	static bool read_type_with_encoding
-		(const uint8_t encoding, T &value, 
-		uint32_t &position, 
-		const uint8_t* const data, 
-		const uint32_t max, 
-		const uint64_t section_start_addr );
-
-	static bool read_string 
-		(std::string &s, 
-		uint32_t & position, 
-		const uint8_t* const data, 
-		const uint32_t max);
-
-
-	// see https://en.wikipedia.org/wiki/LEB128
-	static bool read_uleb128 
-		( uint64_t &result, 
-		uint32_t& position, 
-		const uint8_t* const data, 
-		const uint32_t max);
-
-	// see https://en.wikipedia.org/wiki/LEB128
-	static bool read_sleb128 ( 
-		int64_t &result, 
-		uint32_t & position, 
-		const uint8_t* const data, 
-		const uint32_t max);
-	
-	static bool read_length(
-		uint64_t &act_length, 
-		uint32_t &position, 
-		const uint8_t* const data, 
-		const uint32_t max);
-};
-
-template <int ptrsize>
-class eh_program_insn_t 
-{
-	public: 
-	
-	eh_program_insn_t() ;
-	eh_program_insn_t(const std::string &s) ;
-
-	void print(uint64_t &pc, int64_t caf=1) const;
-
-	void push_byte(uint8_t c) ;
-
-	static void print_uleb_operand(
-		uint32_t pos, 
-		const uint8_t* const data, 
-		const uint32_t max) ;
-
-	static void print_sleb_operand(
-		uint32_t pos, 
-		const uint8_t* const data, 
-		const uint32_t max) ;
-
-	bool parse_insn(
-		uint8_t opcode, 
-		uint32_t& pos, 
-		const uint8_t* const data, 
-		const uint32_t &max);
-
-	bool isNop() const ;
-	bool isRestoreState() const ;
-	bool isRememberState() const ;
-
-	bool Advance(uint64_t &cur_addr, uint64_t CAF) const ;
-
-	const std::vector<uint8_t>& GetBytes() const ;
-	std::vector<uint8_t>& GetBytes() ;
-
-	private:
-
-	std::vector<uint8_t> program_bytes;
-};
-
-template <int ptrsize>
-bool operator<(const eh_program_insn_t<ptrsize>& a, const eh_program_insn_t<ptrsize>& b);
-
-template <int ptrsize>
-class eh_program_t
-{
-	public:
-	void push_insn(const eh_program_insn_t<ptrsize> &i); 
-
-	void print(const uint64_t start_addr=0) const;
-
-	bool parse_program(
-		const uint32_t& program_start_position, 
-		const uint8_t* const data, 
-		const uint32_t &max_program_pos);
-	const std::vector<eh_program_insn_t <ptrsize> >& GetInstructions() const ;
-	std::vector<eh_program_insn_t <ptrsize> >& GetInstructions() ;
-	private:
-	std::vector<eh_program_insn_t <ptrsize> > instructions;
-};
-
-template <int ptrsize>
-bool operator<(const eh_program_t<ptrsize>& a, const eh_program_t<ptrsize>& b);
-
-template <int ptrsize>
-class cie_contents_t : eh_frame_util_t<ptrsize>
-{
-	private:
-	uint64_t cie_position;
-	uint64_t length;
-	uint8_t cie_id;
-	uint8_t cie_version;
-	std::string augmentation;
-	uint64_t code_alignment_factor;
-	int64_t data_alignment_factor;
-	uint64_t return_address_register_column;
-	uint64_t augmentation_data_length;
-	uint8_t personality_encoding;
-	uint64_t personality;
-	uint8_t lsda_encoding;
-	uint8_t fde_encoding;
-	eh_program_t<ptrsize> eh_pgm;
-
-	public:
-
-	cie_contents_t() ;
-	
-	const eh_program_t<ptrsize>& GetProgram() const ;
-	uint64_t GetCAF() const ;
-	int64_t GetDAF() const ;
-	uint64_t GetPersonality() const ;
-	uint64_t GetReturnRegister() const ;
-
-	std::string GetAugmentation() const ;
-	uint8_t GetLSDAEncoding() const ;
-	uint8_t GetFDEEncoding() const ;
-
-	bool parse_cie(
-		const uint32_t &cie_position, 
-		const uint8_t* const data, 
-		const uint32_t max, 
-		const uint64_t eh_addr);
-	void print() const ;
-	void build_ir(libIRDB::Instruction_t* insn) const;
-};
-
-template <int ptrsize>
-class lsda_call_site_action_t : private eh_frame_util_t<ptrsize>
-{
-	private:
-	int64_t action;
-
-	public:
-	lsda_call_site_action_t() ;
-	int64_t GetAction() const ;
-
-	bool parse_lcsa(uint32_t& pos, const uint8_t* const data, const uint64_t max, bool &end);
-	void print() const;
-};
-
-template <int ptrsize>
-bool operator< (const lsda_call_site_action_t <ptrsize> &lhs, const lsda_call_site_action_t <ptrsize> &rhs);
-
-template <int ptrsize>
-class lsda_type_table_entry_t: private eh_frame_util_t<ptrsize>
-{
-	private:
-	uint64_t pointer_to_typeinfo;
-	uint64_t tt_encoding;
-	uint64_t tt_encoding_size;
-
-	public:
-	lsda_type_table_entry_t() ; 
-
-	uint64_t GetTypeInfoPointer() const ;
-	uint64_t GetEncoding() const ;
-	uint64_t GetTTEncodingSize() const ;
-
-	bool parse(
-		const uint64_t p_tt_encoding, 	
-		const uint64_t tt_pos, 	
-		const uint64_t index,
-		const uint8_t* const data, 
-		const uint64_t max,  
-		const uint64_t data_addr
-		);
-
-	void print() const;
-	
-};
-
-template <int ptrsize>
-class lsda_call_site_t : private eh_frame_util_t<ptrsize>
-{
-	private:
-	uint64_t call_site_offset;
-	uint64_t call_site_addr;
-	uint64_t call_site_length;
-	uint64_t call_site_end_addr;
-	uint64_t landing_pad_offset;
-	uint64_t landing_pad_addr;
-	uint64_t action;
-	uint64_t action_table_offset;
-	uint64_t action_table_addr;
-
-	std::vector<lsda_call_site_action_t <ptrsize> > action_table;
-
-	public:
-	lsda_call_site_t() ;
-
-	const std::vector<lsda_call_site_action_t <ptrsize> >& GetActionTable() const { return action_table; }
-	      std::vector<lsda_call_site_action_t <ptrsize> >& GetActionTable()       { return action_table; }
-
-	uint64_t GetLandingPadAddress() const  { return landing_pad_addr ; } 
-
-	bool parse_lcs(	
-		const uint64_t action_table_start_addr, 	
-		const uint64_t cs_table_start_addr, 	
-		const uint8_t cs_table_encoding, 
-		uint32_t &pos, 
-		const uint8_t* const data, 
-		const uint64_t max,  /* call site table max */
-		const uint64_t data_addr, 
-		const uint64_t landing_pad_base_addr,
-		const uint64_t gcc_except_table_max);
-
-	void print() const;
-
-	bool appliesTo(const libIRDB::Instruction_t* insn) const;
-
-	void build_ir(libIRDB::Instruction_t* insn, const std::vector<lsda_type_table_entry_t <ptrsize> > &type_table, const uint8_t& tt_encoding, const OffsetMap_t& om, libIRDB::FileIR_t* firp) const;
-};
-
-
-// short hand for a vector of call sites
-template <int ptrsize>  using call_site_table_t = std::vector<lsda_call_site_t <ptrsize> > ;
-
-template <int ptrsize>
-class lsda_t : private eh_frame_util_t<ptrsize>
-{
-	private:
-	uint8_t landing_pad_base_encoding;
-	uint64_t landing_pad_base_addr; // often ommitted. when ommitted, filled in from FDE region start.
-	uint8_t type_table_encoding;
-	uint64_t type_table_offset;
-	uint64_t type_table_addr;
-	uint8_t cs_table_encoding;
-	uint64_t cs_table_start_offset;
-	uint64_t cs_table_start_addr;
-	uint64_t cs_table_length;
-	uint64_t cs_table_end_addr;
-	uint64_t action_table_start_addr;
-	call_site_table_t <ptrsize>  call_site_table;
-	std::vector<lsda_type_table_entry_t <ptrsize> > type_table;
-
-	public:
-
-	uint8_t GetTTEncoding() const ;
-	
-	lsda_t() ;
-
-	bool parse_lsda(const uint64_t lsda_addr, const libIRDB::DataScoop_t* gcc_except_scoop, const uint64_t fde_region_start);
-	void print() const;
-	void build_ir(libIRDB::Instruction_t* insn, const OffsetMap_t& om, libIRDB::FileIR_t* firp) const;
-
-        const call_site_table_t<ptrsize> GetCallSites() const { return call_site_table;}
-
-};
-
-
-
-template <int ptrsize>
-class fde_contents_t : eh_frame_util_t<ptrsize>
-{
-	uint32_t fde_position;
-	uint32_t cie_position;
-	uint64_t length;
-	uint8_t id;
-	uint64_t fde_start_addr;
-	uint64_t fde_end_addr;
-	uint64_t fde_range_len;
-	uint64_t lsda_addr;
-
-
-	lsda_t<ptrsize> lsda;
-	eh_program_t<ptrsize> eh_pgm;
-	cie_contents_t<ptrsize> cie_info;
-
-	public:
-	fde_contents_t() ;
-	fde_contents_t(const uint64_t start_addr, const uint64_t end_addr)
-		: 
-		fde_start_addr(start_addr),
-		fde_end_addr(end_addr)
-	{} 
-
-	bool appliesTo(const libIRDB::Instruction_t* insn) const;
-
-	uint64_t GetFDEStartAddress() const { return fde_start_addr; } 
-	uint64_t GetFDEEndAddress() const {return fde_end_addr; }
-
-	const cie_contents_t<ptrsize>& GetCIE() const ;
-	cie_contents_t<ptrsize>& GetCIE() ;
-
-	const eh_program_t<ptrsize>& GetProgram() const ;
-	eh_program_t<ptrsize>& GetProgram() ;
-
-	const lsda_t<ptrsize>& GetLSDA() const { return lsda; }
-
-	bool parse_fde(
-		const uint32_t &fde_position, 
-		const uint32_t &cie_position, 
-		const uint8_t* const data, 
-		const uint64_t max, 
-		const uint64_t eh_addr,
-		const libIRDB::DataScoop_t* gcc_except_scoop);
-
-	void print() const;
-
-	void build_ir(libIRDB::Instruction_t* insn, const OffsetMap_t &om, libIRDB::FileIR_t* firp) const;
-
-};
-
-template <int ptrsize>
-bool operator<(const fde_contents_t<ptrsize>& a, const fde_contents_t<ptrsize>& b) { return a.GetFDEEndAddress()-1 < b.GetFDEStartAddress(); }
-
-
-class split_eh_frame_t 
-{
-	public:
-
-		virtual bool parse()=0;
-		virtual void build_ir() const =0;
-		virtual void print() const=0;
-		virtual libIRDB::Instruction_t* find_lp(libIRDB::Instruction_t*) const =0;
-
-		static std::unique_ptr<split_eh_frame_t> factory(libIRDB::FileIR_t *firp);
-
-};
-
-template <int ptrsize>
-class split_eh_frame_impl_t : public split_eh_frame_t
-{
-	private: 
-
-	libIRDB::FileIR_t* firp;
-	libIRDB::DataScoop_t* eh_frame_scoop;
-	libIRDB::DataScoop_t* eh_frame_hdr_scoop;
-	libIRDB::DataScoop_t* gcc_except_table_scoop;
-	OffsetMap_t offset_to_insn_map;
-	std::vector<cie_contents_t <ptrsize> > cies;
-	std::set<fde_contents_t <ptrsize> > fdes;
-
-
-	bool init_offset_map();
-
-	bool iterate_fdes();
-
-	public:
-
-	split_eh_frame_impl_t(libIRDB::FileIR_t* p_firp);
-
-	bool parse();
-
-	void print() const;
-
-	void build_ir() const;
-
-	libIRDB::Instruction_t* find_lp(libIRDB::Instruction_t*) const ;
-};
-
-void split_eh_frame(libIRDB::FileIR_t* firp);
-
-#endif
diff --git a/libIRDB/test/fill_in_cfg.cpp b/libIRDB/test/fill_in_cfg.cpp
index a1d33d216756fd44530fc2ced4008fd24d9404bc..e0719bcce5cd5f0a60ecaed62ec1fe1752715108 100644
--- a/libIRDB/test/fill_in_cfg.cpp
+++ b/libIRDB/test/fill_in_cfg.cpp
@@ -29,7 +29,7 @@
 #include <ctype.h>
 #include <exeio.h>
 #include "elfio/elfio.hpp"
-#include "eh_frame.hpp"
+#include "split_eh_frame.hpp"
 
 int odd_target_count=0;
 int bad_target_count=0;
@@ -554,24 +554,26 @@ void fill_in_scoops(FileIR_t *firp)
 void fill_in_landing_pads(FileIR_t *firp)
 {
 	const auto eh_frame_rep_ptr = split_eh_frame_t::factory(firp);
-	eh_frame_rep_ptr->parse();
+	// eh_frame_rep_ptr->parse(); already parsed now.
 	if(getenv("EHIR_VERBOSE"))
 		eh_frame_rep_ptr->print();
 	cout<<"Completed eh-frame parsing"<<endl;
 
 	map<Function_t*,set<Instruction_t*> > insns_to_add_to_funcs;
 
-	for_each(firp->GetInstructions().begin(), firp->GetInstructions().end(), [&](Instruction_t* t)
+	// for_each(firp->GetInstructions().begin(), firp->GetInstructions().end(), [&](Instruction_t* t)
+	for(const auto t : firp->GetInstructions())
 	{
 		if(t->GetFunction()==NULL)
-			return;
+			continue;
 		auto lp=eh_frame_rep_ptr->find_lp(t);
 		if(lp && lp->GetFunction()==NULL)
 			insns_to_add_to_funcs[t->GetFunction()].insert(lp);
-	});
+	};
 
 
-	for_each(insns_to_add_to_funcs.begin(), insns_to_add_to_funcs.end(), [&](pair<Function_t* const,set<Instruction_t*> > & p)
+	// for_each(insns_to_add_to_funcs.begin(), insns_to_add_to_funcs.end(), [&](pair<Function_t* const,set<Instruction_t*> > & p)
+	for(const auto & p : insns_to_add_to_funcs)
 	{
 		auto & func=p.first; 	
 		auto insns=p.second; 	/* copy */
@@ -603,7 +605,7 @@ void fill_in_landing_pads(FileIR_t *firp)
 			if(fallthru) insns.insert(fallthru);
 		}
 		cout<<"Found LP outside of function "<<func->GetName()<<" added "<<insn_count<<" instructions"<<endl;
-	});
+	};
 	
 }
 
diff --git a/libIRDB/test/split_eh_frame.cpp b/libIRDB/test/split_eh_frame.cpp
index 117895efbf7d199841600464ea2690fac4c550e0..093311272a830ddb8fcdfca0d2066070e11a591a 100644
--- a/libIRDB/test/split_eh_frame.cpp
+++ b/libIRDB/test/split_eh_frame.cpp
@@ -12,1254 +12,44 @@
 #include <memory>
 
 #include <exeio.h>
-#include "dwarf2.h"
 
-#include "eh_frame.hpp"
+#include "split_eh_frame.hpp"
+#include "ehp.hpp"
 
 using namespace std;
 using namespace EXEIO;
 using namespace libIRDB;
+using namespace EHP;
 
-#define WHOLE_CONTAINER(s) begin(s), end(s)
+#define ALLOF(s) begin(s), end(s)
 
 template <int ptrsize>
-template <class T> 
-bool eh_frame_util_t<ptrsize>::read_type(T &value, uint32_t &position, const uint8_t* const data, const uint32_t max)
-{
-	if(position + sizeof(T) > max) return true;
-
-	
-	// typecast to the right type
-	auto ptr=(const T*)&data[position];
-
-	// set output parameters
-	position+=sizeof(T);
-	value=*ptr;
-
-	return false;
-	
-}
-template <int ptrsize>
-template <class T> 
-bool eh_frame_util_t<ptrsize>::read_type_with_encoding
-	(const uint8_t encoding, T &value, 
-	uint32_t &position, 
-	const uint8_t* const data, 
-	const uint32_t max, 
-	const uint64_t section_start_addr )
-{
-	auto orig_position=position;
-	auto encoding_lower8=encoding&0xf;
-	auto encoding_upper8=encoding&0xf0;
-	value=0;
-	switch(encoding_lower8)
-	{
-		case DW_EH_PE_omit  :
-			return true;
-
-
-		case DW_EH_PE_uleb128:
-		{
-			auto newval=uint64_t(0);
-			if(eh_frame_util_t<ptrsize>::read_uleb128(newval,position,data,max))
-				return true;
-			value=newval;
-			break;
-		}
-		case DW_EH_PE_sleb128:
-		{
-			auto newval=int64_t(0);
-			if(eh_frame_util_t<ptrsize>::read_sleb128(newval,position,data,max))
-				return true;
-			value=newval;
-			break;
-		}
-		case DW_EH_PE_udata2 :
-		{
-			auto newval=uint16_t(0);
-			if(eh_frame_util_t<ptrsize>::read_type(newval,position,data,max))
-				return true;
-			value=newval;
-			break;
-		}
-		case DW_EH_PE_udata4 :
-		{
-			auto newval=uint32_t(0);
-			if(eh_frame_util_t<ptrsize>::read_type(newval,position,data,max))
-				return true;
-			value=newval;
-			break;
-		}
-		case DW_EH_PE_udata8 :
-		{
-			auto newval=uint64_t(0);
-			if(eh_frame_util_t<ptrsize>::read_type(newval,position,data,max))
-				return true;
-			value=newval;
-			break;
-		}
-		case DW_EH_PE_absptr:
-		{
-			if(ptrsize==8)
-			{
-				if(eh_frame_util_t<ptrsize>::read_type_with_encoding(DW_EH_PE_udata8, value, position, data, max, section_start_addr))
-					return true;
-				break;
-			}
-			else if(ptrsize==4)
-			{
-				if(eh_frame_util_t<ptrsize>::read_type_with_encoding(DW_EH_PE_udata4, value, position, data, max, section_start_addr))
-					return true;
-				break;
-			}
-			assert(0);
-				
-		}
-		case DW_EH_PE_sdata2 :
-		{
-			auto newval=int16_t(0);
-			if(eh_frame_util_t<ptrsize>::read_type(newval,position,data,max))
-				return true;
-			value=newval;
-			break;
-		}
-		case DW_EH_PE_sdata4 :
-		{
-			auto newval=int32_t(0);
-			if(eh_frame_util_t<ptrsize>::read_type(newval,position,data,max))
-				return true;
-			value=newval;
-			break;
-		}
-		case DW_EH_PE_sdata8 :
-		{
-			auto newval=int64_t(0);
-			if(read_type(newval,position,data,max))
-				return true;
-			value=newval;
-			break;
-		}
-
-		case DW_EH_PE_signed :
-		default:
-			assert(0);
-	};
-
-	switch(encoding_upper8)
-	{
-		case DW_EH_PE_absptr:
-			break; 
-		case DW_EH_PE_pcrel  :
-			value+=section_start_addr+orig_position;
-			break;
-		case DW_EH_PE_textrel:
-		case DW_EH_PE_datarel:
-		case DW_EH_PE_funcrel:
-		case DW_EH_PE_aligned:
-		case DW_EH_PE_indirect:
-		default:
-			assert(0);
-			return true;
-	}
-	return false;
-}
-
-template <int ptrsize>
-bool eh_frame_util_t<ptrsize>::read_string 
-	(string &s, 
-	uint32_t & position, 
-	const uint8_t* const data, 
-	const uint32_t max)
-{
-	while(data[position]!='\0' && position < max)
-	{
-		s+=data[position];	
-		position++;
-	}
-
-	position++;
-	return (position>max);
-}
-
-
-// see https://en.wikipedia.org/wiki/LEB128
-template <int ptrsize>
-bool eh_frame_util_t<ptrsize>::read_uleb128 
-	( uint64_t &result, 
-	uint32_t& position, 
-	const uint8_t* const data, 
-	const uint32_t max)
-{
-	result = 0;
-	auto shift = 0;
-	while( position < max )
-	{
-		auto byte = data[position];
-		position++;
-		result |= ( ( byte & 0x7f ) << shift);
-		if ( ( byte & 0x80) == 0)
-			break;
-		shift += 7;
-	}
-	return ( position > max );
-
-}
-// see https://en.wikipedia.org/wiki/LEB128
-template <int ptrsize>
-bool eh_frame_util_t<ptrsize>::read_sleb128 ( 
-	int64_t &result, 
-	uint32_t & position, 
-	const uint8_t* const data, 
-	const uint32_t max)
-{
-	result = 0;
-	auto shift = 0;
-	auto size = 64;  // number of bits in signed integer;
-	auto byte=uint8_t(0);
-	do
-	{
-		byte = data [position]; 
-		position++;
-		result |= ((byte & 0x7f)<< shift);
-		shift += 7;
-	} while( (byte & 0x80) != 0);
-
-	/* sign bit of byte is second high order bit (0x40) */
-	if ((shift < size) && ( (byte & 0x40) !=0 /* sign bit of byte is set */))
-		/* sign extend */
-		result |= - (1 << shift);
-	return ( position > max );
-
-}
-
-template <int ptrsize>
-bool eh_frame_util_t<ptrsize>::read_length(
-	uint64_t &act_length, 
-	uint32_t &position, 
-	const uint8_t* const data, 
-	const uint32_t max)
-{
-	auto eh_frame_scoop_data=data;
-	auto length=uint32_t(0);
-	auto length_64bit=uint64_t(0);
-	if(read_type(length,position, eh_frame_scoop_data, max))
-		return true;
-
-	if(length==0xffffffff)
-	{
-		if(read_type(length_64bit,position, eh_frame_scoop_data, max))
-			return true;
-		act_length=length_64bit;
-	}
-	else
-		act_length=length;
-
-	return false;
-}
-
-template <int ptrsize>
-eh_program_insn_t<ptrsize>::eh_program_insn_t() { }
-
-template <int ptrsize>
-eh_program_insn_t<ptrsize>::eh_program_insn_t(const string &s) 
-	: program_bytes(s.begin(), next(s.begin(), s.size()))
-{ }
-
-template <int ptrsize>
-void eh_program_insn_t<ptrsize>::print(uint64_t &pc, int64_t caf) 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");
-
-	auto data=program_bytes;
-	auto opcode=program_bytes[0];
-	auto opcode_upper2=(uint8_t)(opcode >> 6);
-	auto opcode_lower6=(uint8_t)(opcode & (0x3f));
-	auto pos=uint32_t(1);
-	auto max=program_bytes.size();
-
-	switch(opcode_upper2)
-	{
-		case 1:
-		{
-			// case DW_CFA_advance_loc:
-			pc+=(opcode_lower6*caf);
-			cout<<"				cfa_advance_loc "<<dec<<+opcode_lower6<<" to "<<hex<<pc<<endl;
-			break;
-		}
-		case 2:
-		{
-			uint64_t uleb=0;
-			if(eh_frame_util_t<ptrsize>::read_uleb128(uleb, pos, (const uint8_t* const)data.data(), max))
-				return;
-			// case DW_CFA_offset:
-			cout<<"				cfa_offset "<<dec<<uleb<<endl;
-			break;
-		}
-		case 3:
-		{
-			// case DW_CFA_restore (register #):
-			cout<<"				cfa_restore"<<endl;
-			break;
-		}
-		case 0:
-		{
-			switch(opcode_lower6)
-			{
-			
-				case DW_CFA_nop:
-					cout<<"				nop" <<endl;
-					break;
-				case DW_CFA_remember_state:
-					cout<<"				remember_state" <<endl;
-					break;
-				case DW_CFA_restore_state:
-					cout<<"				restore_state" <<endl;
-					break;
-
-				// takes single uleb128
-				case DW_CFA_undefined:
-					cout<<"				undefined" ;
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max); 
-					cout<<endl;
-					break;
-		
-				case DW_CFA_same_value:
-					cout<<"				same_value ";
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max); 
-					cout<<endl;
-					break;
-				case DW_CFA_restore_extended:
-					cout<<"				restore_extended ";
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max); 
-					cout<<endl;
-					break;
-				case DW_CFA_def_cfa_register:
-					cout<<"				def_cfa_register ";
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max); 
-					cout<<endl;
-					break;
-				case DW_CFA_GNU_args_size:
-					cout<<"				GNU_arg_size ";
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max); 
-					cout<<endl;
-					break;
-				case DW_CFA_def_cfa_offset:
-					cout<<"				def_cfa_offset "; 
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max); 
-					cout<<endl;
-					break;
-
-				case DW_CFA_set_loc:
-				{
-					auto arg=uintptr_t(0xDEADBEEF);
-					switch(ptrsize)
-					{
-						case 4:
-							arg=*(uint32_t*)&data.data()[pos]; break;
-						case 8:
-							arg=*(uint64_t*)&data.data()[pos]; break;
-					}
-					cout<<"				set_loc "<<hex<<arg<<endl;
-					break;
-				}
-				case DW_CFA_advance_loc1:
-				{
-					auto loc=*(uint8_t*)(&data.data()[pos]);
-					pc+=(loc*caf);
-					cout<<"				advance_loc1 "<<+loc<<" to " <<pc << endl;
-					break;
-				}
-
-				case DW_CFA_advance_loc2:
-				{
-					auto loc=*(uint16_t*)(&data.data()[pos]);
-					pc+=(loc*caf);
-					cout<<"				advance_loc2 "<<+loc<<" to " <<pc << endl;
-					break;
-				}
-
-				case DW_CFA_advance_loc4:
-				{
-					auto loc=*(uint32_t*)(&data.data()[pos]);
-					pc+=(loc*caf);
-					cout<<"				advance_loc4 "<<+loc<<" to " <<pc << endl;
-					break;
-				}
-				case DW_CFA_offset_extended:
-					cout<<"				offset_extended ";
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max);
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max);
-					cout<<endl;
-					break;
-				case DW_CFA_register:
-					cout<<"				register ";
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max);
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max);
-					cout<<endl;
-					break;
-				case DW_CFA_def_cfa:
-					cout<<"				def_cfa ";
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max);
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max);
-					cout<<endl;
-					break;
-				case DW_CFA_def_cfa_sf:
-					cout<<"				def_cfa_sf ";
-					print_uleb_operand(pos,(const uint8_t* const)data.data(),max);
-					print_sleb_operand(pos,(const uint8_t* const)data.data(),max);
-					cout<<endl;
-					break;
-
-				case DW_CFA_def_cfa_expression:
-				{
-					auto uleb=uint64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb, pos, (const uint8_t* const)data.data(), max))
-						return ;
-					cout<<"				def_cfa_expression "<<dec<<uleb<<endl;
-					pos+=uleb;		// doing this old school for now, as we aren't printing the expression.
-					break;
-				}
-				case DW_CFA_expression:
-				{
-					auto uleb1=uint64_t(0);
-					auto uleb2=uint64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, (const uint8_t* const)data.data(), max))
-						return ;
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb2, pos, (const uint8_t* const)data.data(), max))
-						return ;
-					cout<<"                              expression "<<dec<<uleb1<<" "<<uleb2<<endl;
-					pos+=uleb2;
-					break;
-				}
-				case DW_CFA_val_expression:
-				{
-					auto uleb1=uint64_t(0);
-					auto uleb2=uint64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, (const uint8_t* const)data.data(), max))
-						return ;
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb2, pos, (const uint8_t* const)data.data(), max))
-						return ;
-					cout<<"                              val_expression "<<dec<<uleb1<<" "<<uleb2<<endl;
-					pos+=uleb2;
-					break;
-				}
-				case DW_CFA_def_cfa_offset_sf:
-				{
-					auto leb=int64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_sleb128(leb, pos, (const uint8_t* const)data.data(), max))
-						return ;
-					cout<<"					def_cfa_offset_sf "<<dec<<leb;
-					break;
-				}
-				case DW_CFA_offset_extended_sf:
-				{
-					auto uleb1=uint64_t(0);
-					auto sleb2=int64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, (const uint8_t* const)data.data(), max))
-						return ;
-					if(eh_frame_util_t<ptrsize>::read_sleb128(sleb2, pos, (const uint8_t* const)data.data(), max))
-						return ;
-					cout<<"                              offset_extended_sf "<<dec<<uleb1<<" "<<sleb2<<endl;
-					break;
-				}
-
-
-				/* SGI/MIPS specific */
-				case DW_CFA_MIPS_advance_loc8:
-
-				/* GNU extensions */
-				case DW_CFA_GNU_window_save:
-				case DW_CFA_GNU_negative_offset_extended:
-				default:
-					cout<<"Unhandled opcode cannot print. opcode="<<opcode<<endl;
-			}
-			break;
-		}
-	}
-
-}
-
-template <int ptrsize>
-void eh_program_insn_t<ptrsize>::push_byte(uint8_t c) { program_bytes.push_back(c); }
-
-template <int ptrsize>
-void eh_program_insn_t<ptrsize>::print_uleb_operand(
-	uint32_t pos, 
-	const uint8_t* const data, 
-	const uint32_t max) 
-{
-	auto uleb=uint64_t(0xdeadbeef);
-	eh_frame_util_t<ptrsize>::read_uleb128(uleb, pos, data, max);
-	cout<<" "<<dec<<uleb;
-}
-
-template <int ptrsize>
-void eh_program_insn_t<ptrsize>::print_sleb_operand(
-	uint32_t pos, 
-	const uint8_t* const data, 
-	const uint32_t max) 
-{
-	auto leb=int64_t(0xdeadbeef);
-	eh_frame_util_t<ptrsize>::read_sleb128(leb, pos, data, max);
-	cout<<" "<<dec<<leb;
-}
-
-template <int ptrsize>
-bool eh_program_insn_t<ptrsize>::parse_insn(
-	uint8_t opcode, 
-	uint32_t& pos, 
-	const uint8_t* const data, 
-	const uint32_t &max)
-{
-	auto &eh_insn = *this;
-	auto insn_start=pos-1;
-	auto opcode_upper2=(uint8_t)(opcode >> 6);
-	auto opcode_lower6=(uint8_t)(opcode & (0x3f));
-
-	// calculate the end of the instruction, which is inherently per-opcode
-	switch(opcode_upper2)
-	{
-		case 1:
-		{
-			// case DW_CFA_advance_loc:
-			break;
-		}
-		case 2:
-		{
-			auto uleb=uint64_t(0);
-			if(eh_frame_util_t<ptrsize>::read_uleb128(uleb, pos, data, max))
-				return true;
-			// case DW_CFA_offset:
-			break;
-		}
-		case 3:
-		{
-			// case DW_CFA_offset:
-			break;
-		}
-		case 0:
-		{
-			switch(opcode_lower6)
-			{
-			
-				case DW_CFA_nop:
-				case DW_CFA_remember_state:
-				case DW_CFA_restore_state:
-					break;
-
-				// takes single uleb128
-				case DW_CFA_undefined:
-				case DW_CFA_same_value:
-				case DW_CFA_restore_extended:
-				case DW_CFA_def_cfa_register:
-				case DW_CFA_GNU_args_size:
-				case DW_CFA_def_cfa_offset:
-				{
-					auto uleb=uint64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb, pos, data, max))
-						return true;
-					break;
-				}
-
-				case DW_CFA_set_loc:
-					pos+=ptrsize;
-					break;
-
-				case DW_CFA_advance_loc1:
-					pos+=1;
-					break;
-
-				case DW_CFA_advance_loc2:
-					pos+=2;
-					break;
-
-				case DW_CFA_advance_loc4:
-					pos+=4;
-					break;
-
-				case DW_CFA_offset_extended:
-				case DW_CFA_register:
-				case DW_CFA_def_cfa:
-				{
-					auto uleb1=uint64_t(1);
-					auto uleb2=uint64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, data, max))
-						return true;
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb2, pos, data, max))
-						return true;
-					break;
-				}
-				case DW_CFA_def_cfa_sf:
-				{
-					auto leb1=uint64_t(0);
-					auto leb2=int64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(leb1, pos, data, max))
-						return true;
-					if(eh_frame_util_t<ptrsize>::read_sleb128(leb2, pos, data, max))
-						return true;
-					break;
-				}
-
-				case DW_CFA_def_cfa_expression:
-				{
-					auto uleb=uint64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb, pos, data, max))
-						return true;
-					pos+=uleb;	
-					break;
-				}
-				case DW_CFA_expression:
-				case DW_CFA_val_expression:
-				{
-					auto uleb1=uint64_t(0);
-					auto uleb2=uint64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, data, max))
-						return true;
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb2, pos, data, max))
-						return true;
-					pos+=uleb2;
-					break;
-				}
-				case DW_CFA_def_cfa_offset_sf:
-				{
-					auto leb=int64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_sleb128(leb, pos, data, max))
-						return true;
-					break;
-				}
-				case DW_CFA_offset_extended_sf:
-				{
-					auto uleb1=uint64_t(0);
-					auto sleb2=int64_t(0);
-					if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, data, max))
-						return true;
-					if(eh_frame_util_t<ptrsize>::read_sleb128(sleb2, pos, data, max))
-						return true;
-					break;
-				}
-				/* Dwarf 2.1 */
-				case DW_CFA_val_offset:
-				case DW_CFA_val_offset_sf:
-
-
-				/* SGI/MIPS specific */
-				case DW_CFA_MIPS_advance_loc8:
-
-				/* GNU extensions */
-				case DW_CFA_GNU_window_save:
-				case DW_CFA_GNU_negative_offset_extended:
-				default:
-					// Unhandled opcode cannot xform this eh-frame
-					cout<<"No decoder for opcode "<<+opcode<<endl;
-					return true;
-			}
-			break;
-		}
-		default:
-			cout<<"No decoder for opcode "<<+opcode<<endl;
-			return true;
-	}
-
-	// insert bytes into the instruction.
-	auto insn_end=pos;
-	for_each( &data[insn_start], &data[insn_end], [&](const uint8_t c)
-	{
-		eh_insn.push_byte(c);
-	});
-	return false;
-}
-
-template <int ptrsize>
-bool eh_program_insn_t<ptrsize>::isNop() const 
-{
-	const auto opcode=program_bytes[0];
-	const auto opcode_upper2=(uint8_t)(opcode >> 6);
-	const auto opcode_lower6=(uint8_t)(opcode & (0x3f));
-	switch(opcode_upper2)
-	{
-		case 0:
-		{
-			switch(opcode_lower6)
-			{
-			
-				case DW_CFA_nop:
-					return true;
-			}
-		}
-	}
-	return false;
-}
-
-template <int ptrsize>
-bool eh_program_insn_t<ptrsize>::isRestoreState() const 
-{
-	const auto opcode=program_bytes[0];
-	const auto opcode_upper2=(uint8_t)(opcode >> 6);
-	const auto opcode_lower6=(uint8_t)(opcode & (0x3f));
-	switch(opcode_upper2)
-	{
-		case 0:
-		{
-			switch(opcode_lower6)
-			{
-				case DW_CFA_restore_state:
-					return true;	
-			}
-		}
-	}
-	return false;
-}
-
-template <int ptrsize>
-bool eh_program_insn_t<ptrsize>::isRememberState() const 
-{
-	const auto opcode=program_bytes[0];
-	const auto opcode_upper2=(uint8_t)(opcode >> 6);
-	const auto opcode_lower6=(uint8_t)(opcode & (0x3f));
-	switch(opcode_upper2)
-	{
-		case 0:
-		{
-			switch(opcode_lower6)
-			{
-				case DW_CFA_remember_state:
-					return true;	
-			}
-		}
-	}
-	return false;
-}
-
-template <int ptrsize>
-bool eh_program_insn_t<ptrsize>::Advance(uint64_t &cur_addr, uint64_t CAF) 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");
-
-	auto data=program_bytes;
-	auto opcode=program_bytes[0];
-	auto opcode_upper2=(uint8_t)(opcode >> 6);
-	auto opcode_lower6=(uint8_t)(opcode & (0x3f));
-	auto pos=uint32_t(1);
-	//auto max=program_bytes.size();
-
-	switch(opcode_upper2)
-	{
-		case 1:
-		{
-			// case DW_CFA_advance_loc:
-			cur_addr+=(opcode_lower6*CAF);
-			return true;
-		}
-		case 0:
-		{
-			switch(opcode_lower6)
-			{
-				case DW_CFA_set_loc:
-				{
-					assert(0);
-					return true;
-				}
-				case DW_CFA_advance_loc1:
-				{
-					auto loc=*(uint8_t*)(&data.data()[pos]);
-					cur_addr+=(loc*CAF);
-					return true;
-				}
-
-				case DW_CFA_advance_loc2:
-				{
-					auto loc=*(uint16_t*)(&data.data()[pos]);
-					cur_addr+=(loc*CAF);
-					return true;
-				}
-
-				case DW_CFA_advance_loc4:
-				{
-					auto loc=*(uint32_t*)(&data.data()[pos]);
-					cur_addr+=(loc*CAF);
-					return true;
-				}
-			}
-		}
-	}
-	return false;
-}
-
-template <int ptrsize>
-const vector<uint8_t>& eh_program_insn_t<ptrsize>::GetBytes() const { return program_bytes; }
-
-template <int ptrsize>
-vector<uint8_t>& eh_program_insn_t<ptrsize>::GetBytes() { return program_bytes; }
-
-
-
-
-
-
-template <int ptrsize>
-bool operator<(const eh_program_insn_t<ptrsize>& a, const eh_program_insn_t<ptrsize>& b)
-{
-	return a.GetBytes() < b.GetBytes(); 
-}
-
-template <int ptrsize>
-void eh_program_t<ptrsize>::push_insn(const eh_program_insn_t<ptrsize> &i) { instructions.push_back(i); }
-
-template <int ptrsize>
-void eh_program_t<ptrsize>::print(const uint64_t start_addr) const
-{
-	auto pc=start_addr;
-	cout << "			Program:                  " << endl ;
-	for_each(instructions.begin(), instructions.end(), [&](const eh_program_insn_t<ptrsize>& i)
-	{ 
-		i.print(pc);
-	});
-}
-
-template <int ptrsize>
-bool eh_program_t<ptrsize>::parse_program(
-	const uint32_t& program_start_position, 
-	const uint8_t* const data, 
-	const uint32_t &max_program_pos)
-{
-	eh_program_t &eh_pgm=*this;
-	auto max=max_program_pos;
-	auto pos=program_start_position;
-	while(pos < max_program_pos)
-	{
-		auto opcode=uint8_t(0);
-		if(eh_frame_util_t<ptrsize>::read_type(opcode,pos,data,max))
-			return true;
-		eh_program_insn_t<ptrsize> eh_insn;
-		if(eh_insn.parse_insn(opcode,pos,data,max))
-			return true;
-
-		eh_pgm.push_insn(eh_insn);
-
-	
-	}
-
-	return false;
-}
-
-template <int ptrsize>
-const vector<eh_program_insn_t <ptrsize> >& eh_program_t<ptrsize>::GetInstructions() const { return instructions; }
-
-template <int ptrsize>
-vector<eh_program_insn_t <ptrsize> >& eh_program_t<ptrsize>::GetInstructions() { return instructions; }
-
-template <int ptrsize>
-bool operator<(const eh_program_t<ptrsize>& a, const eh_program_t<ptrsize>& b)
-{
-	return a.GetInstructions() < b.GetInstructions(); 
-}
-
-template <int ptrsize>
-cie_contents_t<ptrsize>::cie_contents_t() :
-	cie_position(0),
-	length(0),
-	cie_id(0),
-	cie_version(0),
-	code_alignment_factor(0),
-	data_alignment_factor(0),
-	return_address_register_column(0),
-	augmentation_data_length(0),
-	personality_encoding(0),
-	personality(0),
-	lsda_encoding(0),
-	fde_encoding(0)
-{}
-
-
-template <int ptrsize>
-const eh_program_t<ptrsize>& cie_contents_t<ptrsize>::GetProgram() const { return eh_pgm; }
-
-template <int ptrsize>
-uint64_t cie_contents_t<ptrsize>::GetCAF() const { return code_alignment_factor; }
-
-template <int ptrsize>
-int64_t cie_contents_t<ptrsize>::GetDAF() const { return data_alignment_factor; }
-
-template <int ptrsize>
-uint64_t cie_contents_t<ptrsize>::GetPersonality() const { return personality; }
-
-template <int ptrsize>
-uint64_t cie_contents_t<ptrsize>::GetReturnRegister() const { return return_address_register_column; }
-
-
-template <int ptrsize>
-string cie_contents_t<ptrsize>::GetAugmentation() const { return augmentation; }
-
-template <int ptrsize>
-uint8_t cie_contents_t<ptrsize>::GetLSDAEncoding() const { return lsda_encoding;}
-
-template <int ptrsize>
-uint8_t cie_contents_t<ptrsize>::GetFDEEncoding() const { return fde_encoding;}
-
-
-template <int ptrsize>
-bool cie_contents_t<ptrsize>::parse_cie(
-	const uint32_t &cie_position, 
-	const uint8_t* const data, 
-	const uint32_t max, 
-	const uint64_t eh_addr)
-{
-	auto &c=*this;
-	const auto eh_frame_scoop_data= data;
-	auto position=cie_position;
-	auto length= uint64_t(0);
-
-	if(this->read_length(length, position, eh_frame_scoop_data, max))
-		return true;
-
-	auto end_pos=position+length;
-
-	auto cie_id=uint32_t(0);
-	if(this->read_type(cie_id, position, eh_frame_scoop_data, max))
-		return true;
-
-	auto cie_version=uint8_t(0);
-	if(this->read_type(cie_version, position, eh_frame_scoop_data, max))
-		return true;
-
-	if(cie_version==1) 
-	{ } // OK
-	else if(cie_version==3) 
-	{ } // OK
-	else
-	    // Err.
-		return true;	
-
-	auto augmentation=string();
-	if(this->read_string(augmentation, position, eh_frame_scoop_data, max))
-		return true;
-
-	auto code_alignment_factor=uint64_t(0);
-	if(this->read_uleb128(code_alignment_factor, position, eh_frame_scoop_data, max))
-		return true;
-	
-	auto data_alignment_factor=int64_t(0);
-	if(this->read_sleb128(data_alignment_factor, position, eh_frame_scoop_data, max))
-		return true;
-
-	// type depends on version info.  can always promote to 64 bits.
-	auto return_address_register_column=uint64_t(0);
-	if(cie_version==1)
-	{
-		auto return_address_register_column_8=uint8_t(0);
-		if(this->read_type(return_address_register_column_8, position, eh_frame_scoop_data, max))
-			return true;
-		return_address_register_column=return_address_register_column_8;
-	}
-	else if(cie_version==3)
-	{
-		auto return_address_register_column_64=uint64_t(0);
-		if(this->read_uleb128(return_address_register_column_64, position, eh_frame_scoop_data, max))
-			return true;
-		return_address_register_column=return_address_register_column_64;
-	}
-	else
-		assert(0);
-
-	auto augmentation_data_length=uint64_t(0);
-	if(augmentation.find("z") != string::npos)
-	{
-		if(this->read_uleb128(augmentation_data_length, position, eh_frame_scoop_data, max))
-			return true;
-	}
-	auto personality_encoding=uint8_t(DW_EH_PE_omit);
-	auto personality=uint64_t(0);
-	if(augmentation.find("P") != string::npos)
-	{
-		if(this->read_type(personality_encoding, position, eh_frame_scoop_data, max))
-			return true;
-
-		// indirect is OK as a personality encoding, but we don't need to go that far.
-		// we just need to record what's in the CIE, regardless of whether it's the actual
-		// personality routine or it's the pointer to the personality routine.
-		auto personality_encoding_sans_indirect = personality_encoding&(~DW_EH_PE_indirect);
-		if(this->read_type_with_encoding(personality_encoding_sans_indirect, personality, position, eh_frame_scoop_data, max, eh_addr))
-			return true;
-	}
-
-	auto lsda_encoding=uint8_t(DW_EH_PE_omit);
-	if(augmentation.find("L") != string::npos)
-	{
-		if(this->read_type(lsda_encoding, position, eh_frame_scoop_data, max))
-			return true;
-	}
-	auto fde_encoding=uint8_t(DW_EH_PE_omit);
-	if(augmentation.find("R") != string::npos)
-	{
-		if(this->read_type(fde_encoding, position, eh_frame_scoop_data, max))
-			return true;
-	}
-	if(eh_pgm.parse_program(position, eh_frame_scoop_data, end_pos))
-		return true;
-
-
-	c.cie_position=cie_position;
-	c.cie_id=cie_id;
-	c.cie_version=cie_version;
-	c.augmentation=augmentation;
-	c.code_alignment_factor=code_alignment_factor;
-	c.data_alignment_factor=data_alignment_factor;
-	c.return_address_register_column=return_address_register_column;
-	c.augmentation_data_length=augmentation_data_length;
-	c.personality_encoding=personality_encoding;
-	c.personality=personality;
-	c.lsda_encoding=lsda_encoding;
-	c.fde_encoding=fde_encoding;
-
-	// all OK
-	return false;
-}
-
-template <int ptrsize>
-void cie_contents_t<ptrsize>::print() const 
-{
-	cout << "["<<setw(6)<<hex<<cie_position<<"] CIE length="<<dec<<length<<endl;
-	cout << "   CIE_id:                   " << +cie_id << endl;
-	cout << "   version:                  " << +cie_version << endl;
-	cout << "   augmentation:             \"" << augmentation << "\"" << endl;
-	cout << "   code_alignment_factor:    " << code_alignment_factor << endl;
-	cout << "   data_alignment_factor:    " << dec << data_alignment_factor << endl;
-	cout << "   return_address_register:  " << dec << return_address_register_column << endl;
-	cout << "   Augmentation data:        " << endl ;
-	cout << "                             aug data len:         " << hex << +augmentation_data_length << endl;
-	cout << "                             personality_encoding: " << hex << +personality_encoding << endl;
-	cout << "                             personality:          " << hex << +personality << endl;
-	cout << "                             lsda_encoding:        " << hex << +lsda_encoding << endl;
-	cout << "                             fde_encoding:         " << hex << +fde_encoding << endl;
-	cout << "   Program:        " << endl ;
-	eh_pgm.print();
-	
-}
-
-template <int ptrsize>
-void cie_contents_t<ptrsize>::build_ir(Instruction_t* insn) const
-{
-	// nothing to do?  built up one level.
-	//eh_pgm.print();
-}
-
-template <int ptrsize>
-lsda_call_site_action_t<ptrsize>::lsda_call_site_action_t() :
-	action(0)
-{}
-
-
-template <int ptrsize>
-int64_t lsda_call_site_action_t<ptrsize>::GetAction() const { return action;}
-
-
-template <int ptrsize>
-bool lsda_call_site_action_t<ptrsize>::parse_lcsa(uint32_t& pos, const uint8_t* const data, const uint64_t max, bool &end)
-{
-	end=false;
-	if(this->read_sleb128(action, pos, data, max))
-		return true;
-
-	auto next_action=pos;
-	auto next_pos_offset=int64_t(0);
-	if(this->read_sleb128(next_pos_offset, pos, data, max))
-		return true;
-
-	if(next_pos_offset==0)
-		end=true;
-	else
-		pos=next_action+next_pos_offset;
-	return false;
-}
-
-template <int ptrsize>
-void lsda_call_site_action_t<ptrsize>::print() const
-{
-	cout<<"					"<<action<<endl;
-}
-
-template <int ptrsize>
-bool operator< (const lsda_call_site_action_t <ptrsize> &lhs, const lsda_call_site_action_t <ptrsize> &rhs)
-{ 	
-	return lhs.GetAction() < rhs.GetAction(); 
-}
-
-template <int ptrsize>
-lsda_type_table_entry_t<ptrsize>::lsda_type_table_entry_t() : 
-	pointer_to_typeinfo(0), tt_encoding(0)
-{}
-
-
-template <int ptrsize>
-uint64_t lsda_type_table_entry_t<ptrsize>::GetTypeInfoPointer() const { return pointer_to_typeinfo; }
-
-template <int ptrsize>
-uint64_t lsda_type_table_entry_t<ptrsize>::GetEncoding() const { return tt_encoding; }
-
-template <int ptrsize>
-uint64_t lsda_type_table_entry_t<ptrsize>::GetTTEncodingSize() const { return tt_encoding_size; }
-
-
-template <int ptrsize>
-bool lsda_type_table_entry_t<ptrsize>::parse(
-	const uint64_t p_tt_encoding, 	
-	const uint64_t tt_pos, 	
-	const uint64_t index,
-	const uint8_t* const data, 
-	const uint64_t max,  
-	const uint64_t data_addr
-	)
-{
-	tt_encoding=p_tt_encoding;
-	const auto tt_encoding_sans_indirect = tt_encoding&(~DW_EH_PE_indirect);
-	const auto tt_encoding_sans_indir_sans_pcrel = tt_encoding_sans_indirect & (~DW_EH_PE_pcrel);
-	const auto has_pcrel = (tt_encoding & DW_EH_PE_pcrel) == DW_EH_PE_pcrel;
-	switch(tt_encoding & 0xf) // get just the size field
-	{
-		case DW_EH_PE_udata4:
-		case DW_EH_PE_sdata4:
-			tt_encoding_size=4;
-			break;
-		default:
-			assert(0);
-	}
-	const auto orig_act_pos=uint32_t(tt_pos+(-index*tt_encoding_size));
-	auto act_pos=uint32_t(tt_pos+(-index*tt_encoding_size));
-	if(this->read_type_with_encoding(tt_encoding_sans_indir_sans_pcrel, pointer_to_typeinfo, act_pos, data, max, data_addr))
-		return true;
-
-	// check if there's a 0 in the field
-	if(pointer_to_typeinfo != 0 && has_pcrel)
-		pointer_to_typeinfo += orig_act_pos + data_addr;
-
-	return false;
-}
-
-
-template <int ptrsize>
-void lsda_type_table_entry_t<ptrsize>::print() const
-{
-	cout<<"				pointer_to_typeinfo: 0x"<<hex<<pointer_to_typeinfo<<endl;
-}
-
-
-
-
-template <int ptrsize>
-lsda_call_site_t<ptrsize>::lsda_call_site_t() :
-	call_site_offset(0),
-	call_site_addr(0),
-	call_site_length(0),
-	call_site_end_addr(0),
-	landing_pad_offset(0),
-	landing_pad_addr(0),
-	action(0),
-	action_table_offset(0),
-	action_table_addr(0)
-{}
-
-
-
-template <int ptrsize>
-bool lsda_call_site_t<ptrsize>::parse_lcs(	
-	const uint64_t action_table_start_addr, 	
-	const uint64_t cs_table_start_addr, 	
-	const uint8_t cs_table_encoding, 
-	uint32_t &pos, 
-	const uint8_t* const data, 
-	const uint64_t max,  /* call site table max */
-	const uint64_t data_addr, 
-	const uint64_t landing_pad_base_addr,
-	const uint64_t gcc_except_table_max)
-{
-	
-	if(this->read_type_with_encoding(cs_table_encoding, call_site_offset, pos, data, max, data_addr))
-		return true;
-	call_site_addr=landing_pad_base_addr+call_site_offset;
-	if(this->read_type_with_encoding(cs_table_encoding, call_site_length, pos, data, max, data_addr))
-		return true;
-	call_site_end_addr=call_site_addr+call_site_length;
-	if(this->read_type_with_encoding(cs_table_encoding, landing_pad_offset, pos, data, max, data_addr))
-		return true;
-
-	// calc the actual addr.
-	if(landing_pad_offset == 0)
-		landing_pad_addr=0;
-	else
-		landing_pad_addr=landing_pad_base_addr+landing_pad_offset;
-
-	if(this->read_uleb128(action, pos, data, max))
-		return true;
-
-	if(action == 0)
-	{ /* no action table -- means no cleanup is needed, just unwinding. */ }
-	else if( action > 0 )
-	{
-		action_table_offset=action-1;
-		action_table_addr=action_table_start_addr+action-1;
-
-		// parse action tables
-		bool end=false;
-		auto act_table_pos=uint32_t(action_table_addr-data_addr);
-		while(!end)
-		{
-			lsda_call_site_action_t<ptrsize> lcsa;
-			if(lcsa.parse_lcsa(act_table_pos, data, gcc_except_table_max, end))
-				return true;
-			action_table.push_back(lcsa);
-			
-		}
-	}
-	else if( action < 0 )
-	{
-		assert(0); // how can the index into the action table be negative?
-	}
-	else
-	{
-		assert(0); // how is this possible?
-	}
-
-	return false;
-}
-
-
-template <int ptrsize>
-void lsda_call_site_t<ptrsize>::print() const
-{
-	cout<<"				CS Offset        : 0x"<<hex<<call_site_offset<<endl;
-	cout<<"				CS len           : 0x"<<hex<<call_site_length<<endl;
-	cout<<"				landing pad off. : 0x"<<hex<<landing_pad_offset<<endl;
-	cout<<"				action (1+addr)  : 0x"<<hex<<action<<endl;
-	cout<<"				---interpreted---"<<endl;
-	cout<<"				CS Addr          : 0x"<<hex<<call_site_addr<<endl;
-	cout<<"				CS End Addr      : 0x"<<hex<<call_site_end_addr<<endl;
-	cout<<"				landing pad addr : 0x"<<hex<<landing_pad_addr<<endl;
-	cout<<"				act-tab off      : 0x"<<hex<<action_table_offset<<endl;
-	cout<<"				act-tab addr     : 0x"<<hex<<action_table_addr<<endl;
-	cout<<"				act-tab 	 : "<<endl;
-	for_each(action_table.begin(), action_table.end(), [&](const lsda_call_site_action_t<ptrsize>& p)
-	{
-		p.print();
-	});
-}
-
-
-template <int ptrsize>
-bool lsda_call_site_t<ptrsize>::appliesTo(const Instruction_t* insn) const
+bool split_eh_frame_impl_t<ptrsize>::lsda_call_site_appliesTo(const LSDACallSite_t& cs, const Instruction_t* insn)  const
 {
 	assert(insn && insn->GetAddress());
 	auto insn_addr=insn->GetAddress()->GetVirtualOffset();
 
+	const auto call_site_addr=cs.getCallSiteAddress();
+	const auto call_site_end_addr=cs.getCallSiteEndAddress();
+
 	return ( call_site_addr <=insn_addr && insn_addr<call_site_end_addr );
 }
 
-
 template <int ptrsize>
-void lsda_call_site_t<ptrsize>::build_ir(Instruction_t* insn, const vector<lsda_type_table_entry_t <ptrsize> > &type_table, const uint8_t& tt_encoding, const OffsetMap_t& om, FileIR_t* firp) const
+void split_eh_frame_impl_t<ptrsize>::lsda_call_site_build_ir
+	(
+	    const LSDACallSite_t& cs,
+	    Instruction_t* insn, 
+	    const /*vector<lsda_type_table_entry_t <ptrsize> > &*/ std::shared_ptr<EHP::TypeTableVector_t> type_table_ptr, 
+	    const uint8_t& tt_encoding
+	) const
 {
-	assert(appliesTo(insn));
+	const auto &type_table=*type_table_ptr;
+	const auto &om=offset_to_insn_map;
+	const auto landing_pad_addr=cs.getLandingPadAddress();
+	const auto action_table_ptr=cs.getActionTable();
+	const auto &action_table=*action_table_ptr;
+	assert(lsda_call_site_appliesTo(cs,insn));
 
 	// find landing pad instruction.
 	auto lp_insn=(Instruction_t*)NULL;
@@ -1280,9 +70,9 @@ void lsda_call_site_t<ptrsize>::build_ir(Instruction_t* insn, const vector<lsda_
 	}
 	else
 	{
-		for_each(action_table.begin(), action_table.end(), [&](const lsda_call_site_action_t<ptrsize>& p)
+		for_each(action_table.begin(), action_table.end(), [&](const shared_ptr<LSDACallSiteAction_t>& p)
 		{
-			const auto action=p.GetAction();
+			const auto action=p->getAction();
 			if(action==0)
 			{
 				new_ehcs->GetTTOrderVector().push_back(action);
@@ -1296,15 +86,15 @@ void lsda_call_site_t<ptrsize>::build_ir(Instruction_t* insn, const vector<lsda_
 				// the type table reveral was done during parsing, type table is right-side-up now.
 				//type_table.at(index).print();
 				auto wrt=(DataScoop_t*)NULL; 
-				if(type_table.at(index).GetTypeInfoPointer()!=0)
+				if(type_table.at(index)->getTypeInfoPointer()!=0)
 				{
-					wrt=firp->FindScoop(type_table.at(index).GetTypeInfoPointer());
+					wrt=firp->FindScoop(type_table.at(index)->getTypeInfoPointer());
 					assert(wrt);
 				}
-				const auto offset=index*type_table.at(index).GetTTEncodingSize();
+				const auto offset=index*type_table.at(index)->getTTEncodingSize();
 				auto addend=0;
 				if(wrt!=NULL) 
-					addend=type_table.at(index).GetTypeInfoPointer()-wrt->GetStart()->GetVirtualOffset();
+					addend=type_table.at(index)->getTypeInfoPointer()-wrt->GetStart()->GetVirtualOffset();
 				auto newreloc=new Relocation_t(BaseObj_t::NOT_IN_DATABASE, offset, "type_table_entry", wrt, addend);
 				new_ehcs->GetRelocations().insert(newreloc);
 				firp->GetRelocations().insert(newreloc);
@@ -1337,183 +127,23 @@ void lsda_call_site_t<ptrsize>::build_ir(Instruction_t* insn, const vector<lsda_
 	}
 }
 
-
-template <int ptrsize>
-uint8_t lsda_t<ptrsize>::GetTTEncoding() const { return type_table_encoding; }
-
-template <int ptrsize>
-lsda_t<ptrsize>::lsda_t() :
-	landing_pad_base_encoding(0),
-	landing_pad_base_addr(0),
-	type_table_encoding(0),
-	type_table_offset(0),
-	type_table_addr(0),
-	cs_table_encoding(0),
-	cs_table_start_offset(0),
-	cs_table_start_addr(0),
-	cs_table_length(0),
-	cs_table_end_addr(0),
-	action_table_start_addr(0)
-{}
-	
-template <int ptrsize>
-bool lsda_t<ptrsize>::parse_lsda(const uint64_t lsda_addr, const DataScoop_t* gcc_except_scoop, const uint64_t fde_region_start)
-{
-	// make sure there's a scoop and that we're in the range.
-	if(!gcc_except_scoop)
-		return true;
-	if(lsda_addr<gcc_except_scoop->GetStart()->GetVirtualOffset())
-		return true;
-	if(lsda_addr>=gcc_except_scoop->GetEnd()->GetVirtualOffset())
-		return true;
-
-	const auto &data=gcc_except_scoop->GetContents();
-	const auto data_addr=gcc_except_scoop->GetStart()->GetVirtualOffset();
-	const auto max=gcc_except_scoop->GetContents().size();
-	auto pos=uint32_t(lsda_addr-data_addr);
-	auto start_pos=pos;
-
-	if(this->read_type(landing_pad_base_encoding, pos, (const uint8_t* const)data.data(), max))
-		return true;
-	if(landing_pad_base_encoding!=DW_EH_PE_omit)
-	{
-		if(this->read_type_with_encoding(landing_pad_base_encoding,landing_pad_base_addr, pos, (const uint8_t* const)data.data(), max, data_addr))
-			return true;
-	}
-	else
-		landing_pad_base_addr=fde_region_start;
-
-	if(this->read_type(type_table_encoding, pos, (const uint8_t* const)data.data(), max))
-		return true;
-
-	auto type_table_pos=0;
-	if(type_table_encoding!=DW_EH_PE_omit)
-	{
-		if(this->read_uleb128(type_table_offset, pos, (const uint8_t* const)data.data(), max))
-			return true;
-		type_table_addr=lsda_addr+type_table_offset+(pos-start_pos);
-		type_table_pos=pos+type_table_offset;
-	}
-	else
-		type_table_addr=0;
-
-	if(this->read_type(cs_table_encoding, pos, (const uint8_t* const)data.data(), max))
-		return true;
-
-	if(this->read_uleb128(cs_table_length, pos, (const uint8_t* const)data.data(), max))
-		return true;
-
-	auto cs_table_end=pos+cs_table_length;
-	//auto cs_table_start_pos=pos;
-	cs_table_start_offset=pos;
-	cs_table_start_addr=lsda_addr+pos-start_pos;
-	cs_table_end_addr=cs_table_start_addr+cs_table_length;
-
-	// action table comes immediately after the call site table.
-	action_table_start_addr=cs_table_start_addr+cs_table_length;
-	while(1)
-	{
-		lsda_call_site_t<ptrsize> lcs;
-		if(lcs.parse_lcs(action_table_start_addr,
-			cs_table_start_addr,cs_table_encoding, pos, (const uint8_t* const)data.data(), cs_table_end, data_addr, landing_pad_base_addr, max))
-		{
-			return true;
-		}
-
-		call_site_table.push_back(lcs);
-		
-		if(pos>=cs_table_end)
-			break;	
-	}
-
-	if(type_table_encoding!=DW_EH_PE_omit)
-	{
-		for(const auto cs_tab_entry : call_site_table)
-		{
-			for(const auto act_tab_entry : cs_tab_entry.GetActionTable())
-			{
-				const auto type_filter=act_tab_entry.GetAction();
-				const auto parse_and_insert_tt_entry = [&] (const unsigned long index) -> bool
-				{
-					// cout<<"Parsing TypeTable at -"<<index<<endl;
-					// 1-based indexing because of odd backwards indexing of type table.
-					lsda_type_table_entry_t <ptrsize> ltte;
-					if(ltte.parse(type_table_encoding, type_table_pos, index, (const uint8_t* const)data.data(), max, data_addr ))
-						return true;
-					type_table.resize(std::max(index,type_table.size()));
-					type_table.at(index-1)=ltte;
-					return false;
-				};
-		
-				if(type_filter==0)
-				{	
-					// type-filter==0 means no TT entry in the action table.
-				}
-				else if(type_filter>0)
-				{
-					// type_filter > 0 indicates singleton type table entry
-					if(parse_and_insert_tt_entry(type_filter))
-						return true;
-				}
-				else if(type_filter<0)
-				{
-					// a type filter < 0 indicates a dynamic exception specification is in play.
-					// these are not common and even less likely to be needed for correct execution.
-					// we ignore for now.  A warning is printed if they are found in build_ir. 
-				}
-				else 
-					assert(0);
-
-			};
-		
-		};
-
-	}
-
-	return false;
-}
-
 template <int ptrsize>
-void lsda_t<ptrsize>::print() const
+void split_eh_frame_impl_t<ptrsize>::lsda_build_ir(const LSDA_t& lsda, Instruction_t* insn) const
 {
-	cout<<"		LSDA:"<<endl;
-	cout<<"			LP base encoding   : 0x"<<hex<<+landing_pad_base_encoding<<endl;
-	cout<<"			LP base addr	   : 0x"<<hex<<+landing_pad_base_addr<<endl;
-	cout<<"			TypeTable encoding : 0x"<<hex<<+type_table_encoding<<endl;
-	cout<<"			TypeTable offset   : 0x"<<hex<<type_table_offset<<endl;
-	cout<<"			TypeTable addr     : 0x"<<hex<<+type_table_addr<<endl;
-	cout<<"			CS tab encoding    : 0x"<<hex<<+cs_table_encoding<<endl;
-	cout<<"			CS tab addr        : 0x"<<hex<<+cs_table_start_addr<<endl;
-	cout<<"			CS tab offset      : 0x"<<hex<<+cs_table_start_offset<<endl;
-	cout<<"			CS tab length      : 0x"<<hex<<+cs_table_length<<endl;
-	cout<<"			CS tab end addr    : 0x"<<hex<<+cs_table_end_addr<<endl;
-	cout<<"			Act tab start_addr : 0x"<<hex<<+action_table_start_addr<<endl;
-	cout<<"			CS tab :"<<endl;
-	int i=0;
-	for_each(call_site_table.begin(), call_site_table.end(), [&](const lsda_call_site_t<ptrsize>& p)
-	{
-		cout<<"			[ "<<hex<<i++<<"] call site table entry "<<endl;
-		p.print();
-	});
-	i=0;
-	for_each(type_table.begin(), type_table.end(), [&](const lsda_type_table_entry_t<ptrsize>& p)
-	{
-		cout<<"			[ -"<<dec<<++i<<"] Type table entry "<<endl;
-		p.print();
-	});
-}
+	const auto  call_site_table_ptr=lsda.getCallSites();
+	const auto& call_site_table=*call_site_table_ptr;
+	const auto& type_table_ptr=lsda.getTypeTable();
+//	auto& type_table=*type_table_ptr;
 
-template <int ptrsize>
-void lsda_t<ptrsize>::build_ir(Instruction_t* insn, const OffsetMap_t& om, FileIR_t* firp) const
-{
-	auto cs_it=find_if(call_site_table.begin(), call_site_table.end(), [&](const lsda_call_site_t<ptrsize>& p)
+	const auto cs_ptr_it=find_if(ALLOF(call_site_table), [&](const shared_ptr<LSDACallSite_t> &p)
 	{
-		return p.appliesTo(insn);
+		return lsda_call_site_appliesTo(*p, insn);
 	});
 
-	if(cs_it!= call_site_table.end())
+	if(cs_ptr_it!= call_site_table.end())
 	{
-		cs_it->build_ir(insn, type_table, GetTTEncoding(), om, firp);
+		const auto cs_ptr=*cs_ptr_it;
+		lsda_call_site_build_ir(*cs_ptr,insn, type_table_ptr, lsda.getTTEncoding());
 	}
 	else
 	{
@@ -1521,282 +151,82 @@ void lsda_t<ptrsize>::build_ir(Instruction_t* insn, const OffsetMap_t& om, FileI
 	}
 }
 
-
-template <int ptrsize>
-fde_contents_t<ptrsize>::fde_contents_t() :
-	fde_position(0),
-	cie_position(0),
-	length(0),
-	id(0),
-	fde_start_addr(0),
-	fde_end_addr(0),
-	fde_range_len(0),
-	lsda_addr(0)
-{}
-
-
 template <int ptrsize>
-bool fde_contents_t<ptrsize>::appliesTo(const Instruction_t* insn) const
+bool split_eh_frame_impl_t<ptrsize>::fde_contents_appliesTo(const FDEContents_t& fde, const Instruction_t* insn)  const
 {
 	assert(insn && insn->GetAddress());
 	auto insn_addr=insn->GetAddress()->GetVirtualOffset();
-
+	const auto fde_start_addr=fde.getStartAddress();
+	const auto fde_end_addr=fde.getEndAddress();
 	return ( fde_start_addr<=insn_addr && insn_addr<fde_end_addr );
 }
 
 template <int ptrsize>
-const cie_contents_t<ptrsize>& fde_contents_t<ptrsize>::GetCIE() const { return cie_info; }
-
-template <int ptrsize>
-cie_contents_t<ptrsize>& fde_contents_t<ptrsize>::GetCIE() { return cie_info; }
-
-template <int ptrsize>
-const eh_program_t<ptrsize>& fde_contents_t<ptrsize>::GetProgram() const { return eh_pgm; }
-
-template <int ptrsize>
-eh_program_t<ptrsize>& fde_contents_t<ptrsize>::GetProgram() { return eh_pgm; }
-
-template <int ptrsize>
-bool fde_contents_t<ptrsize>::parse_fde(
-	const uint32_t &fde_position, 
-	const uint32_t &cie_position, 
-	const uint8_t* const data, 
-	const uint64_t max, 
-	const uint64_t eh_addr,
-	const DataScoop_t* gcc_except_scoop)
-{
-	auto &c=*this;
-	const auto eh_frame_scoop_data=data;
-
-	if(cie_info.parse_cie(cie_position, data, max, eh_addr))
-		return true;
-
-	auto pos=fde_position;
-	auto length=uint64_t(0);
-	if(this->read_length(length, pos, eh_frame_scoop_data, max))
-		return true;
-
-
-	auto end_pos=pos+length;
-	//auto end_length_position=pos;
-
-	auto cie_id=uint32_t(0);
-	if(this->read_type(cie_id, pos, eh_frame_scoop_data, max))
-		return true;
-
-	auto fde_start_addr=uint64_t(0);
-	if(this->read_type_with_encoding(c.GetCIE().GetFDEEncoding(),fde_start_addr, pos, eh_frame_scoop_data, max, eh_addr))
-		return true;
-
-	auto fde_range_len=uint64_t(0);
-	if(this->read_type_with_encoding(c.GetCIE().GetFDEEncoding() & 0xf /* drop pc-rel bits */,fde_range_len, pos, eh_frame_scoop_data, max, eh_addr))
-		return true;
-
-	auto fde_end_addr=fde_start_addr+fde_range_len;
-
-	auto augmentation_data_length=uint64_t(0);
-	if(c.GetCIE().GetAugmentation().find("z") != string::npos)
-	{
-		if(this->read_uleb128(augmentation_data_length, pos, eh_frame_scoop_data, max))
-			return true;
-	}
-	auto lsda_addr=uint64_t(0);
-	if(c.GetCIE().GetLSDAEncoding()!= DW_EH_PE_omit)
-	{
-		if(this->read_type_with_encoding(c.GetCIE().GetLSDAEncoding(), lsda_addr, pos, eh_frame_scoop_data, max, eh_addr))
-			return true;
-		if(c.lsda.parse_lsda(lsda_addr,gcc_except_scoop, fde_start_addr))
-			return true;
-	}
-
-	if(c.eh_pgm.parse_program(pos, eh_frame_scoop_data, end_pos))
-		return true;
-
-	c.fde_position=fde_position;
-	c.cie_position=cie_position;
-	c.length=length;
-	c.id=id;
-	c.fde_start_addr=fde_start_addr;
-	c.fde_end_addr=fde_end_addr;
-	c.fde_range_len=fde_range_len;
-	c.lsda_addr=lsda_addr;
-
-	return false;
-}
-
-template <int ptrsize>
-void fde_contents_t<ptrsize>::print() const
-{
-
-	cout << "["<<setw(6)<<hex<<fde_position<<"] FDE length="<<dec<<length;
-	cout <<" cie=["<<setw(6)<<hex<<cie_position<<"]"<<endl;
-	cout<<"		FDE len addr:		"<<dec<<length<<endl;
-	cout<<"		FDE Start addr:		"<<hex<<fde_start_addr<<endl;
-	cout<<"		FDE End addr:		"<<hex<<fde_end_addr<<endl;
-	cout<<"		FDE len:		"<<dec<<fde_range_len<<endl;
-	cout<<"		FDE LSDA:		"<<hex<<lsda_addr<<endl;
-	eh_pgm.print(fde_start_addr);
-	if(GetCIE().GetLSDAEncoding()!= DW_EH_PE_omit)
-		lsda.print();
-	else
-		cout<<"		No LSDA for this FDE."<<endl;
-}
-
-template <int ptrsize>
-void fde_contents_t<ptrsize>::build_ir(Instruction_t* insn, const OffsetMap_t &om, FileIR_t* firp) const
+void split_eh_frame_impl_t<ptrsize>::fde_contents_build_ir(const FDEContents_t& fde, Instruction_t* insn) const
 {
+	const auto fde_start_addr=fde.getStartAddress();
+	const auto fde_end_addr=fde.getEndAddress();
+	const auto lsda_ptr=fde.getLSDA();
+	const auto &lsda=*lsda_ptr;
+	const auto lsda_addr=fde.getLSDAAddress();
+	
 	// assert this is the right FDE.
 	assert( fde_start_addr<= insn->GetAddress()->GetVirtualOffset() && insn->GetAddress()->GetVirtualOffset() <= fde_end_addr);
 
 	//eh_pgm.print(fde_start_addr);
 	if(lsda_addr!=0)
-		lsda.build_ir(insn,om,firp);
+		lsda_build_ir(lsda,insn);
 }
 
-
-
-
 template <int ptrsize>
-bool split_eh_frame_impl_t<ptrsize>::init_offset_map()
+bool split_eh_frame_impl_t<ptrsize>::init_offset_map() 
 {
-	for_each(firp->GetInstructions().begin(), firp->GetInstructions().end(), [&](Instruction_t* i)
+	//for_each(firp->GetInstructions().begin(), firp->GetInstructions().end(), [&](Instruction_t* i)
+	for(const auto i : firp->GetInstructions())
 	{
 		offset_to_insn_map[i->GetAddress()->GetVirtualOffset()]=i;
-	});
-	return false;
-}
-
-
-template <int ptrsize>
-bool split_eh_frame_impl_t<ptrsize>::iterate_fdes()
-{
-	auto eh_frame_scoop_data=(const uint8_t* const)eh_frame_scoop->GetContents().c_str();
-	auto data=eh_frame_scoop_data;
-	auto eh_addr= eh_frame_scoop->GetStart()->GetVirtualOffset();
-	auto max=eh_frame_scoop->GetContents().size();
-	auto position=uint32_t(0);
-
-	//cout << "----------------------------------------"<<endl;
-	while(1)
-	{
-		auto old_position=position;
-		auto act_length=uint64_t(0);
-
-		if(eh_frame_util_t<ptrsize>::read_length(act_length, position, eh_frame_scoop_data, max))
-			break;
-
-		auto next_position=position + act_length;
-		auto cie_offset=uint32_t(0);
-		auto cie_offset_position=position;
-
-		if(eh_frame_util_t<ptrsize>::read_type(cie_offset,position, eh_frame_scoop_data, max))
-			break;
-
-		//cout << " [ " << setw(6) << hex << old_position << "] " ;
-		if(act_length==0)
-		{
-			//cout << "Zero terminator " << endl;
-			break;
-		}
-		else if(cie_offset==0)
-		{
-			//cout << "CIE length="<< dec << act_length << endl;
-			cie_contents_t<ptrsize> c;
-			if(c.parse_cie(old_position, data, max, eh_addr))
-				return true;
-			cies.push_back(c);
-		}
-		else
-		{
-			fde_contents_t<ptrsize> f;
-			auto cie_position = cie_offset_position - cie_offset;
-			//cout << "FDE length="<< dec << act_length << " cie=[" << setw(6) << hex << cie_position << "]" << endl;
-			if(f.parse_fde(old_position, cie_position, data, max, eh_addr, gcc_except_table_scoop))
-				return true;
-			//const auto old_fde_size=fdes.size();
-			fdes.insert(f);
-		}
-		//cout << "----------------------------------------"<<endl;
-		
-
-		// next CIE/FDE
-		assert(position<=next_position); 	// so we don't accidentally over-read a CIE/FDE
-		position=next_position;
-	}
-	return false;
-}
-
-
-template <int ptrsize>
-split_eh_frame_impl_t<ptrsize>::split_eh_frame_impl_t(FileIR_t* p_firp)
-	: firp(p_firp),
-	  eh_frame_scoop(NULL),
-	  eh_frame_hdr_scoop(NULL),
-	  gcc_except_table_scoop(NULL)
-{
-	assert(firp!=NULL);
-
-	// function to find a scoop by name.
-	auto lookup_scoop_by_name=[&](const string &name) -> DataScoop_t* 
-	{
-		auto scoop_it=find_if(firp->GetDataScoops().begin(), firp->GetDataScoops().end(), [name](DataScoop_t* scoop)
-		{
-			return scoop->GetName()==name;
-		});
-
-		if(scoop_it!=firp->GetDataScoops().end())
-			return *scoop_it;
-		return NULL;
 	};
-
-	eh_frame_scoop=lookup_scoop_by_name(".eh_frame");
-	eh_frame_hdr_scoop=lookup_scoop_by_name(".eh_frame_hdr");
-	gcc_except_table_scoop=lookup_scoop_by_name(".gcc_except_table");
-
-}
-
-
-template <int ptrsize>
-bool split_eh_frame_impl_t<ptrsize>::parse()
-{
-	if(eh_frame_scoop==NULL)
-		return true; // no frame info in this binary
-
-
-	if(init_offset_map())
-		return true;
-
-	if(iterate_fdes())
-		return true;
-
 	return false;
 }
 
 
-template <int ptrsize>
-void split_eh_frame_impl_t<ptrsize>::print() const
-{
-	for_each(cies.begin(), cies.end(), [&](const cie_contents_t<ptrsize>  &p)
-	{
-		p.print();
-	});
-	for_each(fdes.begin(), fdes.end(), [&](const fde_contents_t<ptrsize>  &p)
-	{
-		p.print();
-	});
-}
-
-
 template <int ptrsize>
 void split_eh_frame_impl_t<ptrsize>::build_ir() const
 {
 	typedef pair<EhProgram_t*,uint64_t> whole_pgm_t;
+	//const auto fdes_ptr=eh_frame_parser->getFDEs();
+	//const auto &fdes=*fdes_ptr;
 
 	auto reusedpgms=size_t(0);
-	struct EhProgramComparator_t { 
-//			bool operator() (const EhProgram_t* a, const EhProgram_t* b) { return *a < *b; } 
-		bool operator() (const whole_pgm_t& a, const whole_pgm_t& b) 
-		{ return tie(*a.first, a.second) < tie(*b.first,b.second); } 
+	struct EhProgramComparator_t 
+	{
+		bool operator() (const whole_pgm_t& lhs, const whole_pgm_t& rhs) 
+		{
+			const auto &a=*(lhs.first);
+			const auto &b=*(rhs.first);
+			return
+				make_tuple(
+				    a.GetCIEProgram(),
+				    a.GetFDEProgram(),
+				    a.GetCodeAlignmentFactor(),
+				    a.GetDataAlignmentFactor(),
+				    a.GetReturnRegNumber(),
+				    a.GetPointerSize(), 
+				    lhs.second
+				   )
+				<
+				make_tuple(
+				    b.GetCIEProgram(),
+				    b.GetFDEProgram(),
+				    b.GetCodeAlignmentFactor(),
+				    b.GetDataAlignmentFactor(),
+				    b.GetReturnRegNumber(),
+				    b.GetPointerSize(), 
+				    rhs.second
+				   );
+
+//			return tie(*a.first, a.second) < tie(*b.first,b.second); 
+		}
 	};
 
 	// this is used to avoid adding duplicate entries to the program's IR, it allows a lookup by value
@@ -1806,33 +236,48 @@ void split_eh_frame_impl_t<ptrsize>::build_ir() const
 	// find the right cie and fde, and build the IR from those for this instruction.
 	auto build_ir_insn=[&](Instruction_t* insn) -> void
 	{
+		/*
 		const auto tofind=fde_contents_t<ptrsize>( insn->GetAddress()->GetVirtualOffset(), insn->GetAddress()->GetVirtualOffset()+1 );
 		const auto fie_it=fdes.find(tofind);
+		*/
+		const auto find_addr=insn->GetAddress()->GetVirtualOffset();
+		/*
+		too slow
+		const auto finder=[&](const shared_ptr<FDEContents_t>& fde) -> bool 
+			{ return fde->getStartAddress() <= find_addr && find_addr < fde->getEndAddress(); };
+		const auto fie_ptr_it=find_if ( ALLOF(*fdes), finder);
+		*/
+		const auto fie_ptr=eh_frame_parser->findFDE(find_addr);
 
-		if(fie_it!=fdes.end())
+		if(fie_ptr != nullptr ) 
 		{
+			// const auto fie_ptr=*fie_ptr_it;
 
 			if(getenv("EHIR_VERBOSE")!=NULL)
 			{
 				cout<<hex<<insn->GetAddress()->GetVirtualOffset()<<":"
 				    <<insn->GetBaseID()<<":"<<insn->getDisassembly()<<" -> "<<endl;
 				//fie_it->GetCIE().print();
-				fie_it->print();
+				fie_ptr->print();
 			}
 
-			const auto fde_addr=fie_it->GetFDEStartAddress();
-			const auto caf=fie_it->GetCIE().GetCAF(); 
-			const auto daf=fie_it->GetCIE().GetDAF(); 
-			const auto return_reg=fie_it->GetCIE().GetReturnRegister(); 
-			const auto personality=fie_it->GetCIE().GetPersonality(); 
+			const auto fde_addr=fie_ptr->getStartAddress();
+			const auto caf=fie_ptr->getCIE().getCAF(); 
+			const auto daf=fie_ptr->getCIE().getDAF(); 
+			const auto return_reg=fie_ptr->getCIE().getReturnRegister(); 
+			const auto personality=fie_ptr->getCIE().getPersonality(); 
 			const auto insn_addr=insn->GetAddress()->GetVirtualOffset();
 
-			auto import_pgm = [&](EhProgramListing_t& out_pgm, const eh_program_t<ptrsize> in_pgm) -> void
+			auto import_pgm = [&](EhProgramListing_t& out_pgm_final, const EHProgram_t& in_pgm) -> void
 			{
+				auto out_pgm=vector<shared_ptr<EHProgramInstruction_t> >();
 				auto cur_addr=fde_addr;
-				for(const auto & insn : in_pgm.GetInstructions())
+				const auto in_pgm_instructions_ptr=in_pgm.getInstructions();
+				const auto in_pgm_instructions=*in_pgm_instructions_ptr;
+				for(const auto & insn_ptr : in_pgm_instructions)
 				{
-					if(insn.Advance(cur_addr, caf))
+					const auto & insn=*insn_ptr;
+					if(insn.advance(cur_addr, caf))
 					{	
 						if(cur_addr > insn_addr)
 							break;
@@ -1853,17 +298,18 @@ void split_eh_frame_impl_t<ptrsize>::build_ir() const
 								cerr<<"Error in CIE/FDE program:  unmatched restore_state command"<<endl;
 								break;
 							}
-							const auto back_str=out_pgm.back();
+							const auto back_insn=out_pgm.back();
 							out_pgm.pop_back();
-							const auto back_insn=eh_program_insn_t<ptrsize>(back_str);
-							if(back_insn.isRememberState())
+							//const auto back_insn=eh_program_insn_t<ptrsize>(back_str);
+							if(back_insn->isRememberState())
 								break;
 						}
 					}
 					else
 					{
-						string to_push(insn.GetBytes().begin(),insn.GetBytes().end());
-						out_pgm.push_back(to_push);
+						// string to_push(insn.GetBytes().begin(),insn.GetBytes().end());
+						// out_pgm.push_back(to_push);
+						out_pgm.push_back(insn_ptr);
 					}
 
 				}
@@ -1871,13 +317,19 @@ void split_eh_frame_impl_t<ptrsize>::build_ir() const
 				{
 					cout<<"\tPgm has insn_count="<<out_pgm.size()<<endl;
 				}
+				transform
+				    (
+				        ALLOF(out_pgm), 
+				        back_inserter(out_pgm_final), 
+				        [](const shared_ptr<EHProgramInstruction_t>& p){ return string(ALLOF(p->getBytes()));}
+				    ); 
 			}; 
 
 			// build an eh program on the stack;
 
 			auto ehpgm=EhProgram_t(BaseObj_t::NOT_IN_DATABASE,caf,daf,return_reg, ptrsize);
-			import_pgm(ehpgm.GetCIEProgram(), fie_it->GetCIE().GetProgram());
-			import_pgm(ehpgm.GetFDEProgram(), fie_it->GetProgram());
+			import_pgm(ehpgm.GetCIEProgram(), fie_ptr->getCIE().getProgram());
+			import_pgm(ehpgm.GetFDEProgram(), fie_ptr->getProgram());
 
 
 			if(getenv("EHIR_VERBOSE")!=NULL)
@@ -1945,8 +397,7 @@ void split_eh_frame_impl_t<ptrsize>::build_ir() const
 			}
 			
 			// build the IR from the FDE.
-			fie_it->GetCIE().build_ir(insn);
-			fie_it->build_ir(insn, offset_to_insn_map,firp);
+			fde_contents_build_ir(*fie_ptr.get(), insn);
 		}
 		else
 		{
@@ -1994,8 +445,12 @@ void split_eh_frame_impl_t<ptrsize>::build_ir() const
 	cout<<"# ATTRIBUTE Split_Exception_Handler::total_eh_programs_created="<<dec<<firp->GetAllEhPrograms().size()<<endl;
 	cout<<"# ATTRIBUTE Split_Exception_Handler::total_eh_programs_reused="<<dec<<reusedpgms<<endl;
 	cout<<"# ATTRIBUTE Split_Exception_Handler::total_eh_programs="<<dec<<firp->GetAllEhPrograms().size()+reusedpgms<<endl;
-	cout<<"# ATTRIBUTE Split_Exception_Handler::pct_eh_programs="<<std::fixed<<((float)firp->GetAllEhPrograms().size()/(float)firp->GetAllEhPrograms().size()+reusedpgms)*100.00<<"%"<<endl;
-	cout<<"# ATTRIBUTE Split_Exception_Handler::pct_eh_programs_reused="<<std::fixed<<((float)reusedpgms/(float)firp->GetAllEhPrograms().size()+reusedpgms)*100.00<<"%"<<endl;
+	cout<<"# ATTRIBUTE Split_Exception_Handler::pct_eh_programs="<<std::fixed
+	    <<((float)firp->GetAllEhPrograms().size()/((float)firp->GetAllEhPrograms().size()+reusedpgms))*100.00
+	    <<"%" <<endl;
+	cout<<"# ATTRIBUTE Split_Exception_Handler::pct_eh_programs_reused="<<std::fixed
+	    <<((float)reusedpgms/((float)firp->GetAllEhPrograms().size()+reusedpgms))*100.00
+	    <<"%"<<endl;
 
 	remove_scoop(eh_frame_scoop);
 	remove_scoop(eh_frame_hdr_scoop);
@@ -2006,34 +461,97 @@ void split_eh_frame_impl_t<ptrsize>::build_ir() const
 template <int ptrsize>
 libIRDB::Instruction_t* split_eh_frame_impl_t<ptrsize>::find_lp(libIRDB::Instruction_t* i) const 
 {
-	const auto tofind=fde_contents_t<ptrsize>( i->GetAddress()->GetVirtualOffset(), i->GetAddress()->GetVirtualOffset()+1);
-	const auto fde_it=fdes.find(tofind);
-
-	if(fde_it==fdes.end())
-		return NULL;
-	
-	const auto &the_fde=*fde_it;
-	const auto &the_lsda=the_fde.GetLSDA();
-	const auto &cstab  = the_lsda.GetCallSites();
-
-	const auto cstab_it=find_if(cstab.begin(), cstab.end(), [&](const lsda_call_site_t <ptrsize>& cs)
-		{ return cs.appliesTo(i); });
+	const auto find_addr=i->GetAddress()->GetVirtualOffset();
+	//const auto tofind=fde_contents_t<ptrsize>( i->GetAddress()->GetVirtualOffset(), i->GetAddress()->GetVirtualOffset()+1);
+	//const auto fde_it=fdes.find(tofind);
+	/* too slow
+	const auto fde_ptr_it=find_if
+		(
+		    ALLOF(*fdes),
+		    [&](const shared_ptr<FDEContents_t>& fde) { return fde->getStartAddress() <= find_addr && find_addr < fde->getEndAddress(); }
+		);
+	*/
+	const auto fde_ptr=eh_frame_parser->findFDE(find_addr);
+
+	if(fde_ptr==nullptr)
+		return nullptr;
+
+	const auto &the_fde=*fde_ptr;
+	const auto &the_lsda_ptr=the_fde.getLSDA();
+	const auto &the_lsda=*the_lsda_ptr;
+	const auto &cstab_ptr  = the_lsda.getCallSites();
+	const auto &cstab  = *cstab_ptr;
+
+	const auto cstab_it=find_if(ALLOF(cstab), [&](const shared_ptr<LSDACallSite_t>& cs)
+		{ return lsda_call_site_appliesTo(*cs,i); });
 
 	if(cstab_it==cstab.end())
-		return NULL;
+		return nullptr;
 
-	const auto &the_cstab_entry=*cstab_it;
-	const auto lp_addr= the_cstab_entry.GetLandingPadAddress();
+	const auto &the_cstab_entry_ptr=*cstab_it;
+	const auto &the_cstab_entry=*the_cstab_entry_ptr;
+	const auto lp_addr= the_cstab_entry.getLandingPadAddress();
 
 	const auto om_it=offset_to_insn_map.find(lp_addr);
 
 	if(om_it==offset_to_insn_map.end())
-		return NULL;
+		return nullptr;
 
 	auto lp=om_it->second;
 	return lp;
 }
 
+template <int ptrsize>
+void split_eh_frame_impl_t<ptrsize>::print() const
+{
+	eh_frame_parser->print();
+}
+
+template <int ptrsize>
+split_eh_frame_impl_t<ptrsize>::split_eh_frame_impl_t(FileIR_t* p_firp)
+	: firp(p_firp),
+	  eh_frame_scoop(NULL),
+	  eh_frame_hdr_scoop(NULL),
+	  gcc_except_table_scoop(NULL)
+{
+	assert(firp!=NULL);
+
+	// function to find a scoop by name.
+	auto lookup_scoop_by_name=[&](const string &the_name) -> DataScoop_t* 
+	{
+		//auto scoop_it=find_if(ALLOF(firp->GetDataScoops()), [the_name](DataScoop_t* scoop)
+		const auto scoop_it=find_if(
+			firp->GetDataScoops().begin(), 
+			firp->GetDataScoops().end(), 
+			[the_name](DataScoop_t* scoop)
+			{
+				return scoop->GetName()==the_name;
+			});
+
+		if(scoop_it!=firp->GetDataScoops().end())
+			return *scoop_it;
+		return NULL;
+	};
+	auto scoop_address=[&](const DataScoop_t* p) -> uint64_t { return p==NULL ? 0  : p->GetStart()->GetVirtualOffset(); };
+	auto scoop_contents=[&](const DataScoop_t* p) -> string  { return p==NULL ? "" : p->GetContents(); };
+
+	eh_frame_scoop=lookup_scoop_by_name(".eh_frame");
+	eh_frame_hdr_scoop=lookup_scoop_by_name(".eh_frame_hdr");
+	gcc_except_table_scoop=lookup_scoop_by_name(".gcc_except_table");
+
+	eh_frame_parser=EHFrameParser_t::factory
+		( 
+		    ptrsize,
+		    scoop_contents(eh_frame_scoop),         scoop_address(eh_frame_scoop), 
+		    scoop_contents(eh_frame_hdr_scoop),     scoop_address(eh_frame_hdr_scoop), 
+		    scoop_contents(gcc_except_table_scoop), scoop_address(gcc_except_table_scoop)
+		);
+
+	if(eh_frame_parser!=NULL)
+		fdes=eh_frame_parser->getFDEs();
+
+	(void)init_offset_map();
+}
 
 unique_ptr<split_eh_frame_t> split_eh_frame_t::factory(FileIR_t *firp)
 {
@@ -2049,7 +567,6 @@ void split_eh_frame(FileIR_t* firp)
 	auto found_err=false;
 	//auto eh_frame_splitter=(unique_ptr<split_eh_frame_t>)NULL;
 	const auto eh_frame_splitter=split_eh_frame_t::factory(firp);
-	found_err=eh_frame_splitter->parse();
 	eh_frame_splitter->build_ir();
 
 	assert(!found_err);
diff --git a/libIRDB/test/split_eh_frame.hpp b/libIRDB/test/split_eh_frame.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0e0d69063ea5a7b7d050fd0afe8a722d52f19de8
--- /dev/null
+++ b/libIRDB/test/split_eh_frame.hpp
@@ -0,0 +1,95 @@
+#ifndef eh_frame_hpp
+#define eh_frame_hpp
+
+#include <libIRDB-core.hpp>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <limits>
+#include <stdlib.h>
+#include <string.h>
+#include <map>
+#include <assert.h>
+#include <elf.h>
+#include <algorithm>
+#include <memory>
+
+#include <exeio.h>
+#include <ehp.hpp>
+
+
+
+
+using OffsetMap_t = std::map<libIRDB::virtual_offset_t, libIRDB::Instruction_t*>;
+
+class split_eh_frame_t 
+{
+	public:
+
+		virtual void build_ir() const =0;
+		virtual void print() const=0;
+		virtual libIRDB::Instruction_t* find_lp(libIRDB::Instruction_t*) const =0;
+
+		static std::unique_ptr<split_eh_frame_t> factory(libIRDB::FileIR_t *firp);
+
+};
+
+template <int ptrsize>
+class split_eh_frame_impl_t : public split_eh_frame_t
+{
+	private: 
+
+	libIRDB::FileIR_t* firp;
+	libIRDB::DataScoop_t* eh_frame_scoop;
+	libIRDB::DataScoop_t* eh_frame_hdr_scoop;
+	libIRDB::DataScoop_t* gcc_except_table_scoop;
+	OffsetMap_t offset_to_insn_map;
+
+	std::unique_ptr<const EHP::EHFrameParser_t> eh_frame_parser;
+	std::shared_ptr<const EHP::FDEVector_t> fdes;
+
+	bool init_offset_map();
+
+	bool lsda_call_site_appliesTo
+		(
+		    const EHP::LSDACallSite_t& cs, 
+		    const libIRDB::Instruction_t* insn
+		) const;
+	void lsda_call_site_build_ir
+		(
+		    const EHP::LSDACallSite_t& cs,
+		    libIRDB::Instruction_t* insn, 
+		    /* const std::vector<lsda_type_table_entry_t <ptrsize> > &*/ std::shared_ptr<EHP::TypeTableVector_t> type_table_ptr, 
+		    const uint8_t& tt_encoding
+		) const;
+	void lsda_build_ir
+		(
+		    const EHP::LSDA_t& lsda,
+		    libIRDB::Instruction_t* insn
+		) const;
+        bool fde_contents_appliesTo
+		(
+		    const EHP::FDEContents_t& fde,
+		    const libIRDB::Instruction_t* insn
+		) const;
+	void fde_contents_build_ir
+		(
+		    const EHP::FDEContents_t& fde,
+		    libIRDB::Instruction_t* insn
+		) const;
+
+	public:
+
+	split_eh_frame_impl_t(libIRDB::FileIR_t* p_firp);
+
+
+	void print() const;
+
+	void build_ir() const;
+
+	libIRDB::Instruction_t* find_lp(libIRDB::Instruction_t*) const ;
+};
+
+void split_eh_frame(libIRDB::FileIR_t* firp);
+
+#endif
diff --git a/libMEDSannotation/include/MEDS_FuncAnnotation.hpp b/libMEDSannotation/include/MEDS_FuncAnnotation.hpp
index c2c246ff7319c20cdc34baebc0bae764b50759dc..e4dc9347c531c14729f85d769f56b08bc729a5eb 100644
--- a/libMEDSannotation/include/MEDS_FuncAnnotation.hpp
+++ b/libMEDSannotation/include/MEDS_FuncAnnotation.hpp
@@ -37,7 +37,7 @@ using namespace std;
 using namespace MEDS_Annotation;
 
 //
-// Class to handle one MEDS (integer vulnerability) annotation
+// Class to handle one MEDS annotation
 //
 class MEDS_FuncAnnotation : public MEDS_AnnotationBase
 {
@@ -50,8 +50,16 @@ class MEDS_FuncAnnotation : public MEDS_AnnotationBase
 		virtual string getFuncName() const { return m_func_name; }
 		virtual void setFuncName(const string &p_func_name) { m_func_name=p_func_name; }
 
+		virtual bool isLeaf() const { return m_isleaf; }
+		virtual void setLeaf(const bool p_leaf) { m_isleaf = p_leaf; }
+
+		virtual bool hasFramePointer() const { return m_hasfp; }
+		virtual void setHasFramePointer(const bool p_hasfp) { m_hasfp = p_hasfp; }
+
 	private:
 		string m_func_name;
+		bool m_isleaf;
+		bool m_hasfp;
 };
 
 }
diff --git a/libMEDSannotation/include/MEDS_Register.hpp b/libMEDSannotation/include/MEDS_Register.hpp
index 34b8558c2f1e5c0f459e1109a068976fe4146976..3339850bed7ea3d50a1c39e1596e5049eea355e1 100644
--- a/libMEDSannotation/include/MEDS_Register.hpp
+++ b/libMEDSannotation/include/MEDS_Register.hpp
@@ -51,6 +51,7 @@ class Register
   		static RegisterName getRegister(std::string);
   		static RegisterName getRegister(char *str);
   		static bool isValidRegister(std::string);
+  		static bool isValidRegister(const RegisterName);
   		static bool is64bit(RegisterName);
   		static bool is32bit(RegisterName);
   		static bool is16bit(RegisterName);
@@ -60,6 +61,8 @@ class Register
   		static RegisterName getFreeRegister64(const RegisterSet_t &p_used);
   		static std::string readRegisterSet(const std::string &in, RegisterSet_t &out);
 		static RegisterName promoteTo64(const RegisterName p_reg);
+		static RegisterName demoteTo32(const RegisterName p_reg);
+		static RegisterName demoteTo16(const RegisterName p_reg);
 
 };
 
diff --git a/libMEDSannotation/src/MEDS_Register.cpp b/libMEDSannotation/src/MEDS_Register.cpp
index bfe94cf6c47b01cf9432dedb2d0681be1fb249e8..57aab2f4b618d170551f5a7519abb60761f83d6a 100644
--- a/libMEDSannotation/src/MEDS_Register.cpp
+++ b/libMEDSannotation/src/MEDS_Register.cpp
@@ -38,6 +38,11 @@ bool Register::isValidRegister(std::string p_reg)
 	return getRegister(p_reg) != rn_UNKNOWN;
 }
 
+bool Register::isValidRegister(const RegisterName p_reg)
+{
+	return isValidRegister(Register::toString(p_reg));
+}
+
 RegisterName Register::getRegister(std::string p_reg)
 {
 	if (strcasecmp(p_reg.c_str(), "EFLAGS") ==0)
@@ -522,3 +527,62 @@ RegisterName Register::promoteTo64(const RegisterName p_reg)
 			break;
 	}
 }
+
+RegisterName Register::demoteTo32(const RegisterName p_reg)
+{
+	if (is32bit(p_reg))
+		return p_reg;
+
+	switch (p_reg)
+	{
+		case rn_RAX:   return  rn_EAX;
+		case rn_RBX:   return  rn_EBX;
+		case rn_RCX:   return  rn_ECX;
+		case rn_RDX:   return  rn_EDX;
+		case rn_RBP:   return  rn_EBP;
+		case rn_RSP:   return  rn_ESP;
+		case rn_RSI:   return  rn_ESI;
+		case rn_RDI:   return  rn_EDI;
+		case  rn_R8:   return  rn_R8D;
+		case  rn_R9:   return  rn_R9D;
+		case rn_R10:   return rn_R10D;
+		case rn_R11:   return rn_R11D;
+		case rn_R12:   return rn_R12D;
+		case rn_R13:   return rn_R13D;
+		case rn_R14:   return rn_R14D;
+		case rn_R15:   return rn_R15D;
+		default:
+			return rn_UNKNOWN;
+			break;
+	}
+}
+
+RegisterName Register::demoteTo16(const RegisterName p_reg)
+{
+	if (is16bit(p_reg))
+		return p_reg;
+
+	switch (p_reg)
+	{
+		case rn_RAX: case  rn_EAX:   return rn_AX;
+		case rn_RBX: case  rn_EBX:   return rn_BX;
+		case rn_RCX: case  rn_ECX:   return rn_CX;
+		case rn_RDX: case  rn_EDX:   return rn_DX;
+		case rn_RBP: case  rn_EBP:   return rn_BP;
+		case rn_RSP: case  rn_ESP:   return rn_SP;
+		case rn_RSI: case  rn_ESI:   return rn_SI;
+		case rn_RDI: case  rn_EDI:   return rn_DI;
+		case  rn_R8: case  rn_R8D:   return rn_R8W;
+		case  rn_R9: case  rn_R9D:   return rn_R9W;
+		case rn_R10: case rn_R10D:   return rn_R10W;
+		case rn_R11: case rn_R11D:   return rn_R11W;
+		case rn_R12: case rn_R12D:   return rn_R12W;
+		case rn_R13: case rn_R13D:   return rn_R13W;
+		case rn_R14: case rn_R14D:   return rn_R14W;
+		case rn_R15: case rn_R15D:   return rn_R15W;
+		default:
+			return rn_UNKNOWN;
+			break;
+	}
+}
+
diff --git a/libMEDSannotation/src/MEDS_SafeFuncAnnotation.cpp b/libMEDSannotation/src/MEDS_SafeFuncAnnotation.cpp
index b5ad37b3f113d1dd454eaaf1edeafe657488d103..de7af940b984d1d2daf2694bdaf419f9c962f5d2 100644
--- a/libMEDSannotation/src/MEDS_SafeFuncAnnotation.cpp
+++ b/libMEDSannotation/src/MEDS_SafeFuncAnnotation.cpp
@@ -39,6 +39,8 @@ MEDS_SafeFuncAnnotation::MEDS_SafeFuncAnnotation(const string &p_rawLine)
 {
 	init();
 	m_rawInputLine=p_rawLine;
+	setLeaf(false);
+	setHasFramePointer(true);
 	parse();
 }
 
@@ -104,5 +106,27 @@ void MEDS_SafeFuncAnnotation::parse()
 		markUnsafe();	 // sets valid
 	}
 
+        if (m_rawInputLine.find(" FUNC_LEAF ")!=string::npos)
+	{
+		if(getenv("VERBOSE"))
+			cout<<"Found FUNC_LEAF for "<<vo.to_string()<<endl;
+		setLeaf(true);
+	}
+	else
+	{
+		setLeaf(false);
+	}
+
+        if (m_rawInputLine.find(" NOFP ")!=string::npos)
+	{
+		if(getenv("VERBOSE"))
+			cout<<"Found NOFP (no frame pointer) for "<<vo.to_string()<<endl;
+		setHasFramePointer(false);
+	}
+	else
+	{
+		setHasFramePointer(true);
+	}
+
 }
 
diff --git a/libcapstone b/libcapstone
index 4f05e83334ec6a10e1ed93018affe9091a576f84..bfa649ff1a0ed3807f94ac2d5690c5c3108cc75f 160000
--- a/libcapstone
+++ b/libcapstone
@@ -1 +1 @@
-Subproject commit 4f05e83334ec6a10e1ed93018affe9091a576f84
+Subproject commit bfa649ff1a0ed3807f94ac2d5690c5c3108cc75f
diff --git a/libehp b/libehp
new file mode 160000
index 0000000000000000000000000000000000000000..9e90afedeaa8474d158a452205f6271172c7d78d
--- /dev/null
+++ b/libehp
@@ -0,0 +1 @@
+Subproject commit 9e90afedeaa8474d158a452205f6271172c7d78d
diff --git a/tools/selective_cfi/color_map.hpp b/tools/selective_cfi/color_map.hpp
index 8082c7d7ad921a5a5cf7071ddf406ee823353a23..2ffb0992de1f55ef5f8517fefeffe522a3b54361 100644
--- a/tools/selective_cfi/color_map.hpp
+++ b/tools/selective_cfi/color_map.hpp
@@ -25,7 +25,7 @@
 #include <stdint.h>
 
 
-typedef int64_t NonceValueType_t;
+typedef uint64_t NonceValueType_t;
 
 class ColoredSlotValue_t
 {
@@ -63,8 +63,8 @@ class ColoredSlotAllocator_t
 	
 	private:
 		int slot_number;
-		int used;
-		int max_value;
+		NonceValueType_t used;
+		NonceValueType_t max_value;
 };
 
 typedef std::map<int,ColoredSlotValue_t> ColoredSlotValues_t;
@@ -75,7 +75,9 @@ class ColoredInstructionNonces_t
 	public:
 		ColoredInstructionNonces_t(libIRDB::FileIR_t *the_firp)
 			: firp(the_firp), slot_size(1), slot_values(255) { }
-
+		ColoredInstructionNonces_t(libIRDB::FileIR_t *the_firp, int the_slot_size)
+			: firp(the_firp), slot_size(the_slot_size), 
+                          slot_values(MaxNonceValForSlotSize(the_slot_size))  { }               
 		ColoredSlotValues_t  GetColorsOfIBT (libIRDB::Instruction_t* i) 
 		{ return color_assignments[i]; }
 
@@ -96,7 +98,7 @@ class ColoredInstructionNonces_t
 
 		// used to describe how big a nonce slot is.  for now, 1 byte.
 		const int slot_size;
-		const int slot_values;
+		const NonceValueType_t slot_values;
 
 		// information for each slot we've used.
 		std::vector<ColoredSlotAllocator_t> slots_used;
@@ -110,6 +112,15 @@ class ColoredInstructionNonces_t
 		// the slot that each IB uses. ICFS_t -> slot_value
 		std::map<libIRDB::ICFS_t, ColoredSlotValue_t> slot_assignments;
 
+                NonceValueType_t MaxNonceValForSlotSize(int slot_size)
+                {
+                    NonceValueType_t max_nonce_val = ~((NonceValueType_t) 0);
+                    size_t max_nonce_size_bits = sizeof(NonceValueType_t)*8;
+                    size_t slot_size_bits = slot_size*8;
+
+                    return max_nonce_val >> (max_nonce_size_bits - slot_size_bits);
+                }
+
 
 };
 
@@ -130,4 +141,3 @@ class UniqueICFSSetSorter_t
 };
 
 #endif
-
diff --git a/tools/selective_cfi/scfi_driver.cpp b/tools/selective_cfi/scfi_driver.cpp
index e5004122212f369e7dc32fbdc58dcbf9b95efb77..cd5374c12928d4508f0298dafca8899a99064610 100644
--- a/tools/selective_cfi/scfi_driver.cpp
+++ b/tools/selective_cfi/scfi_driver.cpp
@@ -36,7 +36,10 @@ using namespace libIRDB;
 void usage(char* name)
 {
 	cerr<<" Usage: "<<name<<" <variant_id>  \n"
+"               [--nonce-size [1|2|4|8]]  \n"
+"		[--exe-nonce-size [1|2|4|8]]  \n"
 "		[--color|--no-color]  \n"
+"		[--color-exe-nonces|--no-color-exe-nonces]  \n"         
 "		[--protect-jumps|--no-protect-jumps]  \n"
 "		[--protect-calls|--no-protect-calls]  \n"
 "		[--protect-rets|--no-protect-rets] \n"
@@ -45,7 +48,7 @@ void usage(char* name)
 "		[ --multimodule | --no-multimodule ] \n"
 "		[--exe-nonce-for-call|--no-exe-nonce-for-call]  \n"
 " \n"
-"default: --no-color --protect-jumps --protect-calls --protect-rets --protect-safefn --common-slow-path --no-multimodule --no-exe-nonce-for-call\n"; 
+"default: --no-color --no-color-exe-nonces --no-protect-jumps --protect-calls --protect-rets --protect-safefn --common-slow-path --no-multimodule --no-exe-nonce-for-call --nonce-size 1 --exe-nonce-size 4\n"; 
 }
 
 int main(int argc, char **argv)
@@ -66,16 +69,43 @@ int main(int argc, char **argv)
 #endif
 
 	bool do_coloring=false;
+        bool do_color_exe_nonces=false;
 	bool do_common_slow_path=true;
-	bool do_jumps=false;
+	bool do_jumps=false; // do_jumps=true will cause failures b/c registers stay live over ind jumps
 	bool do_calls=true;
 	bool do_rets=true;
 	bool do_safefn=true;
 	bool do_multimodule=false;
 	bool do_exe_nonce_for_call=false;
+        int nonce_size=1;
+        int exe_nonce_size=4;
 	for(int  i=2;i<argc;i++)
 	{
-		if(string(argv[i])=="--color")
+                if(string(argv[i])=="--nonce-size" && 
+                        string(argv[i+1]).length()==1 && isdigit(string(argv[i+1])[0]))
+                {
+                    nonce_size = stoi(string(argv[i+1]));
+                    if(!(nonce_size == 1 || nonce_size == 2 || nonce_size == 4 || nonce_size == 8))
+                    {
+                        cerr<<"Unknown option: "<< argv[i] << endl;
+			usage(argv[0]);
+			exit(1);
+                    }
+                    ++i; // Skip over size argument
+                }
+                else if(string(argv[i])=="--exe-nonce-size" && 
+                        string(argv[i+1]).length()==1 && isdigit(string(argv[i+1])[0]))
+                {
+                    exe_nonce_size = stoi(string(argv[i+1]));
+                    if(!(exe_nonce_size == 1 || exe_nonce_size == 2 || exe_nonce_size == 4 || exe_nonce_size == 8))
+                    {
+                        cerr<<"Unknown option: "<< argv[i] << endl;
+			usage(argv[0]);
+			exit(1);
+                    }
+                    ++i; // Skip over size argument
+                }
+		else if(string(argv[i])=="--color")
 		{
 			cout<<"Using coloring..."<<endl;
 			do_coloring=true;
@@ -85,6 +115,16 @@ int main(int argc, char **argv)
 			cout<<"Not using coloring..."<<endl;
 			do_coloring=false;
 		}
+                else if(string(argv[i])=="--color-exe-nonces")
+		{
+			cout<<"Using coloring for exe nonces..."<<endl;
+			do_color_exe_nonces=true;
+		}
+		else if(string(argv[i])=="--no-color-exe-nonces")
+		{
+			cout<<"Not using coloring for exe nonces..."<<endl;
+			do_color_exe_nonces=false;
+		}
 		else if(string(argv[i])=="--protect-calls")
 		{
 			cout<<"protecting calls..."<<endl;
@@ -191,7 +231,7 @@ int main(int argc, char **argv)
 
                 try
                 {
-			SCFI_Instrument scfii(firp, do_coloring, do_common_slow_path, do_jumps, do_calls, do_rets, do_safefn, do_multimodule, do_exe_nonce_for_call);
+			SCFI_Instrument scfii(firp, nonce_size, exe_nonce_size, do_coloring, do_color_exe_nonces, do_common_slow_path, do_jumps, do_calls, do_rets, do_safefn, do_multimodule, do_exe_nonce_for_call);
 
 
 			int success=scfii.execute();
diff --git a/tools/selective_cfi/scfi_instr.cpp b/tools/selective_cfi/scfi_instr.cpp
index d61ee94167f853f7253b1084cdff48ae61c29c71..739da1ea7ad240316cd2fb1ba14b5bfb77543de7 100644
--- a/tools/selective_cfi/scfi_instr.cpp
+++ b/tools/selective_cfi/scfi_instr.cpp
@@ -114,22 +114,44 @@ assert(0);
 
 unsigned int SCFI_Instrument::GetExeNonceOffset(Instruction_t* insn)
 {
-        /* using executable nonce with 4 byte multi-byte nop
-         * (which is 3 byte opcode, 0x0F1F80). Note that multi-byte nops
-         *  are not supported on older processors (~< 2006) */
-	return -3;
+        if(exe_nonce_color_map)
+	{
+		assert(insn->GetIBTargets());
+                // We can't know the offset yet because this nonce may need to get
+                // shoved into multiple exe nonces, so just return the position.
+		cout << "EXE NONCE OFFSET IS: "<< exe_nonce_color_map->GetColorOfIB(insn).GetPosition() << endl;
+		return exe_nonce_color_map->GetColorOfIB(insn).GetPosition();
+	}
+        // Otherwise, only one nonce per target and it's always in the first position
+	return 0;
 }
 
 NonceValueType_t SCFI_Instrument::GetExeNonce(Instruction_t* insn)
 {
-	// using 0xAABBCCDD (coloring not yet supported)
-	return 0xaabbccdd;
+	if(exe_nonce_color_map)
+	{
+		assert(insn->GetIBTargets());
+		return exe_nonce_color_map->GetColorOfIB(insn).GetNonceValue();
+	}
+        // Otherwise, all nonces are the same
+        switch(exe_nonce_size)
+        {
+            case 1:
+                return 0xcc;
+            case 2:
+                return 0xbbcc;
+            case 4:
+                return 0xaabbccdd;
+            case 8:
+                return 0xaabbccdd00112233; 
+            default:
+                exit(1); // wat?
+        }
 }
 
 unsigned int SCFI_Instrument::GetExeNonceSize(Instruction_t* insn)
 {
-	//using 4 byte executable nonce
-	return 4;
+    return exe_nonce_size;
 }
 
 unsigned int SCFI_Instrument::GetNonceOffset(Instruction_t* insn)
@@ -151,14 +173,25 @@ NonceValueType_t SCFI_Instrument::GetNonce(Instruction_t* insn)
 		assert(insn->GetIBTargets());
 		return color_map->GetColorOfIB(insn).GetNonceValue();
 	}
-	return 0xf4;
+        // Otherwise, all nonces are the same
+	switch(nonce_size)
+        {
+            case 1:
+                return 0xcc;
+            case 2:
+                return 0xbbcc;
+            case 4:
+                return 0xaabbccdd;
+            case 8:
+		return 0xaabbccdd00112233;                
+            default:
+                exit(1); // wat?
+        }
 }
 
 unsigned int SCFI_Instrument::GetNonceSize(Instruction_t* insn)
 {
-	/* in time we look up the nonce size for this insn */
-	/* for now, it's just f4 as the nonce */
-	return 1;
+    return nonce_size;
 }
 
 bool SCFI_Instrument::mark_targets() 
@@ -199,7 +232,7 @@ bool SCFI_Instrument::mark_targets()
 			if(do_coloring)
 			{
 				ColoredSlotValues_t v=color_map->GetColorsOfIBT(insn);
-				int size=1;
+				int size=GetNonceSize(insn);
 				for(auto i=0U;i<v.size();i++)
 				{
 					if(!v[i].IsValid())
@@ -223,34 +256,74 @@ bool SCFI_Instrument::mark_targets()
 			}
 			else
 			{
-				// cfi_nonce=f4.
-				type="cfi_nonce=";
-				type+=to_string(GetNonce(insn));
-
+				type=string("cfi_nonce=(pos=") +  to_string(-((int) GetNonceOffset(insn))) + ",nv="
+                                    + to_string(GetNonce(insn)) + ",sz="+ to_string(GetNonceSize(insn))+ ")";
 				Relocation_t* reloc=create_reloc(insn);
-				reloc->SetOffset(-GetNonceOffset(insn));
+				reloc->SetOffset(-((int) GetNonceOffset(insn)));
 				reloc->SetType(type);
-				cout<<"Found nonce="+type+"  for "<<std::hex<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl;
+				cout<<"Created reloc='"+type+"' for "<<std::hex<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl;
 			}
 		}
 
 		if(do_exe_nonce_for_call && DecodedInstruction_t(insn).isCall()) 
                 {
 		    ++exe_nonce_targets;
-                    string type;
-                    if(do_coloring)
+                 
+                    if(do_color_exe_nonces)
                     {
-                        assert(0); //coloring not yet supported for exe nonces
+                        // The colors we want are not on the call, but on its return target.
+                        ColoredSlotValues_t v=exe_nonce_color_map->GetColorsOfIBT(insn->GetFallthrough());
+			
+			// The return target gets a regular nonce as well, so there may be an inserted jmp
+			// in the way of the original IBT that has our colors.
+			if(v.size() == 0)
+			{
+			    v=exe_nonce_color_map->GetColorsOfIBT(insn->GetFallthrough()->GetTarget());
+			}
+
+                        int nonceSz=GetExeNonceSize(insn); //Multiple sizes not yet supported	
+    
+                        for(auto i=0U;i<v.size();i++)
+                        {
+                            int noncePos;
+                            NonceValueType_t nonceVal;
+                            if(!v[i].IsValid())
+                            {
+                                // This position is not valid, but need to fill it with something anyway
+                                // because nonces are executable
+                                noncePos = i; //FIXME: BAD COUPLING. Relies on the fact that i == position number
+                                nonceVal = 0xc;
+                            }
+                            else
+                            {
+                                noncePos=v[i].GetPosition();
+                                nonceVal = v[i].GetNonceValue();
+                            }
+                            PlaceExeNonceReloc(insn, nonceVal, nonceSz, noncePos);
+                        }
+                        // Place exe nonce reloc to fill extra space (if any)
+                        int isExtraSpace = (v.size()*nonceSz) % EXE_NONCE_ARG_SIZE;
+                        if(isExtraSpace)
+                        {
+                            int extraSpace = EXE_NONCE_ARG_SIZE - ((v.size()*nonceSz) % EXE_NONCE_ARG_SIZE);
+                            int extraSpacePos = v.size();
+                            int extraSpaceBytePos = GetNonceBytePos(nonceSz, extraSpacePos-1)+nonceSz;
+                            CreateExeNonceReloc(insn, 0, extraSpace, extraSpaceBytePos);
+                        }
                     }
                     else
                     {
-                        type="cfi_exe_nonce=";
-                        type+=to_string(GetExeNonce(insn));
-
-                        Relocation_t* reloc=create_reloc(insn);
-                        reloc->SetOffset(-GetExeNonceOffset(insn));
-                        reloc->SetType(type);
-                        cout<<"Found nonce="+type+"  for "<<std::hex<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl;
+                    	int nonceSz = GetExeNonceSize(insn);
+                        PlaceExeNonceReloc(insn, GetExeNonce(insn), nonceSz, GetExeNonceOffset(insn));
+                        // Place exe nonce reloc to fill extra space (if any)
+                        int isExtraSpace = nonceSz % EXE_NONCE_ARG_SIZE;
+                        if(isExtraSpace)
+                        {
+                            int extraSpace = EXE_NONCE_ARG_SIZE - (nonceSz % EXE_NONCE_ARG_SIZE);
+                            int extraSpacePos = 1;
+                            int extraSpaceBytePos = GetNonceBytePos(nonceSz, extraSpacePos-1)+nonceSz;
+                            CreateExeNonceReloc(insn, 0, extraSpace, extraSpaceBytePos);
+                        } 
                     }
                 } 
 	}
@@ -260,6 +333,110 @@ bool SCFI_Instrument::mark_targets()
 	return true;
 }
 
+
+void SCFI_Instrument::CreateExeNonceReloc(Instruction_t* insn, NonceValueType_t nonceVal, int nonceSz, int bytePos) 
+{
+    string type=string("cfi_exe_nonce=(pos=") +  to_string(bytePos) + ",nv="
+        + to_string(nonceVal) + ",sz="+ to_string(nonceSz)+ ")";
+    Relocation_t* reloc=create_reloc(insn);
+    reloc->SetOffset(bytePos);
+    reloc->SetType(type);
+    cout<<"Created reloc='"+type+"' for "<<std::hex<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl;
+}
+
+
+int SCFI_Instrument::GetNonceBytePos(int nonceSz, int noncePos)
+{
+    // To get to the nonce, we must pass over noncePos other nonces, which may involve
+    // jumping over some exe nonce opcodes, depending on the exe nonce argument size.
+    int nonceBytePos =   (((noncePos*nonceSz)/EXE_NONCE_ARG_SIZE)+1)*EXE_NONCE_OPCODE_SIZE
+                            + noncePos*nonceSz;
+    return nonceBytePos;
+}
+
+
+/* Nonces are just bit strings. To fit them into exe
+ * nonces that have a limited argument size, they may need to
+ * be split over more than one exe nonce. To be stored as tightly 
+ * as possible, more than one nonce may be fit into one exe nonce. 
+ * 
+ * To handle this, the GetExeNonceFit function returns a list
+ * of one or more NonceParts that together specify where in memory 
+ * the complete nonce string is located.
+ * This function makes some CRITICAL ASSUMPTIONS. Look at the function definition in scfi_instr.hpp */
+std::vector<SCFI_Instrument::NoncePart_t> SCFI_Instrument::GetExeNonceFit(NonceValueType_t nonceVal, int nonceSz, int noncePos)
+{
+    // Checking an assumption
+    if(nonceSz > EXE_NONCE_ARG_SIZE)
+        assert(nonceSz % EXE_NONCE_ARG_SIZE == 0);
+    else
+        assert(EXE_NONCE_ARG_SIZE % nonceSz == 0);
+    
+    // If our nonce will fit into a single exe nonce
+    if(EXE_NONCE_ARG_SIZE >= nonceSz)
+    {
+        // To get to our nonce, we must pass over noncePos other nonces, which may involve
+        // jumping over some exe nonce opcodes, depending on the exe nonce argument size.
+        int nonceBytePos =   GetNonceBytePos(nonceSz, noncePos);
+        std::vector<NoncePart_t> noncePartList;
+        NoncePart_t nonce = {nonceVal, nonceBytePos, nonceSz};
+        noncePartList.push_back(nonce);
+        return noncePartList;
+    } 
+    else //Otherwise, our nonce will have to be split over multiple exe nonces
+    {
+        // We will be dividing the nonce into nonceSz/EXE_NONCE_ARG_SIZE nonce parts,
+        // and each part corresponds to one entire exe nonce.
+         
+        std::vector<NoncePart_t> noncePartList;
+        for(int exeNonceIndex=0; exeNonceIndex < nonceSz/EXE_NONCE_ARG_SIZE; exeNonceIndex++)
+        {
+            // Calculate our nonce part info. The idea is to treat
+            // the nonce part as if it were a complete nonce in a scenario where
+            // nonce size = exe nonce arg size. This requires recalculation of the
+            // nonce position.
+            
+            int noncePartSz = EXE_NONCE_ARG_SIZE;
+            int noncePartPos = exeNonceIndex + noncePos*(nonceSz/EXE_NONCE_ARG_SIZE);
+            int noncePartBytePos = GetNonceBytePos(noncePartSz, noncePartPos);
+    
+            NonceValueType_t mask = 0;
+	    mask = ~mask;
+            NonceValueType_t noncePartVal =  (nonceVal >> exeNonceIndex*EXE_NONCE_ARG_SIZE*8)
+                               & (mask >> (8-EXE_NONCE_ARG_SIZE)*8);
+ 	    cout << "CALCD NONCE BYTE POS AS: " << noncePartBytePos << endl;            
+            // Store the calculated nonce part info
+            NoncePart_t part = {noncePartVal, noncePartBytePos, noncePartSz};
+            noncePartList.push_back(part);
+        }
+        return noncePartList;
+    }
+}
+
+
+// This function supports marking targets for colored 1, 2, 4, or 8 byte exe nonces.
+// The exe nonce argument sizes can be 1, 2, 4, or 8 bytes.
+void SCFI_Instrument::PlaceExeNonceReloc(Instruction_t* insn, NonceValueType_t nonceVal, int nonceSz, int noncePos)
+{   
+    // Get the nonce parts our nonce will be divided into to fit into the exe nonces
+    std::vector<NoncePart_t> nonceParts = GetExeNonceFit(nonceVal, nonceSz, noncePos);
+    // Create exe nonce relocs for each part.
+    for(std::vector<NoncePart_t>::iterator it = nonceParts.begin(); it != nonceParts.end(); ++it)
+    {
+        NoncePart_t theNoncePart = *it;
+        // If this nonce part is next to an exe nonce opcode, create a reloc for the opcode too
+        bool nextToExeNonceOpCode = !((noncePos*nonceSz) % EXE_NONCE_ARG_SIZE);
+        if(nextToExeNonceOpCode)
+        {
+            CreateExeNonceReloc(insn, EXE_NONCE_OPCODE_VAL, EXE_NONCE_OPCODE_SIZE,
+                                      theNoncePart.bytePos-EXE_NONCE_OPCODE_SIZE   );
+        }
+        // Create an exe nonce reloc for the nonce part.
+        CreateExeNonceReloc(insn, theNoncePart.val, theNoncePart.size, theNoncePart.bytePos);
+    }
+}
+
+
 /*
  * targ_change_to_push - use the mode in the insnp to create a new instruction that is a push instruction.
  */
@@ -341,13 +518,6 @@ static void move_relocs(Instruction_t* from, Instruction_t* to)
 void SCFI_Instrument::AddJumpCFI(Instruction_t* insn)
 {
 	assert(do_rets);
-	ColoredSlotValue_t v2;
-	if(insn->GetIBTargets() && color_map)
-		v2=color_map->GetColorOfIB(insn);
-	ColoredSlotValue_t *v=&v2;
-	string reg="ecx";	// 32-bit reg 
-	if(firp->GetArchitectureBitWidth()==64)
-		reg="rcx";	// 64-bit reg.
 
 	string pushbits=change_to_push(insn);
 	cout<<"Converting ' "<<insn->getDisassembly()<<"' to '";
@@ -359,26 +529,30 @@ void SCFI_Instrument::AddJumpCFI(Instruction_t* insn)
 
 	// move any pc-rel relocation bits to the push, which will access memory now 
 	mov_reloc(after,insn,"pcrel");
-	after->SetIBTargets(insn->GetIBTargets());
-	insn->SetIBTargets(NULL);
-
-	AddReturnCFI(after,v);
+	
+	if(do_exe_nonce_for_call)
+        {
+            // This may be inefficient b/c jumps will not normally be targeting 
+            // return targets. However, that does happen in multimodule returns
+            // so this is needed.
+            AddReturnCFIForExeNonce(after);
+        }
+        else
+        {
+            AddReturnCFI(after);
+        }
 	// cout<<"Warning, JUMPS not CFI's yet"<<endl;
 	return;
 }
 
-//TODO: Does not work with coloring
+
 void SCFI_Instrument::AddCallCFIWithExeNonce(Instruction_t* insn)
 {
 	string reg="ecx";       // 32-bit reg 
         if(firp->GetArchitectureBitWidth()==64)
                 reg="r11";      // 64-bit reg.
 
-	string decoration="";
-        int nonce_size=GetNonceSize(insn);
-        int nonce_offset=GetNonceOffset(insn);
-        unsigned int nonce=GetNonce(insn);
-        Instruction_t* call=NULL, *jne=NULL, *stub=NULL;
+        Instruction_t* call=NULL, *stub=NULL;
 
 
         // convert a call indtarg to:
@@ -389,19 +563,7 @@ void SCFI_Instrument::AddCallCFIWithExeNonce(Instruction_t* insn)
         //stub: cmp <nonce size> PTR [ecx-<nonce size>], Nonce
         //      jne slow
 	//	jmp reg          
-
-        switch(nonce_size)
-        {
-                case 1:
-                        decoration="byte ";
-                        break;
-                case 2: // handle later
-                case 4: // handle later
-                default:
-                        cerr<<"Cannot handle nonce of size "<<std::dec<<nonce_size<<endl;
-                        assert(0);
-
-        }
+ 
 
         // insert the pop/checking code.
 	string pushbits=change_to_push(insn);
@@ -412,18 +574,23 @@ void SCFI_Instrument::AddCallCFIWithExeNonce(Instruction_t* insn)
 	insn->GetRelocations()=call->GetRelocations();
 	call->GetRelocations().clear();
 
-        stub=addNewAssembly(firp,stub,string("cmp ")+decoration+
-                " ["+reg+"-"+to_string(nonce_offset)+"], "+to_string(nonce));
-        jne=insertAssemblyAfter(firp,stub,"jne 0");
-	insertAssemblyAfter(firp,jne,string("jmp ")+reg);
-
-        // set the jne's target to itself, and create a reloc that zipr/strata will have to resolve.
-        jne->SetTarget(jne);    // needed so spri/spasm/irdb don't freak out about missing target for new insn.
-        Relocation_t* reloc=create_reloc(jne);
-        reloc->SetType("slow_cfi_path");
-        reloc->SetOffset(0);
-        cout<<"Setting slow path for: "<<"slow_cfi_path"<<endl;
-
+       	// Jump to non-exe nonce check code
+	stub = addNewAssembly(firp, NULL, string("push ")+reg);
+    	Instruction_t* ret = insertDataBitsAfter(firp, stub, getRetDataBits());
+    	ret->SetIBTargets(call->GetIBTargets());
+	
+        if(do_exe_nonce_for_call)
+        {
+            // This may be inefficient b/c jumps will not normally be targeting 
+            // return targets. However, that does happen in multimodule returns
+            // so this is needed.
+            AddReturnCFIForExeNonce(ret);
+        }
+        else
+        {
+            AddReturnCFI(ret);
+        }	
+ 
 	// convert the indirct call to a direct call to the stub.
         string call_bits=call->GetDataBits();
         call_bits.resize(5);
@@ -442,10 +609,75 @@ void SCFI_Instrument::AddExecutableNonce(Instruction_t* insn)
 //	insertDataBitsAfter(firp, insn, ExecutableNonceValue, NULL);
 }
 
+// Returns the insn starting a non-exe nonce check for an insn, in case the exe nonce check fails
+Instruction_t* SCFI_Instrument::GetExeNonceSlowPath(Instruction_t* insn)
+{
+    // Jump to non-exe nonce check code
+    Instruction_t* ret = addNewDatabits(firp, NULL, getRetDataBits());
+    ret->SetIBTargets(insn->GetIBTargets()); 
+    AddReturnCFI(ret);
+    return ret;
+}
+
+
+// This function supports nonce checks for 1, 2, 4, or 8 byte nonces
+// with 1, 2, 4, or 4 byte exe nonce argument sizes.
+// TODO: Support 8 byte exe nonce arg sizes
+void SCFI_Instrument::InsertExeNonceComparisons(Instruction_t* insn, 
+        NonceValueType_t nonceVal, int nonceSz, int noncePos, 
+        Instruction_t* exeNonceSlowPath)
+{
+    
+    int noncePartSz; 
+    if(nonceSz > EXE_NONCE_ARG_SIZE)
+        noncePartSz = EXE_NONCE_ARG_SIZE;
+    else
+        noncePartSz = nonceSz;
+    
+    string reg="ecx";	// 32-bit reg 
+    if(firp->GetArchitectureBitWidth()==64)
+        reg="r11";	// 64-bit reg.
+    
+    string decoration="";
+    switch(noncePartSz)
+    {
+        case 8:
+            cerr<<"Cannot handle nonce part of size "<<std::dec<<nonceSz<<endl;
+            assert(0);
+	    break;
+        case 4: 
+            decoration="dword ";
+            break;
+        case 2:	// handle later
+            decoration="word ";
+            break;
+        case 1: //handle later
+            decoration="byte ";
+            break;
+	default:
+            cerr<<"Cannot handle nonce of size "<<std::dec<<nonceSz<<endl;
+            assert(0);		
+    }
+    
+    // Get the nonce parts our nonce will be divided into to fit into the exe nonces
+    std::vector<NoncePart_t> nonceParts = GetExeNonceFit(nonceVal, nonceSz, noncePos);
+    // Create exe nonce comparisons for each part.
+    Instruction_t* tmp = insn;
+    Instruction_t* jne=NULL;
+    for(std::vector<NoncePart_t>::iterator it = nonceParts.begin(); it != nonceParts.end(); ++it)
+    {
+        NoncePart_t theNoncePart = *it;
+	cout << "ADDING CMP FOR BYTE POS: " << theNoncePart.bytePos << "FOR NONCE WITH POSITION: " << noncePos << "AND SIZE: " << nonceSz << endl;
+        tmp=insertAssemblyAfter(firp,tmp,string("cmp ")+decoration+
+		" ["+reg+"+"+to_string(theNoncePart.bytePos)+"], "+to_string(theNoncePart.val));
+        jne=tmp=insertAssemblyAfter(firp,tmp,"jne 0");
+        jne->SetTarget(exeNonceSlowPath);
+    }
+}
+
 
 void SCFI_Instrument::AddReturnCFIForExeNonce(Instruction_t* insn, ColoredSlotValue_t *v)
 {
-	assert(!do_coloring);
 
 	if(!do_rets)
 		return;
@@ -482,15 +714,18 @@ void SCFI_Instrument::AddReturnCFIForExeNonce(Instruction_t* insn, ColoredSlotVa
 
 		// rewrite the "old" isntruction, as that's what insertAssemblyBefore returns
 		insn=newafter;
+		//Needed b/c AddReturnCFI may be called on this ret insn
+                //But also clean up and change ret_with_pop to ret (as it should be now) to be safe
+                setInstructionAssembly(firp,insn, string("ret"), insn->GetFallthrough(), insn->GetTarget()); 
 	}
+        //TODO: Handle uncommon slow path
 		
-	//TODO: Fix possible TOCTOU race condition (see Abadi CFI paper)
+	//TODO: Fix possible TOCTOU race condition? (see Abadi CFI paper)
 	//	Ret address can be changed between nonce check and ret insn execution (in theory)
-        string decoration="";
 	int nonce_size=GetExeNonceSize(insn);
-	int nonce_offset=-GetExeNonceOffset(insn);
-	unsigned int nonce=GetExeNonce(insn);
-	Instruction_t* jne=NULL, *tmp=NULL;
+	int nonce_pos=GetExeNonceOffset(insn);
+	NonceValueType_t nonce=GetExeNonce(insn);
+        Instruction_t* exeNonceSlowPath = GetExeNonceSlowPath(insn);
 	
 
 	// convert a return to:
@@ -498,32 +733,11 @@ void SCFI_Instrument::AddReturnCFIForExeNonce(Instruction_t* insn, ColoredSlotVa
 	// 	cmp <nonce size> PTR [ecx+<offset>], Nonce
 	// 	jne exit_node	; no need for slow path here			
 	// 	ret             ; ignore race condition for now
-        
-        switch(nonce_size)
-	{
-                case 4: 
-                    decoration="dword ";
-                    break;
-		case 1: //handle later
-		case 2:	// handle later
-		default:
-			cerr<<"Cannot handle nonce of size "<<std::dec<<nonce_size<<endl;
-			assert(0);
-		
-	}
 
-	// insert the pop/checking code.
+	// insert the mov/checking code.
 	insertAssemblyBefore(firp,insn,string("mov ")+reg+string(", [")+rspreg+string("]"));
-	tmp=insertAssemblyAfter(firp,insn,string("cmp ")+decoration+
-		" ["+reg+"+"+to_string(nonce_offset)+"], "+to_string(nonce));
-        jne=tmp=insertAssemblyAfter(firp,tmp,"jne 0");
-        // set the jne's target to itself, and create a reloc that zipr/strata will have to resolve.
-	jne->SetTarget(jne);	// needed so spri/spasm/irdb don't freak out about missing target for new insn.
-	Relocation_t* reloc=create_reloc(jne);
-	reloc->SetType("exit_node"); 
-	reloc->SetOffset(0);
-	cout<<"Setting exit node"<<endl;
-	// leave the ret instruction (risk of successful race condition exploit << performance benefit)
+        InsertExeNonceComparisons(insn, nonce, nonce_size, nonce_pos, exeNonceSlowPath);
+       	// leave the ret instruction (risk of successful race condition exploit << performance benefit)
 
 	return;
 	
@@ -573,6 +787,8 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v)
 
 		// rewrite the "old" isntruction, as that's what insertAssemblyBefore returns
 		insn=newafter;
+		//Clean up and change ret_with_pop to ret (as it should be now) to be safe
+                setInstructionAssembly(firp,insn, string("ret"), insn->GetFallthrough(), insn->GetTarget()); 
 	}
 		
 	int size=1;
@@ -603,7 +819,7 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v)
 	string decoration="";
 	int nonce_size=GetNonceSize(insn);
 	int nonce_offset=GetNonceOffset(insn);
-	unsigned int nonce=GetNonce(insn);
+	NonceValueType_t nonce=GetNonce(insn);
 	Instruction_t* jne=NULL, *tmp=NULL;
 	
 
@@ -617,10 +833,17 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v)
 	switch(nonce_size)
 	{
 		case 1:
-			decoration="byte ";
-			break;
+                    decoration="byte ";
+                    break;
 		case 2:	// handle later
+                    decoration="word ";
+                    break;
 		case 4: // handle later
+                    decoration="dword ";
+                    break;
+                case 8:
+                    decoration="dword "; // 8 byte nonces will be split into 2 compares
+                    break;
 		default:
 			cerr<<"Cannot handle nonce of size "<<std::dec<<nonce_size<<endl;
 			assert(0);
@@ -629,10 +852,27 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v)
 
 	// insert the pop/checking code.
 	insertAssemblyBefore(firp,insn,string("pop ")+reg);
-	tmp=insertAssemblyAfter(firp,insn,string("cmp ")+decoration+
+        if(nonce_size != 8)
+        {
+            tmp=insertAssemblyAfter(firp,insn,string("cmp ")+decoration+
 		" ["+reg+"-"+to_string(nonce_offset)+"], "+to_string(nonce));
-    jne=tmp=insertAssemblyAfter(firp,tmp,"jne 0");
-
+        }
+        else
+        {
+            tmp=insertAssemblyAfter(firp,insn,string("cmp ")+decoration+
+		" ["+reg+"-"+to_string(nonce_offset)+"], "+to_string((uint32_t) nonce)); // upper 32 bits chopped off by cast
+            jne=tmp=insertAssemblyAfter(firp,tmp,"jne 0");
+            tmp=insertAssemblyAfter(firp,tmp,string("cmp ")+decoration+
+		" ["+reg+"-"+to_string(nonce_offset - 4)+"], "+to_string((uint32_t) (nonce >> 32)));
+            // set the jne's target to itself, and create a reloc that zipr/strata will have to resolve.
+            jne->SetTarget(jne);	// needed so spri/spasm/irdb don't freak out about missing target for new insn.
+            Relocation_t* reloc=create_reloc(jne);
+            reloc->SetType(slow_cfi_path_reloc_string); 
+            reloc->SetOffset(0);
+            cout<<"Setting slow path for: "<<slow_cfi_path_reloc_string<<endl;
+        }
+        
+        jne=tmp=insertAssemblyAfter(firp,tmp,"jne 0");
 	// convert the ret instruction to a jmp ecx
 	cout<<"Converting "<<hex<<tmp->GetFallthrough()->GetBaseID()<<":"<<tmp->GetFallthrough()->getDisassembly()<<"to jmp+reg"<<endl;
 	setInstructionAssembly(firp,tmp->GetFallthrough(), string("jmp ")+reg, NULL,NULL);
@@ -643,7 +883,7 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v)
 	reloc->SetType(slow_cfi_path_reloc_string); 
 	reloc->SetOffset(0);
 	cout<<"Setting slow path for: "<<slow_cfi_path_reloc_string<<endl;
-
+	
 	return;
 }
 
@@ -1347,12 +1587,31 @@ bool SCFI_Instrument::execute()
 	// do not move later.
 	if(do_coloring)
 	{
-		color_map.reset(new ColoredInstructionNonces_t(firp)); 
+		color_map.reset(new ColoredInstructionNonces_t(firp, nonce_size)); 
 		assert(color_map);
 		success = success && color_map->build();
 	
 	}
-	
+        
+	if(do_color_exe_nonces)
+        {
+            // A separate color map is created for exe nonces so that exe and 
+            // non-exe colored nonces can be different sizes.
+            // Note that these independent color slots will not conflict with
+            // the non-exe slots, but ONLY because exe nonces come after a target,
+            // while non-exe nonces come before.
+            exe_nonce_color_map.reset(new ColoredInstructionNonces_t(firp, exe_nonce_size)); 
+            assert(exe_nonce_color_map);
+            success = success && exe_nonce_color_map->build();
+            // Note that it is in theory possible (but I'm assuming unlikely) that 
+            // unnecessary colored exe nonce slots will be added due to 
+            // insn's sharing the same IBTs on func ret sites but having 
+            // differing IBT's on non-func ret sites. (Because we reuse the non-exe
+            // nonce color map, which pays attention to all IBT's and
+            // not just the IBT's that target func ret sites, yet we are only putting
+            // exe nonces on func ret sites).
+        }
+        
 	success = success && instrument_jumps();	// to handle moving of relocs properly if
 							// an insn is both a IBT and a IB,
 							// we instrument first, then add relocs for targets
diff --git a/tools/selective_cfi/scfi_instr.hpp b/tools/selective_cfi/scfi_instr.hpp
index 30cbcd06d422ddbb647aadd31a0f64bbc9996369..93f3568fca18686e1410de5e95e36a42929e5414 100644
--- a/tools/selective_cfi/scfi_instr.hpp
+++ b/tools/selective_cfi/scfi_instr.hpp
@@ -34,7 +34,10 @@ class SCFI_Instrument
 {
 	public:
 		SCFI_Instrument(libIRDB::FileIR_t *the_firp, 
+                                int p_nonce_size=1,
+                                int p_exe_nonce_size=4,
 				bool p_do_coloring=true,
+                                bool p_do_color_exe_nonces=true,
 				bool p_do_common_slow_path=true,
 				bool p_do_jumps=false,
 				bool p_do_calls=true,
@@ -45,7 +48,10 @@ class SCFI_Instrument
 			) 
 			: 
 		  	  firp(the_firp), 
+                          nonce_size(p_nonce_size),
+                          exe_nonce_size(p_exe_nonce_size),
 			  do_coloring(p_do_coloring), 
+                          do_color_exe_nonces(p_do_color_exe_nonces),
 			  do_common_slow_path(p_do_common_slow_path), 
 			  do_jumps(p_do_jumps), 
 			  do_calls(p_do_calls), 
@@ -59,6 +65,7 @@ class SCFI_Instrument
 		{ 
 			std::cout<<std::boolalpha;
 			std::cout<<"# ATTRIBUTE Selective_Control_Flow_Integrity::do_coloring="<<p_do_coloring<<std::endl;
+                        std::cout<<"# ATTRIBUTE Selective_Control_Flow_Integrity::do_color_exe_nonces="<<p_do_color_exe_nonces<<std::endl;
 			std::cout<<"# ATTRIBUTE Selective_Control_Flow_Integrity::do_common_slow_path="<<p_do_common_slow_path<<std::endl;
 			std::cout<<"# ATTRIBUTE Selective_Control_Flow_Integrity::do_jumps="<<p_do_jumps<<std::endl;
 			std::cout<<"# ATTRIBUTE Selective_Control_Flow_Integrity::do_calls="<<p_do_calls<<std::endl;
@@ -67,11 +74,6 @@ class SCFI_Instrument
 			std::cout<<"# ATTRIBUTE Selective_Control_Flow_Integrity::do_multimodule="<<p_do_multimodule<<std::endl;
 			preds.AddFile(the_firp); 
 
-			if(do_exe_nonce_for_call && p_do_coloring)
-			{
-				std::cerr<<"Cannot do coloring+exe_nonce_for_call!"<<std::endl;
-				exit(1);
-			}
 		}
 		bool execute();
 
@@ -101,6 +103,7 @@ class SCFI_Instrument
 		bool instrument_jumps();
 
 		// helper
+                libIRDB::Instruction_t* GetExeNonceSlowPath(libIRDB::Instruction_t* insn);
 		libIRDB::Relocation_t* create_reloc(libIRDB::Instruction_t* insn);
 		libIRDB::Relocation_t* FindRelocation(libIRDB::Instruction_t* insn, std::string type);
 		bool isSafeFunction(libIRDB::Instruction_t* insn);
@@ -141,19 +144,54 @@ class SCFI_Instrument
 		// predecessors of instructions.
 		libIRDB::InstructionPredecessors_t preds;
 		libIRDB::FileIR_t* firp;
-		bool do_coloring;
-		bool do_common_slow_path;
-		bool do_jumps;
-		bool do_calls;
-		bool do_rets;
-		bool do_multimodule;
-		bool protect_safefn;
-		bool do_exe_nonce_for_call;
+                const int nonce_size;
+                const int exe_nonce_size;
+		const bool do_coloring;
+                const bool do_color_exe_nonces;
+		const bool do_common_slow_path;
+		const bool do_jumps;
+		const bool do_calls;
+		const bool do_rets;
+		const bool do_multimodule;
+		const bool protect_safefn;
+		const bool do_exe_nonce_for_call;
 		std::unique_ptr<ColoredInstructionNonces_t> color_map;
-		libIRDB::Instruction_t *ret_shared;
+                std::unique_ptr<ColoredInstructionNonces_t> exe_nonce_color_map;
+		const libIRDB::Instruction_t *ret_shared;
 		libIRDB::Instruction_t *zestcfi_function_entry;
 		std::string ExecutableNonceValue;
+                
+                // Exe Nonce helpers
+                const int EXE_NONCE_OPCODE_SIZE = 3;
+                // Enter opcode val in reverse-byte order, as nonce_relocs reverses the bytes before placement
+                // (The nonce values themselves are placed little endian, but the opcode should be placed big-endian)
+                const int EXE_NONCE_OPCODE_VAL = 0x801F0F; // actual opcode = 0x0F1F80
+                const int EXE_NONCE_ARG_SIZE = 4;
+                /* Nonces are just bit strings. To fit them into exe
+                 * nonces that have a limited argument size, they may need to
+                 * be split over more than one exe nonce. To be stored as tightly 
+                 * as possible, more than one nonce may be fit into one exe nonce. 
+                 * 
+                 * To handle this, the GetExeNonceFit function returns a list
+                 * of one or more NonceParts that together specify where in memory
+                 * the complete nonce string is located. */
+                struct NoncePart_t {
+                    NonceValueType_t val;
+                    int bytePos;
+                    int size;
+                };
+                /* CRITICAL ASSUMPTIONS:
+                 *   1.) The exe nonce being used is constant throughout the module.
+                 *       (It's opcode size, argument size, and opcode value should be constant).
+                 *   2.) No nonce is split across exe nonces unless it completely fills all of them.
+                 *       (i.e. nonceSize % argSize == 0 OR argSize % nonceSize == 0).  
+                 */
+                std::vector<NoncePart_t> GetExeNonceFit(NonceValueType_t nonceVal, int nonceSz, int noncePos);
+		int GetNonceBytePos(int nonceSz, int noncePos);
+                void CreateExeNonceReloc(libIRDB::Instruction_t* insn, NonceValueType_t nonceVal, int nonceSz, int bytePos);
+                void PlaceExeNonceReloc(libIRDB::Instruction_t* insn, NonceValueType_t nonceVal, int nonceSz, int noncePos);
+                void InsertExeNonceComparisons(libIRDB::Instruction_t* insn, NonceValueType_t nonceVal, int nonceSz, 
+                                                              int noncePos, libIRDB::Instruction_t* exeNonceSlowPath );
 };
 
 #endif
-
diff --git a/tools/selective_cfi/tests/cfi_all_configs.sh b/tools/selective_cfi/tests/cfi_all_configs.sh
new file mode 100644
index 0000000000000000000000000000000000000000..44eaa1343a544c3021145253844e37adf292d386
--- /dev/null
+++ b/tools/selective_cfi/tests/cfi_all_configs.sh
@@ -0,0 +1,444 @@
+#!/bin/bash
+
+configs=(do_cfi 
+	do_cfi_2_byte 
+	do_cfi_4_byte 
+	do_cfi_8_byte 
+	do_coloring_cfi 
+	do_coloring_cfi_2_byte
+        do_coloring_cfi_4_byte 
+	do_coloring_cfi_8_byte 
+	do_cfi_exe_nonces 
+	do_cfi_exe_nonces_1_byte
+	do_cfi_exe_nonces_2_byte 
+	do_cfi_exe_nonces_8_byte 
+	do_cfi_exe_nonces_2_byte_non_exe
+  	do_cfi_exe_nonces_4_byte_non_exe 
+	do_cfi_exe_nonces_8_byte_non_exe 
+	do_cfi_exe_nonces_1_byte_2_byte_non_exe 
+	do_cfi_exe_nonces_1_byte_4_byte_non_exe
+  	do_cfi_exe_nonces_1_byte_8_byte_non_exe 
+	do_cfi_exe_nonces_2_byte_2_byte_non_exe
+	do_cfi_exe_nonces_2_byte_4_byte_non_exe 
+	do_cfi_exe_nonces_2_byte_8_byte_non_exe
+	do_cfi_exe_nonces_8_byte_2_byte_non_exe 
+	do_cfi_exe_nonces_8_byte_4_byte_non_exe
+	do_cfi_exe_nonces_8_byte_8_byte_non_exe 
+	do_cfi_exe_nonces_color_non_exe 
+	do_cfi_exe_nonces_1_byte_color_non_exe 
+	do_cfi_exe_nonces_2_byte_color_non_exe 
+	do_cfi_exe_nonces_8_byte_color_non_exe 
+	do_cfi_exe_nonces_2_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_4_byte_non_exe_color_non_exe 
+	do_cfi_exe_nonces_8_byte_non_exe_color_non_exe	 		
+	do_cfi_exe_nonces_1_byte_2_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_1_byte_4_byte_non_exe_color_non_exe 			
+	do_cfi_exe_nonces_1_byte_8_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_2_byte_2_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_2_byte_4_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_2_byte_8_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_8_byte_2_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_8_byte_4_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_8_byte_8_byte_non_exe_color_non_exe
+	do_cfi_exe_nonces_color_exe
+	do_cfi_exe_nonces_1_byte_color_exe
+	do_cfi_exe_nonces_2_byte_color_exe
+	do_cfi_exe_nonces_8_byte_color_exe
+	do_cfi_exe_nonces_2_byte_non_exe_color_exe
+	do_cfi_exe_nonces_4_byte_non_exe_color_exe
+	do_cfi_exe_nonces_8_byte_non_exe_color_exe
+	do_cfi_exe_nonces_1_byte_2_byte_non_exe_color_exe
+	do_cfi_exe_nonces_1_byte_4_byte_non_exe_color_exe
+	do_cfi_exe_nonces_1_byte_8_byte_non_exe_color_exe
+	do_cfi_exe_nonces_2_byte_2_byte_non_exe_color_exe
+	do_cfi_exe_nonces_2_byte_4_byte_non_exe_color_exe
+	do_cfi_exe_nonces_2_byte_8_byte_non_exe_color_exe
+	do_cfi_exe_nonces_8_byte_2_byte_non_exe_color_exe
+	do_cfi_exe_nonces_8_byte_4_byte_non_exe_color_exe
+	do_cfi_exe_nonces_8_byte_8_byte_non_exe_color_exe
+	do_cfi_exe_nonces_color_both
+	do_cfi_exe_nonces_1_byte_color_both
+	do_cfi_exe_nonces_2_byte_color_both
+	do_cfi_exe_nonces_8_byte_color_both
+	do_cfi_exe_nonces_2_byte_non_exe_color_both
+	do_cfi_exe_nonces_4_byte_non_exe_color_both
+	do_cfi_exe_nonces_8_byte_non_exe_color_both
+	do_cfi_exe_nonces_1_byte_2_byte_non_exe_color_both
+	do_cfi_exe_nonces_1_byte_4_byte_non_exe_color_both
+	do_cfi_exe_nonces_1_byte_8_byte_non_exe_color_both
+	do_cfi_exe_nonces_2_byte_2_byte_non_exe_color_both
+	do_cfi_exe_nonces_2_byte_4_byte_non_exe_color_both
+	do_cfi_exe_nonces_2_byte_8_byte_non_exe_color_both
+	do_cfi_exe_nonces_8_byte_2_byte_non_exe_color_both
+	do_cfi_exe_nonces_8_byte_4_byte_non_exe_color_both
+	do_cfi_exe_nonces_8_byte_8_byte_non_exe_color_both)
+
+do_cfi()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false"
+}
+
+do_cfi_2_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 2"
+}
+
+do_cfi_4_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4"
+}
+
+do_cfi_8_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 8"
+}
+
+###############################################################################
+
+do_coloring_cfi()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false"
+}
+
+do_coloring_cfi_2_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 2"
+}
+
+do_coloring_cfi_4_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4"
+}
+
+do_coloring_cfi_8_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 8"
+}
+
+###############################################################################
+
+do_cfi_exe_nonces()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false"
+}
+
+do_cfi_exe_nonces_1_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1"
+}
+
+do_cfi_exe_nonces_2_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2"
+}
+
+do_cfi_exe_nonces_8_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8"
+}
+
+do_cfi_exe_nonces_2_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 2"
+}
+
+do_cfi_exe_nonces_4_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4"
+}
+
+do_cfi_exe_nonces_8_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 8"
+}
+
+do_cfi_exe_nonces_1_byte_2_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 2"
+}
+
+do_cfi_exe_nonces_1_byte_4_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 4"
+}
+
+do_cfi_exe_nonces_1_byte_8_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 8"
+}
+
+do_cfi_exe_nonces_2_byte_2_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 2"
+}
+
+do_cfi_exe_nonces_2_byte_4_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 4"
+}
+
+do_cfi_exe_nonces_2_byte_8_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 8"
+}
+
+do_cfi_exe_nonces_8_byte_2_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 2"
+}
+
+do_cfi_exe_nonces_8_byte_4_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 4"
+}
+
+do_cfi_exe_nonces_8_byte_8_byte_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 8"
+}
+
+###############################################################################
+
+do_cfi_exe_nonces_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_1_byte_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_4_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_1_byte_2_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_1_byte_4_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_1_byte_8_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_2_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_4_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_8_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_2_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_4_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_8_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color
+}
+
+###############################################################################
+
+do_cfi_exe_nonces_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_1_byte_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_2_byte_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_8_byte_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_2_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_4_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_8_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_1_byte_2_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_1_byte_4_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_1_byte_8_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_2_byte_2_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_2_byte_4_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_2_byte_8_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_8_byte_2_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_8_byte_4_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_8_byte_8_byte_non_exe_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color-exe-nonces
+}
+
+###############################################################################
+
+do_cfi_exe_nonces_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_1_byte_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_4_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_1_byte_2_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_1_byte_4_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_1_byte_8_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_2_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_4_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_2_byte_8_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 2" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_2_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 2" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_4_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte_8_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:"--nonce-size 8" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+} 
diff --git a/tools/selective_cfi/tests/cfi_smokescreen_configs.sh b/tools/selective_cfi/tests/cfi_smokescreen_configs.sh
new file mode 100644
index 0000000000000000000000000000000000000000..8b5d6d2e62ad04f6831db4193254b7b656f6e4f1
--- /dev/null
+++ b/tools/selective_cfi/tests/cfi_smokescreen_configs.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+
+configs=(do_cfi_4_byte 
+	 do_coloring_cfi_4_byte 
+	 do_cfi_exe_nonces_1_byte
+	 do_cfi_exe_nonces
+	 do_cfi_exe_nonces_4_byte_non_exe_color_non_exe
+	 do_cfi_exe_nonces_8_byte
+	 do_cfi_exe_nonces_1_byte_color_exe
+	 do_cfi_exe_nonces_color_exe
+	 do_cfi_exe_nonces_8_byte_color_exe
+	 do_cfi_exe_nonces_4_byte_non_exe_color_both)
+
+
+do_cfi_4_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4"
+}
+
+do_coloring_cfi_4_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4"
+}
+
+do_cfi_exe_nonces_1_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1"
+}
+
+do_cfi_exe_nonces()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false"
+}
+
+do_cfi_exe_nonces_4_byte_non_exe_color_non_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color
+}
+
+do_cfi_exe_nonces_8_byte()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8"
+}
+
+do_cfi_exe_nonces_1_byte_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 1" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_8_byte_color_exe()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--exe-nonce-size 8" --step-option selective_cfi:--color-exe-nonces
+}
+
+do_cfi_exe_nonces_4_byte_non_exe_color_both()
+{
+        $PS $1 $2 --backend zipr --critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" --step-option selective_cfi:"--nonce-size 4" --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:--color
+}
diff --git a/tools/selective_cfi/tests/test_dude.sh b/tools/selective_cfi/tests/test_dude.sh
index 845911fd2be921a0849d4f336213971dfd9f3642..d873f0ff044672b1550e828d90283098fd9431c8 100755
--- a/tools/selective_cfi/tests/test_dude.sh
+++ b/tools/selective_cfi/tests/test_dude.sh
@@ -1,29 +1,6 @@
 #!/bin/bash  
 
-do_cfi()
-{
-	if [[ -f $2 ]]; then
-		echo "Eliding rebuild of $2"
-	else
-		(set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false" )
-	fi
-}
-
-# Note: exe nonce cfi doesn't always run against non-exe nonce cfi modules
-do_cfi_exe_nonces()
-{
-        $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false"
-}
-
-do_coloring_cfi()
-{
-	if [[ -f $2 ]]; then
-		echo "Eliding rebuild of $2"
-	else
-		(set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false" )
-	fi
-}
-
+source cfi_all_configs.sh
 
 get_correct()
 {
@@ -42,7 +19,7 @@ test()
 	cmp out correct
 	if [[ $? = 1 ]] || [[ $fail = 1 ]] ; then
 		fails=$(expr $fails + 1 )
-		echo test failed $1 $2 $3
+		echo test failed $1 $2 $3 | tee -a dude_test_log.txt
 		echo "=== out ==="
 		cat out
 		echo "======"
@@ -66,17 +43,22 @@ build()
 
 protect()
 {
-	do_cfi ./dude.exe ./dude.exe.cfi
-	do_cfi ./libfoo.so.orig ./libfoo.so.cfi
-	do_cfi ./libdude.so.orig ./libdude.so.cfi
-
-	do_cfi_exe_nonces ./dude.exe ./dude.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfoo.so.orig ./libfoo.so.exe.nonce.cfi
-        do_cfi_exe_nonces ./libdude.so.orig ./libdude.so.exe.nonce.cfi
-
-	do_coloring_cfi ./dude.exe ./dude.exe.cfi.color
-	do_coloring_cfi ./libfoo.so.orig ./libfoo.so.cfi.color
-	do_coloring_cfi ./libdude.so.orig ./libdude.so.cfi.color
+	files=(dude.exe dude.exe.pie libfoo.so.orig libdude.so.orig)
+
+        dude_exe_varients=(dude.exe)
+	dude_exe_pie_varients=(dude.exe.pie)
+        libfoo_so_orig_varients=(libfoo.so.orig)
+	libdude_so_orig_varients=(libdude.so.orig)
+
+        for file in "${files[@]}"; do
+                for config in "${configs[@]}"; do
+                        echo Protecting file "$file" with config "$config" | tee -a dude_protection_log.txt
+                        "$config" ./"$file" ./"$file"".""$config" | tee -a dude_protection_log.txt
+                        varient_array_name="$(echo "$file" | sed -e 's/\./_/g')""_varients"
+                        declare -n varient_array="$varient_array_name"
+                        varient_array+=("$file"".""$config")
+                done
+        done	
 }
 
 clean()
@@ -84,13 +66,24 @@ clean()
 	rm out
 	rm correct
 	rm -Rf dude.exe* peasoup_exe* lib*.so*
+
+	for config in "${configs[@]}"; do
+                rm *."$config"
+        done
 }
 
 report ()
 {
 	total=$(expr $passes + $fails)
-	echo "Passes:  $passes / $total"
-	echo "Fails :  $fails / $total"
+	echo "Passes:  $passes / $total" | tee -a dude_test_log.txt
+	echo "Fails :  $fails / $total" | tee -a dude_test_log.txt
+
+	if grep -q "Warning " ./dude_protection_log.txt
+        then
+                echo PROTECTION WARNINGS DETECTED!
+        else
+                echo ALL PROTECTIONS SUCCESSFUL
+        fi
 }
 
 main()
@@ -99,58 +92,17 @@ main()
 	protect
 	get_correct
 
-	test dude.exe libfoo.so.orig libdude.so.orig		# unprotected - should pass!
-	test dude.exe libfoo.so.cfi libdude.so.orig		
-	test dude.exe libfoo.so.cfi.color libdude.so.orig		
-	test dude.exe libfoo.so.orig libdude.so.cfi		
-	test dude.exe libfoo.so.orig libdude.so.cfi.color		
-	test dude.exe libfoo.so.cfi libdude.so.cfi
-	test dude.exe libfoo.so.cfi libdude.so.cfi.color
-	test dude.exe libfoo.so.cfi.color libdude.so.cfi
-
-	test dude.exe libfoo.so.orig libdude.so.orig            # unprotected - should pass!
-        test dude.exe libfoo.so.exe.nonce.cfi libdude.so.orig
-        test dude.exe libfoo.so.orig libdude.so.exe.nonce.cfi
-        test dude.exe libfoo.so.exe.nonce.cfi libdude.so.exe.nonce.cfi
-
-	test dude.exe.cfi libfoo.so.orig libdude.so.orig	
-	test dude.exe.cfi libfoo.so.cfi libdude.so.orig		
-	test dude.exe.cfi libfoo.so.cfi.color libdude.so.orig		
-	test dude.exe.cfi libfoo.so.orig libdude.so.cfi		
-	test dude.exe.cfi libfoo.so.orig libdude.so.cfi.color		
-	test dude.exe.cfi libfoo.so.cfi libdude.so.cfi
-	test dude.exe.cfi libfoo.so.cfi libdude.so.cfi.color
-	test dude.exe.cfi libfoo.so.cfi.color libdude.so.cfi
-
-	test dude.exe.nonce.cfi libfoo.so.orig libdude.so.orig
-        test dude.exe.nonce.cfi libfoo.so.exe.nonce.cfi libdude.so.orig
-        test dude.exe.nonce.cfi libfoo.so.orig libdude.so.exe.nonce.cfi
-        test dude.exe.nonce.cfi libfoo.so.exe.nonce.cfi libdude.so.exe.nonce.cfi
-
-	test dude.exe.cfi.color libfoo.so.orig libdude.so.orig	
-	test dude.exe.cfi.color libfoo.so.cfi libdude.so.orig		
-	test dude.exe.cfi.color libfoo.so.cfi.color libdude.so.orig		
-	test dude.exe.cfi.color libfoo.so.orig libdude.so.cfi		
-	test dude.exe.cfi.color libfoo.so.orig libdude.so.cfi.color		
-	test dude.exe.cfi.color libfoo.so.cfi libdude.so.cfi
-	test dude.exe.cfi.color libfoo.so.cfi libdude.so.cfi.color
-	test dude.exe.cfi.color libfoo.so.cfi.color libdude.so.cfi
-
-	test dude.exe.pie libfoo.so.orig libdude.so.orig		# unprotected - should pass!
-	test dude.exe.pie libfoo.so.cfi libdude.so.orig		
-	test dude.exe.pie libfoo.so.cfi.color libdude.so.orig		
-	test dude.exe.pie libfoo.so.orig libdude.so.cfi		
-	test dude.exe.pie libfoo.so.orig libdude.so.cfi.color		
-	test dude.exe.pie libfoo.so.cfi libdude.so.cfi
-	test dude.exe.pie libfoo.so.cfi libdude.so.cfi.color
-	test dude.exe.pie libfoo.so.cfi.color libdude.so.cfi
-
-	test dude.exe.pie libfoo.so.orig libdude.so.orig                # unprotected - should pass!
-        test dude.exe.pie libfoo.so.exe.nonce.cfi libdude.so.orig
-        test dude.exe.pie libfoo.so.orig libdude.so.exe.nonce.cfi
-        test dude.exe.pie libfoo.so.exe.nonce.cfi libdude.so.exe.nonce.cfi
-
-
+	dude_varients=("${dude_exe_varients[@]}" "${dude_exe_pie_varients[@]}")
+	
+	for dude_varient in "${dude_varients[@]}"; do
+                for libfoo_varient in "${libfoo_so_orig_varients[@]}"; do
+                        for libdude_varient in "${libdude_so_orig_varients[@]}"; do
+                                test "$dude_varient" "$libfoo_varient" "$libdude_varient"
+                        done
+                done
+        done	
+
+	
 	report
 	if [[ $1 == "-k" ]] ; then
 		echo "Skipping cleanup"
@@ -163,3 +115,4 @@ passes=0
 fails=0
 
 main $*
+
diff --git a/tools/selective_cfi/tests/test_fib.sh b/tools/selective_cfi/tests/test_fib.sh
index 24c0eb53da7a17dbbc1aa220bd4c3f1cc8747b92..396988bf4219529c880ce5592545ff827f729078 100755
--- a/tools/selective_cfi/tests/test_fib.sh
+++ b/tools/selective_cfi/tests/test_fib.sh
@@ -1,22 +1,6 @@
 #!/bin/bash  
 
-do_cfi()
-{
-	(set -x; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false")
-}
-
-# Note: exe nonce cfi doesn't always run against non-exe nonce cfi modules
-do_cfi_exe_nonces()
-{
-        (set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false")
-}
-
-do_coloring_cfi()
-{
-	(set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false")
-}
-
-
+source cfi_all_configs.sh
 
 get_correct()
 {
@@ -40,7 +24,7 @@ test()
 	cmp out correct
 	if [ $? = 1 ]; then
 		fails=$(expr $fails + 1 )
-		echo test failed $1 $2 $3 $4
+		echo test failed $1 $2 $3 $4 | tee -a fib_test_log.txt
 		echo "=== out ==="
 		cat out
 		echo "======"
@@ -62,70 +46,27 @@ build()
 	gcc -o fib.exe.pie fib.c -fPIC -fpie -pie -w -L. -lfib -lfib2
 	mv libfib.so libfib.so.orig
 	mv libfib2.so libfib2.so.orig
-
-	gcc -o libfib2.O.so libfib2.c -O -w -shared -fPIC
-	gcc -o libfib2.O2.so libfib2.c -O2 -w -shared -fPIC
-	gcc -o libfib2.O3.so libfib2.c -O3 -w -shared -fPIC
-	gcc -o libfib2.Os.so libfib2.c -Os -w -shared -fPIC
-	mv libfib2.O.so libfib2.O.so.orig
-	mv libfib2.O2.so libfib2.O2.so.orig
-	mv libfib2.O3.so libfib2.O3.so.orig
-	mv libfib2.Os.so libfib2.Os.so.orig
-
-	gcc -o libfib.O.so libfib.c -O -w -shared -fPIC
-	gcc -o libfib.O2.so libfib.c -O2 -w -shared -fPIC
-	gcc -o libfib.O3.so libfib.c -O3 -w -shared -fPIC
-	gcc -o libfib.Os.so libfib.c -Os -w -shared -fPIC
-	mv libfib.O.so libfib.O.so.orig
-	mv libfib.O2.so libfib.O2.so.orig
-	mv libfib.O3.so libfib.O3.so.orig
-	mv libfib.Os.so libfib.Os.so.orig
 }
 
 
 protect()
 {
-	do_cfi ./fib.exe ./fib.exe.cfi
-	do_cfi ./libfib.so.orig ./libfib.so.cfi
-	do_cfi ./libfib2.so.orig ./libfib2.so.cfi
-
-	do_cfi_exe_nonces ./fib.exe ./fib.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfib.so.orig ./libfib.so.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfib2.so.orig ./libfib2.so.exe.nonce.cfi
-
-	do_coloring_cfi ./fib.exe ./fib.exe.cfi.color
-	do_coloring_cfi ./libfib.so.orig ./libfib.so.cfi.color
-	do_coloring_cfi ./libfib2.so.orig ./libfib2.so.cfi.color
-
-	do_cfi ./libfib2.O.so.orig ./libfib2.O.so.cfi
-	do_cfi ./libfib2.O2.so.orig ./libfib2.O2.so.cfi
-	do_cfi ./libfib2.O3.so.orig ./libfib2.O3.so.cfi
-	do_cfi ./libfib2.Os.so.orig ./libfib2.Os.so.cfi
-
-	do_cfi_exe_nonces ./libfib2.O.so.orig ./libfib2.O.so.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfib2.O2.so.orig ./libfib2.O2.so.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfib2.O3.so.orig ./libfib2.O3.so.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfib2.Os.so.orig ./libfib2.Os.so.exe.nonce.cfi
-
-	do_coloring_cfi ./libfib2.O.so.orig ./libfib2.O.so.cfi.color
-	do_coloring_cfi ./libfib2.O2.so.orig ./libfib2.O2.so.cfi.color
-	do_coloring_cfi ./libfib2.O3.so.orig ./libfib2.O3.so.cfi.color
-	do_coloring_cfi ./libfib2.Os.so.orig ./libfib2.Os.so.cfi.color
-
-	do_cfi ./libfib.O.so.orig ./libfib.O.so.cfi
-	do_cfi ./libfib.O2.so.orig ./libfib.O2.so.cfi
-	do_cfi ./libfib.O3.so.orig ./libfib.O3.so.cfi
-	do_cfi ./libfib.Os.so.orig ./libfib.Os.so.cfi
-
-	do_cfi_exe_nonces ./libfib.O.so.orig ./libfib.O.so.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfib.O2.so.orig ./libfib.O2.so.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfib.O3.so.orig ./libfib.O3.so.exe.nonce.cfi
-        do_cfi_exe_nonces ./libfib.Os.so.orig ./libfib.Os.so.exe.nonce.cfi
-
-	do_coloring_cfi ./libfib.O.so.orig ./libfib.O.so.cfi.color
-	do_coloring_cfi ./libfib.O2.so.orig ./libfib.O2.so.cfi.color
-	do_coloring_cfi ./libfib.O3.so.orig ./libfib.O3.so.cfi.color
-	do_coloring_cfi ./libfib.Os.so.orig ./libfib.Os.so.cfi.color
+	files=(libfib.so.orig libfib2.so.orig fib.exe fib.exe.pie)
+
+	libfib_so_orig_varients=(libfib.so.orig)
+	libfib2_so_orig_varients=(libfib2.so.orig)
+	fib_exe_varients=(fib.exe)
+	fib_exe_pie_varients=(fib.exe.pie)	
+ 
+        for file in "${files[@]}"; do
+                for config in "${configs[@]}"; do
+                        echo Protecting file "$file" with config "$config" | tee -a fib_protection_log.txt
+                        "$config" ./"$file" ./"$file"".""$config" | tee -a fib_protection_log.txt
+                        varient_array_name="$(echo "$file" | sed -e 's/\./_/g')""_varients"
+                        declare -n varient_array="$varient_array_name"
+                        varient_array+=("$file"".""$config")
+                done
+        done	
 }
 
 clean()
@@ -133,13 +74,24 @@ clean()
 	rm out
 	rm correct
 	rm -Rf fib.exe* peasoup_exe* lib*.so*
+
+ 	for config in "${configs[@]}"; do
+                rm *."$config"
+        done	
 }
 
 report ()
 {
 	total=$(expr $passes + $fails)
-	echo "Passes:  $passes / $total"
-	echo "Fails :  $fails / $total"
+	echo "Passes:  $passes / $total" | tee -a fib_test_log.txt
+	echo "Fails :  $fails / $total" | tee -a fib_test_log.txt
+
+	if grep -q "Warning " ./fib_protection_log.txt
+        then
+                echo PROTECTION WARNINGS DETECTED!
+        else
+                echo ALL PROTECTIONS SUCCESSFUL
+        fi
 }
 
 main()
@@ -147,250 +99,18 @@ main()
 	build
 	protect
 
-	test fib.exe 2 libfib.so.orig libfib2.so.orig
-	test fib.exe 3 libfib.so.orig libfib2.so.orig
-	test fib.exe 4 libfib.so.orig libfib2.so.orig
-	test fib.exe 5 libfib.so.orig libfib2.so.orig
-	test fib.exe 6 libfib.so.orig libfib2.so.orig
-
-	test fib.exe 2 libfib.so.cfi libfib2.so.orig
-	test fib.exe 3 libfib.so.cfi libfib2.so.orig
-	test fib.exe 4 libfib.so.cfi libfib2.so.orig
-	test fib.exe 5 libfib.so.cfi libfib2.so.orig
-	test fib.exe 6 libfib.so.cfi libfib2.so.orig
-
-	test fib.exe 2 libfib.so.orig libfib2.so.cfi
-	test fib.exe 3 libfib.so.orig libfib2.so.cfi
-	test fib.exe 4 libfib.so.orig libfib2.so.cfi
-	test fib.exe 5 libfib.so.orig libfib2.so.cfi
-	test fib.exe 6 libfib.so.orig libfib2.so.cfi
-
-	test fib.exe 2 libfib.so.cfi libfib2.so.cfi
-	test fib.exe 3 libfib.so.cfi libfib2.so.cfi
-	test fib.exe 4 libfib.so.cfi libfib2.so.cfi
-	test fib.exe 5 libfib.so.cfi libfib2.so.cfi
-	test fib.exe 6 libfib.so.cfi libfib2.so.cfi
-
-	test fib.exe.cfi 2 libfib.so.orig libfib2.so.orig
-	test fib.exe.cfi 3 libfib.so.orig libfib2.so.orig
-	test fib.exe.cfi 4 libfib.so.orig libfib2.so.orig
-	test fib.exe.cfi 5 libfib.so.orig libfib2.so.orig
-	test fib.exe.cfi 6 libfib.so.orig libfib2.so.orig
-
-	test fib.exe.cfi 2 libfib.so.cfi libfib2.so.orig
-	test fib.exe.cfi 3 libfib.so.cfi libfib2.so.orig
-	test fib.exe.cfi 4 libfib.so.cfi libfib2.so.orig
-	test fib.exe.cfi 5 libfib.so.cfi libfib2.so.orig
-	test fib.exe.cfi 6 libfib.so.cfi libfib2.so.orig
-
-	test fib.exe.cfi 2 libfib.so.orig libfib2.so.cfi
-	test fib.exe.cfi 3 libfib.so.orig libfib2.so.cfi
-	test fib.exe.cfi 4 libfib.so.orig libfib2.so.cfi
-	test fib.exe.cfi 5 libfib.so.orig libfib2.so.cfi
-	test fib.exe.cfi 6 libfib.so.orig libfib2.so.cfi
-
-	test fib.exe.cfi 2 libfib.so.cfi libfib2.so.cfi
-	test fib.exe.cfi 3 libfib.so.cfi libfib2.so.cfi
-	test fib.exe.cfi 4 libfib.so.cfi libfib2.so.cfi
-	test fib.exe.cfi 5 libfib.so.cfi libfib2.so.cfi
-	test fib.exe.cfi 6 libfib.so.cfi libfib2.so.cfi
-
-	test fib.exe 2 libfib.so.exe.nonce.cfi libfib2.so.orig
-        test fib.exe 3 libfib.so.exe.nonce.cfi libfib2.so.orig
-        test fib.exe 4 libfib.so.exe.nonce.cfi libfib2.so.orig
-        test fib.exe 5 libfib.so.exe.nonce.cfi libfib2.so.orig
-        test fib.exe 6 libfib.so.exe.nonce.cfi libfib2.so.orig
-
-	test fib.exe 2 libfib.so.orig libfib2.so.exe.nonce.cfi
-        test fib.exe 3 libfib.so.orig libfib2.so.exe.nonce.cfi
-        test fib.exe 4 libfib.so.orig libfib2.so.exe.nonce.cfi
-        test fib.exe 5 libfib.so.orig libfib2.so.exe.nonce.cfi
-        test fib.exe 6 libfib.so.orig libfib2.so.exe.nonce.cfi
-
-	test fib.exe 2 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-        test fib.exe 3 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-        test fib.exe 4 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-        test fib.exe 5 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-        test fib.exe 6 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-
-	test fib.exe.nonce.cfi 2 libfib.so.orig libfib2.so.orig
-        test fib.exe.nonce.cfi 3 libfib.so.orig libfib2.so.orig
-        test fib.exe.nonce.cfi 4 libfib.so.orig libfib2.so.orig
-        test fib.exe.nonce.cfi 5 libfib.so.orig libfib2.so.orig
-        test fib.exe.nonce.cfi 6 libfib.so.orig libfib2.so.orig
-
-	test fib.exe.nonce.cfi 2 libfib.so.exe.nonce.cfi libfib2.so.orig
-        test fib.exe.nonce.cfi 3 libfib.so.exe.nonce.cfi libfib2.so.orig
-        test fib.exe.nonce.cfi 4 libfib.so.exe.nonce.cfi libfib2.so.orig
-        test fib.exe.nonce.cfi 5 libfib.so.exe.nonce.cfi libfib2.so.orig
-        test fib.exe.nonce.cfi 6 libfib.so.exe.nonce.cfi libfib2.so.orig
-
-	test fib.exe.nonce.cfi 2 libfib.so.orig libfib2.so.exe.nonce.cfi
-        test fib.exe.nonce.cfi 3 libfib.so.orig libfib2.so.exe.nonce.cfi
-        test fib.exe.nonce.cfi 4 libfib.so.orig libfib2.so.exe.nonce.cfi
-        test fib.exe.nonce.cfi 5 libfib.so.orig libfib2.so.exe.nonce.cfi
-        test fib.exe.nonce.cfi 6 libfib.so.orig libfib2.so.exe.nonce.cfi
-
-	test fib.exe.nonce.cfi 2 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-        test fib.exe.nonce.cfi 3 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-        test fib.exe.nonce.cfi 4 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-        test fib.exe.nonce.cfi 5 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-        test fib.exe.nonce.cfi 6 libfib.so.exe.nonce.cfi libfib2.so.exe.nonce.cfi
-
-	test fib.exe.cfi.color 2 libfib.so.orig libfib2.so.orig
-	test fib.exe.cfi.color 3 libfib.so.orig libfib2.so.orig
-	test fib.exe.cfi.color 4 libfib.so.orig libfib2.so.orig
-	test fib.exe.cfi.color 5 libfib.so.orig libfib2.so.orig
-	test fib.exe.cfi.color 6 libfib.so.orig libfib2.so.orig
-
-	test fib.exe.cfi.color 2 libfib.so.cfi libfib2.so.orig
-	test fib.exe.cfi.color 3 libfib.so.cfi libfib2.so.orig
-	test fib.exe.cfi.color 4 libfib.so.cfi libfib2.so.orig
-	test fib.exe.cfi.color 5 libfib.so.cfi libfib2.so.orig
-	test fib.exe.cfi.color 6 libfib.so.cfi libfib2.so.orig
-
-	test fib.exe.cfi.color 2 libfib.so.orig libfib2.so.cfi
-	test fib.exe.cfi.color 3 libfib.so.orig libfib2.so.cfi
-	test fib.exe.cfi.color 4 libfib.so.orig libfib2.so.cfi
-	test fib.exe.cfi.color 5 libfib.so.orig libfib2.so.cfi
-	test fib.exe.cfi.color 6 libfib.so.orig libfib2.so.cfi
-
-	test fib.exe.cfi.color 2 libfib.so.cfi libfib2.so.cfi
-	test fib.exe.cfi.color 3 libfib.so.cfi libfib2.so.cfi
-	test fib.exe.cfi.color 4 libfib.so.cfi libfib2.so.cfi
-	test fib.exe.cfi.color 5 libfib.so.cfi libfib2.so.cfi
-	test fib.exe.cfi.color 6 libfib.so.cfi libfib2.so.cfi
+	fib_varients=("${fib_exe_varients[@]}" "${fib_exe_pie_varients[@]}")
+
+	for fib_varient in "${fib_varients[@]}"; do
+                for libfib_varient in "${libfib_so_orig_varients[@]}"; do
+			for libfib2_varient in "${libfib2_so_orig_varients[@]}"; do
+				for i in {2...6}; do
+                        		test "$fib_varient" $i "$libfib_varient" "$libfib2_varient"
+				done
+			done
+                done
+        done	
 	
-	test fib.exe 2 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe 3 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe 4 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe 5 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe 6 libfib.so.cfi.color libfib2.so.orig
-
-	test fib.exe 2 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe 3 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe 4 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe 5 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe 6 libfib.so.orig libfib2.so.cfi.color
-
-	test fib.exe 2 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe 3 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe 4 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe 5 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe 6 libfib.so.cfi.color libfib2.so.cfi.color
-
-	test fib.exe.cfi 2 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe.cfi 3 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe.cfi 4 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe.cfi 5 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe.cfi 6 libfib.so.cfi.color libfib2.so.orig
-
-	test fib.exe.cfi 2 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe.cfi 3 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe.cfi 4 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe.cfi 5 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe.cfi 6 libfib.so.orig libfib2.so.cfi.color
-
-	test fib.exe.cfi 2 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe.cfi 3 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe.cfi 4 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe.cfi 5 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe.cfi 6 libfib.so.cfi.color libfib2.so.cfi.color
-
-	test fib.exe.cfi.color 2 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe.cfi.color 3 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe.cfi.color 4 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe.cfi.color 5 libfib.so.cfi.color libfib2.so.orig
-	test fib.exe.cfi.color 6 libfib.so.cfi.color libfib2.so.orig
-
-	test fib.exe.cfi.color 2 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe.cfi.color 3 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe.cfi.color 4 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe.cfi.color 5 libfib.so.orig libfib2.so.cfi.color
-	test fib.exe.cfi.color 6 libfib.so.orig libfib2.so.cfi.color
-
-	test fib.exe.cfi.color 2 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe.cfi.color 3 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe.cfi.color 4 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe.cfi.color 5 libfib.so.cfi.color libfib2.so.cfi.color
-	test fib.exe.cfi.color 6 libfib.so.cfi.color libfib2.so.cfi.color
-
-	# some tests for different optimization levels
-	test fib.exe.cfi.color 4 libfib.so.orig libfib2.O.so.cfi
-	test fib.exe.cfi.color 4 libfib.so.orig libfib2.O2.so.cfi
-	test fib.exe.cfi.color 4 libfib.so.orig libfib2.O3.so.cfi
-	test fib.exe.cfi.color 4 libfib.so.orig libfib2.Os.so.cfi
-
-	test fib.exe 4 libfib.so.orig libfib2.O.so.exe.nonce.cfi
-        test fib.exe 4 libfib.so.orig libfib2.O2.so.exe.nonce.cfi
-        test fib.exe 4 libfib.so.orig libfib2.O3.so.exe.nonce.cfi
-        test fib.exe 4 libfib.so.orig libfib2.Os.so.exe.nonce.cfi
-
-	test fib.exe.cfi.color 4 libfib.so.cfi.color libfib2.O.so.cfi.color
-	test fib.exe.cfi.color 4 libfib.so.cfi.color libfib2.O2.so.cfi.color
-	test fib.exe.cfi.color 4 libfib.so.cfi.color libfib2.O3.so.cfi.color
-	test fib.exe.cfi.color 4 libfib.so.cfi.color libfib2.Os.so.cfi.color
-
-	test fib.exe.cfi.color 4 libfib.O3.so.orig libfib2.O.so.cfi
-	test fib.exe.cfi.color 4 libfib.O2.so.orig libfib2.O2.so.cfi
-	test fib.exe.cfi.color 4 libfib.Os.so.orig libfib2.O3.so.cfi
-	test fib.exe.cfi.color 4 libfib.O.so.orig libfib2.Os.so.cfi
-
-	test fib.exe 4 libfib.O3.so.orig libfib2.O.so.exe.nonce.cfi
-        test fib.exe 4 libfib.O2.so.orig libfib2.O2.so.exe.nonce.cfi
-        test fib.exe 4 libfib.Os.so.orig libfib2.O3.so.exe.nonce.cfi
-        test fib.exe 4 libfib.O.so.orig libfib2.Os.so.exe.nonce.cfi
-
-	test fib.exe.cfi.color 4 libfib.O2.so.cfi.color libfib2.O.so.cfi.color
-	test fib.exe.cfi.color 4 libfib.O3.so.cfi.color libfib2.O2.so.cfi.color
-	test fib.exe.cfi.color 4 libfib.O.so.cfi.color libfib2.O3.so.cfi.color
-	test fib.exe.cfi.color 4 libfib.Os.so.cfi.color libfib2.Os.so.cfi.color
-
-	test fib.exe.cfi.color 5 libfib.so.orig libfib2.O.so.cfi
-	test fib.exe.cfi.color 5 libfib.so.orig libfib2.O2.so.cfi
-	test fib.exe.cfi.color 5 libfib.so.orig libfib2.O3.so.cfi
-	test fib.exe.cfi.color 5 libfib.so.orig libfib2.Os.so.cfi
-
-	test fib.exe 5 libfib.so.orig libfib2.O.so.exe.nonce.cfi
-        test fib.exe 5 libfib.so.orig libfib2.O2.so.exe.nonce.cfi
-        test fib.exe 5 libfib.so.orig libfib2.O3.so.exe.nonce.cfi
-        test fib.exe 5 libfib.so.orig libfib2.Os.so.exe.nonce.cfi
-
-	test fib.exe.cfi.color 5 libfib.so.cfi.color libfib2.O.so.cfi.color
-	test fib.exe.cfi.color 5 libfib.so.cfi.color libfib2.O2.so.cfi.color
-	test fib.exe.cfi.color 5 libfib.so.cfi.color libfib2.O3.so.cfi.color
-	test fib.exe.cfi.color 5 libfib.so.cfi.color libfib2.Os.so.cfi.color
-
-	test fib.exe.cfi.color 5 libfib.O3.so.orig libfib2.O.so.cfi
-	test fib.exe.cfi.color 5 libfib.O2.so.orig libfib2.O2.so.cfi
-	test fib.exe.cfi.color 5 libfib.Os.so.orig libfib2.O3.so.cfi
-	test fib.exe.cfi.color 5 libfib.O.so.orig libfib2.Os.so.cfi
-
-	test fib.exe.cfi.color 5 libfib.O2.so.cfi.color libfib2.O.so.cfi.color
-	test fib.exe.cfi.color 5 libfib.O3.so.cfi.color libfib2.O2.so.cfi.color
-	test fib.exe.cfi.color 5 libfib.O.so.cfi.color libfib2.O3.so.cfi.color
-	test fib.exe.cfi.color 5 libfib.Os.so.cfi.color libfib2.Os.so.cfi.color
-
-	test fib.exe.cfi.color 6 libfib.so.orig libfib2.O.so.cfi
-	test fib.exe.cfi.color 6 libfib.so.orig libfib2.O2.so.cfi
-	test fib.exe.cfi.color 6 libfib.so.orig libfib2.O3.so.cfi
-	test fib.exe.cfi.color 6 libfib.so.orig libfib2.Os.so.cfi
-
-	test fib.exe.cfi.color 6 libfib.so.cfi.color libfib2.O.so.cfi.color
-	test fib.exe.cfi.color 6 libfib.so.cfi.color libfib2.O2.so.cfi.color
-	test fib.exe.cfi.color 6 libfib.so.cfi.color libfib2.O3.so.cfi.color
-	test fib.exe.cfi.color 6 libfib.so.cfi.color libfib2.Os.so.cfi.color
-
-	test fib.exe.cfi.color 6 libfib.O3.so.orig libfib2.O.so.cfi
-	test fib.exe.cfi.color 6 libfib.O2.so.orig libfib2.O2.so.cfi
-	test fib.exe.cfi.color 6 libfib.Os.so.orig libfib2.O3.so.cfi
-	test fib.exe.cfi.color 6 libfib.O.so.orig libfib2.Os.so.cfi
-
-	test fib.exe.cfi.color 6 libfib.O2.so.cfi.color libfib2.O.so.cfi.color
-	test fib.exe.cfi.color 6 libfib.O3.so.cfi.color libfib2.O2.so.cfi.color
-	test fib.exe.cfi.color 6 libfib.O.so.cfi.color libfib2.O3.so.cfi.color
-	test fib.exe.cfi.color 6 libfib.Os.so.cfi.color libfib2.Os.so.cfi.color
-
 	report
 	clean
 }
diff --git a/tools/selective_cfi/tests/test_foo.sh b/tools/selective_cfi/tests/test_foo.sh
index 827972ac22ced6af4e25777a470ffeb4118eb41f..5f0cd9aebb5e6ca22e6cecec9757d686f2e66137 100755
--- a/tools/selective_cfi/tests/test_foo.sh
+++ b/tools/selective_cfi/tests/test_foo.sh
@@ -1,21 +1,6 @@
-#!/bin/bash 
-
-do_cfi()
-{
-	$PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false"
-}
-
-# Note: exe nonce cfi doesn't always run against non-exe nonce cfi modules
-do_cfi_exe_nonces()
-{
-        $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false"
-}
-
-do_coloring_cfi()
-{
-	$PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only --step-option fix_calls:--fix-all --step-option selective_cfi:--color --step-option zipr:"--add-sections false"
-}
+#!/bin/bash
 
+source cfi_smokescreen_configs.sh 
 
 get_correct()
 {
@@ -32,7 +17,7 @@ test()
 	cmp out correct
 	if [ $? = 1 ]; then
 		fails=$(expr $fails + 1 )
-		echo test failed
+		echo test "$1" "$2" failed | tee -a foo_test_log.txt
 	else
 		passes=$(expr $passes + 1 )
 		echo test passed.
@@ -45,30 +30,67 @@ build()
 	gcc -o libfoo.so libfoo.c -w -shared -fPIC
 	gcc -o foo.exe foo.c -w -L. -lfoo
 	mv libfoo.so libfoo.so.orig
+
+	gcc -o libfoo.O.so libfoo.c -O -w -shared -fPIC
+        gcc -o libfoo.O2.so libfoo.c -O2 -w -shared -fPIC
+        gcc -o libfoo.O3.so libfoo.c -O3 -w -shared -fPIC
+        gcc -o libfoo.Os.so libfoo.c -Os -w -shared -fPIC
+        mv libfoo.O.so libfoo.O.so.orig
+        mv libfoo.O2.so libfoo.O2.so.orig
+        mv libfoo.O3.so libfoo.O3.so.orig
+        mv libfoo.Os.so libfoo.Os.so.orig
 }
 
 
 protect()
 {
-	do_coloring_cfi ./foo.exe ./foo.exe.cfi
-	do_cfi ./libfoo.so.orig ./libfoo.so.cfi
-	do_cfi_exe_nonces ./libfoo.so.orig ./libfoo.so.exe.nonce.cfi
-	do_cfi_exe_nonces ./foo.exe ./foo.exe.nonce.cfi
-	do_cfi ./foo.exe ./foo.exe.no-color.cfi
+	files=(foo.exe libfoo.so.orig libfoo.O.so.orig libfoo.O2.so.orig libfoo.O3.so.orig libfoo.Os.so.orig)
+
+	foo_exe_varients=(foo.exe)
+	libfoo_so_orig_varients=(libfoo.so.orig)
+	libfoo_O_so_orig_varients=(libfoo.O.so.orig)
+        libfoo_O2_so_orig_varients=(libfoo.O2.so.orig)
+        libfoo_O3_so_orig_varients=(libfoo.O3.so.orig)
+        libfoo_Os_so_orig_varients=(libfoo.Os.so.orig)
+		
+ 	for file in "${files[@]}"; do
+		for config in "${configs[@]}"; do
+			echo Protecting file "$file" with config "$config" | tee -a foo_protection_log.txt
+			"$config" ./"$file" ./"$file"".""$config" | tee -a foo_protection_log.txt
+			varient_array_name="$(echo "$file" | sed -e 's/\./_/g')""_varients"
+			declare -n varient_array="$varient_array_name"
+			varient_array+=("$file"".""$config")
+		done	
+	done
+	
 }
 
 clean()
 {
 	rm out
 	rm correct
-	rm -Rf foo.exe peasoup_exe* libfoo.so libfoo.so.orig libfoo.so.cfi foo.cfi foo.exe.cfi
+	rm -rf peasoup_executable_directory.*
+	rm *.orig
+	rm *.exe
+	rm *.so
+	
+	for config in "${configs[@]}"; do
+		rm *."$config"
+	done
 }
 
 report ()
 {
 	total=$(expr $passes + $fails)
-	echo "Passes:  $passes / $total"
-	echo "Fails :  $fails / $total"
+	echo "Passes:  $passes / $total" | tee -a foo_test_log.txt
+	echo "Fails :  $fails / $total" | tee -a foo_test_log.txt
+	
+	if grep -q "Warning " ./foo_protection_log.txt
+	then
+		echo PROTECTION WARNINGS DETECTED!
+	else
+		echo ALL PROTECTIONS SUCCESSFUL
+	fi
 }
 
 main()
@@ -76,15 +98,19 @@ main()
 	build
 	protect
 	get_correct
-	test foo.exe libfoo.so.orig 		# unprotected - should pass!
-	test foo.exe.cfi libfoo.so.orig		# main exe
-	test foo.exe libfoo.so.cfi		# shared lib only
-	test foo.exe.cfi libfoo.so.cfi		# both protected
 
-	test foo.exe.nonce.cfi libfoo.so.exe.nonce.cfi
-	test foo.exe libfoo.so.exe.nonce.cfi
+	libfoo_varients=("${libfoo_so_orig_varients[@]}" "${libfoo_O_so_orig_varients[@]}" "${libfoo_O2_so_orig_varients[@]}"
+                         "${libfoo_O3_so_orig_varients[@]}" "${libfoo_Os_so_orig_varients[@]}")
+
+	
+	for foo_varient in "${foo_exe_varients[@]}"; do
+		for libfoo_varient in "${libfoo_varients[@]}"; do
+			test "$foo_varient" "$libfoo_varient"
+		done
+	done	
+	
 	report
-#	clean
+	clean
 }
 
 passes=0 
diff --git a/tools/selective_cfi/tests/test_libc.sh b/tools/selective_cfi/tests/test_libc.sh
index e1993f244b7aa55b6eeaf69efa182bd3ee11c5d3..52638634e3ae4dbd500ccd2a7e4e49f974fa8ec9 100755
--- a/tools/selective_cfi/tests/test_libc.sh
+++ b/tools/selective_cfi/tests/test_libc.sh
@@ -2,28 +2,8 @@
 
 libcpath=""
 
-do_cfi()
-{
-	(set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false")
-	if [ ! $? -eq 0 ]; then
-		echo "do_cfi(): failed to protect"
-	fi
-}
-
-do_cfi_color()
-{
-	(set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all --step-option selective_cfi:--color  --step-option zipr:"--add-sections false" )
-	if [ ! $? -eq 0 ]; then
-		echo "do_coloring_cfi(): failed to protect"
-	fi
-}
-
-# Note: exe nonce cfi doesn't always run against non-exe nonce cfi modules
-do_cfi_exe_nonces()
-{
-        (set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" )
-}
 
+source cfi_all_configs.sh
 
 
 get_correct()
@@ -43,7 +23,7 @@ test()
 	cmp out correct
 	if [ $? = 1 ]; then
 		fails=$(expr $fails + 1 )
-		echo test failed
+		echo test $pgm $libc failed | tee -a libc_test_log.txt
 	else
 		passes=$(expr $passes + 1 )
 		echo test passed.
@@ -63,15 +43,20 @@ build()
 
 protect()
 {
-	do_cfi_exe_nonces libc.so.6.orig libc-2.19.so.noncecfi
-	do_cfi_exe_nonces libc_driver.exe libc_driver.exe.noncecfi
-
-	do_cfi libc.so.6.orig libc-2.19.so.cfi
-	do_cfi libc_driver.exe libc_driver.exe.cfi
-
-	do_cfi_color libc.so.6.orig libc-2.19.so.colorcfi
-	do_cfi_color libc_driver.exe libc_driver.exe.colorcfi
-
+	files=(libc_driver.exe libc.so.6.orig)
+
+        libc_driver_exe_varients=(libc_driver.exe)
+        libc_so_6_orig_varients=(libc.so.6.orig)
+
+        for file in "${files[@]}"; do
+                for config in "${configs[@]}"; do
+                        echo Protecting file "$file" with config "$config" | tee -a libc_protection_log.txt
+                        "$config" ./"$file" ./"$file"".""$config" | tee -a libc_protection_log.txt
+                        varient_array_name="$(echo "$file" | sed -e 's/\./_/g')""_varients"
+                        declare -n varient_array="$varient_array_name"
+                        varient_array+=("$file"".""$config")
+                done
+        done	
 }
 
 clean()
@@ -79,13 +64,17 @@ clean()
 	rm out
 	rm correct
 	rm -Rf *.orig *libc*.exe *libc.*cfi *peasoup_exec*
+
+	for config in "${configs[@]}"; do
+                rm *."$config"
+        done
 }
 
 report ()
 {
 	total=$(expr $passes + $fails)
-	echo "Passes:  $passes / $total"
-	echo "Fails :  $fails / $total"
+	echo "Passes:  $passes / $total" | tee -a libc_test_log.txt
+	echo "Fails :  $fails / $total" | tee -a libc_test_log.txt
 }
 
 main()
@@ -93,26 +82,12 @@ main()
 	build
 	protect
 	get_correct
-	test libc_driver.exe 		libc.so.6.orig
-	test libc_driver.exe.cfi 	libc.so.6.orig
-	test libc_driver.exe.colorcfi 	libc.so.6.orig
-	test libc_driver.exe.noncecfi 	libc.so.6.orig
-
-	test libc_driver.exe 		libc.so.6.cfi
-	test libc_driver.exe.cfi 	libc.so.6.cfi
-	test libc_driver.exe.colorcfi 	libc.so.6.cfi
-	test libc_driver.exe.noncecfi 	libc.so.6.cfi
-
-	test libc_driver.exe		libc.so.6.colorcfi
-	test libc_driver.exe.cfi	libc.so.6.colorcfi
-	test libc_driver.exe.colorcfi	libc.so.6.colorcfi
-	test libc_driver.exe.noncecfi	libc.so.6.colorcfi
-
-	test libc_driver.exe		libc.so.6.noncecfi
-	test libc_driver.exe.cfi	libc.so.6.noncecfi
-	test libc_driver.exe.colorcfi	libc.so.6.noncecfi
-	test libc_driver.exe.noncecfi	libc.so.6.noncecfi
 
+	for libc_driver_varient in "${libc_driver_exe_varients[@]}"; do
+                for libc_varient in "${libc_so_6_orig_varients[@]}"; do
+                        test "$libc_driver_varient" "$libc_varient"
+                done
+        done	
 
 	report
 	clean
diff --git a/tools/selective_cfi/tests/test_pow.sh b/tools/selective_cfi/tests/test_pow.sh
index a2fdfc63ede26eb0d0f3779f79faa9db975c9e28..18bc4e38934185b4a88de0b0f6286f53429e40ee 100755
--- a/tools/selective_cfi/tests/test_pow.sh
+++ b/tools/selective_cfi/tests/test_pow.sh
@@ -1,22 +1,7 @@
 #!/bin/bash 
 
-do_cfi()
-{
-	(set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all --step-option zipr:"--add-sections false")
-}
-
-# Note: exe nonce cfi doesn't always run against non-exe nonce cfi modules
-do_cfi_exe_nonces()
-{
-        (set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option zipr:"--add-sections false" )
-}
-
-do_coloring_cfi()
-{
-	(set -x ; $PS $1 $2 --backend zipr --step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all --step-option selective_cfi:--color  --step-option zipr:"--add-sections false" )
-}
-
 
+source cfi_all_configs.sh
 
 
 get_correct()
@@ -31,6 +16,8 @@ test()
 	shift
 	lib=$1
 	shift
+
+	get_correct $1 $2
 	
 	local fail=0
 	cp $lib libm.so.6  || fail=1
@@ -39,7 +26,7 @@ test()
 	cmp out correct
 	if [[ $? = 1 ]] || [[ $fail = 1 ]] ; then
 		fails=$(expr $fails + 1 )
-		echo test failed
+		echo test $exe $lib $1 $2 failed | tee -a pow_test_log.txt
 	else
 		passes=$(expr $passes + 1 )
 		echo test passed.
@@ -62,10 +49,20 @@ build()
 
 protect()
 {
-	do_coloring_cfi ./pow.exe ./pow.exe.cfi
-	do_cfi ./libm.so.6.orig ./libm.so.6.cfi
-	do_cfi_exe_nonces ./pow.exe ./pow.exe.nonce.cfi
-	do_cfi_exe_nonces ./libm.so.6.orig ./libm.so.6.exe.nonce.cfi
+	files=(pow.exe libm.so.6.orig)
+
+        pow_exe_varients=(pow.exe)
+        libm_so_6_orig_varients=(libm.so.6.orig)
+                
+        for file in "${files[@]}"; do
+                for config in "${configs[@]}"; do
+                        echo Protecting file "$file" with config "$config" | tee -a pow_protection_log.txt
+                        "$config" ./"$file" ./"$file"".""$config" | tee -a pow_protection_log.txt
+                        varient_array_name="$(echo "$file" | sed -e 's/\./_/g')""_varients"
+                        declare -n varient_array="$varient_array_name"
+                        varient_array+=("$file"".""$config")
+                done    
+        done
 }
 
 clean()
@@ -73,40 +70,32 @@ clean()
 	rm out
 	rm correct
 	rm -Rf pow.exe peasoup_exe* libm.so.6 libm.so.6.orig libm.so.6.cfi pow.cfi pow.exe.cfi
+
+	for config in "${configs[@]}"; do
+                rm *."$config"
+        done
 }
 
 report ()
 {
 	total=$(expr $passes + $fails)
-	echo "Passes:  $passes / $total"
-	echo "Fails :  $fails / $total"
+	echo "Passes:  $passes / $total" | tee -a pow_test_log.txt
+	echo "Fails :  $fails / $total" | tee -a pow_test_log.txt
 }
 
 main()
 {
 	build
 	protect
-	get_correct 3 5
-	test pow.exe libm.so.6.orig 	3 5	# unprotected - should pass! 3 5
-	test pow.exe.cfi libm.so.6.orig	3 5	# main exe
-	test pow.exe libm.so.6.cfi	3 5	# shared lib only
-	test pow.exe.cfi libm.so.6.cfi	3 5	# both protected
-	get_correct 5 8
-	test pow.exe libm.so.6.orig 	5 8	# unprotected - should pass! 3 5
-	test pow.exe.cfi libm.so.6.orig	5 8	# main exe
-	test pow.exe libm.so.6.cfi	5 8	# shared lib only
-	test pow.exe.cfi libm.so.6.cfi	5 8	# both protected
-	get_correct 3 5
-        test pow.exe libm.so.6.orig     3 5     # unprotected - should pass! 3 5
-        test pow.exe.nonce.cfi libm.so.6.orig 3 5     # main exe
-        test pow.exe libm.so.6.exe.nonce.cfi      3 5     # shared lib only
-        test pow.exe.nonce.cfi libm.so.6.exe.nonce.cfi  3 5     # both protected
-        get_correct 5 8
-        test pow.exe libm.so.6.orig     5 8     # unprotected - should pass! 3 5
-        test pow.exe.nonce.cfi libm.so.6.orig 5 8     # main exe
-        test pow.exe libm.so.6.exe.nonce.cfi      5 8     # shared lib only
-        test pow.exe.nonce.cfi libm.so.6.exe.nonce.cfi  5 8     # both protected
 
+	
+        for pow_varient in "${pow_exe_varients[@]}"; do
+                for libm_varient in "${libm_so_6_orig_varients[@]}"; do
+                        test "$pow_varient" "$libm_varient" 3 5
+			test "$pow_varient" "$libm_varient" 5 8
+                done
+        done
+	
 	report
 	if [[ ! $1 == -k ]]; then
 		clean
diff --git a/tools/selective_cfi/tests/test_spec.sh b/tools/selective_cfi/tests/test_spec.sh
index 65c670897ca080d1278890ded91c9763863217a0..844ef86ddf31f7c39cfe66433f9d327696e44da6 100755
--- a/tools/selective_cfi/tests/test_spec.sh
+++ b/tools/selective_cfi/tests/test_spec.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-#benchmarks="473.astar"
+#benchmarks="401.bzip2"
 # 447.dealII // broken build
 benchmarks=" 400.perlbench 401.bzip2 403.gcc 410.bwaves 416.gamess 429.mcf 433.milc 434.zeusmp 435.gromacs 436.cactusADM 437.leslie3d 444.namd 445.gobmk 450.soplex 453.povray 454.calculix 456.hmmer 458.sjeng 459.GemsFDTD 462.libquantum 464.h264ref 465.tonto 470.lbm 471.omnetpp 473.astar 481.wrf 482.sphinx3 483.xalancbmk "
 
@@ -137,27 +137,48 @@ main()
 
 
 	local zipr_flags="--backend zipr"
-	local mm_basic_cfi_flags="--step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all "
-	local mm_basic_cfi_exe_nonces_flags="--step move_globals=on --step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call "
+	local mm_basic_cfi_flags="--critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--fix-all "
+	local mm_basic_cfi_exe_nonces_flags="--critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call "
+	#local mm_all_colored_8_byte_cfi_flags="--critical-step move_globals=on --critical-step selective_cfi=on --step-option selective_cfi:--multimodule --step-option move_globals:--elftables-only  --step-option fix_calls:--no-fix-safefn --step-option selective_cfi:--exe-nonce-for-call --step-option selective_cfi:\"--nonce-size 8\" --step-option selective_cfi:--color --step-option selective_cfi:--color-exe-nonces --step-option selective_cfi:\"--exe-nonce-size 8\""	
 	local mm_color_cfi_flags="$mm_basic_cfi_flags --step-option selective_cfi:--color"
+	local cfi_4_byte_flags="$mm_basic_cfi_flags --step-option selective_cfi:\"--nonce-size 4\""
+        local coloring_cfi_4_byte_flags="$mm_color_cfi_flags --step-option selective_cfi:\"--nonce-size 4\""
+        local cfi_exe_nonces_1_byte_flags="$mm_basic_cfi_exe_nonces_flags --step-option selective_cfi:\"--exe-nonce-size 1\""
+        local cfi_exe_nonces_4_byte_non_exe_color_non_exe_flags="$mm_basic_cfi_exe_nonces_flags --step-option selective_cfi:\"--nonce-size 4\" --step-option selective_cfi:--color"
+        local cfi_exe_nonces_8_byte_flags="$mm_basic_cfi_exe_nonces_flags --step-option selective_cfi:\"--exe-nonce-size 8\""
+        local cfi_exe_nonces_1_byte_color_exe_flags="$mm_basic_cfi_exe_nonces_flags --step-option selective_cfi:\"--exe-nonce-size 1\" --step-option selective_cfi:--color-exe-nonces"
+        local cfi_exe_nonces_color_exe_flags="$mm_basic_cfi_exe_nonces_flags --step-option selective_cfi:--color-exe-nonces"
+        local cfi_exe_nonces_8_byte_color_exe_flags="$mm_basic_cfi_exe_nonces_flags --step-option selective_cfi:\"--exe-nonce-size 8\" --step-option selective_cfi:--color-exe-nonces"
+        local cfi_exe_nonces_4_byte_non_exe_color_both_flags="$mm_basic_cfi_exe_nonces_flags --step-option selective_cfi:\"--nonce-size 4\" --step-option selective_cfi:--color --step-option selective_cfi:--color-exe-nonces"
+
 	local trace_flags="-o zipr:--traceplacement:on -o zipr:true"
 	
 
 	# no $PS -- aka, baseline.
-	run_test original $SPEC/config/ubuntu14.04lts-64bit.cfg
+	#run_test original $SPEC/config/ubuntu14.04lts-64bit.cfg
 
 	# zipr, basic cfi, basic cfi with exe nonces for calls, color cfi
-	PSOPTS="$zipr_flags"  				       run_test zipr                    $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
-	PSOPTS="$zipr_flags $mm_basic_cfi_flags " 	       run_test mm-basic-cfi            $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
-	PSOPTS="$zipr_flags $mm_basic_cfi_exe_nonces_flags "   run_test mm-basic-cfi-exe-nonces $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
-	PSOPTS="$zipr_flags $mm_color_cfi_flags" 	       run_test mm-color-cfi            $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
-
-	# zipr, basic cfi, color cfi
+	#PSOPTS="$zipr_flags"  				       run_test zipr                    $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $mm_basic_cfi_flags " 	       run_test mm-basic-cfi            $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $mm_basic_cfi_exe_nonces_flags "   run_test mm-basic-cfi-exe-nonces $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $mm_color_cfi_flags" 	       run_test mm-color-cfi            $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $cfi_4_byte_flags "   run_test cfi_4_byte $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	PSOPTS="$zipr_flags $coloring_cfi_4_byte_flags "   run_test coloring_cfi_4_byte $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	PSOPTS="$zipr_flags $cfi_exe_nonces_1_byte_flags "   run_test cfi_exe_nonces_1_byte $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	PSOPTS="$zipr_flags $cfi_exe_nonces_4_byte_non_exe_color_non_exe_flags "   run_test cfi_exe_nonces_4_byte_non_exe_color_non_exe $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	PSOPTS="$zipr_flags $cfi_exe_nonces_8_byte_flags "   run_test cfi_exe_nonces_8_byte $SPEC/config/ubuntu14.04lts-64bit-withps.cfg	
+	PSOPTS="$zipr_flags $cfi_exe_nonces_1_byte_color_exe_flags "   run_test cfi_exe_nonces_1_byte_color_exe $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	PSOPTS="$zipr_flags $cfi_exe_nonces_color_exe_flags "   run_test cfi_exe_nonces_color_exe $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	PSOPTS="$zipr_flags $cfi_exe_nonces_8_byte_color_exe_flags "   run_test cfi_exe_nonces_8_byte_color_exe $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	PSOPTS="$zipr_flags $cfi_exe_nonces_4_byte_non_exe_color_both_flags "   run_test cfi_exe_nonces_4_byte_non_exe_color_both $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+
+	 zipr, basic cfi, color cfi
 	# with trace placement
-	PSOPTS="$zipr_flags $trace_flags "  					run_test zipr-trace         		$SPEC/config/ubuntu14.04lts-64bit-withps.cfg
-	PSOPTS="$zipr_flags $mm_basic_cfi_flags  $trace_flags " 		run_test mm-basic-cfi-trace 		$SPEC/config/ubuntu14.04lts-64bit-withps.cfg
-	PSOPTS="$zipr_flags $mm_basic_cfi_exe_nonces_flags $trace_flags "   	run_test mm-basic-cfi-exe-nonces-trace 	$SPEC/config/ubuntu14.04lts-64bit-withps.cfg
-	PSOPTS="$zipr_flags $mm_color_cfi_flags $trace_flags " 			run_test mm-color-cfi-trace 		$SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $trace_flags "  					run_test zipr-trace         		$SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $mm_basic_cfi_flags  $trace_flags " 		run_test mm-basic-cfi-trace 		$SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $mm_basic_cfi_exe_nonces_flags $trace_flags "   	run_test mm-basic-cfi-exe-nonces-trace 	$SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $mm_color_cfi_flags $trace_flags " 			run_test mm-color-cfi-trace 		$SPEC/config/ubuntu14.04lts-64bit-withps.cfg
+	#PSOPTS="$zipr_flags $mm_all_colored_8_byte_cfi_flags "      run_test mm-all-colored-8-byte-cfi  $SPEC/config/ubuntu14.04lts-64bit-withps.cfg
 
 	get_raw_results