From bf2b3edbbd9ae89cd44b2af63671e8aeb83b227c Mon Sep 17 00:00:00 2001
From: whh8b <whh8b@git.zephyr-software.com>
Date: Sat, 8 Apr 2017 00:47:08 +0000
Subject: [PATCH] Finish callback invocation code.

---
 unpin.cpp | 66 +++++++++++++++++++++++++++++++++++--------------------
 unpin.h   | 11 +++++++++-
 2 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/unpin.cpp b/unpin.cpp
index 3b814b0..41ebe56 100644
--- a/unpin.cpp
+++ b/unpin.cpp
@@ -84,18 +84,23 @@ static bool has_cfi_reloc(Instruction_t* insn)
 	return false;
 }
 
-static bool should_cfi_pin(Instruction_t* insn)
+bool Unpin_t::should_cfi_pin(Instruction_t* insn)
 {
 	// add command line option that:
 	// 	1) return false if !has_cfi_reloc(insn)
 	// 	2) return true if option is on.
-	return false;
+	return m_should_cfi_pin;
 }
 
-ZiprOptionsNamespace_t *Unpin_t::RegisterOptions(ZiprOptionsNamespace_t *global) 
+ZiprOptionsNamespace_t *Unpin_t::RegisterOptions(ZiprOptionsNamespace_t *global)
 {
+	ZiprOptionsNamespace_t *unpin_ns = new ZiprOptionsNamespace_t("unpin");
 	global->AddOption(&m_verbose);
-	return NULL;
+
+	m_should_cfi_pin.SetDescription("Pin CFI instructions.");
+	unpin_ns->AddOption(&m_should_cfi_pin);
+
+	return unpin_ns;
 }
 
 void Unpin_t::DoUnpin()
@@ -245,6 +250,37 @@ void Unpin_t::DoUnpinForScoops()
 	cout<<"#ATTRIBUTE scoop_unpin_missed_unpins="<<dec<<missed_unpins<<endl;
 }
 
+Zipr_SDK::ZiprPreference Unpin_t::RetargetCallback(
+	const RangeAddress_t &callback_address,
+	const DollopEntry_t *callback_entry,
+	RangeAddress_t &target_address)
+{
+	MemorySpace_t &ms=*zo->GetMemorySpace();
+	Instruction_t *insn = callback_entry->Instruction();
+	Zipr_SDK::InstructionLocationMap_t &locMap=*(zo->GetLocationMap());
+	for(
+		RelocationSet_t::iterator rit=insn->GetRelocations().begin();
+		rit!=insn->GetRelocations().end();
+		rit++
+		)
+	{
+		Relocation_t *reloc = *rit;
+		if (reloc->GetType()==string("callback_to_scoop"))
+		{
+			DataScoop_t *wrt = dynamic_cast<DataScoop_t*>(reloc->GetWRT());
+			int addend = reloc->GetAddend();
+
+			target_address = wrt->GetStart()->GetVirtualOffset() + addend;
+		
+			if (m_verbose) {
+				cout << "Unpin::callback_to_scoop: target_addr "
+				     << std::hex << target_address << endl;
+			}
+		}
+	}
+	return Must;
+}
+
 void Unpin_t::DoUpdate()
 {
 	DoUpdateForScoops();
@@ -287,8 +323,6 @@ void Unpin_t::DoUpdateForInstructions()
 		   )
 		{
 			Relocation_t* reloc=*rit;
-
-			
 			// this probably won't work on shared objects.
 			// complicated with the push64-reloc plugin also rewriting these things?
 			if(reloc->GetType()==string("32-bit") || reloc->GetType()==string("push64"))
@@ -474,12 +508,11 @@ void Unpin_t::DoUpdateForInstructions()
 				cout<<"unpin:immedptr_to_scoop:Converting "<<hex<<from_insn->GetBaseID()<<":"<<disasm.CompleteInstr
 			 	    <<" to "<<disasm2.CompleteInstr<<" for scoop: "<<wrt->GetName()<<endl;
 
-
 			}
 			else if(reloc->GetType()==string("callback_to_scoop"))
 			{
 				DataScoop_t *wrt = dynamic_cast<DataScoop_t*>(reloc->GetWRT());
-				int offset = reloc->GetOffset();
+				int addend = reloc->GetAddend();
 				char bytes[]={(char)0x48,
 				              (char)0x8d,
 				              (char)0x64,
@@ -493,30 +526,16 @@ void Unpin_t::DoUpdateForInstructions()
 					     << from_insn->GetDataBits().length() << " bytes long." << endl;
 				
 				call_addr = locMap[from_insn];
-				target_addr = wrt->GetStart()->GetVirtualOffset() + offset;
 			
 				if (m_verbose) {
-					cout << "Unpin::callback_to_scoop: target_addr "
-					     << std::hex << target_addr << endl;
 					cout << "Unpin::callback_to_scoop: call_addr " 
 					     << std::hex << call_addr << endl;
 				}
 
 				/*
-				 * Adjust the target address relative to the position 
-				 * of the instruction.
-				 */
-				target_addr -= (call_addr + from_insn->GetDataBits().length());
-
-				/*
-				 * Update the call instruction.
+				 * Put down the bogus pop.
 				 */
 				at = call_addr + 1;
-				ms.PlopBytes(call_addr+1, (const char *)&target_addr, 4);
-
-				/*
-				 * Now, put down the bogus pop.
-				 */
 				at = call_addr + from_insn->GetDataBits().length();
 				ms.PlopBytes(at, bytes, sizeof(bytes));
 
@@ -529,7 +548,6 @@ void Unpin_t::DoUpdateForInstructions()
 			}
 		}
 	}
-
 }
 
 void Unpin_t::DoUpdateForScoops()
diff --git a/unpin.h b/unpin.h
index cfedfeb..1fa125f 100644
--- a/unpin.h
+++ b/unpin.h
@@ -32,11 +32,13 @@
 #define unpin_h
 
 #include <libIRDB-core.hpp>
+#include <zipr_sdk.h>
+#include <zipr_all.h>
 
 class Unpin_t : public Zipr_SDK::ZiprPluginInterface_t
 {
 	public:
-		Unpin_t( Zipr_SDK::Zipr_t* zipr_object) : zo(zipr_object), m_verbose("verbose") { };
+		Unpin_t( Zipr_SDK::Zipr_t* zipr_object) : zo(zipr_object), m_verbose("verbose"), m_should_cfi_pin("should_cfi_pin", false) { };
 		virtual void PinningBegin()
 		{
 			DoUnpin();
@@ -47,7 +49,13 @@ class Unpin_t : public Zipr_SDK::ZiprPluginInterface_t
 		}
 
 		virtual Zipr_SDK::ZiprOptionsNamespace_t *RegisterOptions(Zipr_SDK::ZiprOptionsNamespace_t *);
+
+		Zipr_SDK::ZiprPreference RetargetCallback(
+			const Zipr_SDK::RangeAddress_t &callback_address,
+			const Zipr_SDK::DollopEntry_t *callback_entry,
+			Zipr_SDK::RangeAddress_t &target_address);
 	private:
+		bool should_cfi_pin(Instruction_t* insn);
 
 		// workhorses 
 		void DoUnpin();
@@ -61,6 +69,7 @@ class Unpin_t : public Zipr_SDK::ZiprPluginInterface_t
 		Zipr_SDK::Zipr_t* zo;
 
 		Zipr_SDK::ZiprBooleanOption_t m_verbose;
+		Zipr_SDK::ZiprBooleanOption_t m_should_cfi_pin;
 };
 
 #endif
-- 
GitLab