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