From 3a2d79620e96974049c8827b253568840b9612c9 Mon Sep 17 00:00:00 2001
From: an7s <an7s@git.zephyr-software.com>
Date: Tue, 24 May 2016 19:39:26 +0000
Subject: [PATCH] Add support for return target set threshold

Former-commit-id: 3b75e01403bc75aaf545596fba0b34245d2f19f9
---
 tools/simple_cdi/scdi_driver.cpp |  8 +++--
 tools/simple_cdi/scdi_instr.cpp  | 58 +++++++++++++++++---------------
 tools/simple_cdi/scdi_instr.hpp  | 11 +++---
 3 files changed, 42 insertions(+), 35 deletions(-)

diff --git a/tools/simple_cdi/scdi_driver.cpp b/tools/simple_cdi/scdi_driver.cpp
index dbbb81622..33d9dbc84 100644
--- a/tools/simple_cdi/scdi_driver.cpp
+++ b/tools/simple_cdi/scdi_driver.cpp
@@ -35,7 +35,7 @@ using namespace libIRDB;
 
 void usage(char* name)
 {
-	cerr<<"Usage: "<<name<<" <variant_id>\n"; 
+	cerr<<"Usage: "<<name<<" <variant_id> --threshold <return_set_threshold> (default=1)\n"; 
 }
 
 int main(int argc, char **argv)
@@ -48,6 +48,9 @@ int main(int argc, char **argv)
 
         string programName(argv[0]);
         int variantID = atoi(argv[1]);
+	int threshold = 1;
+
+	// FIXME: implement getting threshold value from arguments
 
         VariantID_t *pidp=NULL;
 
@@ -74,8 +77,7 @@ int main(int argc, char **argv)
 
                 try
                 {
-			SimpleCDI_Instrument scdii(firp);
-
+			SimpleCDI_Instrument scdii(firp, threshold);
 
 			int success=scdii.execute();
 
diff --git a/tools/simple_cdi/scdi_instr.cpp b/tools/simple_cdi/scdi_instr.cpp
index 6b2025354..a6a6329c5 100644
--- a/tools/simple_cdi/scdi_instr.cpp
+++ b/tools/simple_cdi/scdi_instr.cpp
@@ -230,11 +230,7 @@ bool SimpleCDI_Instrument::add_scdi_instrumentation(Instruction_t* insn)
 		cout <<"["<<string(d.CompleteInstr)<<"] [" << string(d.Instruction.Mnemonic)<< "] IBTargets size: " << ibts->size() << " analysis_status: " << ibts->GetAnalysisStatus() << endl;
 	}
 
-	// only handle ret if complete && ib target size == 1
-
-	// @todo: for debugging, hlt
-	// @todo: can handle size == 2 with just one cmp
-	if (string(d.Instruction.Mnemonic) == string("ret ")) 
+	if (is_return(insn))
 	{
 		// instrumentation must be coordinated with needs_scdi_instrumentation()
 		if (ibts && ibts->IsComplete() && ibts->size() == 1)
@@ -266,6 +262,7 @@ bool SimpleCDI_Instrument::add_scdi_instrumentation(Instruction_t* insn)
 	}
 
 	assert(strstr("ret ", d.Instruction.Mnemonic)==NULL);
+	assert(strstr("retn ", d.Instruction.Mnemonic)==NULL);
 	
 	// pre-instrument
 	// push reg
@@ -306,17 +303,27 @@ bool SimpleCDI_Instrument::add_scdi_instrumentation(Instruction_t* insn)
 	return success;
 }
 
-
-bool SimpleCDI_Instrument::needs_scdi_instrumentation(Instruction_t* insn)
+bool SimpleCDI_Instrument::is_return(Instruction_t* insn)
 {
-	DISASM d;
-	insn->Disassemble(d);
-
-	bool isReturn = false;
+	if (insn) 
+	{
+		DISASM d;
+		insn->Disassemble(d);
+		return string(d.Instruction.Mnemonic) == string("ret "); 
+
+		// FIXME: handle retn immd, but this means the instrumentation should pop/lea immd
+	/*	return (string(d.Instruction.Mnemonic) == string("ret ") ||
+		    string(d.Instruction.Mnemonic) == string("retn "));
+	*/
+	}
 
-	if (string(d.Instruction.Mnemonic) == string("ret "))
-		isReturn = true;
+	return false;
+}
 
+// only complete returns need to be instrumented
+bool SimpleCDI_Instrument::needs_scdi_instrumentation(Instruction_t* insn, int target_size_threshold)
+{
+	const bool isReturn = is_return(insn);
 
 	if (isReturn)
 		num_returns++;
@@ -332,24 +339,19 @@ bool SimpleCDI_Instrument::needs_scdi_instrumentation(Instruction_t* insn)
 			num_complete_returns++;
 	}
 
-	if (string(d.Instruction.Mnemonic) == string("ret "))
+	if (isReturn)
 	{
-		if (ibts->IsComplete() && ibts->size() == 1)
-			return true;
+		if (ibts->IsComplete())
+		{
+			if (target_set_threshold < 0)
+				return true;
+			else 
+				return ibts->size() <= target_size_threshold;
+		}
 		else 
 			return false;
 	}
 
-/*
-	if (ibts->IsComplete() && ibts->size() <= 2)
-		return true;
-*/
-
-/*
-	if(ibts->IsComplete() && ibts->size() >0 )
-		return true;
-*/
-
 	return false;
 }
 
@@ -363,9 +365,8 @@ bool SimpleCDI_Instrument::convert_ibs()
                 ++it)
         {
 		Instruction_t* insn=*it;
-		if(needs_scdi_instrumentation(insn))
+		if(needs_scdi_instrumentation(insn, target_set_threshold))
 			success = success && add_scdi_instrumentation(insn);
-			
 	}
 
 	return success;
@@ -374,6 +375,7 @@ bool SimpleCDI_Instrument::convert_ibs()
 void SimpleCDI_Instrument::display_stats(std::ostream &out)
 {
 	float fraction = NAN;
+	out << "# ATTRIBUTE target_set_threshold=" << dec << target_set_threshold << endl;
 	out << "# ATTRIBUTE complete_ibts=" << dec << num_complete_ibts << endl;
 	out << "# ATTRIBUTE num_returns=" << num_returns << endl;
 	if (num_complete_returns>0)
diff --git a/tools/simple_cdi/scdi_instr.hpp b/tools/simple_cdi/scdi_instr.hpp
index 5c05d876e..70c43cbef 100644
--- a/tools/simple_cdi/scdi_instr.hpp
+++ b/tools/simple_cdi/scdi_instr.hpp
@@ -28,24 +28,27 @@
 class SimpleCDI_Instrument
 {
 	public:
-		SimpleCDI_Instrument(libIRDB::FileIR_t *the_firp) : firp(the_firp), 
+		SimpleCDI_Instrument(libIRDB::FileIR_t *the_firp, int p_target_set_threshold=1) : firp(the_firp), 
 			single_target_set_jumps(0),
 			single_target_set_returns(0),
 			num_complete_ibts(0),
 			num_returns(0),
-			num_complete_returns(0) {}
+			num_complete_returns(0),
+			target_set_threshold(p_target_set_threshold) {}
 		bool execute();
 
 	private:
 
-
+		bool is_return(libIRDB::Instruction_t* insn);
 		bool add_scdi_instrumentation(libIRDB::Instruction_t* insn);
-		bool needs_scdi_instrumentation(libIRDB::Instruction_t* insn);
+		bool needs_scdi_instrumentation(libIRDB::Instruction_t* insn, int p_target_set_threshold);
 		bool convert_ibs();
 		void display_stats(std::ostream &out);
 	
 		libIRDB::FileIR_t* firp;
 
+		int target_set_threshold;
+
 		int single_target_set_jumps;
 		int single_target_set_returns;
 		int num_complete_ibts;
-- 
GitLab