From 17c2172cfd219215d2fbd0b990c58cf57beed06a Mon Sep 17 00:00:00 2001
From: jdh8d <jdh8d@git.zephyr-software.com>
Date: Fri, 15 Sep 2017 15:44:41 +0000
Subject: [PATCH] Added emt support for prefork+bilr+p1 (sketchy still), K6+NOG
 (seems stable with all xforms enabled).  I also did some peasoup/cfar fixes
 to support determunistic ID assignment for IRDB objects -- this was needed
 for marshaling because the EMT plugin uses ID matching to find identical
 objects (stack, scoop, instruction, etc.)  Next, I fixed bugs in p1transform
 where the p1.map wasn't getting proper IDs. Lastly, I added an option to
 zipr/elfwrite to disable bss-optimization, this was necessary for marshaling
 as that bss segments stay named/mapped to the binary and cannot be combined
 with other segments.

---
 include/elfwrite.h  | 17 ++++++++++++++--
 include/zipr_impl.h |  3 ++-
 src/elfwrite.cpp    | 49 +++++++++++++++++++++++++++++++++------------
 src/zipr.cpp        |  6 ++++--
 4 files changed, 57 insertions(+), 18 deletions(-)

diff --git a/include/elfwrite.h b/include/elfwrite.h
index 0c412bb..eaa2bb9 100644
--- a/include/elfwrite.h
+++ b/include/elfwrite.h
@@ -70,6 +70,18 @@ class ElfWriter
 		public:
 			LoadSegment_t() :filesz(0), memsz(0), filepos(0), start_page(0), m_perms(0) { }
 
+			LoadSegment_t( unsigned int p_filesz, unsigned int p_memsz, unsigned int p_filepos, unsigned int p_start_page, unsigned int p_m_perms)
+				:
+				filesz(p_filesz),
+				memsz(p_memsz), 
+				filepos(p_filepos),
+				start_page(p_start_page),
+				m_perms(p_m_perms)
+			{
+				
+			}
+
+
 		unsigned int filesz; 
 		unsigned int memsz; 
 		unsigned int filepos;
@@ -82,7 +94,7 @@ class ElfWriter
 	typedef std::map<libIRDB::virtual_offset_t, PageData_t> PageMap_t;
 
 	public: 
-		ElfWriter(libIRDB::FileIR_t* firp, bool write_sections) : m_firp(firp), m_write_sections(write_sections) { }
+		ElfWriter(libIRDB::FileIR_t* firp, bool write_sections, bool bss_opts) : m_firp(firp), m_write_sections(write_sections), m_bss_opts(bss_opts) { }
 		virtual ~ElfWriter() {}
 		void Write(const ELFIO::elfio *elfiop, libIRDB::FileIR_t* firp, const std::string &out_file, const std::string &infile);
 
@@ -112,6 +124,7 @@ class ElfWriter
 	protected:
 		libIRDB::FileIR_t* m_firp;
 		bool m_write_sections;
+		bool m_bss_opts;
 	private:
 		libIRDB::virtual_offset_t DetectMinAddr(const ELFIO::elfio *elfiop, libIRDB::FileIR_t* firp, const std::string &out_file);
 		libIRDB::virtual_offset_t DetectMaxAddr(const ELFIO::elfio *elfiop, libIRDB::FileIR_t* firp, const std::string &out_file);
@@ -134,7 +147,7 @@ class ElfWriterImpl : public ElfWriter
 {
 	public:
 
-		ElfWriterImpl(libIRDB::FileIR_t* firp, bool write_sections) : ElfWriter(firp, write_sections) { } 
+		ElfWriterImpl(libIRDB::FileIR_t* firp, bool write_sections, bool bss_opts ) : ElfWriter(firp, write_sections, bss_opts) { } 
 	
 	protected:
 		int GetFileHeaderSize()  { return sizeof(T_Elf_Ehdr); } 
diff --git a/include/zipr_impl.h b/include/zipr_impl.h
index f4a340d..44824fd 100644
--- a/include/zipr_impl.h
+++ b/include/zipr_impl.h
@@ -55,6 +55,7 @@ class ZiprImpl_t : public Zipr_t
 			m_verbose("verbose", true),
 			m_apply_nop("apply_nop", false),
 			m_add_sections("add-sections", false),
+			m_bss_opts("bss-opts", true),
 			m_variant("variant"),
 			m_architecture("architecture"),
 			m_seed("seed", 0),
@@ -490,7 +491,7 @@ class ZiprImpl_t : public Zipr_t
 		// Options
 		ZiprOptions_t m_zipr_options;
 		ZiprStringOption_t m_output_filename, m_callbacks, m_objcopy;
-		ZiprBooleanOption_t m_replop, m_verbose, m_apply_nop, m_add_sections;
+		ZiprBooleanOption_t m_replop, m_verbose, m_apply_nop, m_add_sections, m_bss_opts;
 		ZiprIntegerOption_t m_variant, m_architecture, m_seed;
 		ZiprStringOption_t m_dollop_map_filename;
 
diff --git a/src/elfwrite.cpp b/src/elfwrite.cpp
index e65edb0..4b63029 100644
--- a/src/elfwrite.cpp
+++ b/src/elfwrite.cpp
@@ -156,34 +156,50 @@ void ElfWriter::SortSegmap()
 
 void ElfWriter::CreateSegmap(const ELFIO::elfio *elfiop, FileIR_t* firp, const string &out_file)
 {
+	const auto should_bss_optimize= [&] (const PageData_t& perms)
+	{
+		return (perms.is_zero_initialized() && m_bss_opts);
+	};
+
+
+
 	// init some segment vars.
-	virtual_offset_t segstart=pagemap.begin()->first;
-	PageData_t segperms=pagemap.begin()->second;
-	virtual_offset_t segend=segstart+PAGE_SIZE;
-	virtual_offset_t initend=segstart;
-	if(pagemap.begin()->second.is_zero_initialized())
-		initend=segstart;
-	else
-		initend=segend;
+	auto segstart=pagemap.begin()->first;
+	auto segperms=pagemap.begin()->second;
+	auto segend=segstart+PAGE_SIZE;
+	auto initend=segstart;
 
-	PageMap_t::iterator it=pagemap.begin(); 
+	const auto update_initend=[&](const PageData_t& perms)
+	{
+		if(should_bss_optimize(perms))
+			initend=segstart;
+		else
+			initend=segend;
+	};
+
+	update_initend(segperms);
+
+	auto it=pagemap.begin(); 
 	++it;	// handled first one above.
 
 	for( /* init'd above */; it!=pagemap.end(); ++it)
 	{
 		// grab page address and perms
-		virtual_offset_t pagestart=it->first;
-		const PageData_t &perms=it->second;
+		const auto pagestart=it->first;
+		const auto &perms=it->second;
 
 
 		// if we switch perms, or skip a page 
 		if( (perms.m_perms!=segperms.m_perms) || (segend!=pagestart))
 		{
+/*
 			LoadSegment_t *seg=new LoadSegment_t;
 			seg->memsz=segend-segstart;
 			seg->filesz=initend-segstart;
 			seg->start_page=segstart;
 			seg->m_perms=segperms.m_perms;
+*/
+			const auto seg=new LoadSegment_t(initend-segstart, segend-segstart, 0, segstart,segperms.m_perms);
 			segvec.push_back(seg);
 
 			cout<<"Found segment "<<hex<<segstart<<"-"<<(segend-1)<<", perms="<<segperms.m_perms<<", memsz="<<seg->memsz<<", filesz="<<seg->filesz<<endl;
@@ -191,28 +207,35 @@ void ElfWriter::CreateSegmap(const ELFIO::elfio *elfiop, FileIR_t* firp, const s
 			segperms=perms;
 			segstart=pagestart;
 			segend=segstart+PAGE_SIZE;
-			if(perms.is_zero_initialized())
+
+			update_initend(perms);
+/*
+			if( should_bss_optimize(perms) ) // perms.is_zero_initialized() && m_bss_opts)
 				initend=segstart;
 			else
 				initend=segend;
+*/
 
 		}
 		else
 		{
 			// else, same permission and next page, extend segment. 
 			segend=pagestart+PAGE_SIZE;
-			if(!perms.is_zero_initialized())
+			if(! should_bss_optimize(perms) ) // !perms.is_zero_initialized() || ! m_bss_opts)
 				initend=pagestart+PAGE_SIZE;
 		}
 		
 	}
 
 	// make sure we print the last one
+/*
 	LoadSegment_t *seg=new LoadSegment_t;
 	seg->memsz=segend-segstart;
 	seg->filesz=initend-segstart;
 	seg->start_page=segstart;
 	seg->m_perms=segperms.m_perms;
+*/
+	const auto seg=new LoadSegment_t(initend-segstart, segend-segstart, 0, segstart,segperms.m_perms);
 	segvec.push_back(seg);
 
 	cout<<"Found segment "<<hex<<segstart<<"-"<<(segend-1)<<", perms="<<segperms.m_perms<<", memsz="<<seg->memsz<<", filesz="<<seg->filesz<<endl;
diff --git a/src/zipr.cpp b/src/zipr.cpp
index c71d9d1..addf5e7 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -156,6 +156,7 @@ ZiprOptionsNamespace_t *ZiprImpl_t::RegisterOptions(ZiprOptionsNamespace_t *glob
 
 
 	m_add_sections.SetDescription("Enable writing of section headers using elfwriter.");
+	m_bss_opts.SetDescription("Enable/Disable optimizing BSS segments so they aren't written to the binary.");
 	m_verbose.SetDescription("Enable verbose output");
 	m_apply_nop.SetDescription("Apply NOP to patches that fallthrough.");
 	m_variant.SetDescription("Variant ID.");
@@ -185,6 +186,7 @@ ZiprOptionsNamespace_t *ZiprImpl_t::RegisterOptions(ZiprOptionsNamespace_t *glob
 	global->AddOption(&m_verbose);
 	global->AddOption(&m_apply_nop);
 	global->AddOption(&m_add_sections);
+	global->AddOption(&m_bss_opts);
 
 	zipr_namespace->MergeNamespace(memory_space.RegisterOptions(global));
 	return zipr_namespace;
@@ -3729,11 +3731,11 @@ void ZiprImpl_t::OutputBinaryFile(const string &name)
 	ElfWriter *ew=NULL;
 	if(m_firp->GetArchitectureBitWidth()==64)
 	{
-		ew=new ElfWriter64(m_firp, m_add_sections);
+		ew=new ElfWriter64(m_firp, m_add_sections, m_bss_opts);
 	}
 	else if(m_firp->GetArchitectureBitWidth()==32)
 	{
-		ew=new ElfWriter32(m_firp, m_add_sections);
+		ew=new ElfWriter32(m_firp, m_add_sections, m_bss_opts);
 	}
 	else assert(0);
 
-- 
GitLab