mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-09-03 21:29:03 +00:00
Copy constants to 32-bit addressable data pool. This fixes -pie builds on
x86_64: program resides above 32-bit barrier and JIT generated code wants (knowingly) to access globals directly.
This commit is contained in:
parent
d9b4b31490
commit
d475faf4ba
@ -25,7 +25,7 @@ int __op_param1, __op_param2, __op_param3;
|
|||||||
int __op_jmp0, __op_jmp1;
|
int __op_jmp0, __op_jmp1;
|
||||||
|
|
||||||
#define DYNGEN_IMPL 1
|
#define DYNGEN_IMPL 1
|
||||||
#define DEFINE_GEN(NAME,ARGS) void basic_dyngen::NAME ARGS
|
#define DEFINE_GEN(NAME,RET,ARGS) RET basic_dyngen::NAME ARGS
|
||||||
#include "basic-dyngen-ops.hpp"
|
#include "basic-dyngen-ops.hpp"
|
||||||
|
|
||||||
basic_dyngen::basic_dyngen(dyngen_cpu_base cpu, int cache_size)
|
basic_dyngen::basic_dyngen(dyngen_cpu_base cpu, int cache_size)
|
||||||
|
@ -69,7 +69,7 @@ class basic_dyngen
|
|||||||
|
|
||||||
// Generic code generators
|
// Generic code generators
|
||||||
# define DEFINE_CST(NAME,VALUE) static const unsigned long NAME = VALUE;
|
# define DEFINE_CST(NAME,VALUE) static const unsigned long NAME = VALUE;
|
||||||
# define DEFINE_GEN(NAME,ARGS) void NAME ARGS;
|
# define DEFINE_GEN(NAME,RET,ARGS) RET NAME ARGS;
|
||||||
# include "basic-dyngen-ops.hpp"
|
# include "basic-dyngen-ops.hpp"
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -546,7 +546,7 @@ static char *gen_dot_prefix(const char *sym_name)
|
|||||||
{
|
{
|
||||||
static char name[256];
|
static char name[256];
|
||||||
assert(sym_name[0] == '.');
|
assert(sym_name[0] == '.');
|
||||||
snprintf(name, sizeof(name), "dg_dot_%s", sym_name + 1);
|
snprintf(name, sizeof(name), "dot_%s", sym_name + 1);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,23 +861,25 @@ int load_object(const char *filename, FILE *outfile)
|
|||||||
name = get_sym_name(sym);
|
name = get_sym_name(sym);
|
||||||
/* emit local symbols */
|
/* emit local symbols */
|
||||||
if (strstart(name, ".LC", NULL)) {
|
if (strstart(name, ".LC", NULL)) {
|
||||||
if (sym->st_shndx == (rodata_cst16_sec - shdr)) {
|
const char *dot_name = gen_dot_prefix(name);
|
||||||
fprintf(outfile, "#ifdef DYNGEN_IMPL\n");
|
fprintf(outfile, "DEFINE_GEN(gen_const_%s,uint8 *,(void))\n", dot_name);
|
||||||
print_data(outfile, gen_dot_prefix(name), rodata_cst16 + sym->st_value, 16);
|
fprintf(outfile, "#ifdef DYNGEN_IMPL\n");
|
||||||
fprintf(outfile, "#endif\n");
|
fprintf(outfile, "{\n");
|
||||||
}
|
int dot_size = 0;
|
||||||
else if (sym->st_shndx == (rodata_cst8_sec - shdr)) {
|
if (sym->st_shndx == (rodata_cst16_sec - shdr))
|
||||||
fprintf(outfile, "#ifdef DYNGEN_IMPL\n");
|
print_data(outfile, dot_name, rodata_cst16 + sym->st_value, (dot_size = 16));
|
||||||
print_data(outfile, gen_dot_prefix(name), rodata_cst8 + sym->st_value, 8);
|
else if (sym->st_shndx == (rodata_cst8_sec - shdr))
|
||||||
fprintf(outfile, "#endif\n");
|
print_data(outfile, dot_name, rodata_cst8 + sym->st_value, (dot_size = 8));
|
||||||
}
|
else if (sym->st_shndx == (rodata_cst4_sec - shdr))
|
||||||
else if (sym->st_shndx == (rodata_cst4_sec - shdr)) {
|
print_data(outfile, dot_name, rodata_cst4 + sym->st_value, (dot_size = 4));
|
||||||
fprintf(outfile, "#ifdef DYNGEN_IMPL\n");
|
|
||||||
print_data(outfile, gen_dot_prefix(name), rodata_cst4 + sym->st_value, 4);
|
|
||||||
fprintf(outfile, "#endif\n");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
error("invalid section for local data %s (%x)\n", name, sym->st_shndx);
|
error("invalid section for local data %s (%x)\n", name, sym->st_shndx);
|
||||||
|
fprintf(outfile, " static uint8 *data_p = NULL;\n");
|
||||||
|
fprintf(outfile, " if (data_p == NULL)\n");
|
||||||
|
fprintf(outfile, " data_p = copy_data(%s, %d);\n", dot_name, dot_size);
|
||||||
|
fprintf(outfile, " return data_p;\n");
|
||||||
|
fprintf(outfile, "}\n");
|
||||||
|
fprintf(outfile, "#endif\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1899,7 +1901,7 @@ void gen_code(const char *name, const char *demangled_name,
|
|||||||
if (prefix && strstr(func_name, prefix) == func_name)
|
if (prefix && strstr(func_name, prefix) == func_name)
|
||||||
func_name += strlen(prefix);
|
func_name += strlen(prefix);
|
||||||
|
|
||||||
fprintf(outfile, "DEFINE_GEN(gen_%s,(", func_name);
|
fprintf(outfile, "DEFINE_GEN(gen_%s,void,(", func_name);
|
||||||
if (nb_args == 0) {
|
if (nb_args == 0) {
|
||||||
fprintf(outfile, "void");
|
fprintf(outfile, "void");
|
||||||
} else {
|
} else {
|
||||||
@ -2181,7 +2183,7 @@ void gen_code(const char *name, const char *demangled_name,
|
|||||||
if (strstart(sym_name, "__op_param", &p))
|
if (strstart(sym_name, "__op_param", &p))
|
||||||
snprintf(name, sizeof(name), "param%s", p);
|
snprintf(name, sizeof(name), "param%s", p);
|
||||||
else if (strstart(sym_name, ".LC", NULL))
|
else if (strstart(sym_name, ".LC", NULL))
|
||||||
snprintf(name, sizeof(name), "(long)(%s)", gen_dot_prefix(sym_name));
|
snprintf(name, sizeof(name), "(long)(gen_const_%s())", gen_dot_prefix(sym_name));
|
||||||
else
|
else
|
||||||
snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
|
snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
|
||||||
type = ELF32_R_TYPE(rel->r_info);
|
type = ELF32_R_TYPE(rel->r_info);
|
||||||
|
@ -47,7 +47,7 @@ static uint8 *g_translation_cache_end_p;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
basic_jit_cache::basic_jit_cache(int init_cache_size)
|
basic_jit_cache::basic_jit_cache(int init_cache_size)
|
||||||
: tcode_start(NULL), code_start(NULL), code_p(NULL), code_end(NULL)
|
: tcode_start(NULL), code_start(NULL), code_p(NULL), code_end(NULL), data(NULL)
|
||||||
{
|
{
|
||||||
init_translation_cache(init_cache_size);
|
init_translation_cache(init_cache_size);
|
||||||
}
|
}
|
||||||
@ -55,6 +55,15 @@ basic_jit_cache::basic_jit_cache(int init_cache_size)
|
|||||||
basic_jit_cache::~basic_jit_cache()
|
basic_jit_cache::~basic_jit_cache()
|
||||||
{
|
{
|
||||||
kill_translation_cache();
|
kill_translation_cache();
|
||||||
|
|
||||||
|
// Release data pool
|
||||||
|
data_chunk_t *p = data;
|
||||||
|
while (p) {
|
||||||
|
data_chunk_t *d = p;
|
||||||
|
p = p->next;
|
||||||
|
D(bug("basic_jit_cache: Release data pool %p (%d KB)\n", d, d->size / 1024));
|
||||||
|
vm_release(d, d->size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -121,3 +130,39 @@ basic_jit_cache::kill_translation_cache()
|
|||||||
vm_release(tcode_start, cache_size);
|
vm_release(tcode_start, cache_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8 *
|
||||||
|
basic_jit_cache::copy_data(const uint8 *block, uint32 size)
|
||||||
|
{
|
||||||
|
const int ALIGN = 16;
|
||||||
|
uint8 *ptr;
|
||||||
|
|
||||||
|
if (data && (data->offs + size) < data->size)
|
||||||
|
ptr = (uint8 *)data + data->offs;
|
||||||
|
else {
|
||||||
|
// No free space left, allocate a new chunk
|
||||||
|
uint32 to_alloc = sizeof(*data) + size + ALIGN;
|
||||||
|
uint32 page_size = vm_get_page_size();
|
||||||
|
to_alloc = (to_alloc + page_size - 1) & -page_size;
|
||||||
|
|
||||||
|
D(bug("basic_jit_cache: Allocate data pool (%d KB)\n", to_alloc / 1024));
|
||||||
|
ptr = (uint8 *)vm_acquire(to_alloc, VM_MAP_PRIVATE | VM_MAP_32BIT);
|
||||||
|
if (ptr == VM_MAP_FAILED) {
|
||||||
|
fprintf(stderr, "FATAL: Could not allocate data pool!\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
data_chunk_t *dcp = (data_chunk_t *)ptr;
|
||||||
|
dcp->size = to_alloc;
|
||||||
|
dcp->offs = (sizeof(*data) + ALIGN - 1) & -ALIGN;
|
||||||
|
dcp->next = data;
|
||||||
|
data = dcp;
|
||||||
|
|
||||||
|
ptr += dcp->offs;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ptr, block, size);
|
||||||
|
data->offs += (size + ALIGN - 1) & -ALIGN;
|
||||||
|
D(bug("basic_jit_cache: DATA %p, %d bytes [data=%p, offs=%u]\n", ptr, size, data, data->offs));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
@ -37,6 +37,14 @@ class basic_jit_cache
|
|||||||
uint8 *code_p;
|
uint8 *code_p;
|
||||||
uint8 *code_end;
|
uint8 *code_end;
|
||||||
|
|
||||||
|
// Data pool (32-bit addressable)
|
||||||
|
struct data_chunk_t {
|
||||||
|
uint32 size;
|
||||||
|
uint32 offs;
|
||||||
|
data_chunk_t *next;
|
||||||
|
};
|
||||||
|
data_chunk_t *data;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Initialize translation cache
|
// Initialize translation cache
|
||||||
@ -72,6 +80,9 @@ public:
|
|||||||
void emit_ptr(uintptr v) { emit_generic<uintptr>(v); }
|
void emit_ptr(uintptr v) { emit_generic<uintptr>(v); }
|
||||||
void copy_block(const uint8 *block, uint32 size);
|
void copy_block(const uint8 *block, uint32 size);
|
||||||
void emit_block(const uint8 *block, uint32 size);
|
void emit_block(const uint8 *block, uint32 size);
|
||||||
|
|
||||||
|
// Emit data to constant pool
|
||||||
|
uint8 *copy_data(const uint8 *block, uint32 size);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define DYNGEN_IMPL 1
|
#define DYNGEN_IMPL 1
|
||||||
#define DEFINE_GEN(NAME,ARGS) void powerpc_dyngen::NAME ARGS
|
#define DEFINE_GEN(NAME,RET,ARGS) RET powerpc_dyngen::NAME ARGS
|
||||||
#include "ppc-dyngen-ops.hpp"
|
#include "ppc-dyngen-ops.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class powerpc_dyngen
|
|||||||
{
|
{
|
||||||
// Code generators for PowerPC synthetic instructions
|
// Code generators for PowerPC synthetic instructions
|
||||||
#ifndef NO_DEFINE_ALIAS
|
#ifndef NO_DEFINE_ALIAS
|
||||||
# define DEFINE_GEN(NAME,ARGS) void NAME ARGS;
|
# define DEFINE_GEN(NAME,RET,ARGS) RET NAME ARGS;
|
||||||
# include "ppc-dyngen-ops.hpp"
|
# include "ppc-dyngen-ops.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user