mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-26 14:55:36 +03:00
Align stack on 16 byte boundary in hamsandwich trampolines.
This commit is contained in:
parent
3987085572
commit
423eb0499b
@ -57,6 +57,7 @@
|
|||||||
#include <stdlib.h> // memalign
|
#include <stdlib.h> // memalign
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <am-utility.h>
|
||||||
|
|
||||||
namespace Trampolines
|
namespace Trampolines
|
||||||
{
|
{
|
||||||
@ -79,6 +80,26 @@ namespace Trampolines
|
|||||||
0x89, 0xE5, // mov ebp, esp
|
0x89, 0xE5, // mov ebp, esp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Align stack on 16 byte boundary
|
||||||
|
*/
|
||||||
|
const unsigned char codeAlignStack16[] = {
|
||||||
|
0x83, 0xE4, 0xF0, // and esp, 0xFFFFFFF0
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate stack space (8-bit) by adding to ESP
|
||||||
|
*/
|
||||||
|
const unsigned char codeAllocStack[] = {
|
||||||
|
0x83, 0xEC, 0xFF, // sub esp, 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset of codeAllocStack to modify at runtime
|
||||||
|
* to contain amount of stack space to allocate.
|
||||||
|
*/
|
||||||
|
const unsigned int codeAllocStackReplace = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@ -154,14 +175,16 @@ namespace Trampolines
|
|||||||
* Epilogue of a simple function
|
* Epilogue of a simple function
|
||||||
*/
|
*/
|
||||||
const unsigned char codeEpilogue[] = {
|
const unsigned char codeEpilogue[] = {
|
||||||
|
0x89, 0xEC, // mov esp, ebp
|
||||||
0x5D, // pop ebp
|
0x5D, // pop ebp
|
||||||
0xC3 // ret
|
0xC3 // ret
|
||||||
};
|
};
|
||||||
const unsigned char codeEpilogueN[] = {
|
const unsigned char codeEpilogueN[] = {
|
||||||
|
0x89, 0xEC, // mov esp, ebp
|
||||||
0x5D, // pop ebp
|
0x5D, // pop ebp
|
||||||
0xC2, 0xCD, 0xAB // retn 0xABCD
|
0xC2, 0xCD, 0xAB // retn 0xABCD
|
||||||
};
|
};
|
||||||
const int codeEpilogueNReplace = 2;
|
const int codeEpilogueNReplace = 4;
|
||||||
|
|
||||||
const unsigned char codeBreakpoint[] = {
|
const unsigned char codeBreakpoint[] = {
|
||||||
0xCC // int 3
|
0xCC // int 3
|
||||||
@ -300,6 +323,42 @@ namespace Trampolines
|
|||||||
Append(&code[0],sizeof(::Trampolines::Bytecode::codeEpilogueN));
|
Append(&code[0],sizeof(::Trampolines::Bytecode::codeEpilogueN));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aligns stack on 16 byte boundary for functions that use aligned SSE instructions.
|
||||||
|
* This also allocates extra stack space to allow the specified number of slots to be used
|
||||||
|
* for function paramaters that will be pushed onto the stack.
|
||||||
|
*/
|
||||||
|
void AlignStack16(int slots)
|
||||||
|
{
|
||||||
|
const size_t stackNeeded = slots * sizeof(void *);
|
||||||
|
const size_t stackReserve = ke::Align(stackNeeded, 16);
|
||||||
|
const size_t stackExtra = stackReserve - stackNeeded;
|
||||||
|
|
||||||
|
// Stack space should fit in a byte
|
||||||
|
assert(stackExtra <= 0xFF);
|
||||||
|
|
||||||
|
const size_t codeAlignStackSize = sizeof(::Trampolines::Bytecode::codeAlignStack16);
|
||||||
|
const size_t codeAllocStackSize = sizeof(::Trampolines::Bytecode::codeAllocStack);
|
||||||
|
unsigned char code[codeAlignStackSize + codeAllocStackSize];
|
||||||
|
|
||||||
|
memcpy(&code[0], &::Trampolines::Bytecode::codeAlignStack16[0], codeAlignStackSize);
|
||||||
|
|
||||||
|
if (stackExtra > 0)
|
||||||
|
{
|
||||||
|
unsigned char *c = &code[codeAlignStackSize];
|
||||||
|
memcpy(c, &::Trampolines::Bytecode::codeAllocStack[0], codeAllocStackSize);
|
||||||
|
|
||||||
|
c += ::Trampolines::Bytecode::codeAllocStackReplace;
|
||||||
|
*c = (unsigned char)stackExtra;
|
||||||
|
|
||||||
|
Append(&code[0], codeAlignStackSize + codeAllocStackSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(&code[0], codeAlignStackSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes the "this" pointer onto the callee stack. Pushes ECX for MSVC, and param0 on GCC.
|
* Pushes the "this" pointer onto the callee stack. Pushes ECX for MSVC, and param0 on GCC.
|
||||||
*/
|
*/
|
||||||
@ -552,10 +611,12 @@ inline void *CreateGenericTrampoline(bool thiscall, bool voidcall, bool retbuf,
|
|||||||
if (thiscall)
|
if (thiscall)
|
||||||
{
|
{
|
||||||
tramp.ThisPrologue();
|
tramp.ThisPrologue();
|
||||||
|
tramp.AlignStack16(paramcount + 2); // Param count + this ptr + extra ptr
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tramp.Prologue();
|
tramp.Prologue();
|
||||||
|
tramp.AlignStack16(paramcount + 1); // Param count + extra ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
while (paramcount)
|
while (paramcount)
|
||||||
|
Loading…
Reference in New Issue
Block a user