From ac13ebc803c4ca1fa32887500fe2fe4cb520f690 Mon Sep 17 00:00:00 2001
From: Jason Hiser <jdhiser@gmail.com>
Date: Mon, 16 Dec 2019 13:48:56 -0500
Subject: [PATCH] some fixups for windows pgms

---
 src/cmdstr.hpp  | 88 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/ehwrite.cpp |  3 +-
 src/pewrite.cpp |  7 ++--
 src/zipr.cpp    | 21 +++++++-----
 4 files changed, 107 insertions(+), 12 deletions(-)
 create mode 100644 src/cmdstr.hpp

diff --git a/src/cmdstr.hpp b/src/cmdstr.hpp
new file mode 100644
index 000000000..48d67c5e5
--- /dev/null
+++ b/src/cmdstr.hpp
@@ -0,0 +1,88 @@
+#ifndef cmdstr_hpp 
+#define cmdstr_hpp 
+
+/*BINFMTCXX: -std=c++11 -Wall -Werror
+*/
+
+#include <spawn.h> // see manpages-posix-dev
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <iostream>
+#include <string>
+#include <vector>
+using namespace std;
+
+
+static inline pair<string,int> command_to_string( const string& command)
+{
+	auto ret=string();
+	int exit_code=0;
+	int cout_pipe[2];
+	int cerr_pipe[2];
+	posix_spawn_file_actions_t action;
+
+	if(pipe(cout_pipe) || pipe(cerr_pipe))
+		cout << "pipe returned an error.\n";
+
+	posix_spawn_file_actions_init(&action);
+	posix_spawn_file_actions_addclose(&action, cout_pipe[0]);
+	posix_spawn_file_actions_addclose(&action, cerr_pipe[0]);
+	posix_spawn_file_actions_adddup2(&action, cout_pipe[1], 1);
+	posix_spawn_file_actions_adddup2(&action, cerr_pipe[1], 2);
+
+	posix_spawn_file_actions_addclose(&action, cout_pipe[1]);
+	posix_spawn_file_actions_addclose(&action, cerr_pipe[1]);
+
+	//  string command = "echo bla"; // example #1
+	//  string command = "pgmcrater -width 64 -height 9 |pgmtopbm |pnmtoplainpnm";
+	vector<char> argsmem[] = {{'s', 'h', '\0'}, {'-', 'c', '\0'}}; // allows non-const access to literals
+	char *args[] = {&argsmem[0][0], &argsmem[1][0],const_cast<char*>(command.c_str()),nullptr};
+
+	pid_t pid;
+	if(posix_spawnp(&pid, args[0], &action, NULL, args, environ) != 0)
+		cout << "posix_spawnp failed with error: " << strerror(errno) << "\n";
+
+	close(cout_pipe[1]), close(cerr_pipe[1]); // close child-side of pipes
+
+	// Read from pipes
+	string buffer(1024,' ');
+	std::vector<pollfd> plist = { {cout_pipe[0],POLLIN}, {cerr_pipe[0],POLLIN} };
+	for ( int rval; (rval=poll(&plist[0],plist.size(),/*timeout*/-1))>0; ) 
+	{
+		if ( plist[0].revents&POLLIN) {
+			const auto bytes_read = read(cout_pipe[0], &buffer[0], buffer.length());
+			// cout << "read " << bytes_read << " bytes from stdout.\n";
+			// cout << buffer.substr(0, static_cast<size_t>(bytes_read)) << "\n";
+			ret += buffer.substr(0, static_cast<size_t>(bytes_read));
+		}
+		else if ( plist[1].revents&POLLIN ) {
+			const auto bytes_read = read(cerr_pipe[0], &buffer[0], buffer.length());
+			// cout << "read " << bytes_read << " bytes from stderr.\n";
+			// cout << buffer.substr(0, static_cast<size_t>(bytes_read)) << "\n";
+			ret +=  buffer.substr(0, static_cast<size_t>(bytes_read));
+		}
+		else 
+			break; // nothing left to read
+	}
+
+	waitpid(pid,&exit_code,0);
+	cout << "exit code: " << exit_code << "\n";
+
+	posix_spawn_file_actions_destroy(&action);
+	return {ret,exit_code};
+}
+
+static inline int command_to_stream(const string& command, ostream& stream)
+{
+        cout << "Issuing command: " << command << endl;
+        const auto res = command_to_string(command);
+
+        stream << res.first << endl;
+        return res.second;
+}
+
+#endif
diff --git a/src/ehwrite.cpp b/src/ehwrite.cpp
index 331461d2c..2a00872e5 100644
--- a/src/ehwrite.cpp
+++ b/src/ehwrite.cpp
@@ -17,6 +17,7 @@
 #include <zipr_dwarf2.hpp>
 
 #include "exeio.h"
+#include "cmdstr.hpp"
 
 using namespace IRDB_SDK;
 using namespace std;
@@ -1506,7 +1507,7 @@ void ElfEhWriter_t<ptrsize>::CompileEhOutput()
 	// create and execute the command to build the ehframe.
 	auto cmd=(string)"$PEASOUP_HOME/tools/eh_frame_tools/eh_to_bin.sh "+ehframe_s_filename+" "+eh_frame_hdr_addr_str+" "+ehframe_exe_filename;
 	cout << "Running: " << cmd << endl;
-	auto res=system(cmd.c_str());
+	auto res=command_to_stream(cmd,cout); // system(cmd.c_str());
 
 	// err check.
 	if( res==-1 || WEXITSTATUS(res)!=0 )
diff --git a/src/pewrite.cpp b/src/pewrite.cpp
index 5a5b9b147..4c72dc4a6 100644
--- a/src/pewrite.cpp
+++ b/src/pewrite.cpp
@@ -87,8 +87,9 @@ void PeWriter<width,uintMa_t>::InitHeaders()
 	assert(pebliss);
 
 	const auto orig_file_full_headers_str     = pebliss -> get_full_headers_data();
-	const auto orig_file_full_headres_cstr    = orig_file_full_headers_str.c_str();
-	const auto orig_file_standard_coff_header = (standard_coff_header_t*)(orig_file_full_headres_cstr+sizeof(dos_header)+sizeof(coff_header_t));
+	const auto orig_file_full_headers_cstr    = orig_file_full_headers_str.c_str();
+	const auto coff_header_offset             = *reinterpret_cast<const uint32_t*>(orig_file_full_headers_cstr + 0x3c);	// coff header at header ptr at 0x3c
+	const auto orig_file_standard_coff_header = (standard_coff_header_t*)(orig_file_full_headers_cstr+coff_header_offset+sizeof(coff_header_t));
 
 	// calculate the total size (last-first), rounded to page boundaries so that the OS can allocate that much virtual memory
 	// for this object.
@@ -146,7 +147,7 @@ void PeWriter<width,uintMa_t>::InitHeaders()
 		(uint32_t)image_size,                           // sizeof_image in memory (not including headers?)
 		0x1000,                                         // sizeof_headers (OK to over estimate?)
 		0,                                              // checksum ?? need to fix later
-		3,                                              // subsystem ?? read from input file?
+		pebliss->get_subsystem(),                       // subsystem ?? read from input file?
 		pebliss->get_dll_characteristics(),             // dll_characteristics 
 		uintMa_t(pebliss->get_stack_size_reserve_64()), // sizeof_stack_reserve
 		uintMa_t(pebliss->get_stack_size_commit_64 ()), // sizeof_stack_commit
diff --git a/src/zipr.cpp b/src/zipr.cpp
index 14bfdc5be..20f4b14e9 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -40,6 +40,7 @@
 #include <iostream>   // std::cout
 #include <string>     // std::string, std::to_string
 #include <fstream>
+#include "cmdstr.hpp"
 
 #define ALLOF(a) begin(a),end(a)
 
@@ -1922,8 +1923,8 @@ void ZiprImpl_t::OutputBinaryFile(const string &name)
 	ew.reset(nullptr); // explicitly free ew as we're done with it
 
 	// change permissions on output file
-	auto chmod_cmd=string("chmod +x ")+output_filename;
-	auto res=system(chmod_cmd.c_str());
+	const auto chmod_cmd=string("chmod +x ")+output_filename;
+	const auto res=command_to_stream(chmod_cmd,cout);
 	assert(res!=-1);
 
 }
@@ -2184,21 +2185,25 @@ void  ZiprImpl_t::FixNoFallthroughs()
 
 void  ZiprImpl_t::FixTwoByteWithPrefix()
 {
+	const auto is_x64 = m_firp->getArchitecture()->getMachineType() == admtX86_64;
+	const auto is_x32 = m_firp->getArchitecture()->getMachineType() == admtI386;  
+
+	if(!is_x64 && !is_x32) return; // only do this for x86 machines.
+
 	for(const auto insn : m_firp->getInstructions())
 	{
 		const auto d=DecodedInstruction_t::factory(insn);
-		if(!d->isBranch()) continue;	// skip non-branches
-		if(d->isReturn()) continue;	// skip returns
-		if(d->getOperands().size()!=1) continue;	// skip branches that have no operands or more than one
+		if(!d->isBranch())                  continue;	// skip non-branches
+		if(d->isReturn())                   continue;	// skip returns
+		if(d->getOperands().size()!=1)      continue;	// skip branches that have no operands or more than one
 		if(!d->getOperand(0)->isConstant()) continue;	// skip anything where the operand isn't a constant
-		if(d->getPrefixCount()==0) continue;	// prevents arm instructions from being xformed.
 
 		
 		while (true)
 		{
-			const auto b=insn->getDataBits()[0];
+			const auto b=static_cast<uint8_t>(insn->getDataBits()[0]);
 			// basic prefix check
-			const auto prefixes=set<uint8_t>({0x2e, 0x3e, 0x64, 0x65, 0xf2, 0xf3});
+			const auto prefixes=set<uint8_t>({0x2e, 0x36, 0x3e, 0x26, 0x64, 0x65, 0x2e, 0x3e, 0xf0, 0xf2, 0xf3, 0x66, 0x67});
 			if(prefixes.find(b)!=end(prefixes))
 			{
 				// remove prefix 
-- 
GitLab