diff --git a/src/memory_space.cpp b/src/memory_space.cpp
index 7fe90a954b5f434e3e27d32a9bd1201afc698d16..1f2d58e9462c253fdd577259f51cf6450b0ea020 100644
--- a/src/memory_space.cpp
+++ b/src/memory_space.cpp
@@ -270,7 +270,7 @@ Range_t ZiprMemorySpace_t::GetFreeRange(int size)
 		Range_t r=*it;
 		if(r.GetEnd()==(RangeAddress_t)-1)
 			big_range=r;
-		if(r.GetEnd() - r.GetStart() >= (unsigned) size)
+		else if(r.GetEnd() - r.GetStart() >= (unsigned) size)
 			v.push_back(r);
 
 		// that's enough randomization
diff --git a/src/zipr.cpp b/src/zipr.cpp
index 9dd996d9e0ac6cda4f1754dcb746cff6000079f0..3757bc932aba21f772cdc8eed3f2e5a83afe37f7 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -507,6 +507,15 @@ void ZiprImpl_t::FindFreeRanges(const std::string &name)
 	string textra_contents, textra_name;
 	RangeAddress_t max_addr=0;
 	std::map<RangeAddress_t, int> ordered_sections;
+	DataScoopByAddressSet_t sorted_scoop_set;
+
+
+	/*
+	 * This function should be the *only* place where
+	 * scoops are added to m_zipr_scoops. This assert
+	 * is here to maintain that variant.
+	 */
+	assert(m_zipr_scoops.empty());
 
 	/*
 	 * Make an ordered list of the sections
@@ -518,11 +527,8 @@ void ZiprImpl_t::FindFreeRanges(const std::string &name)
 		section* sec = elfiop->sections[i];
 		assert(sec);
 		ordered_sections.insert(std::pair<RangeAddress_t,int>(sec->get_address(), i));
-
-
 	}
 
-
 	CreateExecutableScoops(ordered_sections);
 
 	// scan sections for a max-addr.
@@ -548,8 +554,6 @@ void ZiprImpl_t::FindFreeRanges(const std::string &name)
 
 		if( (sec->get_flags() & SHF_ALLOC) ==0 )
 			continue;
-
-
 	}
 
 	/*
@@ -561,7 +565,17 @@ void ZiprImpl_t::FindFreeRanges(const std::string &name)
 		cout << "Filling gaps that are larger than " << std::dec
 		     << m_paddable_minimum_distance << " bytes." << endl;
 
-	DataScoopByAddressSet_t sorted_scoop_set(ALLOF(m_firp->GetDataScoops()));
+	/*
+	 * Only put pinned data scoops into the list of
+	 * scoops to consider for adding gap filling.
+	 */
+	copy_if(ALLOF(m_firp->GetDataScoops()),
+	        inserter(sorted_scoop_set, sorted_scoop_set.begin()),
+	        [](DataScoop_t* ds)
+	        {
+	        	return ds->GetStart()->GetVirtualOffset() != 0;
+	        }
+	);
 	for( auto it=sorted_scoop_set.begin(); it!=sorted_scoop_set.end(); ++it )
 	{
 		auto this_scoop=*it;
@@ -569,23 +583,25 @@ void ZiprImpl_t::FindFreeRanges(const std::string &name)
 		RangeAddress_t this_end = this_scoop->GetEnd()->GetVirtualOffset(),
 		               next_start = 0;
 
-		if(this_scoop->GetStart()->GetVirtualOffset()==0)
-		{
-			// unpinned scoops can get ignored.
-			continue;
-		}
+		assert(this_scoop->GetStart()->GetVirtualOffset()!=0);
 
 		if (m_verbose)
 			cout << "There's a scoop between " << std::hex
 			     << this_scoop->GetStart()->GetVirtualOffset()
 			     << " and " << std::hex << this_scoop->GetEnd()->GetVirtualOffset()
+			     << " with permissions " << std::hex << this_scoop->getRawPerms()
 			     << endl;
 
+		/*
+		 * Never pad after the last scoop.
+		 */
 		if (std::next(it,1) != sorted_scoop_set.end())
 		{
 			next_scoop = *std::next(it,1);
 			next_start = next_scoop->GetStart()->GetVirtualOffset();
-
+			unsigned int new_padding_scoop_size = 0;
+			RangeAddress_t new_padding_scoop_start = this_end + 1;
+			RangeAddress_t new_padding_scoop_end = next_start - 1;
 
 			if (this_end > next_start) {
 				/*
@@ -600,27 +616,73 @@ void ZiprImpl_t::FindFreeRanges(const std::string &name)
 				continue;
 			}
 
-			if ((next_start - this_end) > (unsigned int)m_paddable_minimum_distance)
+			if (m_verbose)
+				cout << "Considering a gap between: 0x" << std::hex 
+				     << new_padding_scoop_start << "-0x"
+				     << std::hex << new_padding_scoop_end
+				     << endl;
+
+			/*
+			 * If the adjacent scoop is writable, we
+			 * do not want to put an executable scoop
+			 * in the same page.
+			 */
+			if (this_scoop->isWriteable())
+			{
+				new_padding_scoop_start = page_round_up(new_padding_scoop_start);
+
+				if (m_verbose)
+					cout << "Adjacent scoop is writable. Adjusting start up to 0x"
+					     << std::hex << new_padding_scoop_start << "." << endl;
+			}
+
+			/*
+			 * If the next scoop is writable, we
+			 * do not want to put an executable scoop
+			 * in the same page.
+			 */
+			if (next_scoop->isWriteable())
+			{
+				new_padding_scoop_end = page_round_down(new_padding_scoop_end);
+
+				if (m_verbose)
+					cout << "Next scoop is writable. Adjusting end down to 0x"
+					     << std::hex << new_padding_scoop_end << "." << endl;
+			}
+
+			/*
+			 * After making the proper adjustments, we know
+			 * the size of the gap. So, now we have to determine
+			 * whether to pad or not:
+			 *
+			 * 1. Is the gap bigger than the user-defined gap criteria
+			 * 2. One or both of the surrounding segments are not
+			 *    writable (a policy decision not to pad between
+			 *    writable segments.
+			 */
+			new_padding_scoop_size = new_padding_scoop_start - new_padding_scoop_end;
+			if ((new_padding_scoop_size>(unsigned int)m_paddable_minimum_distance) &&
+			    (!this_scoop->isWriteable() || !next_scoop->isWriteable())
+				 )
 			{
 				DataScoop_t *new_padding_scoop = nullptr;
-				AddressID_t *new_padding_scoop_start_addr = new AddressID_t(),
-				            *new_padding_scoop_end_addr = new AddressID_t();
-				RangeAddress_t new_padding_scoop_start, new_padding_scoop_end;
 				string new_padding_scoop_contents, new_padding_scoop_name;
-
-				//new_padding_scoop_start = page_round_up(this_end + 1);
-				new_padding_scoop_start = this_end + 1;
-				//new_padding_scoop_end = page_round_down(next_start - 1);
-				new_padding_scoop_end = next_start - 1;
+				int new_padding_scoop_perms = 0x5;
+				AddressID_t *new_padding_scoop_start_addr = nullptr,
+				            *new_padding_scoop_end_addr = nullptr;
 
 				new_padding_scoop_name = "zipr_scoop_"+
 				                         to_string(new_padding_scoop_start);
 
+				new_padding_scoop_start_addr = new AddressID_t();
+				new_padding_scoop_end_addr = new AddressID_t();
 				new_padding_scoop_start_addr->SetVirtualOffset(new_padding_scoop_start);
 				new_padding_scoop_end_addr->SetVirtualOffset(new_padding_scoop_end);
+				m_firp->GetAddresses().insert(new_padding_scoop_start_addr);
+				m_firp->GetAddresses().insert(new_padding_scoop_end_addr);
 
-				cout << "New free space: 0x" << std::hex << new_padding_scoop_start
-				     << "-0x"
+				cout << "Gap filling with a scoop between 0x"
+				     << std::hex << new_padding_scoop_start << " and 0x"
 				     << std::hex << new_padding_scoop_end
 				     << endl;
 
@@ -629,38 +691,39 @@ void ZiprImpl_t::FindFreeRanges(const std::string &name)
 				                                    new_padding_scoop_start_addr,
 				                                    new_padding_scoop_end_addr,
 				                                    NULL,
-				                                    5,
+				                                    new_padding_scoop_perms,
 				                                    false,
 				                                    new_padding_scoop_contents);
 				new_padding_scoop_contents.resize(new_padding_scoop->GetSize());
 				new_padding_scoop->SetContents(new_padding_scoop_contents);
 
+				/*
+				 * Insert this scoop into a list of scoops that Zipr added.
+				 */
 				m_zipr_scoops.insert(new_padding_scoop);
-				m_firp->GetAddresses().insert(new_padding_scoop_start_addr);
-				m_firp->GetAddresses().insert(new_padding_scoop_end_addr);
 
+				/*
+				 * Tell Zipr that it can put executable code in this section.
+				 */
 				memory_space.AddFreeRange(Range_t(new_padding_scoop_start,
 				                                  new_padding_scoop_end), true);
 			}
 		}
 	}
 
-	// scan scoops for a max-addr.
-	for( auto scoop : m_zipr_scoops)
-	{
-		RangeAddress_t  end=scoop->GetEnd()->GetVirtualOffset();
-
-		if(scoop->GetStart()->GetVirtualOffset()==0)
-		{
-			// unpinned scoops can get ignored.
-			continue;
-		}
-
-		if(end >= max_addr)
+	/*
+	 * Scan the scoops that we added to see if we went beyond
+	 * the previously highest known address. This should never
+	 * happen because we never pad after the last scoop.
+	 */
+	auto max_addr_zipr_scoops_result = max_element(ALLOF(m_zipr_scoops),
+		[](DataScoop_t *a, DataScoop_t *b)
 		{
-			max_addr=end+1;
+			return a->GetEnd()->GetVirtualOffset() <
+			       b->GetEnd()->GetVirtualOffset();
 		}
-	}
+	);
+	assert(max_addr>=(*max_addr_zipr_scoops_result)->GetEnd()->GetVirtualOffset());
 
 	max_addr=PlaceUnplacedScoops(max_addr);
 
@@ -2519,18 +2582,18 @@ void ZiprImpl_t::PlaceDollops()
 				                         );
 				last_de_fits = (std::next(dit,1)==dit_end) /* last */ &&
 				               (placement.GetEnd()>=(cur_addr+ /* fits */
-							DetermineWorstCaseDollopEntrySize(dollop_entry,
-							                            to_place->FallthroughDollop()!=NULL))
-							                            /* with or without fallthrough */
+				                DetermineWorstCaseDollopEntrySize(dollop_entry,
+				                to_place->FallthroughDollop()!=NULL))
+				               /* with or without fallthrough */
 							         );
 				disallowed_override = !allowed_coalescing && 
 				                      !(de_and_fallthrough_fit ||
-															  fits_entirely ||
-															  last_de_fits ||
-															  initial_placement_abuts_pin ||
-															  initial_placement_abuts_fallthrough
-															 ) && 
-															 all_fallthroughs_fit && 
+				                        fits_entirely ||
+				                        last_de_fits ||
+				                        initial_placement_abuts_pin ||
+				                        initial_placement_abuts_fallthrough
+				                       ) && 
+				                       all_fallthroughs_fit && 
 				                       ((placement.GetEnd() - 
 				                        (cur_addr + 
 				                         DetermineWorstCaseDollopEntrySize(
@@ -3234,8 +3297,8 @@ RangeAddress_t ZiprImpl_t::_PlopDollopEntry(DollopEntry_t *entry, RangeAddress_t
 			updated_addr = std::max(zpi->PlopDollopEntry(entry,
 			                                             placed_address,
 			                                             target_address,
-																									 insn_wcis,
-																									 pp_placed_insn),
+		 	                                             insn_wcis,
+		 	                                             pp_placed_insn),
 			                        updated_addr);
 			if (m_verbose)
 				cout << zpi->ToString() << " placed entry " 
@@ -4265,6 +4328,7 @@ void ZiprImpl_t::UpdateScoops()
 			++it;
 			continue;
 		}
+
 		assert(m_zipr_scoops.find(scoop)!=m_zipr_scoops.end());
 
 		/*