mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-26 06:45:37 +03:00
Combine prologue and epilogue code for void and non-void functions in hamsandwich trampolines.
This commit is contained in:
parent
fe52f1eeac
commit
3987085572
@ -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.ThisPrologue();
|
||||||
{
|
|
||||||
tramp.ThisVoidPrologue();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tramp.VoidPrologue();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (thiscall)
|
tramp.Prologue();
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
tramp.VoidEpilogue();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
tramp.Epilogue();
|
||||||
tramp.ReturnEpilogueAndFree();
|
|
||||||
#elif defined(__linux__) || defined(__APPLE__)
|
|
||||||
tramp.ReturnEpilogue();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return tramp.Finish(NULL);
|
#endif
|
||||||
|
|
||||||
|
return tramp.Finish(NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user