From 95cfa65fb84514f7d6c389fd631b61264431ffca Mon Sep 17 00:00:00 2001
From: jdh8d <jdh8d@git.zephyr-software.com>
Date: Sun, 27 Dec 2015 01:29:51 +0000
Subject: [PATCH] updates to handle ICFS better.

Former-commit-id: f66e63420631190271a4540d85026cd85d64d3fe
---
 .gitattributes                       |   2 +
 libIRDB/include/core/icfs.hpp        |  16 +---
 libIRDB/include/core/instruction.hpp |  66 ++++++-------
 libIRDB/test/SConscript              |   4 +
 libIRDB/test/fill_in_indtargs.cpp    |  34 ++++---
 tools/selective_cfi/SConscript       |   2 +-
 tools/selective_cfi/color_map.cpp    |  83 +++++++++++++++++
 tools/selective_cfi/color_map.hpp    | 133 +++++++++++++++++++++++++++
 tools/selective_cfi/scfi_driver.cpp  |  15 ++-
 tools/selective_cfi/scfi_instr.cpp   | 113 ++++++++++++++++++-----
 tools/selective_cfi/scfi_instr.hpp   |  11 ++-
 11 files changed, 391 insertions(+), 88 deletions(-)
 create mode 100644 tools/selective_cfi/color_map.cpp
 create mode 100644 tools/selective_cfi/color_map.hpp

diff --git a/.gitattributes b/.gitattributes
index 2e88f925e..df19ed873 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1109,6 +1109,8 @@ tools/safefr/fill_in_safefr.cpp -text
 tools/selective_cfi/Makefile.in -text
 tools/selective_cfi/SConscript -text
 tools/selective_cfi/SConstruct -text
+tools/selective_cfi/color_map.cpp -text
+tools/selective_cfi/color_map.hpp -text
 tools/selective_cfi/scfi_driver.cpp -text
 tools/selective_cfi/scfi_instr.cpp -text
 tools/selective_cfi/scfi_instr.hpp -text
diff --git a/libIRDB/include/core/icfs.hpp b/libIRDB/include/core/icfs.hpp
index 3331c6326..78b4f6c5a 100644
--- a/libIRDB/include/core/icfs.hpp
+++ b/libIRDB/include/core/icfs.hpp
@@ -33,21 +33,9 @@ class ICFS_t : public InstructionSet_t, public BaseObj_t
 		}
 		std::string WriteToDB(File_t *fid);
 		 
-		ICFS_t& operator=(const InstructionSet_t &other) 
+		void SetTargets(const InstructionSet_t &other) 
 		{
-			if (this == &other)
-				return *this;
-
-			this->clear();
-
-			for (InstructionSet_t::const_iterator it = other.begin();
-				 it != other.end(); ++it)
-			{
-				this->insert(*it);				
-			}
-
-			return *this;
-			
+			InstructionSet_t::operator=(other);
 		}
 		void SetComplete(bool complete) { is_complete = complete; }
 		bool IsComplete() const { return is_complete; }			
diff --git a/libIRDB/include/core/instruction.hpp b/libIRDB/include/core/instruction.hpp
index 674588b66..ebe3f4507 100644
--- a/libIRDB/include/core/instruction.hpp
+++ b/libIRDB/include/core/instruction.hpp
@@ -28,40 +28,40 @@ typedef	std::set<Relocation_t*> RelocationSet_t;
 // The basic instruction of a variant.
 class Instruction_t : public BaseObj_t
 {
-    public:
+	public:
 		Instruction_t();
 		Instruction_t(db_id_t id, AddressID_t *addr, Function_t *func, db_id_t orig_id, 
 		std::string data, std::string callback, std::string comment, AddressID_t *my_indTarg, db_id_t doip_id);
 
-        AddressID_t* GetAddress() const { return my_address; } 
-        Function_t* GetFunction() const { return my_function; } 
-        db_id_t GetOriginalAddressID() const { return orig_address_id; } 
-        Instruction_t* GetFallthrough() const { return fallthrough; } 
-        Instruction_t* GetTarget() const { return target; } 
+		AddressID_t* GetAddress() const { return my_address; } 
+		Function_t* GetFunction() const { return my_function; } 
+		db_id_t GetOriginalAddressID() const { return orig_address_id; } 
+		Instruction_t* GetFallthrough() const { return fallthrough; } 
+		Instruction_t* GetTarget() const { return target; } 
 		ICFS_t* GetIBTargets() const { return icfs; }
-        std::string GetDataBits()  const { return data; } 
-        std::string GetCallback()  const { return callback; } 
-        std::string GetComment()   const { return comment; } 
+		std::string GetDataBits()  const { return data; } 
+		std::string GetCallback()  const { return callback; } 
+		std::string GetComment()   const { return comment; } 
 
   
-        void SetAddress(AddressID_t* newaddr)  { my_address=newaddr; }
-        void SetFunction(Function_t* func   )  { my_function=func;}
-        void SetOriginalAddressID(db_id_t origid) { orig_address_id=origid; /* you shouldn't do this, unless you know what you're doing! */}
-        void SetFallthrough(Instruction_t* i) { fallthrough=i; }
-        void SetTarget(Instruction_t* i)      { target=i; }
-        void SetIBTargets(ICFS_t *p_icfs)     { icfs=p_icfs; }
-        void SetDataBits(std::string orig)    { data=orig; }
-        void SetCallback(std::string orig)    { callback=orig; }
-        void SetComment(std::string orig)     { comment=orig; }
+		void SetAddress(AddressID_t* newaddr)  { my_address=newaddr; }
+		void SetFunction(Function_t* func   )  { my_function=func;}
+		void SetOriginalAddressID(db_id_t origid) { orig_address_id=origid; /* you shouldn't do this, unless you know what you're doing! */}
+		void SetFallthrough(Instruction_t* i) { fallthrough=i; }
+		void SetTarget(Instruction_t* i)	  { target=i; }
+		void SetIBTargets(ICFS_t *p_icfs)	 { icfs=p_icfs; }
+		void SetDataBits(std::string orig)	{ data=orig; }
+		void SetCallback(std::string orig)	{ callback=orig; }
+		void SetComment(std::string orig)	 { comment=orig; }
 
-		AddressID_t* GetIndirectBranchTargetAddress()	       { return indTarg; }
+		AddressID_t* GetIndirectBranchTargetAddress()		{ return indTarg; }
 		void SetIndirectBranchTargetAddress(AddressID_t* myIndTarg) { indTarg=myIndTarg; }
 
 		void WriteToDB() { assert(0); }
-        std::string WriteToDB(File_t *fid, db_id_t newid, bool p_withHeader);
-        int Disassemble(DISASM &d) const; 
+		std::string WriteToDB(File_t *fid, db_id_t newid, bool p_withHeader);
+		int Disassemble(DISASM &d) const; 
 		std::string getDisassembly() const;
-        bool Assemble(std::string assembly);
+		bool Assemble(std::string assembly);
 
 		bool IsFunctionExit() const;
 
@@ -72,16 +72,16 @@ class Instruction_t : public BaseObj_t
 
 		bool IsSyscall() { return getDisassembly().find("int 0x80") != std::string::npos; }
 
-    private:
-        AddressID_t*    my_address;
-        Function_t*     my_function;
-        db_id_t         orig_address_id;        // const, should not change.
-        Instruction_t*  fallthrough;
-        Instruction_t*  target;
-        std::string     data;
-        std::string     callback;    // name of callback handler (if any)
-        std::string     comment;
-		AddressID_t*    indTarg;
+	private:
+		AddressID_t*	my_address;
+		Function_t*	 my_function;
+		db_id_t		 orig_address_id;		// const, should not change.
+		Instruction_t*  fallthrough;
+		Instruction_t*  target;
+		std::string	 data;
+		std::string	 callback;	// name of callback handler (if any)
+		std::string	 comment;
+		AddressID_t*	indTarg;
 		RelocationSet_t relocs;
-		ICFS_t*         icfs;
+		ICFS_t*		 icfs;
 };
diff --git a/libIRDB/test/SConscript b/libIRDB/test/SConscript
index 0f831fd8a..8d3ef63ca 100644
--- a/libIRDB/test/SConscript
+++ b/libIRDB/test/SConscript
@@ -20,7 +20,11 @@ print LIBS
 
 myenv=myenv.Clone(CPPPATH=Split(cpppath))
 ehframe=myenv.Object("read_ehframe.cpp");
+
 pgm=myenv.Program("fill_in_indtargs.exe",  ehframe+Split("fill_in_indtargs.cpp check_thunks.cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
+install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm)
+Default(install)
+
 pgm=myenv.Program("fix_calls.exe",  ehframe+Split("fix_calls.cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
 install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm)
 Default(install)
diff --git a/libIRDB/test/fill_in_indtargs.cpp b/libIRDB/test/fill_in_indtargs.cpp
index 648f8cf31..1543dae19 100644
--- a/libIRDB/test/fill_in_indtargs.cpp
+++ b/libIRDB/test/fill_in_indtargs.cpp
@@ -62,10 +62,10 @@ set<virtual_offset_t> targets;
 set< pair< virtual_offset_t, virtual_offset_t> > ranges;
 
 // a way to map an instruction to its set of predecessors. 
-map< Instruction_t* , set<Instruction_t*> > preds;
+map< Instruction_t* , InstructionSet_t > preds;
 
 // keep track of jmp tables
-map< Instruction_t*, set<Instruction_t*> > jmptables;
+map< Instruction_t*, InstructionSet_t > jmptables;
 
 void check_for_PIC_switch_table32_type2(Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases);
 void check_for_PIC_switch_table32_type3(Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases);
@@ -240,11 +240,11 @@ Instruction_t *lookupInstruction(FileIR_t *firp, virtual_offset_t virtual_offset
 
 void mark_jmptables(FileIR_t *firp)
 {
-	map< Instruction_t*, set<Instruction_t*> >::iterator it;
+	map< Instruction_t*, InstructionSet_t >::iterator it;
 	for (it = jmptables.begin(); it != jmptables.end(); ++it)
 	{
 		Instruction_t* instr = it->first;
-		set<Instruction_t*> instruction_targets = it->second;
+		const InstructionSet_t &instruction_targets = it->second;
 
 		// ignore if instr already marked complete.
 		// FIXME: assert that fill_in_indtarg analysis matches already complete analysis.
@@ -254,7 +254,7 @@ void mark_jmptables(FileIR_t *firp)
 		assert(instruction_targets.size() > 0);
 
 		ICFS_t* new_icfs = new ICFS_t(next_icfs_set_id++, true);
-		*new_icfs = instruction_targets;
+		new_icfs->SetTargets(instruction_targets);
 		firp->GetAllICFS().insert(new_icfs);
 
 		instr->SetIBTargets(new_icfs);
@@ -1457,8 +1457,15 @@ void icfs_set_indirect_calls(FileIR_t* const firp, ICFS_t* const targets)
            )
     	{
         	Function_t *func=*it;
+
+		// no entry point, doesn't count
 		if(!func->GetEntryPoint())
 			continue;
+
+		// if it's no an indirectly called function, it doesn't count
+		if(!func->GetEntryPoint()->GetIndirectBranchTargetAddress())
+			continue;
+
 		targets->insert(func->GetEntryPoint());
 	}
 }
@@ -1489,6 +1496,7 @@ void check_for_ret(FileIR_t* const firp, Instruction_t* const insn)
 	if(strstr(d.Instruction.Mnemonic, "ret")==NULL)
 		return;
 
+
 	// already analysed by ida.
 	if(insn->GetIBTargets() && insn->GetIBTargets()->IsComplete())
 		return;
@@ -1496,10 +1504,17 @@ void check_for_ret(FileIR_t* const firp, Instruction_t* const insn)
 	insn->SetIBTargets(hellnode_tgts);
 }
 
+// find any indirect jumps in the pgm and mark them as having a hell node ICFS if they don't
+// already have a complete ICFS.
 void check_for_indirect_jmp(FileIR_t* const firp, Instruction_t* const insn)
 {
+	cout<<"In check_for_indirect_jmp, whta?!"<<endl;
 	assert(firp && insn);
 
+	// already analysed by ida.
+	if(insn->GetIBTargets() && insn->GetIBTargets()->IsComplete())
+		return;
+
 	DISASM d;
 	insn->Disassemble(d);
 
@@ -1508,17 +1523,10 @@ void check_for_indirect_jmp(FileIR_t* const firp, Instruction_t* const insn)
 
 	if(d.Argument1.ArgType&REGISTER_TYPE)
 	{
-		// already analysed by ida.
-		if(insn->GetIBTargets() && insn->GetIBTargets()->IsComplete())
-			return;
 		insn->SetIBTargets(hellnode_tgts);
 	}
-	else if(d.Argument1.ArgType&MEMORY_TYPE &&
-			(!d.Argument1.ArgType&RELATIVE_))
+	else if(d.Argument1.ArgType&MEMORY_TYPE)
 	{
-		// already analysed by ida.
-		if(insn->GetIBTargets() && insn->GetIBTargets()->IsComplete())
-			return;
 		insn->SetIBTargets(hellnode_tgts);
 	}
 }
diff --git a/tools/selective_cfi/SConscript b/tools/selective_cfi/SConscript
index f7748b1ad..5f94194fb 100644
--- a/tools/selective_cfi/SConscript
+++ b/tools/selective_cfi/SConscript
@@ -24,7 +24,7 @@ LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
 LIBS=Split( env.subst('$BASE_IRDB_LIBS')+ "  IRDB-cfg IRDB-util transform rewrite MEDSannotation ") 
 myenv=myenv.Clone(CPPPATH=Split(cpppath))
 pgm=myenv.Program(pgm,  files,  LIBPATH=LIBPATH, LIBS=LIBS)
-install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm)
+install=myenv.Install("$SECURITY_TRANSFORMS_HOME/plugins_install/", pgm)
 Default(install)
 
 	
diff --git a/tools/selective_cfi/color_map.cpp b/tools/selective_cfi/color_map.cpp
new file mode 100644
index 000000000..c01212218
--- /dev/null
+++ b/tools/selective_cfi/color_map.cpp
@@ -0,0 +1,83 @@
+
+#include "color_map.hpp"
+
+using namespace std;
+using namespace libIRDB;
+
+
+bool ColoredInstructionNonces_t::create()
+{
+	UniqueICFSSet_t unique_icfs;
+
+	assert(firp);
+	const ICFSSet_t& all_icfs=firp->GetAllICFS();
+	for(ICFSSet_t::iterator it=all_icfs.begin(); it!=all_icfs.end(); ++it)
+	{
+		ICFS_t* p=*it;
+		assert(p);
+		unique_icfs.insert( *p );
+	}
+
+	ColoredSlotValue_t v;
+	for(UniqueICFSSet_t::iterator it=unique_icfs.begin(); it!=unique_icfs.end(); ++it)
+	{
+		const ICFS_t& the_icfs=*it;
+
+		for(int slot_no=0; ; slot_no++)
+		{
+			// check if we need to allocate a new slot
+			if(slot_no<slots_used.size())
+			{
+				// skip any slots that are full.
+				if(!slots_used[slot_no].CanReserve())
+					goto next_slot;
+			}
+			else
+			{
+				// allocate slot
+				slots_used.push_back(ColoredSlotAllocator_t(slot_no,slot_values));
+			}
+
+			// check if any of the targets for this branch already have a slot filled.
+			for(ICFS_t::iterator it2=the_icfs.begin(); it2!=the_icfs.end(); ++it2)
+			{
+				Instruction_t* target=*it2;
+				if(color_assignments[target][slot_no].IsValid())
+					goto next_slot;
+			}
+
+			// if we get here, the slot is valid for all targets, we can reserve it.
+			v=slots_used[slot_no].Reserve();
+
+			// and record the reservation for each target.
+			slot_assignments[the_icfs]=v;
+			for(ICFS_t::iterator it2=the_icfs.begin(); it2!=the_icfs.end(); ++it2)
+			{
+				Instruction_t* target=*it2;
+				color_assignments[target][slot_no]=v;
+				cout<<"Setting [slot][color] for "<<target->GetBaseID()<<":"<<target->getDisassembly()
+				    <<"=["<<v.GetPosition()<<"]["<<hex<<v.GetNonceValue()<<dec<<"]"<<endl;
+			}
+
+			// and we're done with this ICFS
+			break;
+
+
+			// inc the slot no and try again.
+			next_slot:
+				// try next;
+				; // neded statement for compiler to accept 
+		}
+
+	}
+
+	// output stats
+	cout<<"#ATTRIBUTE slots_used="<<slots_used.size()<<endl;
+	for(int slot_no=0; slot_no<slots_used.size(); slot_no++)
+	{
+		cout<<"#ATTRIBUTE used_slot"<<slot_no<<"="<<slots_used[slot_no].SlotsUsed()<<endl;
+	}
+
+	return true;
+}
+
diff --git a/tools/selective_cfi/color_map.hpp b/tools/selective_cfi/color_map.hpp
new file mode 100644
index 000000000..d577e3f61
--- /dev/null
+++ b/tools/selective_cfi/color_map.hpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014-2015 - Zephyr Software LLC
+ *
+ * This file may be used and modified for non-commercial purposes as long as
+ * all copyright, permission, and nonwarranty notices are preserved.
+ * Redistribution is prohibited without prior written consent from Zephyr
+ * Software.
+ *
+ * Please contact the authors for restrictions applying to commercial use.
+ *
+ * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author: Zephyr Software
+ * e-mail: jwd@zephyr-software.com
+ * URL   : http://www.zephyr-software.com/
+ *
+ */
+
+#ifndef color_map_hpp
+#define color_map_hpp
+
+#include <libIRDB-core.hpp>
+#include <stdint.h>
+
+
+typedef int64_t NonceValueType_t;
+
+class ColoredSlotValue_t
+{
+	public:
+		ColoredSlotValue_t(int np, NonceValueType_t nv) : position(np), nonce_value(nv), valid(true) { };
+		ColoredSlotValue_t() : valid(false) {}
+
+		// void SetPosition(int pos) { slot_position=pos; }
+		int GetPosition() const { return position;}
+
+		// void SetNonceValue(NonceValueType_t p_nv) { nonce_value=p_nv; }
+		NonceValueType_t const GetNonceValue() { return nonce_value; }
+
+		bool IsValid() const { return valid; }
+
+	private:
+		int position;
+		NonceValueType_t nonce_value;
+		bool valid;
+};
+
+class ColoredSlotAllocator_t
+{
+	public:
+		ColoredSlotAllocator_t(int sn, int mv) : slot_number(sn), used(0), max_value(mv) { }
+
+		bool CanReserve() const { return used < max_value; }
+		ColoredSlotValue_t Reserve() 
+		{ 
+			assert(CanReserve()); 
+			return ColoredSlotValue_t(slot_number, used++); 
+		}
+		int SlotsUsed() const { return used ; }
+ 
+	
+	private:
+		int slot_number;
+		int used;
+		int max_value;
+};
+
+typedef std::map<int,ColoredSlotValue_t> ColoredSlotValues_t;
+
+
+class ColoredInstructionNonces_t 
+{
+	public:
+		ColoredInstructionNonces_t(libIRDB::FileIR_t *the_firp)
+			: firp(the_firp) { }
+
+		ColoredSlotValues_t  GetColorsOfIBT (libIRDB::Instruction_t* i) 
+		{ return color_assignments[i]; }
+
+		ColoredSlotValue_t  GetColorOfIB (libIRDB::Instruction_t* i) 
+		{ assert(i->GetIBTargets()); return slot_assignments[*i->GetIBTargets()]; }
+
+		int NumberSlotsUsed() { return slots_used.size(); }
+
+		bool build() { return create(); }
+
+	private:
+
+		// helper to assign colors to slots.
+		bool create();
+
+		// the IR we're working on.
+		libIRDB::FileIR_t* firp;
+
+		// used to describe how big a nonce slot is.  for now, 1 byte.
+		const int slot_size=1;
+		const int slot_values=255;
+
+		// information for each slot we've used.
+		std::vector<ColoredSlotAllocator_t> slots_used;
+
+		// information for each IBT.
+		// a map for each instruction, which contains a ColorSlotValue_t for each slot used.
+		//  instruction -> ( int-> slot_value )
+		std::map<libIRDB::Instruction_t*, ColoredSlotValues_t> color_assignments;
+
+		// information for each IB (as indexed by the IBs ICFS).
+		// the slot that each IB uses. ICFS_t -> slot_value
+		std::map<libIRDB::ICFS_t, ColoredSlotValue_t> slot_assignments;
+
+
+};
+
+
+// a simple way to sort ICFS.   
+
+class UniqueICFSSetSorter_t;
+typedef std::set<libIRDB::ICFS_t, UniqueICFSSetSorter_t> UniqueICFSSet_t;
+
+class UniqueICFSSetSorter_t
+{
+        public:
+                bool operator() (const libIRDB::ICFS_t& a, const libIRDB::ICFS_t& b) const
+                {
+                        if(a.size() == b.size()) return a<b;
+                        return a.size() < b.size() ;
+                }
+};
+
+#endif
+
diff --git a/tools/selective_cfi/scfi_driver.cpp b/tools/selective_cfi/scfi_driver.cpp
index 45c82f5c6..b1eb37d87 100644
--- a/tools/selective_cfi/scfi_driver.cpp
+++ b/tools/selective_cfi/scfi_driver.cpp
@@ -35,12 +35,12 @@ using namespace libIRDB;
 
 void usage(char* name)
 {
-	cerr<<"Usage: "<<name<<" <variant_id>\n"; 
+	cerr<<"Usage: "<<name<<" <variant_id> (--color|--no-color)\n"; 
 }
 
 int main(int argc, char **argv)
 {
-        if(argc != 2)
+        if(argc < 2)
         {
                 usage(argv[0]);
                 exit(1);
@@ -52,6 +52,15 @@ int main(int argc, char **argv)
                 exit(1);
 	}
 
+	bool do_coloring=false;
+	for(int  i=0;i<argc;i++)
+	{
+		if(string(argv[i])=="--color")
+			do_coloring=true;
+		else if(string(argv[i])=="--no-color")
+			do_coloring=false;
+	}
+
         string programName(argv[0]);
         int variantID = atoi(argv[1]);
 
@@ -80,7 +89,7 @@ int main(int argc, char **argv)
 
                 try
                 {
-			SCFI_Instrument scfii(firp);
+			SCFI_Instrument scfii(firp, do_coloring);
 
 
 			int success=scfii.execute();
diff --git a/tools/selective_cfi/scfi_instr.cpp b/tools/selective_cfi/scfi_instr.cpp
index 7f03a4b81..ed4936668 100644
--- a/tools/selective_cfi/scfi_instr.cpp
+++ b/tools/selective_cfi/scfi_instr.cpp
@@ -22,7 +22,9 @@
 #include "utils.hpp"
 #include "scfi_instr.hpp"
 #include "Rewrite_Utility.hpp"
+#include "color_map.hpp"
 #include <stdlib.h>
+#include <memory>
 
 
 
@@ -252,11 +254,25 @@ bool SCFI_Instrument::needs_scfi_instrumentation(Instruction_t* insn)
 
 }
 
+unsigned int SCFI_Instrument::GetNonceOffset(Instruction_t* insn)
+{
+	if(color_map)
+	{
+		assert(insn->GetIBTargets());
+		return color_map->GetColorOfIB(insn).GetPosition() * GetNonceSize(insn);
+	}
+	return GetNonceSize(insn);
+}
 
-unsigned int SCFI_Instrument::GetNonce(Instruction_t* insn)
+NonceValueType_t SCFI_Instrument::GetNonce(Instruction_t* insn)
 {
 	/* in time we look up the nonce category for this insn */
 	/* for now, it's just f4 as the nonce */
+	if(color_map)
+	{
+		assert(insn->GetIBTargets());
+		return color_map->GetColorOfIB(insn).GetNonceValue();
+	}
 	return 0xf4;
 }
 
@@ -280,13 +296,34 @@ bool SCFI_Instrument::mark_targets()
 		{
 			ind_targets++;
 			string type;
-			type="cfi_nonce=";
-			type+=to_string(GetNonce(insn));
-
-			Relocation_t* reloc=create_reloc(insn);
-			reloc->SetOffset(-GetNonceSize(insn));
-			reloc->SetType(type);
-			cout<<"Found indtarget  for "<<std::dec<<insn->GetBaseID()<<":"<<insn->GetComment()<<endl;
+			if(do_coloring)
+			{
+				ColoredSlotValues_t v=color_map->GetColorsOfIBT(insn);
+				int size=1;
+				for(int i=0;i<v.size();i++)
+				{
+					if(!v[i].IsValid())
+						continue;
+					int position=v[i].GetPosition();
+					NonceValueType_t noncevalue=v[i].GetNonceValue();
+					type=string("cfi_nonce=(pos=") +  to_string(position) + ",nv="
+						+ to_string(noncevalue) + ",sz="+ to_string(size)+ ")";
+					Relocation_t* reloc=create_reloc(insn);
+					reloc->SetOffset(-position*size);
+					reloc->SetType(type);
+					cout<<"Created reloc='"+type+"' for "<<std::dec<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl;
+				}
+			}
+			else
+			{
+				type="cfi_nonce=";
+				type+=to_string(GetNonce(insn));
+
+				Relocation_t* reloc=create_reloc(insn);
+				reloc->SetOffset(-GetNonceOffset(insn));
+				reloc->SetType(type);
+				cout<<"Found nonce="+type+"  for "<<std::dec<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl;
+			}
 		}
 	}
 	cout<<"# ATTRIBUTE ind_targets_found="<<std::dec<<ind_targets<<endl;
@@ -355,17 +392,20 @@ void mov_reloc(Instruction_t* from, Instruction_t* to, string type )
 
 void SCFI_Instrument::AddJumpCFI(Instruction_t* insn)
 {
+	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.
-#ifdef CGC
-	// insert the pop/checking code.
 
 	string pushbits=change_to_push(insn);
-
 	cout<<"Converting ' "<<insn->getDisassembly()<<"' to '";
 	Instruction_t* after=insertDataBitsBefore(firp,insn,pushbits); 
-	cout<<insn->getDisassembly()<<"'"<<endl;
+#ifdef CGC
+	// insert the pop/checking code.
+	cout<<insn->getDisassembly()<<"+jmp slowpath'"<<endl;
 
 	string jmpBits=getJumpDataBits();
         after->SetDataBits(jmpBits);
@@ -375,25 +415,33 @@ void SCFI_Instrument::AddJumpCFI(Instruction_t* insn)
 	after->SetTarget(after);
 	return;
 #else
-	string pushbits=change_to_push(insn);
-	cout<<"Converting ' "<<insn->getDisassembly()<<"' to '";
 	
-	Instruction_t* after=insertDataBitsBefore(firp,insn,pushbits); 
 	after->SetDataBits(getRetDataBits());
-	cout <<insn->getDisassembly()<<" + ret "<<endl ;
+	cout <<insn->getDisassembly()<<" + ret' "<<endl ;
 
 	// 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);
+	AddReturnCFI(after,v);
 	// cout<<"Warning, JUMPS not CFI's yet"<<endl;
 	return;
 #endif
 }
 
 
-void SCFI_Instrument::AddReturnCFI(Instruction_t* insn)
+void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v)
 {
+
+	ColoredSlotValue_t v2; 
+	if(v==NULL && color_map)
+	{
+		v2=color_map->GetColorOfIB(insn);
+		v=&v2;
+	}
+
+
 	string reg="ecx";	// 32-bit reg 
 	if(firp->GetArchitectureBitWidth()==64)
 		reg="r11";	// 64-bit reg.
@@ -420,14 +468,23 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn)
 		if(sp_adjust>0)
 		{
 			sprintf(buf, "lea %s, [%s+%d]", rspreg.c_str(), rspreg.c_str(), sp_adjust);
-			Instruction_t* newinsn=insertAssemblyAfter(firp,insn,buf);
 		}
 
-
 		// rewrite the "old" isntruction, as that's what insertAssemblyBefore returns
 		insn=newafter;
 	}
 		
+	int size=1;
+	string slow_cfi_path_reloc_string="slow_cfi_path=(1,0xf4,1)";
+	if( v && v->IsValid())
+	{
+		slow_cfi_path_reloc_string="slow_cfi_path=("+ to_string(v->GetPosition()) +","
+			                  + to_string(v->GetNonceValue())+","+ to_string(size) +")";
+	}
+	cout<<"Cal'd (unused) slow-path cfi reloc as: "<<slow_cfi_path_reloc_string<<endl;
+// fixme:  would like to mark a slow path per nonce type using the variables calc'd above.
+	
+	
 
 #ifdef CGC
 	// insert the pop/checking code.
@@ -446,6 +503,7 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn)
 
 	string decoration="";
 	int nonce_size=GetNonceSize(insn);
+	int nonce_offset=GetNonceOffset(insn);
 	unsigned int nonce=GetNonce(insn);
 	Instruction_t* jne=NULL, *tmp=NULL;
 	
@@ -484,6 +542,7 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn)
 	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");
+// fixme: record nonce value for each slot.
 	reloc->SetOffset(0);
 
 	return;
@@ -494,7 +553,7 @@ bool SCFI_Instrument::instrument_jumps()
 {
 	int cfi_checks=0;
 
-	// we do this in two passes.  first pass:  find instructions.
+	// for each instruction
 	for(InstructionSet_t::iterator it=firp->GetInstructions().begin();
 		it!=firp->GetInstructions().end();
 		++it)
@@ -551,11 +610,23 @@ bool SCFI_Instrument::execute()
 
 	bool success=true;
 
+	if(do_coloring)
+	{
+		color_map=new ColoredInstructionNonces_t(firp); 
+		assert(color_map);
+		success = success && color_map->build();
+	
+	}
+	
 	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
 	success = success && mark_targets();
 
+
+	delete color_map;
+	color_map=NULL;
+
 	return success;
 }
 
diff --git a/tools/selective_cfi/scfi_instr.hpp b/tools/selective_cfi/scfi_instr.hpp
index 44e704621..d0d62991a 100644
--- a/tools/selective_cfi/scfi_instr.hpp
+++ b/tools/selective_cfi/scfi_instr.hpp
@@ -22,13 +22,15 @@
 #define scfi_instrument_hpp
 
 #include <libIRDB-core.hpp>
+#include "color_map.hpp"
 
 
 
 class SCFI_Instrument
 {
 	public:
-		SCFI_Instrument(libIRDB::FileIR_t *the_firp) : firp(the_firp) {}
+		SCFI_Instrument(libIRDB::FileIR_t *the_firp, bool p_do_coloring=true) 
+			: firp(the_firp), do_coloring(p_do_coloring), color_map(NULL) {}
 		bool execute();
 
 	private:
@@ -47,19 +49,22 @@ class SCFI_Instrument
 		bool needs_scfi_instrumentation(libIRDB::Instruction_t* insn);
 
 		// return instrumentation
-		void  AddReturnCFI(libIRDB::Instruction_t* insn);
+		void  AddReturnCFI(libIRDB::Instruction_t* insn, ColoredSlotValue_t *v=NULL);
 		// jump instrumentation
 		void AddJumpCFI(libIRDB::Instruction_t* insn);
 
 
 		// Nonce Manipulation.
-		unsigned int GetNonce(libIRDB::Instruction_t* insn);
+		NonceValueType_t GetNonce(libIRDB::Instruction_t* insn);
 		unsigned int GetNonceSize(libIRDB::Instruction_t* insn);
+		unsigned int GetNonceOffset(libIRDB::Instruction_t*);
 
 
 
 	
 		libIRDB::FileIR_t* firp;
+		bool do_coloring;
+		ColoredInstructionNonces_t *color_map;
 
 
 };
-- 
GitLab