bugfix issue #268 - instead of setting linker flags for executable heap, use aligned malloc and mprotect to set executable status for emitted machine code from dynamic recompiler. Written by Sven Eckelmann and Richard Goedeken

This commit is contained in:
Richard Goedeken 2009-10-02 02:57:25 +00:00
parent d3777167e0
commit 9df29003e1
5 changed files with 67 additions and 24 deletions

View file

@ -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

View file

@ -20,6 +20,11 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdlib.h>
#if defined(__GNUC__)
#include <unistd.h>
#include <malloc.h>
#include <sys/mman.h>
#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;
}

View file

@ -22,6 +22,7 @@
#ifndef RECOMP_H
#define RECOMP_H
#include <stddef.h>
#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 */

View file

@ -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;

View file

@ -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;