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:
gbeauche 2006-01-28 22:03:31 +00:00
parent d9b4b31490
commit d475faf4ba
7 changed files with 81 additions and 23 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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