Handle detour patches across page boundaries (#1535)
On Linux if a detour crossed a page boundary we would only change the memory protection of the first page (as we were aligning the address as required, but not taking into account the length). I don't have an easy way to test this but it looks correct. `addr + len` doesn't appear to need to be aligned though, so another option could be to use `(addr - startPage) + length` as len. Also fixed a non-zero offset being passed into CDetour's ApplyPatch function - this is never done internally anywhere, but it doesn't hurt to fix it. Fixes #984
This commit is contained in:
parent
7f2fdf3fe1
commit
5b7c9c5845
@ -34,13 +34,10 @@
|
||||
|
||||
#if defined PLATFORM_POSIX
|
||||
#include <sys/mman.h>
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
#define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1))
|
||||
#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC
|
||||
#endif
|
||||
|
||||
#include <amtl/am-bits.h>
|
||||
#include <jit/x86/x86_macros.h>
|
||||
|
||||
struct patch_t
|
||||
@ -57,8 +54,10 @@ struct patch_t
|
||||
inline void ProtectMemory(void *addr, int length, int prot)
|
||||
{
|
||||
#if defined PLATFORM_POSIX
|
||||
void *addr2 = (void *)ALIGN(addr);
|
||||
mprotect(addr2, sysconf(_SC_PAGESIZE), prot);
|
||||
long pageSize = sysconf(_SC_PAGESIZE);
|
||||
void *startPage = ke::AlignedBase(addr, pageSize);
|
||||
void *endPage = ke::AlignedBase((void *)((intptr_t)addr + length), pageSize);
|
||||
mprotect(startPage, ((intptr_t)endPage - (intptr_t)startPage) + pageSize, prot);
|
||||
#elif defined PLATFORM_WINDOWS
|
||||
DWORD old_prot;
|
||||
VirtualProtect(addr, length, prot, &old_prot);
|
||||
@ -118,9 +117,9 @@ inline void DoGatePatch(unsigned char *target, void *callback)
|
||||
|
||||
inline void ApplyPatch(void *address, int offset, const patch_t *patch, patch_t *restore)
|
||||
{
|
||||
ProtectMemory(address, 20, PAGE_EXECUTE_READWRITE);
|
||||
|
||||
unsigned char *addr = (unsigned char *)address + offset;
|
||||
SetMemPatchable(addr, patch->bytes);
|
||||
|
||||
if (restore)
|
||||
{
|
||||
for (size_t i=0; i<patch->bytes; i++)
|
||||
|
Loading…
Reference in New Issue
Block a user