Combine prologue and epilogue code for void and non-void functions in hamsandwich trampolines.
This commit is contained in:
		@@ -72,28 +72,13 @@ namespace Trampolines
 | 
				
			|||||||
	namespace Bytecode
 | 
						namespace Bytecode
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * Prologue for a void function
 | 
							 * Prologue for a function
 | 
				
			||||||
		 * Clobbers EBX and EAX
 | 
					 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		const unsigned char codeVoidPrologue[] = { 
 | 
							const unsigned char codePrologue[] = {
 | 
				
			||||||
			0x55,						// push ebp
 | 
								0x55,						// push ebp
 | 
				
			||||||
			0x89, 0xE5,					// mov ebp, esp
 | 
								0x89, 0xE5,					// mov ebp, esp
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
					 | 
				
			||||||
		 * Prologue for a function that returns
 | 
					 | 
				
			||||||
		 * Clobbers EBX, EAX too but not after call
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		const unsigned char codeReturnPrologue[] = {
 | 
					 | 
				
			||||||
			0x55,						// push ebp
 | 
					 | 
				
			||||||
			0x89, 0xE5,					// mov ebp, esp
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		const unsigned char codeThisReturnPrologue[] = {
 | 
					 | 
				
			||||||
			0x55,						// push ebp
 | 
					 | 
				
			||||||
			0x89, 0xE5,					// mov ebp, esp
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * Takes a paramter from the trampoline's stack
 | 
							 * Takes a paramter from the trampoline's stack
 | 
				
			||||||
		 * and pushes it onto the target's stack.
 | 
							 * and pushes it onto the target's stack.
 | 
				
			||||||
@@ -166,34 +151,17 @@ namespace Trampolines
 | 
				
			|||||||
		const unsigned int codeFreeStackReplace = 2;
 | 
							const unsigned int codeFreeStackReplace = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * Epilogue of a simple return function
 | 
							 * Epilogue of a simple function
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		const unsigned char codeReturnEpilogue[] = {
 | 
							const unsigned char codeEpilogue[] = {
 | 
				
			||||||
				0x5D,						// pop ebp
 | 
									0x5D,						// pop ebp
 | 
				
			||||||
				0xC3						// ret
 | 
									0xC3						// ret
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		const unsigned char codeReturnEpilogueN[] = {
 | 
							const unsigned char codeEpilogueN[] = {
 | 
				
			||||||
				0x5D,						// pop ebp
 | 
									0x5D,						// pop ebp
 | 
				
			||||||
				0xC2, 0xCD, 0xAB				// retn 0xABCD
 | 
									0xC2, 0xCD, 0xAB				// retn 0xABCD
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		const int codeReturnEpilogueNReplace = 2;
 | 
							const int codeEpilogueNReplace = 2;
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/**
 | 
					 | 
				
			||||||
		 * Epilogue of a void return function
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		const unsigned char codeVoidEpilogue[] = {
 | 
					 | 
				
			||||||
				0x5D,						// pop ebp
 | 
					 | 
				
			||||||
				0xC3						// ret
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const unsigned char codeVoidEpilogueN[] = {
 | 
					 | 
				
			||||||
				0x5D,						// pop ebp
 | 
					 | 
				
			||||||
				0xC2, 0xCD, 0xAB			// retn 0xABCD
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		const int codeVoidEpilogueNReplace = 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const unsigned char codeBreakpoint[] = {
 | 
							const unsigned char codeBreakpoint[] = {
 | 
				
			||||||
			0xCC							// int 3
 | 
								0xCC							// int 3
 | 
				
			||||||
@@ -269,65 +237,50 @@ namespace Trampolines
 | 
				
			|||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * Adds the "return prologue", pushes registers and prepares stack
 | 
							 * Adds the prologue, pushes registers, prepares the stack
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		void ReturnPrologue()
 | 
							void Prologue()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Append(&::Trampolines::Bytecode::codeReturnPrologue[0],sizeof(::Trampolines::Bytecode::codeReturnPrologue));
 | 
								Append(&::Trampolines::Bytecode::codePrologue[0],sizeof(::Trampolines::Bytecode::codePrologue));
 | 
				
			||||||
			m_paramstart=0;
 | 
					 | 
				
			||||||
			m_thiscall=0;
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		void ThisReturnPrologue()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this->ReturnPrologue();
 | 
					 | 
				
			||||||
			m_thiscall=1;
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/**
 | 
					 | 
				
			||||||
		 * Adds the void prologue pushes registers, prepares the stack
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		void VoidPrologue()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Append(&::Trampolines::Bytecode::codeVoidPrologue[0],sizeof(::Trampolines::Bytecode::codeVoidPrologue));
 | 
					 | 
				
			||||||
			m_paramstart=0;
 | 
								m_paramstart=0;
 | 
				
			||||||
			m_thiscall=0;
 | 
								m_thiscall=0;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * Flags this trampoline as a thiscall trampoline, and prepares the void prologue.
 | 
							 * Flags this trampoline as a thiscall trampoline, and prepares the prologue.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		void ThisVoidPrologue()
 | 
							void ThisPrologue()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			this->VoidPrologue();
 | 
								this->Prologue();
 | 
				
			||||||
			m_thiscall=1;
 | 
								m_thiscall=1;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * Epilogue for a returning function pops registers but does not free any more of the stack!
 | 
							 * Epilogue for a function pops registers but does not free any more of the stack!
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		void ReturnEpilogue()
 | 
							void Epilogue()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Append(&::Trampolines::Bytecode::codeReturnEpilogue[0],sizeof(::Trampolines::Bytecode::codeReturnEpilogue));
 | 
								Append(&::Trampolines::Bytecode::codeEpilogue[0],sizeof(::Trampolines::Bytecode::codeEpilogue));
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * Epilogue that also frees it's estimated stack usage.  Useful for stdcall/thiscall/fastcall.
 | 
							 * Epilogue that also frees it's estimated stack usage.  Useful for stdcall/thiscall/fastcall.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		void ReturnEpilogueAndFree()
 | 
							void EpilogueAndFree()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			this->ReturnEpilogue(m_mystack);
 | 
								this->Epilogue(m_mystack);
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * Return epilogue.  Pops registers, and frees given amount of data from the stack.
 | 
							 * Epilogue.  Pops registers, and frees given amount of data from the stack.
 | 
				
			||||||
		 *
 | 
							 *
 | 
				
			||||||
		 * @param howmuch			How many bytes to free from the stack.
 | 
							 * @param howmuch			How many bytes to free from the stack.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		void ReturnEpilogue(int howmuch)
 | 
							void Epilogue(int howmuch)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								unsigned char code[sizeof(::Trampolines::Bytecode::codeEpilogueN)];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			unsigned char code[sizeof(::Trampolines::Bytecode::codeReturnEpilogueN)];
 | 
								memcpy(&code[0],&::Trampolines::Bytecode::codeEpilogueN[0],sizeof(::Trampolines::Bytecode::codeEpilogueN));
 | 
				
			||||||
 | 
					 | 
				
			||||||
			memcpy(&code[0],&::Trampolines::Bytecode::codeReturnEpilogueN[0],sizeof(::Trampolines::Bytecode::codeReturnEpilogueN));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			unsigned char *c=&code[0];
 | 
								unsigned char *c=&code[0];
 | 
				
			||||||
@@ -340,57 +293,11 @@ namespace Trampolines
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			bi.i=howmuch;
 | 
								bi.i=howmuch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			c+=::Trampolines::Bytecode::codeReturnEpilogueNReplace;
 | 
								c+=::Trampolines::Bytecode::codeEpilogueNReplace;
 | 
				
			||||||
			*c++=bi.b[0];
 | 
								*c++=bi.b[0];
 | 
				
			||||||
			*c++=bi.b[1];
 | 
								*c++=bi.b[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Append(&code[0],sizeof(::Trampolines::Bytecode::codeReturnEpilogueN));
 | 
								Append(&code[0],sizeof(::Trampolines::Bytecode::codeEpilogueN));
 | 
				
			||||||
			//Append(&::Trampolines::Bytecode::codeReturnEpilogueN[0],sizeof(::Trampolines::Bytecode::codeReturnEpilogueN));
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/**
 | 
					 | 
				
			||||||
		 * Void epilogue, pops registers and frees the estimated stack usage of the trampoline.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		void VoidEpilogueAndFree()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this->VoidEpilogue(m_mystack);
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		/**
 | 
					 | 
				
			||||||
		 * Void epilogue, pops registers, nothing else done with stack.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		void VoidEpilogue()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Append(&::Trampolines::Bytecode::codeVoidEpilogue[0],sizeof(::Trampolines::Bytecode::codeVoidEpilogue));
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		/**
 | 
					 | 
				
			||||||
		 * Void epilogue, pops registers, frees given amount of data off of the stack.
 | 
					 | 
				
			||||||
		 *
 | 
					 | 
				
			||||||
		 * @param howmuch			How many bytes to free from the stack.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		void VoidEpilogue(int howmuch)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			unsigned char code[sizeof(::Trampolines::Bytecode::codeVoidEpilogueN)];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			memcpy(&code[0],&::Trampolines::Bytecode::codeVoidEpilogueN[0],sizeof(::Trampolines::Bytecode::codeVoidEpilogueN));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			unsigned char *c=&code[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			union 
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				int		i;
 | 
					 | 
				
			||||||
				unsigned char	b[4];
 | 
					 | 
				
			||||||
			} bi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			bi.i=howmuch;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			c+=::Trampolines::Bytecode::codeVoidEpilogueNReplace;
 | 
					 | 
				
			||||||
			*c++=bi.b[0];
 | 
					 | 
				
			||||||
			*c++=bi.b[1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			Append(&code[0],sizeof(::Trampolines::Bytecode::codeVoidEpilogueN));
 | 
					 | 
				
			||||||
			Append(&::Trampolines::Bytecode::codeVoidEpilogueN[0],sizeof(::Trampolines::Bytecode::codeVoidEpilogueN));
 | 
					 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
@@ -642,27 +549,13 @@ inline void *CreateGenericTrampoline(bool thiscall, bool voidcall, bool retbuf,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	Trampolines::TrampolineMaker tramp;
 | 
						Trampolines::TrampolineMaker tramp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (voidcall)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	if (thiscall)
 | 
						if (thiscall)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
			tramp.ThisVoidPrologue();
 | 
							tramp.ThisPrologue();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
			tramp.VoidPrologue();
 | 
							tramp.Prologue();
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (thiscall)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			tramp.ThisReturnPrologue();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			tramp.ReturnPrologue();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (paramcount)
 | 
						while (paramcount)
 | 
				
			||||||
@@ -676,31 +569,21 @@ inline void *CreateGenericTrampoline(bool thiscall, bool voidcall, bool retbuf,
 | 
				
			|||||||
	tramp.PushNum(reinterpret_cast<int>(extraptr));
 | 
						tramp.PushNum(reinterpret_cast<int>(extraptr));
 | 
				
			||||||
	tramp.Call(callee);
 | 
						tramp.Call(callee);
 | 
				
			||||||
	tramp.FreeTargetStack();
 | 
						tramp.FreeTargetStack();
 | 
				
			||||||
	if (voidcall)
 | 
					
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
#if defined(_WIN32)
 | 
					#if defined(_WIN32)
 | 
				
			||||||
		tramp.VoidEpilogueAndFree();
 | 
						tramp.EpilogueAndFree();
 | 
				
			||||||
#elif defined(__linux__) || defined(__APPLE__)
 | 
					#elif defined(__linux__) || defined(__APPLE__)
 | 
				
			||||||
	if (retbuf)
 | 
						if (retbuf)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
			tramp.VoidEpilogue(4);
 | 
							tramp.Epilogue(4);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
			tramp.VoidEpilogue();
 | 
							tramp.Epilogue();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
#if defined(_WIN32)
 | 
					 | 
				
			||||||
		tramp.ReturnEpilogueAndFree();
 | 
					 | 
				
			||||||
#elif defined(__linux__) || defined(__APPLE__)
 | 
					 | 
				
			||||||
		tramp.ReturnEpilogue();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return tramp.Finish(NULL);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tramp.Finish(NULL);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user