From 5dae3c0545d0004fa03937f3fb2e3192b9c236bf Mon Sep 17 00:00:00 2001
From: Jason Hiser <jdhiser@gmail.com>
Date: Mon, 24 Dec 2018 17:27:52 -0500
Subject: [PATCH] dealing with making sure personality routines get placed if a
 dollop uses them

---
 src/zipr.cpp            |  37 +++++++++++---
 src/zipr_dollop_man.cpp | 105 ++++++++++++++++++----------------------
 2 files changed, 77 insertions(+), 65 deletions(-)

diff --git a/src/zipr.cpp b/src/zipr.cpp
index c7bce4e..75cdd8e 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -1129,6 +1129,34 @@ void ZiprImpl_t::PlaceDollops()
 			for ( /* empty */; dit != dit_end; dit++)
 			{
 				DollopEntry_t *dollop_entry = *dit;
+				/* 
+				 * first, check if we need to add any reference dollops to the placement queue
+				 */
+				const auto handle_reloc=[&](const Relocation_t* reloc)
+				{
+					auto wrt_insn=dynamic_cast<Instruction_t*>(reloc->GetWRT());
+					if(wrt_insn)
+					{
+						auto containing=m_dollop_mgr.GetContainingDollop(wrt_insn);
+						assert(containing!=nullptr);
+						if(!containing->IsPlaced())
+						{
+							placement_queue.insert(pair<Dollop_t*, RangeAddress_t>( containing, cur_addr));
+							cout<<"Adding to placement queue for reloc of type="<<reloc->GetType()<<endl;
+						}
+					}
+				};
+
+
+				// make sure each instruction referenced via a relocation is placed in a dollop
+				auto insn=dollop_entry->Instruction();
+				for(auto &reloc : insn->GetRelocations())
+					handle_reloc(reloc);
+				auto ehpgm=insn->GetEhProgram();
+				if(ehpgm)
+					for(auto &reloc : ehpgm->GetRelocations())
+						handle_reloc(reloc);
+
 				/*
 				 * There are several ways that a dollop could end:
 				 * 1. There is no more fallthrough (handled above with
@@ -1320,11 +1348,7 @@ void ZiprImpl_t::PlaceDollops()
 				 * even if we do coaelesce something its fallthrough could
 				 * be preplaced ...
 				 */
-				if (!am_coalescing &&
-				    to_place->FallthroughDollop() &&
-				    fallthrough_has_preplacement &&
-				    fallthrough_dollop_place == cur_addr
-				   )
+				if (!am_coalescing && to_place->FallthroughDollop() && fallthrough_has_preplacement && fallthrough_dollop_place == cur_addr)
 				{
 					if (m_verbose)
 						cout << "Dollop had a fallthrough dollop and "
@@ -1767,9 +1791,6 @@ RangeAddress_t ZiprImpl_t::_PlopDollopEntry(DollopEntry_t *entry, RangeAddress_t
 	return updated_addr;
 }
 
-#define IS_RELATIVE(A) \
-((A.ArgType & MEMORY_TYPE) && (A.ArgType & RELATIVE_))
-
 RangeAddress_t ZiprImpl_t::PlopDollopEntry(
 	DollopEntry_t *entry,
 	RangeAddress_t override_place,
diff --git a/src/zipr_dollop_man.cpp b/src/zipr_dollop_man.cpp
index 13f025b..bb215b8 100644
--- a/src/zipr_dollop_man.cpp
+++ b/src/zipr_dollop_man.cpp
@@ -160,20 +160,11 @@ namespace zipr {
 	}
 
 	Dollop_t *ZiprDollopManager_t::GetContainingDollop(libIRDB::Instruction_t *insn) {
-#if 0
-		try {
-			return m_insn_to_dollop.at(insn);
-		} catch (const std::out_of_range &oor) {
-			return NULL;
-		}
-		return NULL;
-#else
 		InsnToDollopMap_t::iterator it=m_insn_to_dollop.find(insn);
 		if(it!=m_insn_to_dollop.end())
 			return it->second;
 		return NULL;
 			
-#endif
 	}
 
 	void ZiprDollopManager_t::AddDollops(Dollop_t *dollop_head) {
@@ -212,70 +203,70 @@ namespace zipr {
 		 * Push the actual dollop onto the list of dollops
 		 * if it's not already there.
 		 */
-#if 0		
-		if (m_dollops.end()==std::find(m_dollops.begin(), m_dollops.end(), dollop))
-			m_dollops.push_back(dollop);
-#else
-			m_dollops.insert(dollop);
-
-#endif
-	
+		m_dollops.insert(dollop);
 		m_refresh_stats = true;
 	}
 
 	bool ZiprDollopManager_t::UpdateTargets(Dollop_t *dollop) {
-		bool changed = false;
-		bool local_changed = false;
-		int local_changed_count=0;
-		int and_count=0;
-		do {
-			local_changed = false;
-			local_changed_count++;
-			const auto local_dollop=list<DollopEntry_t*>(dollop->begin(), dollop->end());
-			list<DollopEntry_t*>::const_iterator it, it_end;
-			for (it = local_dollop.begin(), it_end = local_dollop.end();
-			     it != it_end;
-					 /* nop */) {
-				DollopEntry_t *entry = *it;
-				it++;
-				if (entry->Instruction() &&
-				    entry->Instruction()->GetTarget()) {
-					Dollop_t *new_target=AddNewDollops(entry->Instruction()->GetTarget());
-					and_count++;
+		const auto handle_reloc=[this](const Relocation_t* reloc) 
+		{
+			auto wrt_insn=dynamic_cast<Instruction_t*>(reloc->GetWRT());
+			if(wrt_insn)
+			{
+				// we don't bother marking a change because
+				// we only need to do this once for relocs
+				// and we are certain to get here once for every dollop
+				AddNewDollops(wrt_insn);	
+				cout<<"Adding new dollop for reloc of type="<<reloc->GetType()<<endl;
 
-					/*
-					 * In the case there is a change, we have to restart.
-					 * The dollop that we are updating could itself have
-					 * contained the target and the call would have
-					 * split this dollop. That makes the iterator go
-					 * haywire.
-					 * 
-					 * But!  We could avoid the break by using a copy of the set.
-					 */
-					if (new_target != entry->TargetDollop()) {
-						entry->TargetDollop(new_target);
-						changed = local_changed = true;
-						//break;
-					}
+			}
+		};
+
+		auto changed = false;
+		const auto local_dollop=list<DollopEntry_t*>(dollop->begin(), dollop->end());
+		for (auto &entry : local_dollop )
+		{
+			auto insn=entry->Instruction();
+			if (insn->GetTarget()) 
+			{
+				auto new_target=AddNewDollops(insn->GetTarget());
+
+				/*
+				 * In the case there is a change, we have to restart.
+				 * The dollop that we are updating could itself have
+				 * contained the target and the call would have
+				 * split this dollop. That makes the iterator go
+				 * haywire.
+				 * 
+				 * But!  We could avoid the break by using a copy of the set, which we do.
+				 */
+				if (new_target != entry->TargetDollop()) {
+					entry->TargetDollop(new_target);
+					changed = true;
 				}
 			}
+
+			// make sure each instruction referenced via a relocation is placed in a dollop
+			for(auto &reloc : insn->GetRelocations())
+				handle_reloc(reloc);
+			auto ehpgm=insn->GetEhProgram();
+			if(ehpgm)
+				for(auto &reloc : ehpgm->GetRelocations())
+					handle_reloc(reloc);
+		}
 			
-		} while (false); // while (local_changed);
 		return changed;
 	}
 
 	void ZiprDollopManager_t::UpdateAllTargets(void) {
-		DollopList_t::iterator it, it_end;
-		bool changed = false;
-		int changed_count=0;
-		int update_count=0;
+		auto changed = false;
+		auto changed_count=0;
+		auto update_count=0;
 		do {
 			changed = false;
 			const auto local_dollops=m_dollops;
-			for (it = local_dollops.begin(), it_end = local_dollops.end(); it != it_end; /* nop */) 
+			for (auto entry : local_dollops)
 			{
-				Dollop_t *entry = *it;
-				it++;
 				changed |= UpdateTargets(entry);
 				update_count++;
 				if((update_count%1000000) == 0 )
-- 
GitLab