diff --git a/Makefile b/Makefile index f174358..5815ae9 100644 --- a/Makefile +++ b/Makefile @@ -43,16 +43,6 @@ ifeq ($(OS), LINUX) LDFLAGS += -Wl,-export-dynamic endif -# set executable stack as a linker option for X86 architecture, for dynamic recompiler -ifeq ($(CPU), X86) - ifeq ($(OS), FREEBSD) - LDFLAGS += -z execstack - endif - ifeq ($(OS), LINUX) - LDFLAGS += -z execstack - endif -endif - # set options ifeq ($(DBG), 1) CFLAGS += -DDBG diff --git a/r4300/recomp.c b/r4300/recomp.c index 876fc55..aafe864 100644 --- a/r4300/recomp.c +++ b/r4300/recomp.c @@ -20,6 +20,11 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include +#if defined(__GNUC__) +#include +#include +#include +#endif #include "recomp.h" #include "recomph.h" //include for function prototypes @@ -2168,7 +2173,7 @@ void init_block(int *source, precomp_block *block) if (!block->block) { long memsize = ((length+1)+(length>>2)) * sizeof(precomp_instr); - block->block = malloc(memsize); + block->block = malloc_exec(memsize); memset(block->block, 0, memsize); already_exist = 0; } @@ -2178,12 +2183,12 @@ void init_block(int *source, precomp_block *block) if (!block->code) { #if defined(PROFILE_R4300) - block->code = malloc(524288); /* allocate so much code space that we'll never have to realloc(), because this may */ - max_code_length = 524288; /* cause instruction locations to move, and break our profiling data */ + max_code_length = 524288; /* allocate so much code space that we'll never have to realloc(), because this may */ + /* cause instruction locations to move, and break our profiling data */ #else - block->code = malloc(32768); max_code_length = 32768; #endif + block->code = malloc_exec(max_code_length); } else { @@ -2574,3 +2579,48 @@ void prefetch_opcode(unsigned int op) recomp_ops[((src >> 26) & 0x3F)](); } +/********************************************************************** + ************** allocate memory with executable bit set *************** + **********************************************************************/ +void *malloc_exec(size_t size) +{ +#if defined(__GNUC__) + int pagesize = sysconf(_SC_PAGE_SIZE); + if (pagesize == -1) + { printf("Memory error: couldn't determine system memory page size.\n"); return NULL; } + + /* Allocate a buffer aligned on a page boundary; + initial protection is PROT_READ | PROT_WRITE */ + void *block = NULL; + if (posix_memalign(&block, pagesize, size) != 0) + { printf("Memory error: couldn't allocate %i byte block of %i-byte aligned memory.\n", size, pagesize); return NULL; } + + if (mprotect(block, size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + { printf("Memory error: couldn't set RWX permissions on %i byte block of memory.\n", size); return NULL; } + + return block; +#else + return malloc(size); +#endif +} + +/********************************************************************** + ************* reallocate memory with executable bit set ************** + **********************************************************************/ +void *realloc_exec(void *ptr, size_t size, size_t newsize) +{ + void* block = malloc_exec(newsize); + if (block != NULL) + { + size_t copysize; + if (size < newsize) + copysize = size; + else + copysize = newsize; + memcpy(block, ptr, copysize); + } + free(ptr); + return block; +} + + diff --git a/r4300/recomp.h b/r4300/recomp.h index d286bef..1b2c859 100644 --- a/r4300/recomp.h +++ b/r4300/recomp.h @@ -22,6 +22,7 @@ #ifndef RECOMP_H #define RECOMP_H +#include #if defined(__x86_64__) #include "x86_64/assemble.h" #else @@ -92,6 +93,8 @@ void prefetch_opcode(unsigned int op); void dyna_jump(); void dyna_start(void (*code)()); void dyna_stop(); +void *malloc_exec(size_t size); +void *realloc_exec(void *ptr, size_t size, size_t newsize); extern precomp_instr *dst; /* precomp_instr structure for instruction being recompiled */ diff --git a/r4300/x86/assemble.c b/r4300/x86/assemble.c index dd99314..4f6203a 100644 --- a/r4300/x86/assemble.c +++ b/r4300/x86/assemble.c @@ -78,8 +78,8 @@ static void put8(unsigned char octet) code_length++; if (code_length == max_code_length) { - max_code_length += 1000; - *inst_pointer = realloc(*inst_pointer, max_code_length); + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); + max_code_length += 8192; } } @@ -87,8 +87,8 @@ static void put16(unsigned short word) { if ((code_length+2) >= max_code_length) { - max_code_length += 1000; - *inst_pointer = realloc(*inst_pointer, max_code_length); + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); + max_code_length += 8192; } *((unsigned short *)(&(*inst_pointer)[code_length])) = word; code_length+=2; @@ -98,8 +98,8 @@ static void put32(unsigned int dword) { if ((code_length+4) >= max_code_length) { - max_code_length += 1000; - *inst_pointer = realloc(*inst_pointer, max_code_length); + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); + max_code_length += 8192; } *((unsigned int *)(&(*inst_pointer)[code_length])) = dword; code_length+=4; diff --git a/r4300/x86_64/assemble.c b/r4300/x86_64/assemble.c index 443f335..bb9fdf1 100644 --- a/r4300/x86_64/assemble.c +++ b/r4300/x86_64/assemble.c @@ -195,8 +195,8 @@ static void put8(unsigned char octet) code_length++; if (code_length == max_code_length) { + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); max_code_length += 8192; - *inst_pointer = realloc(*inst_pointer, max_code_length); } } @@ -204,8 +204,8 @@ static void put16(unsigned short word) { if ((code_length + 2) >= max_code_length) { + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); max_code_length += 8192; - *inst_pointer = realloc(*inst_pointer, max_code_length); } *((unsigned short *) (*inst_pointer + code_length)) = word; code_length += 2; @@ -215,8 +215,8 @@ static void put32(unsigned int dword) { if ((code_length + 4) >= max_code_length) { + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); max_code_length += 8192; - *inst_pointer = realloc(*inst_pointer, max_code_length); } *((unsigned int *) (*inst_pointer + code_length)) = dword; code_length += 4; @@ -226,8 +226,8 @@ static void put64(unsigned long long qword) { if ((code_length + 8) >= max_code_length) { + *inst_pointer = realloc_exec(*inst_pointer, max_code_length, max_code_length+8192); max_code_length += 8192; - *inst_pointer = realloc(*inst_pointer, max_code_length); } *((unsigned long long *) (*inst_pointer + code_length)) = qword; code_length += 8;