mirror of
https://github.com/mupen64plus/mupen64plus-oldsvn.git
synced 2024-05-14 01:59:38 -04:00
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:
parent
d3777167e0
commit
9df29003e1
10
Makefile
10
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue