From ed4a24539f932585fd96a4f467162dabfac77bd9 Mon Sep 17 00:00:00 2001
From: whh8b <whh8b@git.zephyr-software.com>
Date: Wed, 4 May 2016 03:00:02 +0000
Subject: [PATCH] Debug support for plugins to plop instructions.

---
 include/zipr_dollop_man.h | 10 ++++++++-
 include/zipr_impl.h       | 23 +++++++++++++++++---
 src/dollop.cpp            | 24 +++++++++++++++-----
 src/zipr.cpp              | 46 +++++++++++++++++++++++++++++++--------
 src/zipr_dollop_man.cpp   | 11 ++++++++--
 test/SConscript           |  2 +-
 6 files changed, 95 insertions(+), 21 deletions(-)

diff --git a/include/zipr_dollop_man.h b/include/zipr_dollop_man.h
index e532497..b24fbce 100644
--- a/include/zipr_dollop_man.h
+++ b/include/zipr_dollop_man.h
@@ -41,7 +41,8 @@ typedef		std::map<Dollop_t*, DollopPatchList_t > DollopToDollopPatchListMap_t;
 
 class ZiprDollopManager_t : public DollopManager_t {
 	public:
-		ZiprDollopManager_t() : m_refresh_stats(true) {}
+		ZiprDollopManager_t() : m_refresh_stats(true), m_zipr(NULL) {}
+		ZiprDollopManager_t(Zipr_SDK::Zipr_t *zipr) : m_refresh_stats(true), m_zipr(zipr) {}
 
 		/*
 		 * Adders.
@@ -98,6 +99,11 @@ class ZiprDollopManager_t : public DollopManager_t {
 		void PrintStats(std::ostream &out);
 		void PrintPlacementMap(const MemorySpace_t &memory_space,
 		                       const std::string &map_filename);
+	
+		/*
+		 * Helper functions.
+		 */
+		int DetermineWorstCaseInsnSize(libIRDB::Instruction_t *insn);
 	private:
 		/*
 		 * Helper functions.
@@ -119,5 +125,7 @@ class ZiprDollopManager_t : public DollopManager_t {
 		bool m_refresh_stats;
 		size_t m_total_dollop_space, m_total_dollop_entries;
 		unsigned int m_total_dollops, m_truncated_dollops;
+
+		Zipr_SDK::Zipr_t *m_zipr;
 };
 #endif
diff --git a/include/zipr_impl.h b/include/zipr_impl.h
index d8b4ff4..44363c6 100644
--- a/include/zipr_impl.h
+++ b/include/zipr_impl.h
@@ -43,6 +43,7 @@ class ZiprImpl_t : public Zipr_t
 			m_stats(NULL),
 			m_firp(NULL),
 			m_error(false),
+			m_dollop_mgr(this),
 			elfiop(new ELFIO::elfio), 
 			start_of_new_space(0),
 			memory_space(),
@@ -57,7 +58,6 @@ class ZiprImpl_t : public Zipr_t
 			m_architecture("architecture"),
 			m_seed("seed", 0),
 			m_dollop_map_filename("dollop_map_filename", "dollop.map")
-
 		{ 
 			Init();
  		};
@@ -67,7 +67,24 @@ class ZiprImpl_t : public Zipr_t
 		bool Error() {
 			return m_error;
 		}
+		/*
+		 * PluginDetermineWorstCaseInsnSize
+		 * 
+		 * Determine the worst case instruction size
+		 * and account for the possibility that a plugin
+		 * may be plopping this instruction and want
+		 * to do some calculations.
+		 */
+		int PluginDetermineWorstCaseInsnSize(libIRDB::Instruction_t *insn, bool account_for_jump = true);
 
+		/*
+		 * DetermineWorstCaseInsnSize
+		 * 
+		 * Determine the worst case instruction size
+		 * but do not account for the possibility that a plugin
+		 * may be plopping this instruction and want
+		 * to do some calculations.
+		 */
 		int DetermineWorstCaseInsnSize(libIRDB::Instruction_t*, bool account_for_jump = true);
 
 		Zipr_SDK::RangeAddress_t PlopDollopEntry(
@@ -216,6 +233,7 @@ class ZiprImpl_t : public Zipr_t
 		void WriteDollops();
 		void UpdatePins();
 
+		void ReplopDollopEntriesWithTargets();
 		/*
 		 * OptimizePinnedFallthrough()
 		 *
@@ -426,8 +444,7 @@ class ZiprImpl_t : public Zipr_t
 		ZiprIntegerOption_t m_variant, m_architecture, m_seed;
 		ZiprStringOption_t m_dollop_map_filename;
 
-
-
+		std::list<DollopEntry_t *> m_des_to_replop;
 };
 
 #endif
diff --git a/src/dollop.cpp b/src/dollop.cpp
index e4070ec..636bbbf 100644
--- a/src/dollop.cpp
+++ b/src/dollop.cpp
@@ -4,13 +4,14 @@
 namespace Zipr_SDK {
 	using namespace libIRDB;
 	using namespace zipr;
-	Dollop_t::Dollop_t(Instruction_t *start) :
+	Dollop_t::Dollop_t(Instruction_t *start, Zipr_SDK::DollopManager_t *mgr) :
 		m_size(0),
 		m_fallthrough_dollop(NULL),
 		m_fallback_dollop(NULL),
 		m_fallthrough_patched(false),
 		m_coalesced(false),
-		m_was_truncated(false)
+		m_was_truncated(false),
+		m_dollop_mgr(mgr)
 	{
 		Instruction_t *loop = NULL;
 
@@ -40,7 +41,13 @@ namespace Zipr_SDK {
 		     it++)
 		{
 			Instruction_t *cur_insn = (*it)->Instruction();
-			dollop_size += Utils::DetermineWorstCaseInsnSize(cur_insn, false);
+			if (m_dollop_mgr != NULL)
+				dollop_size += m_dollop_mgr->DetermineWorstCaseInsnSize(cur_insn);
+			else
+			{
+				assert(false);
+				dollop_size += Utils::DetermineWorstCaseInsnSize(cur_insn, false);
+			}
 		}
 
 		if ((m_fallthrough_dollop || (back() && 
@@ -97,6 +104,8 @@ namespace Zipr_SDK {
 
 		new_dollop = new Dollop_t();
 
+		new_dollop->SetDollopManager(m_dollop_mgr);
+
 		/*
 		 * Set fallthrough and fallback dollop pointers.
 		 *    ----- ----
@@ -167,12 +176,16 @@ namespace Zipr_SDK {
 		return comp.m_instruction == m_instruction &&
 		       comp.m_target_dollop == m_target_dollop;
 	}
+
 	bool DollopEntry_t::operator!=(const DollopEntry_t &comp) {
 		return !operator==(comp);
 	}
-	Dollop_t *Dollop_t::CreateNewDollop(libIRDB::Instruction_t *start) {
-		return new Zipr_SDK::Dollop_t(start);
+
+	Dollop_t *Dollop_t::CreateNewDollop(libIRDB::Instruction_t *start,
+	                                    Zipr_SDK::DollopManager_t *mgr) {
+		return new Zipr_SDK::Dollop_t(start, mgr);
 	}
+
 	std::ostream &operator<<(std::ostream &out, const Dollop_t &d) {
 		std::list<DollopEntry_t*>::const_iterator it, it_end;
 		Dollop_t *fallthrough = NULL, *fallback = NULL;
@@ -193,6 +206,7 @@ namespace Zipr_SDK {
 		out << std::hex << &p << ":" << std::hex << p.Target();
 		return out;
 	}
+
 	std::ostream &operator<<(std::ostream &out, const DollopEntry_t &p) {
 		out << "Instruction: " << std::hex << p.Instruction() << std::endl;
 		out << "Target Dollop: " << std::hex << p.TargetDollop() << std::endl;
diff --git a/src/zipr.cpp b/src/zipr.cpp
index 6f9b462..5d8f08b 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -339,6 +339,8 @@ void ZiprImpl_t::CreateBinaryFile()
 
 	WriteDollops();
 
+	ReplopDollopEntriesWithTargets();
+
 	UpdatePins();
 
 	// tell plugins we are done plopping and about to link callbacks.
@@ -1337,10 +1339,26 @@ void ZiprImpl_t::WriteDollops()
 			end = _PlopDollopEntry(entry_to_write);
 			should_end = start + _DetermineWorstCaseInsnSize(entry_to_write->Instruction(), false);
 			assert(end <= should_end);
+			if (entry_to_write->TargetDollop())
+				m_des_to_replop.push_back(entry_to_write);
 		}
 	}
 }
 
+void ZiprImpl_t::ReplopDollopEntriesWithTargets()
+{
+	for (DollopEntry_t *entry_to_write : m_des_to_replop)
+	{
+		Instruction_t *src_insn = NULL;
+		RangeAddress_t src_insn_addr;
+
+		src_insn = entry_to_write->Instruction();
+
+		src_insn_addr = final_insn_locations[src_insn];
+		PlopDollopEntry(entry_to_write, src_insn_addr);
+	}
+}
+
 void ZiprImpl_t::PlaceDollops()
 {
 	int count_pins=0;
@@ -1695,12 +1713,6 @@ void ZiprImpl_t::PlaceDollops()
 					
 					m_stats->total_did_not_coalesce++;
 
-					/*
-					 * Since we inserted a new instruction, we should
-					 * check to see whether a plugin wants to plop it.
-					 */
-					AskPluginsAboutPlopping(patch_de->Instruction());
-
 					/*
 					 * Quit the do-while-true loop that is placing
 					 * as many dollops in-a-row as possible.
@@ -1859,6 +1871,11 @@ void ZiprImpl_t::PatchJump(RangeAddress_t at_addr, RangeAddress_t to_addr)
 	}
 }
 
+int ZiprImpl_t::PluginDetermineWorstCaseInsnSize(Instruction_t *insn, bool account_for_jump)
+{
+	return (int)_DetermineWorstCaseInsnSize(insn, account_for_jump);
+}
+
 size_t ZiprImpl_t::_DetermineWorstCaseInsnSize(Instruction_t* insn, bool account_for_jump)
 {
 	std::map<Instruction_t*,DLFunctionHandle_t>::const_iterator plop_it;
@@ -1881,7 +1898,6 @@ size_t ZiprImpl_t::_DetermineWorstCaseInsnSize(Instruction_t* insn, bool account
 	return worst_case_size;
 }
 
-//static int DetermineWorstCaseInsnSize(Instruction_t* insn)
 int ZiprImpl_t::DetermineWorstCaseInsnSize(Instruction_t* insn, bool account_for_jump)
 {
 	return Utils::DetermineWorstCaseInsnSize(insn, account_for_jump);
@@ -1944,6 +1960,9 @@ void ZiprImpl_t::UpdatePins()
 		patch_addr = p.GetAddress();
 		target_addr = target_dollop_entry->Place();
 
+		if (final_insn_locations.end() != final_insn_locations.find(target_dollop_entry->Instruction()))
+			target_addr = final_insn_locations[target_dollop_entry->Instruction()];
+
 		if (plugman.DoesPluginRetargetPin(patch_addr, target_dollop, target_addr, patcher))
 		{
 			if (m_verbose)
@@ -1962,6 +1981,9 @@ void ZiprImpl_t::UpdatePins()
 			 */
 			target_addr = target_dollop_entry->Place();
 
+			if (final_insn_locations.end() != final_insn_locations.find(target_dollop_entry->Instruction()))
+				target_addr = final_insn_locations[target_dollop_entry->Instruction()];
+
 			if (m_verbose)
 				cout << "Patching pin at " << std::hex << patch_addr << " to "
 				     << std::hex << target_addr << ": " << d.CompleteInstr << endl;
@@ -2114,11 +2136,17 @@ RangeAddress_t ZiprImpl_t::PlopDollopEntry(
 
 	if(entry->TargetDollop())
 	{
+		RangeAddress_t target_address = 0;
+		Instruction_t *target_insn = entry->TargetDollop()->front()->Instruction();
+	
+		if (final_insn_locations.end() != final_insn_locations.find(target_insn))
+			target_address = final_insn_locations[target_insn];
+
 		if (m_verbose)
 			cout << "Plopping at " << std::hex << addr
-			     << " with target " << std::hex << entry->TargetDollop()->Place()
+			     << " with target " << std::hex << ((target_address != 0) ? target_address : entry->TargetDollop()->Place())
 					 << endl;
-		ret=PlopDollopEntryWithTarget(entry, addr);
+		ret=PlopDollopEntryWithTarget(entry, addr, target_address);
 	}
 	else if(entry->Instruction()->GetCallback()!="")
 	{
diff --git a/src/zipr_dollop_man.cpp b/src/zipr_dollop_man.cpp
index 9752f06..a1cb1ee 100644
--- a/src/zipr_dollop_man.cpp
+++ b/src/zipr_dollop_man.cpp
@@ -45,7 +45,7 @@ namespace zipr {
 			std::list<DollopEntry_t*>::iterator it, it_end;
 			Dollop_t *original_new_dollop = NULL, *previous_dollop = NULL;
 			Instruction_t *fallthrough = NULL;
-			original_new_dollop = new_dollop = Dollop_t::CreateNewDollop(start);
+			original_new_dollop = new_dollop = Dollop_t::CreateNewDollop(start,this);
 
 			for (it = new_dollop->begin(), it_end = new_dollop->end();
 			     it != it_end;
@@ -125,7 +125,7 @@ namespace zipr {
 				 * and link them together.
 				 */
 				previous_dollop = new_dollop;
-				new_dollop = Dollop_t::CreateNewDollop(fallthrough);
+				new_dollop = Dollop_t::CreateNewDollop(fallthrough, this);
 				previous_dollop->FallthroughDollop(new_dollop);
 				new_dollop->FallbackDollop(previous_dollop);
 			}
@@ -134,6 +134,13 @@ namespace zipr {
 		}
 	}
 
+	int ZiprDollopManager_t::DetermineWorstCaseInsnSize(libIRDB::Instruction_t *insn) {
+		if (m_zipr != NULL)
+			return m_zipr->PluginDetermineWorstCaseInsnSize(insn, false);
+		else
+			return Utils::DetermineWorstCaseInsnSize(insn, false);
+	}
+
 	void ZiprDollopManager_t::PrintDollopPatches(const ostream &out) {
 		std::list<DollopPatch_t*>::const_iterator patch_it, patch_it_end;
 
diff --git a/test/SConscript b/test/SConscript
index 2585952..05fef64 100644
--- a/test/SConscript
+++ b/test/SConscript
@@ -76,6 +76,6 @@ Range=myenv.Program("Range.exe", Split(RangeFiles))
 MemorySpace=myenv.Program("MemorySpace.exe", Split(MemorySpaceFiles))
 Options=myenv.Program("Options.exe", Split(OptionFiles))
 Dollop=myenv.Program("Dollop.exe", Split(DollopFiles))
-Default([MemorySpace, Options, Dollop, Range])
+Default([MemorySpace, Options, Range])
 #Default([Range])
 
-- 
GitLab