LIBTCCAPI tcc_relocate(s) : REMOVED 2nd argument
removed second argument for tcc_relocate(s). previous 'TCC_RELOCATE_AUTO' is now default and only behavior. Rationale: In the past, the option to compile into memory provided by the user was introduced because only one TCCState could exist at a time. This is no longer a limitation. As such it is also possible now to keep any number of compiled code snippets around together with their state in order to run them as needed. - Also - LIBTCCAPI tcc_get_error_func/opaque() removed - tccrun/SELINUX: switch rx/rw mappings such that rx comes first (risc64-link.c:relocate_plt() does not like got < plt) - tcc_relocate_ex(): free local symbols and obsolete sections to reduce memory after tcc_relocate()
This commit is contained in:
parent
a0ab99169e
commit
b671fc0594
11 changed files with 224 additions and 184 deletions
14
configure
vendored
14
configure
vendored
|
@ -56,6 +56,7 @@ build_cross=
|
||||||
# use CC/AR from environment when set
|
# use CC/AR from environment when set
|
||||||
test -n "$CC" && cc="$CC"
|
test -n "$CC" && cc="$CC"
|
||||||
test -n "$AR" && ar="$AR"
|
test -n "$AR" && ar="$AR"
|
||||||
|
test -n "CFLAGS" && CFLAGS="-Wall -O2"
|
||||||
|
|
||||||
# find source path
|
# find source path
|
||||||
source_path=${0%configure}
|
source_path=${0%configure}
|
||||||
|
@ -399,14 +400,6 @@ if test "$mingw32" = "no"; then
|
||||||
default infodir "${sharedir}/info"
|
default infodir "${sharedir}/info"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# set default CFLAGS
|
|
||||||
default CFLAGS "-Wall -O2"
|
|
||||||
|
|
||||||
if test "$mingw32" = "yes" -a "$cc_name" = "gcc"; then
|
|
||||||
# avoid mingw dependencies such as 'libgcc_s_dw2-1.dll'
|
|
||||||
default LDFLAGS "-static"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x"$show_help" = "xyes" ; then
|
if test x"$show_help" = "xyes" ; then
|
||||||
show_help
|
show_help
|
||||||
fi
|
fi
|
||||||
|
@ -464,6 +457,11 @@ if test "$bigendian" = "yes" ; then
|
||||||
confvars="$confvars BIGENDIAN"
|
confvars="$confvars BIGENDIAN"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$mingw32" = "yes" -a "$cc_name" = "gcc"; then
|
||||||
|
# avoid mingw dependencies such as 'libgcc_s_dw2-1.dll'
|
||||||
|
default LDFLAGS "-static"
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$cpu" = "arm"; then
|
if test "$cpu" = "arm"; then
|
||||||
if test "${triplet%eabihf}" != "$triplet" ; then
|
if test "${triplet%eabihf}" != "$triplet" ; then
|
||||||
confvars="$confvars arm_eabihf arm_vfp"
|
confvars="$confvars arm_eabihf arm_vfp"
|
||||||
|
|
36
libtcc.c
36
libtcc.c
|
@ -249,7 +249,7 @@ ST_FUNC char *tcc_load_text(int fd)
|
||||||
#undef free
|
#undef free
|
||||||
#undef realloc
|
#undef realloc
|
||||||
|
|
||||||
static void *default_reallocator(void *ptr, size_t size)
|
static void *default_reallocator(void *ptr, unsigned long size)
|
||||||
{
|
{
|
||||||
void *ptr1;
|
void *ptr1;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
|
@ -275,18 +275,13 @@ static void libc_free(void *ptr)
|
||||||
#define realloc(p, s) use_tcc_realloc(p, s)
|
#define realloc(p, s) use_tcc_realloc(p, s)
|
||||||
|
|
||||||
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
|
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
|
||||||
static TCCReallocFunc reallocator = default_reallocator;
|
static void *(*reallocator)(void*, unsigned long) = default_reallocator;
|
||||||
|
|
||||||
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc)
|
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *realloc)
|
||||||
{
|
{
|
||||||
reallocator = realloc;
|
reallocator = realloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI TCCReallocFunc tcc_get_realloc()
|
|
||||||
{
|
|
||||||
return reallocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* in case MEM_DEBUG is #defined */
|
/* in case MEM_DEBUG is #defined */
|
||||||
#undef tcc_free
|
#undef tcc_free
|
||||||
#undef tcc_malloc
|
#undef tcc_malloc
|
||||||
|
@ -646,7 +641,7 @@ static void error1(int mode, const char *fmt, va_list ap)
|
||||||
}
|
}
|
||||||
cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
|
cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
|
||||||
cstr_vprintf(&cs, fmt, ap);
|
cstr_vprintf(&cs, fmt, ap);
|
||||||
if (!s1 || !s1->error_func) {
|
if (!s1->error_func) {
|
||||||
/* default case: stderr */
|
/* default case: stderr */
|
||||||
if (s1 && s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout)
|
if (s1 && s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout)
|
||||||
printf("\n"); /* print a newline during tcc -E */
|
printf("\n"); /* print a newline during tcc -E */
|
||||||
|
@ -666,22 +661,12 @@ static void error1(int mode, const char *fmt, va_list ap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func)
|
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func)
|
||||||
{
|
{
|
||||||
s->error_opaque = error_opaque;
|
s->error_opaque = error_opaque;
|
||||||
s->error_func = error_func;
|
s->error_func = error_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s)
|
|
||||||
{
|
|
||||||
return s->error_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBTCCAPI void *tcc_get_error_opaque(TCCState *s)
|
|
||||||
{
|
|
||||||
return s->error_opaque;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* error without aborting current compilation */
|
/* error without aborting current compilation */
|
||||||
PUB_FUNC int _tcc_error_noabort(const char *fmt, ...)
|
PUB_FUNC int _tcc_error_noabort(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -2245,6 +2230,15 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
|
||||||
s1->total_output[3]
|
s1->total_output[3]
|
||||||
);
|
);
|
||||||
#ifdef MEM_DEBUG
|
#ifdef MEM_DEBUG
|
||||||
fprintf(stderr, "# %d bytes memory used\n", mem_max_size);
|
fprintf(stderr, "# memory usage");
|
||||||
|
#ifdef TCC_IS_NATIVE
|
||||||
|
if (s1->run_size) {
|
||||||
|
Section *s = s1->symtab;
|
||||||
|
int ms = s->data_offset + s->link->data_offset + s->hash->data_offset;
|
||||||
|
fprintf(stderr, ": %d to run, %d symbols, %d other,",
|
||||||
|
s1->run_size, ms, mem_cur_size - s1->run_size - ms);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " %d max (bytes)\n", mem_max_size);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
41
libtcc.h
41
libtcc.h
|
@ -9,19 +9,16 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct TCCState;
|
/*****************************/
|
||||||
|
/* set custom allocator for all allocations (optional) */
|
||||||
|
|
||||||
|
typedef void *TCCReallocFunc(void *ptr, unsigned long size);
|
||||||
|
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *my_realloc);
|
||||||
|
|
||||||
|
/*****************************/
|
||||||
|
|
||||||
typedef struct TCCState TCCState;
|
typedef struct TCCState TCCState;
|
||||||
|
|
||||||
typedef void (*TCCErrorFunc)(void *opaque, const char *msg);
|
|
||||||
typedef void *(*TCCReallocFunc)(void *ptr, size_t size);
|
|
||||||
|
|
||||||
/* to be used for all allocation (including tcc_new()), otherwise malloc(), realloc(), free() */
|
|
||||||
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc);
|
|
||||||
|
|
||||||
/* return current allocator */
|
|
||||||
LIBTCCAPI TCCReallocFunc tcc_get_realloc();
|
|
||||||
|
|
||||||
/* create a new TCC compilation context */
|
/* create a new TCC compilation context */
|
||||||
LIBTCCAPI TCCState *tcc_new(void);
|
LIBTCCAPI TCCState *tcc_new(void);
|
||||||
|
|
||||||
|
@ -31,14 +28,9 @@ LIBTCCAPI void tcc_delete(TCCState *s);
|
||||||
/* set CONFIG_TCCDIR at runtime */
|
/* set CONFIG_TCCDIR at runtime */
|
||||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
||||||
|
|
||||||
/* set error/warning display callback */
|
/* set error/warning callback (optional) */
|
||||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func);
|
typedef void TCCErrorFunc(void *opaque, const char *msg);
|
||||||
|
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func);
|
||||||
/* return error/warning callback */
|
|
||||||
LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s);
|
|
||||||
|
|
||||||
/* return error/warning callback opaque pointer */
|
|
||||||
LIBTCCAPI void *tcc_get_error_opaque(TCCState *s);
|
|
||||||
|
|
||||||
/* set options as from command line (multiple supported) */
|
/* set options as from command line (multiple supported) */
|
||||||
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
|
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
|
||||||
|
@ -67,6 +59,9 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
|
||||||
/* compile a string containing a C source. Return -1 if error. */
|
/* compile a string containing a C source. Return -1 if error. */
|
||||||
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
||||||
|
|
||||||
|
/* Tip: to have more specific errors/warnings from tcc_compile_string(),
|
||||||
|
you can prefix the string with "#line <num> \"<filename>\"\n" */
|
||||||
|
|
||||||
/*****************************/
|
/*****************************/
|
||||||
/* linking commands */
|
/* linking commands */
|
||||||
|
|
||||||
|
@ -96,18 +91,12 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
|
||||||
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
||||||
|
|
||||||
/* do all relocations (needed before using tcc_get_symbol()) */
|
/* do all relocations (needed before using tcc_get_symbol()) */
|
||||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
|
LIBTCCAPI int tcc_relocate(TCCState *s1);
|
||||||
/* possible values for 'ptr':
|
|
||||||
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
|
|
||||||
- NULL : return required memory size for the step below
|
|
||||||
- memory address : copy code to memory passed by the caller
|
|
||||||
returns -1 if error. */
|
|
||||||
#define TCC_RELOCATE_AUTO (void*)1
|
|
||||||
|
|
||||||
/* return symbol value or NULL if not found */
|
/* return symbol value or NULL if not found */
|
||||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
||||||
|
|
||||||
/* return symbol value or NULL if not found */
|
/* list all (global) symbols and their values via 'symbol_cb()' */
|
||||||
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
|
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
|
||||||
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
||||||
|
|
||||||
|
|
17
tcc.h
17
tcc.h
|
@ -923,13 +923,11 @@ struct TCCState {
|
||||||
Section *lbounds_section; /* contains local data bound description */
|
Section *lbounds_section; /* contains local data bound description */
|
||||||
#endif
|
#endif
|
||||||
/* symbol section */
|
/* symbol section */
|
||||||
Section *symtab_section;
|
union { Section *symtab_section, *symtab; }; /* historical alias */
|
||||||
/* temporary dynamic symbol sections (for dll loading) */
|
/* temporary dynamic symbol sections (for dll loading) */
|
||||||
Section *dynsymtab_section;
|
Section *dynsymtab_section;
|
||||||
/* exported dynamic symbol section */
|
/* exported dynamic symbol section */
|
||||||
Section *dynsym;
|
Section *dynsym;
|
||||||
/* copy of the global symtab_section variable */
|
|
||||||
Section *symtab;
|
|
||||||
/* got & plt handling */
|
/* got & plt handling */
|
||||||
Section *got, *plt;
|
Section *got, *plt;
|
||||||
/* debug sections */
|
/* debug sections */
|
||||||
|
@ -972,6 +970,8 @@ struct TCCState {
|
||||||
int uw_sym;
|
int uw_sym;
|
||||||
unsigned uw_offs;
|
unsigned uw_offs;
|
||||||
# endif
|
# endif
|
||||||
|
#else
|
||||||
|
unsigned shf_RELRO; /* section flags for RELRO sections */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined TCC_TARGET_MACHO
|
#if defined TCC_TARGET_MACHO
|
||||||
|
@ -991,9 +991,12 @@ struct TCCState {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
const char *runtime_main;
|
const char *run_main; /* entry for tcc_run() */
|
||||||
void **runtime_mem;
|
void *run_ptr; /* ptr to runtime_memory */
|
||||||
int nb_runtime_mem;
|
unsigned run_size; /* size of runtime_memory */
|
||||||
|
#ifdef _WIN64
|
||||||
|
void *run_function_table; /* unwind data */
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
|
@ -1542,7 +1545,9 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
|
||||||
ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
|
ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
|
||||||
ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
|
ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
|
||||||
ST_FUNC Section *find_section(TCCState *s1, const char *name);
|
ST_FUNC Section *find_section(TCCState *s1, const char *name);
|
||||||
|
ST_FUNC void free_section(Section *s);
|
||||||
ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
|
ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
|
||||||
|
ST_FUNC void init_symtab(Section *s);
|
||||||
|
|
||||||
ST_FUNC int put_elf_str(Section *s, const char *sym);
|
ST_FUNC int put_elf_str(Section *s, const char *sym);
|
||||||
ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
||||||
|
|
4
tccdbg.c
4
tccdbg.c
|
@ -714,9 +714,11 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
|
||||||
char buf[512];
|
char buf[512];
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
||||||
|
/* we might currently #include the <command-line> */
|
||||||
|
filename = file->prev ? file->prev->filename : file->filename;
|
||||||
|
|
||||||
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
||||||
symbols can be safely used */
|
symbols can be safely used */
|
||||||
filename = file->prev ? file->prev->filename : file->filename;
|
|
||||||
put_elf_sym(symtab_section, 0, 0,
|
put_elf_sym(symtab_section, 0, 0,
|
||||||
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
|
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
|
||||||
SHN_ABS, filename);
|
SHN_ABS, filename);
|
||||||
|
|
48
tccelf.c
48
tccelf.c
|
@ -48,10 +48,10 @@ struct sym_version {
|
||||||
#define SHF_DYNSYM 0x40000000
|
#define SHF_DYNSYM 0x40000000
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
static const int shf_RELRO = SHF_ALLOC;
|
#define shf_RELRO SHF_ALLOC
|
||||||
static const char rdata[] = ".rdata";
|
static const char rdata[] = ".rdata";
|
||||||
#else
|
#else
|
||||||
static const int shf_RELRO = SHF_ALLOC | SHF_WRITE;
|
#define shf_RELRO s1->shf_RELRO
|
||||||
static const char rdata[] = ".data.ro";
|
static const char rdata[] = ".data.ro";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -60,6 +60,13 @@ static const char rdata[] = ".data.ro";
|
||||||
ST_FUNC void tccelf_new(TCCState *s)
|
ST_FUNC void tccelf_new(TCCState *s)
|
||||||
{
|
{
|
||||||
TCCState *s1 = s;
|
TCCState *s1 = s;
|
||||||
|
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
|
shf_RELRO = SHF_ALLOC;
|
||||||
|
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
||||||
|
shf_RELRO |= SHF_WRITE; /* the ELF loader will set it to RO at runtime */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* no section zero */
|
/* no section zero */
|
||||||
dynarray_add(&s->sections, &s->nb_sections, NULL);
|
dynarray_add(&s->sections, &s->nb_sections, NULL);
|
||||||
|
|
||||||
|
@ -76,7 +83,6 @@ ST_FUNC void tccelf_new(TCCState *s)
|
||||||
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
|
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
|
||||||
".strtab",
|
".strtab",
|
||||||
".hashtab", SHF_PRIVATE);
|
".hashtab", SHF_PRIVATE);
|
||||||
s->symtab = symtab_section;
|
|
||||||
|
|
||||||
/* private symbol table for dynamic symbols */
|
/* private symbol table for dynamic symbols */
|
||||||
s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM,
|
s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM,
|
||||||
|
@ -99,9 +105,13 @@ ST_FUNC void tccelf_new(TCCState *s)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_section(Section *s)
|
ST_FUNC void free_section(Section *s)
|
||||||
{
|
{
|
||||||
|
if (!s)
|
||||||
|
return;
|
||||||
tcc_free(s->data);
|
tcc_free(s->data);
|
||||||
|
s->data = NULL;
|
||||||
|
s->data_allocated = s->data_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tccelf_delete(TCCState *s1)
|
ST_FUNC void tccelf_delete(TCCState *s1)
|
||||||
|
@ -127,6 +137,9 @@ ST_FUNC void tccelf_delete(TCCState *s1)
|
||||||
free_section(s1->priv_sections[i]);
|
free_section(s1->priv_sections[i]);
|
||||||
dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
|
dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
|
||||||
|
|
||||||
|
tcc_free(s1->sym_attrs);
|
||||||
|
symtab_section = NULL; /* for tccrun.c:rt_printline() */
|
||||||
|
|
||||||
/* free any loaded DLLs */
|
/* free any loaded DLLs */
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
for ( i = 0; i < s1->nb_loaded_dlls; i++) {
|
for ( i = 0; i < s1->nb_loaded_dlls; i++) {
|
||||||
|
@ -141,9 +154,6 @@ ST_FUNC void tccelf_delete(TCCState *s1)
|
||||||
#endif
|
#endif
|
||||||
/* free loaded dlls array */
|
/* free loaded dlls array */
|
||||||
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
||||||
tcc_free(s1->sym_attrs);
|
|
||||||
|
|
||||||
symtab_section = NULL; /* for tccrun.c:rt_printline() */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save section data state */
|
/* save section data state */
|
||||||
|
@ -261,32 +271,32 @@ ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh
|
||||||
return sec;
|
return sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ST_FUNC void init_symtab(Section *s)
|
||||||
|
{
|
||||||
|
int *ptr, nb_buckets = 1;
|
||||||
|
put_elf_str(s->link, "");
|
||||||
|
section_ptr_add(s, sizeof (ElfW(Sym)));
|
||||||
|
ptr = section_ptr_add(s->hash, (2 + nb_buckets + 1) * sizeof(int));
|
||||||
|
ptr[0] = nb_buckets;
|
||||||
|
ptr[1] = 1;
|
||||||
|
memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
ST_FUNC Section *new_symtab(TCCState *s1,
|
ST_FUNC Section *new_symtab(TCCState *s1,
|
||||||
const char *symtab_name, int sh_type, int sh_flags,
|
const char *symtab_name, int sh_type, int sh_flags,
|
||||||
const char *strtab_name,
|
const char *strtab_name,
|
||||||
const char *hash_name, int hash_sh_flags)
|
const char *hash_name, int hash_sh_flags)
|
||||||
{
|
{
|
||||||
Section *symtab, *strtab, *hash;
|
Section *symtab, *strtab, *hash;
|
||||||
int *ptr, nb_buckets;
|
|
||||||
|
|
||||||
symtab = new_section(s1, symtab_name, sh_type, sh_flags);
|
symtab = new_section(s1, symtab_name, sh_type, sh_flags);
|
||||||
symtab->sh_entsize = sizeof(ElfW(Sym));
|
symtab->sh_entsize = sizeof(ElfW(Sym));
|
||||||
strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
|
strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
|
||||||
put_elf_str(strtab, "");
|
|
||||||
symtab->link = strtab;
|
symtab->link = strtab;
|
||||||
put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
|
|
||||||
|
|
||||||
nb_buckets = 1;
|
|
||||||
|
|
||||||
hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
|
hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
|
||||||
hash->sh_entsize = sizeof(int);
|
hash->sh_entsize = sizeof(int);
|
||||||
symtab->hash = hash;
|
symtab->hash = hash;
|
||||||
hash->link = symtab;
|
hash->link = symtab;
|
||||||
|
init_symtab(symtab);
|
||||||
ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
|
|
||||||
ptr[0] = nb_buckets;
|
|
||||||
ptr[1] = 1;
|
|
||||||
memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
|
|
||||||
return symtab;
|
return symtab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
tccpe.c
6
tccpe.c
|
@ -1349,7 +1349,7 @@ static int pe_check_symbols(struct pe_info *pe)
|
||||||
sprintf(buffer, "IAT.%s", name);
|
sprintf(buffer, "IAT.%s", name);
|
||||||
is->iat_index = put_elf_sym(
|
is->iat_index = put_elf_sym(
|
||||||
symtab_section, 0, sizeof(DWORD),
|
symtab_section, 0, sizeof(DWORD),
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
|
ELFW(ST_INFO)(STB_LOCAL, STT_OBJECT),
|
||||||
0, SHN_UNDEF, buffer);
|
0, SHN_UNDEF, buffer);
|
||||||
|
|
||||||
offset = text_section->data_offset;
|
offset = text_section->data_offset;
|
||||||
|
@ -1970,7 +1970,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||||
|
|
||||||
/* grab the startup code from libtcc1.a */
|
/* grab the startup code from libtcc1.a */
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)
|
if (TCC_OUTPUT_MEMORY != s1->output_type || s1->run_main)
|
||||||
#endif
|
#endif
|
||||||
set_global_sym(s1, start_symbol, NULL, 0);
|
set_global_sym(s1, start_symbol, NULL, 0);
|
||||||
|
|
||||||
|
@ -2078,7 +2078,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
pe.thunk = data_section;
|
pe.thunk = data_section;
|
||||||
pe_build_imports(&pe);
|
pe_build_imports(&pe);
|
||||||
s1->runtime_main = pe.start_symbol;
|
s1->run_main = pe.start_symbol;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
s1->uw_pdata = find_section(s1, ".pdata");
|
s1->uw_pdata = find_section(s1, ".pdata");
|
||||||
#endif
|
#endif
|
||||||
|
|
216
tccrun.c
216
tccrun.c
|
@ -76,8 +76,8 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap);
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length);
|
static int protect_pages(void *ptr, unsigned long length, int mode);
|
||||||
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff);
|
static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff);
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
static void *win64_add_function_table(TCCState *s1);
|
static void *win64_add_function_table(TCCState *s1);
|
||||||
|
@ -88,13 +88,11 @@ static void win64_del_function_table(void *);
|
||||||
/* Do all relocations (needed before using tcc_get_symbol())
|
/* Do all relocations (needed before using tcc_get_symbol())
|
||||||
Returns -1 on error. */
|
Returns -1 on error. */
|
||||||
|
|
||||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
|
LIBTCCAPI int tcc_relocate(TCCState *s1)
|
||||||
{
|
{
|
||||||
|
void *ptr;
|
||||||
int size;
|
int size;
|
||||||
addr_t ptr_diff = 0;
|
unsigned ptr_diff = 0;
|
||||||
|
|
||||||
if (TCC_RELOCATE_AUTO != ptr)
|
|
||||||
return tcc_relocate_ex(s1, ptr, 0);
|
|
||||||
|
|
||||||
size = tcc_relocate_ex(s1, NULL, 0);
|
size = tcc_relocate_ex(s1, NULL, 0);
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
|
@ -103,51 +101,45 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
{
|
{
|
||||||
/* Using mmap instead of malloc */
|
/* Using mmap instead of malloc */
|
||||||
void *prx;
|
void *prw;
|
||||||
char tmpfname[] = "/tmp/.tccrunXXXXXX";
|
char tmpfname[] = "/tmp/.tccrunXXXXXX";
|
||||||
int fd = mkstemp(tmpfname);
|
int fd = mkstemp(tmpfname);
|
||||||
unlink(tmpfname);
|
unlink(tmpfname);
|
||||||
ftruncate(fd, size);
|
ftruncate(fd, size);
|
||||||
|
|
||||||
size = (size + (PAGESIZE-1)) & ~(PAGESIZE-1);
|
ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
|
||||||
ptr = mmap(NULL, size * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
/* mmap RW memory at fixed distance */
|
||||||
/* mmap RX memory at a fixed distance */
|
prw = mmap((char*)ptr + size, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0);
|
||||||
prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
if (ptr == MAP_FAILED || prx == MAP_FAILED)
|
if (ptr == MAP_FAILED || prw == MAP_FAILED)
|
||||||
return tcc_error_noabort("tccrun: could not map memory");
|
return tcc_error_noabort("tccrun: could not map memory");
|
||||||
ptr_diff = (char*)prx - (char*)ptr;
|
ptr_diff = (char*)prw - (char*)ptr; /* = size; */
|
||||||
//printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff);
|
//printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ptr = tcc_malloc(size);
|
ptr = tcc_malloc(size);
|
||||||
#endif
|
#endif
|
||||||
if (tcc_relocate_ex(s1, ptr, ptr_diff))
|
s1->run_ptr = ptr;
|
||||||
return -1;
|
s1->run_size = size;
|
||||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
|
tcc_relocate_ex(s1, ptr, ptr_diff);
|
||||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tcc_run_free(TCCState *s1)
|
ST_FUNC void tcc_run_free(TCCState *s1)
|
||||||
{
|
{
|
||||||
int i;
|
void *ptr = s1->run_ptr;
|
||||||
|
unsigned size = s1->run_size;
|
||||||
|
|
||||||
for (i = 0; i < s1->nb_runtime_mem; i += 2) {
|
|
||||||
unsigned size = (unsigned)(addr_t)s1->runtime_mem[i];
|
|
||||||
void *ptr = s1->runtime_mem[i+1];
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
munmap(ptr, size * 2);
|
munmap(ptr, size * 2);
|
||||||
#else
|
#else
|
||||||
/* unprotect memory to make it usable for malloc again */
|
/* unprotect memory to make it usable for malloc again */
|
||||||
set_pages_executable(s1, 2, ptr, size);
|
protect_pages(ptr, size, 2 /*rw*/);
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
win64_del_function_table(*(void**)ptr);
|
win64_del_function_table(s1->run_function_table);
|
||||||
#endif
|
#endif
|
||||||
tcc_free(ptr);
|
tcc_free(ptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
tcc_free(s1->runtime_mem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_cdtors(TCCState *s1, const char *start, const char *end,
|
static void run_cdtors(TCCState *s1, const char *start, const char *end,
|
||||||
|
@ -198,17 +190,17 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
char **envp = environ;
|
char **envp = environ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s1->runtime_main = s1->nostdlib ? "_start" : "main";
|
s1->run_main = s1->nostdlib ? "_start" : "main";
|
||||||
if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->runtime_main, 0, 1))
|
if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->run_main, 0, 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
tcc_add_symbol(s1, "exit", rt_exit);
|
tcc_add_symbol(s1, "exit", rt_exit);
|
||||||
tcc_add_symbol(s1, "atexit", rt_atexit);
|
tcc_add_symbol(s1, "atexit", rt_atexit);
|
||||||
tcc_add_symbol(s1, "on_exit", rt_on_exit);
|
tcc_add_symbol(s1, "on_exit", rt_on_exit);
|
||||||
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
|
if (tcc_relocate(s1) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1);
|
prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1);
|
||||||
if ((addr_t)-1 == (addr_t)prog_main)
|
if ((addr_t)-1 == (addr_t)prog_main)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -275,28 +267,62 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEBUG_RUNMEN 0
|
/* ------------------------------------------------------------- */
|
||||||
|
/* remove all STB_LOCAL symbols */
|
||||||
|
static void cleanup_symbols(TCCState *s1)
|
||||||
|
{
|
||||||
|
Section *s = s1->symtab;
|
||||||
|
int sym_index, end_sym = s->data_offset / sizeof (ElfSym);
|
||||||
|
/* reset symtab */
|
||||||
|
s->data_offset = s->link->data_offset = s->hash->data_offset = 0;
|
||||||
|
init_symtab(s);
|
||||||
|
/* re-add symbols except STB_LOCAL */
|
||||||
|
for (sym_index = 1; sym_index < end_sym; ++sym_index) {
|
||||||
|
ElfW(Sym) *sym = &((ElfW(Sym) *)s->data)[sym_index];
|
||||||
|
const char *name = (char *)s->link->data + sym->st_name;
|
||||||
|
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
|
||||||
|
continue;
|
||||||
|
//printf("sym %s\n", name);
|
||||||
|
put_elf_sym(s, sym->st_value, sym->st_size, sym->st_info, sym->st_other, sym->st_shndx, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* enable rx/ro/rw permissions */
|
/* free all sections except symbols */
|
||||||
#define CONFIG_RUNMEM_RO 1
|
static void cleanup_sections(TCCState *s1)
|
||||||
|
{
|
||||||
|
struct { Section **secs; int nb_secs; } *p = (void*)&s1->sections;
|
||||||
|
int i, f = 2;
|
||||||
|
do {
|
||||||
|
for (i = --f; i < p->nb_secs; i++) {
|
||||||
|
Section *s = p->secs[i];
|
||||||
|
if (s == s1->symtab || s == s1->symtab->link || s == s1->symtab->hash
|
||||||
|
|| 0 == memcmp(s->name, ".stab", 5)
|
||||||
|
|| 0 == memcmp(s->name, ".debug_", 7)) {
|
||||||
|
s->data = tcc_realloc(s->data, s->data_allocated = s->data_offset);
|
||||||
|
} else {
|
||||||
|
free_section(s);
|
||||||
|
if (0 == (s->sh_flags & SHF_ALLOC))
|
||||||
|
tcc_free(s), p->secs[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (++p, f);
|
||||||
|
}
|
||||||
|
|
||||||
#if CONFIG_RUNMEM_RO
|
/* ------------------------------------------------------------- */
|
||||||
# define PAGE_ALIGN PAGESIZE
|
/* 0 = .text rwx other rw */
|
||||||
#elif defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
/* 1 = .text rx .rdata r .data/.bss rw */
|
||||||
/* To avoid that x86 processors would reload cached instructions
|
#ifndef CONFIG_RUNMEM_RO
|
||||||
each time when data is written in the near, we need to make
|
# define CONFIG_RUNMEM_RO 1
|
||||||
sure that code and data do not share the same 64 byte unit */
|
|
||||||
# define PAGE_ALIGN 64
|
|
||||||
#else
|
|
||||||
# define PAGE_ALIGN 1
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DEBUG_RUNMEN 0
|
||||||
|
|
||||||
/* relocate code. Return -1 on error, required size if ptr is NULL,
|
/* relocate code. Return -1 on error, required size if ptr is NULL,
|
||||||
otherwise copy code into buffer passed by the caller */
|
otherwise copy code into buffer passed by the caller */
|
||||||
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
unsigned offset, length, align, max_align, i, k, f;
|
unsigned offset, length, align, i, k, f;
|
||||||
unsigned n, copy;
|
unsigned n, copy;
|
||||||
addr_t mem, addr;
|
addr_t mem, addr;
|
||||||
|
|
||||||
|
@ -313,11 +339,15 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = max_align = 0, mem = (addr_t)ptr;
|
offset = copy = 0;
|
||||||
#ifdef _WIN64
|
mem = (addr_t)ptr;
|
||||||
offset += sizeof (void*); /* space for function_table pointer */
|
|
||||||
|
#if DEBUG_RUNMEN
|
||||||
|
if (mem)
|
||||||
|
fprintf(stderr, "X: <base> %p len %5x\n",
|
||||||
|
ptr, s1->run_size);
|
||||||
#endif
|
#endif
|
||||||
copy = 0;
|
|
||||||
redo:
|
redo:
|
||||||
for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
|
for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
|
||||||
n = 0; addr = 0;
|
n = 0; addr = 0;
|
||||||
|
@ -329,79 +359,98 @@ redo:
|
||||||
if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
|
if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
|
||||||
continue;
|
continue;
|
||||||
length = s->data_offset;
|
length = s->data_offset;
|
||||||
if (copy) {
|
|
||||||
|
if (copy) { /* final step: copy section data to memory */
|
||||||
|
void *ptr;
|
||||||
if (addr == 0)
|
if (addr == 0)
|
||||||
addr = s->sh_addr;
|
addr = s->sh_addr;
|
||||||
n = (s->sh_addr - addr) + length;
|
n = (s->sh_addr - addr) + length;
|
||||||
ptr = (void*)s->sh_addr;
|
ptr = (void*)s->sh_addr;
|
||||||
if (k == 0)
|
if (k == 0)
|
||||||
ptr = (void*)(s->sh_addr - ptr_diff);
|
ptr = (void*)(s->sh_addr + ptr_diff);
|
||||||
if (NULL == s->data || s->sh_type == SHT_NOBITS)
|
if (NULL == s->data || s->sh_type == SHT_NOBITS)
|
||||||
memset(ptr, 0, length);
|
memset(ptr, 0, length);
|
||||||
else
|
else
|
||||||
memcpy(ptr, s->data, length);
|
memcpy(ptr, s->data, length);
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
if (s == s1->uw_pdata)
|
if (s == s1->uw_pdata)
|
||||||
*(void**)mem = win64_add_function_table(s1);
|
s1->run_function_table = win64_add_function_table(s1);
|
||||||
#endif
|
#endif
|
||||||
if (s->data) {
|
free_section(s);
|
||||||
tcc_free(s->data);
|
|
||||||
s->data = NULL;
|
|
||||||
s->data_allocated = 0;
|
|
||||||
}
|
|
||||||
s->data_offset = 0;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
align = s->sh_addralign - 1;
|
align = s->sh_addralign - 1;
|
||||||
if (++n == 1 && align < (PAGE_ALIGN - 1))
|
if (++n == 1) {
|
||||||
align = (PAGE_ALIGN - 1);
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||||
if (max_align < align)
|
/* To avoid that x86 processors would reload cached instructions
|
||||||
max_align = align;
|
each time when data is written in the near, we need to make
|
||||||
addr = k ? mem : mem + ptr_diff;
|
sure that code and data do not share the same 64 byte unit */
|
||||||
|
if (align < 63)
|
||||||
|
align = 63;
|
||||||
|
#endif
|
||||||
|
/* start new page for different permissions */
|
||||||
|
if (CONFIG_RUNMEM_RO || k < 2)
|
||||||
|
align = PAGESIZE - 1;
|
||||||
|
}
|
||||||
|
addr = k ? mem + ptr_diff : mem;
|
||||||
offset += -(addr + offset) & align;
|
offset += -(addr + offset) & align;
|
||||||
s->sh_addr = mem ? addr + offset : 0;
|
s->sh_addr = mem ? addr + offset : 0;
|
||||||
offset += length;
|
offset += length;
|
||||||
#if DEBUG_RUNMEN
|
#if DEBUG_RUNMEN
|
||||||
if (mem)
|
if (mem)
|
||||||
printf("%d: %-16s %p len %04x align %04x\n",
|
fprintf(stderr, "%d: %-16s %p len %5x align %04x\n",
|
||||||
k, s->name, (void*)s->sh_addr, length, align + 1);
|
k, s->name, (void*)s->sh_addr, length, align + 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (copy) { /* set permissions */
|
if (copy) { /* set permissions */
|
||||||
if (k == 0 && ptr_diff)
|
if (n == 0) /* no data */
|
||||||
continue; /* not with HAVE_SELINUX */
|
continue;
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
if (k == 0) /* SHF_EXECINSTR has its own mapping */
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
f = k;
|
f = k;
|
||||||
#if !CONFIG_RUNMEM_RO
|
if (CONFIG_RUNMEM_RO == 0) {
|
||||||
if (f != 0)
|
if (f != 0)
|
||||||
continue;
|
continue;
|
||||||
f = 3; /* change only SHF_EXECINSTR to rwx */
|
f = 3; /* change only SHF_EXECINSTR to rwx */
|
||||||
#endif
|
|
||||||
#if DEBUG_RUNMEN
|
|
||||||
printf("protect %d %p %04x\n", f, (void*)addr, n);
|
|
||||||
#endif
|
|
||||||
if (n) {
|
|
||||||
if (set_pages_executable(s1, f, (void*)addr, n))
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
#if DEBUG_RUNMEN
|
||||||
|
fprintf(stderr, "protect %3s %p len %5x\n",
|
||||||
|
&"rx\0r \0rw\0rwx"[f*3],
|
||||||
|
(void*)addr, (unsigned)((n + PAGESIZE-1) & ~(PAGESIZE-1)));
|
||||||
|
#endif
|
||||||
|
if (protect_pages((void*)addr, n, f) < 0)
|
||||||
|
return tcc_error_noabort(
|
||||||
|
"mprotect failed "
|
||||||
|
"(did you mean to configure --with-selinux?)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy)
|
if (copy) {
|
||||||
|
/* remove local symbols and free sections except symtab */
|
||||||
|
cleanup_symbols(s1);
|
||||||
|
cleanup_sections(s1);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* relocate symbols */
|
/* relocate symbols */
|
||||||
relocate_syms(s1, s1->symtab, !(s1->nostdlib));
|
relocate_syms(s1, s1->symtab, !(s1->nostdlib));
|
||||||
if (s1->nb_errors)
|
if (s1->nb_errors)
|
||||||
return -1;
|
return -1;
|
||||||
if (0 == mem)
|
|
||||||
return offset + max_align;
|
if (0 == mem) {
|
||||||
|
offset = (offset + (PAGESIZE-1)) & ~(PAGESIZE-1);
|
||||||
|
#ifndef HAVE_SELINUX
|
||||||
|
offset += PAGESIZE; /* extra space to align malloc memory start */
|
||||||
|
#endif
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
s1->pe_imagebase = mem;
|
s1->pe_imagebase = mem;
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
/* relocate sections */
|
|
||||||
#ifndef TCC_TARGET_PE
|
|
||||||
relocate_plt(s1);
|
relocate_plt(s1);
|
||||||
#endif
|
#endif
|
||||||
relocate_sections(s1);
|
relocate_sections(s1);
|
||||||
|
@ -412,7 +461,7 @@ redo:
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
/* allow to run code in memory */
|
/* allow to run code in memory */
|
||||||
|
|
||||||
static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length)
|
static int protect_pages(void *ptr, unsigned long length, int mode)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static const unsigned char protect[] = {
|
static const unsigned char protect[] = {
|
||||||
|
@ -437,7 +486,7 @@ static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long
|
||||||
end = (addr_t)ptr + length;
|
end = (addr_t)ptr + length;
|
||||||
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
|
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
|
||||||
if (mprotect((void *)start, end - start, protect[mode]))
|
if (mprotect((void *)start, end - start, protect[mode]))
|
||||||
return tcc_error_noabort("mprotect failed: did you mean to configure --with-selinux?");
|
return -1;
|
||||||
/* XXX: BSD sometimes dump core with bad system call */
|
/* XXX: BSD sometimes dump core with bad system call */
|
||||||
# if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64
|
# if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64
|
||||||
if (mode == 0 || mode == 3) {
|
if (mode == 0 || mode == 3) {
|
||||||
|
@ -472,6 +521,7 @@ static void win64_del_function_table(void *p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //ndef CONFIG_TCC_BACKTRACE_ONLY
|
#endif //ndef CONFIG_TCC_BACKTRACE_ONLY
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include <unistd.h>
|
|
||||||
#include <libtcc.h>
|
#include <libtcc.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -53,7 +52,7 @@ static int run_callback(const char *src, callback_type callback) {
|
||||||
return -1;
|
return -1;
|
||||||
if (tcc_compile_string(s, src) == -1)
|
if (tcc_compile_string(s, src) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) == -1)
|
if (tcc_relocate(s) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ptr = tcc_get_symbol(s, "f");
|
ptr = tcc_get_symbol(s, "f");
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "libtcc.h"
|
#include "libtcc.h"
|
||||||
|
|
||||||
void handle_error(void *opaque, const char *msg)
|
void handle_error(void *opaque, const char *msg)
|
||||||
|
@ -59,14 +57,9 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(tcc_get_error_func(s) == NULL);
|
/* set custom error/warning printer */
|
||||||
assert(tcc_get_error_opaque(s) == NULL);
|
|
||||||
|
|
||||||
tcc_set_error_func(s, stderr, handle_error);
|
tcc_set_error_func(s, stderr, handle_error);
|
||||||
|
|
||||||
assert(tcc_get_error_func(s) == handle_error);
|
|
||||||
assert(tcc_get_error_opaque(s) == stderr);
|
|
||||||
|
|
||||||
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
||||||
for (i = 1; i < argc; ++i) {
|
for (i = 1; i < argc; ++i) {
|
||||||
char *a = argv[i];
|
char *a = argv[i];
|
||||||
|
@ -92,7 +85,7 @@ int main(int argc, char **argv)
|
||||||
tcc_add_symbol(s, "hello", hello);
|
tcc_add_symbol(s, "hello", hello);
|
||||||
|
|
||||||
/* relocate the code */
|
/* relocate the code */
|
||||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
|
if (tcc_relocate(s) < 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* get entry symbol */
|
/* get entry symbol */
|
||||||
|
|
|
@ -128,7 +128,7 @@ void *reloc_state(TCCState *s, const char *entry)
|
||||||
{
|
{
|
||||||
void *func;
|
void *func;
|
||||||
tcc_add_symbol(s, "add", add);
|
tcc_add_symbol(s, "add", add);
|
||||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
|
if (tcc_relocate(s) < 0) {
|
||||||
fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
|
fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue