From b648c2e6e3b0a4d38c2c58674df013d61488bbec Mon Sep 17 00:00:00 2001
From: whh8b <whh8b@git.zephyr-software.com>
Date: Sat, 2 Apr 2016 16:28:32 +0000
Subject: [PATCH] Add support for retargeting callbacks through the SDK.

---
 include/plugin_man.h |  1 +
 include/zipr_impl.h  |  2 +-
 src/plugin_man.cpp   | 15 +++++++++++++++
 src/zipr.cpp         | 39 +++++++++++++++++++++++++++------------
 4 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/include/plugin_man.h b/include/plugin_man.h
index 24a216a40..86c404f7e 100644
--- a/include/plugin_man.h
+++ b/include/plugin_man.h
@@ -43,6 +43,7 @@ class ZiprPluginManager_t : public ZiprPluginInterface_t
 		virtual bool DoesPluginPlop(libIRDB::Instruction_t*,DLFunctionHandle_t&);
 
 		virtual bool DoesPluginAddress(const Dollop_t *, const RangeAddress_t &, Range_t &, bool &coalesce, DLFunctionHandle_t &);
+		virtual bool DoesPluginRetargetCallback(const RangeAddress_t &, const DollopEntry_t *, RangeAddress_t &, DLFunctionHandle_t &) ;
 		virtual bool DoesPluginRetargetPin(const RangeAddress_t &, const Dollop_t *, RangeAddress_t &, DLFunctionHandle_t &) ;
 
 	private:
diff --git a/include/zipr_impl.h b/include/zipr_impl.h
index 91d4b0889..7a41705fb 100644
--- a/include/zipr_impl.h
+++ b/include/zipr_impl.h
@@ -397,7 +397,7 @@ class ZiprImpl_t : public Zipr_t
 		std::map<RangeAddress_t,libIRDB::Instruction_t*> m_InsnAtAddrs; 
 
 		// unpatched callbacks
-		std::set<std::pair<libIRDB::Instruction_t*,RangeAddress_t> > unpatched_callbacks; 
+		std::set<std::pair<Zipr_SDK::DollopEntry_t*,RangeAddress_t> > unpatched_callbacks; 
 
 		std::map<std::string,RangeAddress_t> callback_addrs;
 
diff --git a/src/plugin_man.cpp b/src/plugin_man.cpp
index 58bea1eef..ee5ed1b37 100644
--- a/src/plugin_man.cpp
+++ b/src/plugin_man.cpp
@@ -111,6 +111,21 @@ bool ZiprPluginManager_t::DoesPluginPlop(Instruction_t *insn, DLFunctionHandle_t
 	return false;
 }
 
+bool ZiprPluginManager_t::DoesPluginRetargetCallback(const RangeAddress_t &callback_addr, const DollopEntry_t *callback_entry, RangeAddress_t &target_address, DLFunctionHandle_t &patcher)
+{
+	DLFunctionHandleSet_t::iterator it=m_handleList.begin();
+	for(m_handleList.begin();it!=m_handleList.end();++it)
+	{
+		ZiprPluginInterface_t* zpi=(ZiprPluginInterface_t*)*it;
+		if(Must==zpi->RetargetCallback(callback_addr,callback_entry,target_address))
+		{
+			patcher = zpi;
+			return true;
+		}
+	}
+	return false;
+}
+
 bool ZiprPluginManager_t::DoesPluginRetargetPin(const RangeAddress_t &patch_addr, const Dollop_t *target_dollop, RangeAddress_t &target_address, DLFunctionHandle_t &patcher) 
 {
 	DLFunctionHandleSet_t::iterator it=m_handleList.begin();
diff --git a/src/zipr.cpp b/src/zipr.cpp
index 38a1fae40..b039f2476 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -1413,7 +1413,7 @@ void ZiprImpl_t::PlaceDollops()
 			continue;
 
 		minimum_valid_req_size = std::min(
-			_DetermineWorstCaseInsnSize(to_place-> front()-> Instruction()),
+			_DetermineWorstCaseInsnSize(to_place->front()->Instruction()),
 			Utils::DetermineWorstCaseDollopSizeInclFallthrough(to_place));
 		/*
 		 * Ask the plugin manager if there are any plugins
@@ -1535,7 +1535,7 @@ void ZiprImpl_t::PlaceDollops()
 				last_de_fits = (std::next(dit,1)==dit_end) /* last */ &&
 				               (placement.GetEnd()>=(cur_addr+ /* fits */
 							_DetermineWorstCaseInsnSize(dollop_entry->Instruction(),
-							                            to_place->FallthroughDollop() != NULL))
+							                            to_place->FallthroughDollop()!=NULL))
 							                            /* with or without fallthrough */
 							         );
 
@@ -2267,7 +2267,7 @@ RangeAddress_t ZiprImpl_t::PlopDollopEntryWithCallback(
 	{
 	char bytes[]={(char)0xe8,(char)0,(char)0,(char)0,(char)0}; // call rel32
 	memory_space.PlopBytes(at, bytes, sizeof(bytes));
-	unpatched_callbacks.insert(pair<Instruction_t*,RangeAddress_t>(insn,at));
+	unpatched_callbacks.insert(pair<DollopEntry_t*,RangeAddress_t>(entry,at));
 	at+=sizeof(bytes);
 	}
 
@@ -2860,24 +2860,39 @@ RangeAddress_t ZiprImpl_t::FindCallbackAddress(RangeAddress_t end_of_new_space,
 
 void ZiprImpl_t::UpdateCallbacks()
 {
-        // first byte of this range is the last used byte.
-	RangeSet_t::iterator it=memory_space.FindFreeRange((RangeAddress_t) -1);
-        assert(memory_space.IsValidRange(it));
+	// first byte of this range is the last used byte.
+	RangeSet_t::iterator range_it=memory_space.FindFreeRange((RangeAddress_t) -1);
+	assert(memory_space.IsValidRange(range_it));
 
-        RangeAddress_t end_of_new_space=it->GetStart();
+	RangeAddress_t end_of_new_space=range_it->GetStart();
 	RangeAddress_t start_addr=GetCallbackStartAddr();
 
-	for( std::set<std::pair<libIRDB::Instruction_t*,RangeAddress_t> >::iterator it=unpatched_callbacks.begin();
-		it!=unpatched_callbacks.end();
-		++it
+	set<std::pair<DollopEntry_t*,RangeAddress_t> >::iterator it, it_end;
+
+	for(it=unpatched_callbacks.begin(), it_end=unpatched_callbacks.end();
+	    it!=it_end;
+	    it++
 	   )
 	{
-		Instruction_t *insn=it->first;
+		DollopEntry_t *entry=it->first;
+		Instruction_t *insn = entry->Instruction();
 		RangeAddress_t at=it->second;
 		RangeAddress_t to=FindCallbackAddress(end_of_new_space,start_addr,insn->GetCallback());
+		DLFunctionHandle_t patcher = NULL;
+
+		if (plugman.DoesPluginRetargetCallback(at, entry, to, patcher))
+		{
+			if (m_verbose)
+			{
+				cout << "Patching retargeted callback at " << std::hex << at << " to "
+				     << patcher->ToString() << "-assigned address: "
+						 << std::hex << to << endl;
+			}
+		}
+
 		if(to)
 		{
-			cout<<"Patching callback "<< insn->GetCallback()<<"at "<<std::hex<<at<<" to jump to "<<to<<endl;
+			cout<<"Patching callback "<< insn->GetCallback()<<" at "<<std::hex<<at<<" to jump to "<<to<<endl;
 			PatchCall(at,to);
 		}
 		else
-- 
GitLab