From 2c28ef3a6aa225e3dbb3dbeed8831aa6a860fba3 Mon Sep 17 00:00:00 2001
From: Jason Hiser <jdhiser@gmail.com>
Date: Mon, 16 Dec 2019 13:47:42 -0500
Subject: [PATCH] windows attempts at fixing stuff

---
 irdb-libs/ir_builders/fill_in_cfg.cpp      | 261 +++++++++++++++------
 irdb-libs/ir_builders/fill_in_indtargs.cpp |   9 +-
 irdb-libs/ir_builders/split_eh_frame.cpp   |   7 +-
 3 files changed, 206 insertions(+), 71 deletions(-)

diff --git a/irdb-libs/ir_builders/fill_in_cfg.cpp b/irdb-libs/ir_builders/fill_in_cfg.cpp
index 010b2fdf2..0c424724a 100644
--- a/irdb-libs/ir_builders/fill_in_cfg.cpp
+++ b/irdb-libs/ir_builders/fill_in_cfg.cpp
@@ -28,6 +28,12 @@
 #include "elfio/elfio.hpp"
 #include "split_eh_frame.hpp"
 #include "back_search.hpp"
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#include <pe_bliss.h>
+#include <pe_structures.h>
+#pragma GCC diagnostic pop
+
+
 
 using namespace std;
 using namespace EXEIO;
@@ -684,60 +690,7 @@ void PopulateCFG::detect_scoops_in_code(FileIR_t *firp)
 
 void PopulateCFG::ctor_detection(FileIR_t *firp)
 {
-	assert(firp);
-	if(do_ctor_detection == cdt_NO) return;
-
-	const auto is_pe = firp->getArchitecture()->getFileType() == adftPE ;
-	if(do_ctor_detection == cdt_PE32AUTO && !is_pe) return;
-
-	// is either a PE file and we are in auto detect mode
-	// or ctor_detection is yes.
-	assert(is_pe || do_ctor_detection == cdt_YES);
-
-	auto find_ctor_start=[&](const exeio_section_t* sec, const VirtualOffset_t end_of_ctor) -> VirtualOffset_t
-		{
-			// values needed later for various things
-			const auto ptrsize   = firp->getArchitectureBitWidth() / 8 ;
-			const auto sec_data  = sec->get_data();
-			const auto sec_start = sec->get_address();
-
-			// check for a null terminator at the stated end of table
-			const auto null_term_addr=end_of_ctor-ptrsize;
-			const auto null_term_value =
-				ptrsize == 8 ?  *(uint64_t*)(sec_data+null_term_addr-sec_start) :
-				ptrsize == 4 ?  *(uint32_t*)(sec_data+null_term_addr-sec_start) :
-		                throw invalid_argument("Unknown ptrsize");
-
-			// not found, return this isn't sane.
-			if(null_term_value!=0) return 0;
-
-			// now scan the table in reverse order for 1) valid entries, or 2) a -1 terminator.
-			auto next_addr=null_term_addr-ptrsize;
-			while(true)
-			{
-				// check for flowing
-				if(next_addr<sec_start) return 0;
-
-				// get the table entry
-				const auto ctor_entry_value =
-					ptrsize == 8 ?  *(uint64_t*)(sec_data+next_addr-sec_start) :
-					ptrsize == 4 ?  *(uint32_t*)(sec_data+next_addr-sec_start) :
-					throw invalid_argument("Unknown ptrsize");
-
-				// check for the -1 terminator
-				if(ptrsize == 8 && (int64_t)ctor_entry_value==int64_t(-1)) return next_addr;
-				if(ptrsize == 4 && (int32_t)ctor_entry_value==int32_t(-1)) return next_addr;
-
-				// check if the table entry isn't a valid address
-				const auto is_before_start = ctor_entry_value <  sec->get_address() ;
-				const auto is_after_end    = ctor_entry_value > (sec->get_address()+sec->get_size());
-				if(is_before_start || is_after_end) return 0;
-
-				next_addr -= ptrsize;
-			}
-		};
-
-	auto create_ctor_scoop=[&](const string& name, const VirtualOffset_t& start_vo, const VirtualOffset_t& end_vo)
+	const auto create_text_scoop=[&](const string& name, const VirtualOffset_t& start_vo, const VirtualOffset_t& end_vo)
 		{
 			auto startaddr             = firp->addNewAddress(firp->getFile()->getBaseID(), start_vo); // start and end address 
 			auto endaddr               = firp->addNewAddress(firp->getFile()->getBaseID(), end_vo);
@@ -757,19 +710,193 @@ void PopulateCFG::ctor_detection(FileIR_t *firp)
 			cout << "Added ctor/dtor scoop called " << name << " at " << hex << start_vo << "-" << end_vo << endl;
 		};	
 
-	const auto text_sec = exeiop->sections[".text"];
-	if(text_sec == nullptr) return;
-	const auto text_end_addr = text_sec->get_address()+text_sec->get_size();
-	const auto dtor_end      = text_end_addr-1;
-	const auto dtor_start    = find_ctor_start(text_sec,text_end_addr);
-	if(dtor_start==0) return;
-	create_ctor_scoop(".dtor", dtor_start, dtor_end);
-
-	const auto ctor_end   = dtor_start-1;
-	const auto ctor_start = find_ctor_start(text_sec,dtor_start);
-	if(ctor_start==0) return;
-	create_ctor_scoop(".ctor", ctor_start, ctor_end);
-	return;
+	const auto gnustyle = [&]() -> bool
+	{
+		assert(firp);
+		if(do_ctor_detection == cdt_NO) return false;
+
+		const auto is_pe = firp->getArchitecture()->getFileType() == adftPE ;
+		if(do_ctor_detection == cdt_PE32AUTO && !is_pe) return false;
+
+		// is either a PE file and we are in auto detect mode
+		// or ctor_detection is yes.
+		assert(is_pe || do_ctor_detection == cdt_YES);
+
+		auto find_ctor_start=[&](const exeio_section_t* sec, const VirtualOffset_t end_of_ctor) -> VirtualOffset_t
+			{
+				// values needed later for various things
+				const auto ptrsize   = firp->getArchitectureBitWidth() / 8 ;
+				const auto sec_data  = sec->get_data();
+				const auto sec_start = sec->get_address();
+
+				// check for a null terminator at the stated end of table
+				const auto null_term_addr=end_of_ctor-ptrsize;
+				const auto null_term_value =
+					ptrsize == 8 ?  *(uint64_t*)(sec_data+null_term_addr-sec_start) :
+					ptrsize == 4 ?  *(uint32_t*)(sec_data+null_term_addr-sec_start) :
+					throw invalid_argument("Unknown ptrsize");
+
+				// not found, return this isn't sane.
+				if(null_term_value!=0) return 0;
+
+				// now scan the table in reverse order for 1) valid entries, or 2) a -1 terminator.
+				auto next_addr=null_term_addr-ptrsize;
+				while(true)
+				{
+					// check for flowing
+					if(next_addr<sec_start) return 0;
+
+					// get the table entry
+					const auto ctor_entry_value =
+						ptrsize == 8 ?  *(uint64_t*)(sec_data+next_addr-sec_start) :
+						ptrsize == 4 ?  *(uint32_t*)(sec_data+next_addr-sec_start) :
+						throw invalid_argument("Unknown ptrsize");
+
+					// check for the -1 terminator
+					if(ptrsize == 8 && (int64_t)ctor_entry_value==int64_t(-1)) return next_addr;
+					if(ptrsize == 4 && (int32_t)ctor_entry_value==int32_t(-1)) return next_addr;
+
+					// check if the table entry isn't a valid address
+					const auto is_before_start = ctor_entry_value <  sec->get_address() ;
+					const auto is_after_end    = ctor_entry_value > (sec->get_address()+sec->get_size());
+					if(is_before_start || is_after_end) return 0;
+
+					next_addr -= ptrsize;
+				}
+			};
+
+
+		const auto text_sec = exeiop->sections[".text"];
+		if(text_sec == nullptr) return false;
+		const auto text_end_addr = text_sec->get_address()+text_sec->get_size();
+		const auto dtor_end      = text_end_addr-1;
+		const auto dtor_start    = find_ctor_start(text_sec,text_end_addr);
+		if(dtor_start==0) return false;
+		create_text_scoop(".dtor", dtor_start, dtor_end);
+
+		const auto ctor_end   = dtor_start-1;
+		const auto ctor_start = find_ctor_start(text_sec,dtor_start);
+		if(ctor_start==0) return false;
+		create_text_scoop(".ctor", ctor_start, ctor_end);
+		return true;
+	};
+
+	const auto winstyle = [&]() -> bool
+	{
+		const auto  reloc_sec = exeiop->sections[".reloc"];
+		if(reloc_sec == nullptr) return false;
+		const auto reloc_data = string(reloc_sec->get_data(), reloc_sec->get_size());
+		const auto peblissp = static_cast<pe_bliss::pe_base*>(exeiop->get_pebliss());
+		if(peblissp == nullptr) return false;
+		const auto pe_image_base = peblissp->get_image_base_64();
+
+		// for each block in the reloc section
+		using reloc_block_header_t = 
+			struct 
+			{
+				uint32_t page;
+				uint32_t block_size;
+			};
+		using reloc_block_t = 
+			struct
+			{
+				uint16_t offset:12; 	// lower bits 
+				uint16_t type:4;	// higher bits than offset?
+			};
+		static_assert(sizeof(reloc_block_header_t)==8, "size of reloc_block_header is wrong");
+		static_assert(sizeof(reloc_block_t)==2, "size of reloc_block is wrong");
+		// start at block 0
+		auto current_offset = VirtualOffset_t(0);
+		while(true)
+		{
+
+			// stop if we fall off the end of the section.
+			if(current_offset + sizeof(reloc_block_header_t) > static_cast<size_t>(reloc_sec->get_size()))
+				break;
+
+			// read the header
+			auto header = reloc_block_header_t();
+			memcpy(&header, &reloc_data.c_str()[current_offset], sizeof(header));
+
+			// start counting the length after we've read the header.
+			auto current_length = size_t(sizeof(header));
+
+			// for each entry in the block
+			while(true)
+			{
+				// stop if we exceed the block
+				if(current_length + sizeof(reloc_block_t) > header.block_size)
+					break;
+				// stop if we exceed the section
+				if(current_offset + current_length + sizeof(reloc_block_t) > static_cast<size_t>(reloc_sec->get_size()))
+					break;
+				
+				// read the block
+				auto block  = reloc_block_t();
+				memcpy(&block, &reloc_data.c_str()[current_offset+current_length], sizeof(block));
+				current_length += sizeof(block);
+
+				// for now, just log
+				const auto rva = pe_image_base + header.page + block.offset;
+				cout << "reloc rva = " << hex << rva << " type = " << block.type << '\n';
+
+				switch(block.type)
+				{
+					case pe_bliss::pe_win::image_rel_based_absolute: /* ignored */
+						break;
+					case pe_bliss::pe_win::image_rel_based_dir64: /* dir64 */
+					{
+						const auto relocd_sec = exeiop->sections.findByAddress(rva);
+						if(!relocd_sec) throw runtime_error("Unexpected relocation address?");
+
+						const auto relocd_sec_name = relocd_sec->get_name();
+						if(relocd_sec_name != ".text") // no need to pin anything besides the text seg.
+							continue;   // try next block
+
+						const auto new_name = "winstyle_scoop_"+to_string(rva);
+						create_text_scoop(new_name, rva, rva+8);
+
+						break;
+					}
+					default:
+						throw runtime_error("Cannot handle PE relocation.");
+
+				}
+			}
+			// update to the next block
+			current_offset += current_length;
+		}
+		return true;
+
+
+	};
+
+
+	const auto scoopify_data_dir_sections = [&]() 
+	{
+		const auto peblissp = static_cast<pe_bliss::pe_base*>(exeiop->get_pebliss());
+
+		for(auto dir=0u; dir<15; dir++)
+		{
+			if(!peblissp->directory_exists(dir))
+				continue;
+
+			const auto dir_rva  = peblissp->get_directory_rva (dir);
+			const auto dir_size = peblissp->get_directory_size(dir);
+
+			cout << "Directory " << dec << dir << " is at " << hex << dir_rva << " - " << dir_rva+dir_size << '\n';
+
+			
+		}
+	};
+
+	
+//	scoopify_data_dir_sections();
+
+	if(gnustyle()) return;
+//	if(winstyle()) return;
+
+	cerr << "Caution!  Could not find any reloc handling for ctor/dtor and/or plts." << endl;
 
 }
 
diff --git a/irdb-libs/ir_builders/fill_in_indtargs.cpp b/irdb-libs/ir_builders/fill_in_indtargs.cpp
index 8b1d93053..7f6d54714 100644
--- a/irdb-libs/ir_builders/fill_in_indtargs.cpp
+++ b/irdb-libs/ir_builders/fill_in_indtargs.cpp
@@ -4114,12 +4114,17 @@ int executeStep()
 	}
 	catch (DatabaseError_t pnide)
 	{
-		cout<<"Unexpected database error: "<<pnide<<endl;
+		cout << "Unexpected database error: " << pnide << endl;
 		return -1;
         }
+	catch (const exception& e)
+	{
+		cout << "Unexpected error: " << e.what() << endl;
+		return -1;
+	}
         catch(...)
         {
-                cerr<<"Unexpected error"<<endl;
+                cerr << "Unexpected error" << endl;
                 return -1;
         }
 
diff --git a/irdb-libs/ir_builders/split_eh_frame.cpp b/irdb-libs/ir_builders/split_eh_frame.cpp
index a10e786a4..ffe5f6418 100644
--- a/irdb-libs/ir_builders/split_eh_frame.cpp
+++ b/irdb-libs/ir_builders/split_eh_frame.cpp
@@ -642,7 +642,10 @@ class pe_eh_split_t
 				cout << "\tfp reg             " << +exc.get_frame_pointer_register_number() << endl;
 				cout << "\tscaled rsp offset  " << +exc.get_scaled_rsp_offset() << endl;
 
-				const auto  unwind_addr     = exc.get_unwind_info_address();
+				const auto unwind_addr     = exc.get_unwind_info_address();
+				if(unwind_addr == 0) 
+					continue; // no unwind info 
+
 				const auto &unwind_sec      = peb_obj->section_from_rva(unwind_addr);
 				const auto next_unwind_addr = i < edd.size() ?                            // last element?
 					edd[i+1].get_unwind_info_address()   :                            // yes: value from start of next unwind info entry 
@@ -748,7 +751,7 @@ void split_eh_frame(FileIR_t* firp, exeio *exeiop)
 {
 	if( firp->getArchitecture()->getFileType()==adftPE )
 	{
-		pe_eh_split_t<64>(firp,exeiop).split_pe_file();
+//		pe_eh_split_t<64>(firp,exeiop).split_pe_file();
 
 	}
 	else
-- 
GitLab