From 795f67428e7863353d7c466c211d8fcbb9e8c988 Mon Sep 17 00:00:00 2001 From: grischka Date: Thu, 16 Apr 2009 22:03:03 +0200 Subject: [PATCH] alternative int tcc_relocate(TCCState *s1, void *ptr); --- libtcc.h | 7 ++-- libtcc_test.c | 18 +++++++- tcc.c | 129 +++++++++++++++++++++++++++------------------------------- 3 files changed, 80 insertions(+), 74 deletions(-) diff --git a/libtcc.h b/libtcc.h index 6cacd732..48c14585 100644 --- a/libtcc.h +++ b/libtcc.h @@ -84,9 +84,10 @@ int tcc_output_file(TCCState *s, const char *filename); tcc_relocate() before. */ int tcc_run(TCCState *s, int argc, char **argv); -/* do all relocations (needed before using tcc_get_symbol()). Return - non zero if link error. */ -int tcc_relocate(TCCState *s); +/* copy code into memory passed in by the caller and do all relocations + (needed before using tcc_get_symbol()). + returns -1 on error and required size if ptr is NULL */ +int tcc_relocate(TCCState *s1, void *ptr); /* return symbol value. return 0 if OK, -1 if symbol not found */ int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name); diff --git a/libtcc_test.c b/libtcc_test.c index c67d4f3e..4c16902a 100644 --- a/libtcc_test.c +++ b/libtcc_test.c @@ -36,6 +36,8 @@ int main(int argc, char **argv) TCCState *s; int (*func)(int); unsigned long val; + void *mem; + int size; s = tcc_new(); if (!s) { @@ -53,13 +55,25 @@ int main(int argc, char **argv) with tcc_add_dll(() and using its symbols directly. */ tcc_add_symbol(s, "add", (unsigned long)&add); - tcc_relocate(s); + /* get needed size of the code */ + size = tcc_relocate(s, NULL); + if (size == -1) + return 1; + /* allocate memory and copy the code into it */ + mem = malloc(size); + tcc_relocate(s, mem); + + /* get entry symbol */ tcc_get_symbol(s, &val, "foo"); func = (void *)val; + /* delete the state */ + tcc_delete(s); + + /* run the code */ func(32); - tcc_delete(s); + free(mem); return 0; } diff --git a/tcc.c b/tcc.c index ef89e60c..56cc0a66 100644 --- a/tcc.c +++ b/tcc.c @@ -542,6 +542,9 @@ struct TCCState { /* output file for preprocessing */ FILE *outfile; + + /* for tcc_relocate */ + int runtime_added; }; /* The current value can be: */ @@ -10277,88 +10280,61 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc) } #endif -/* do all relocations (needed before using tcc_get_symbol()) */ -int tcc_relocate(TCCState *s1) +/* copy code into memory passed in by the caller and do all relocations + (needed before using tcc_get_symbol()). + returns -1 on error and required size if ptr is NULL */ +int tcc_relocate(TCCState *s1, void *ptr) { Section *s; + unsigned long offset, length, mem; int i; s1->nb_errors = 0; - + + if (0 == s1->runtime_added) { #ifdef TCC_TARGET_PE - pe_add_runtime(s1); + pe_add_runtime(s1); + relocate_common_syms(); + tcc_add_linker_symbols(s1); #else - tcc_add_runtime(s1); -#endif - - relocate_common_syms(); - - tcc_add_linker_symbols(s1); -#ifndef TCC_TARGET_PE - build_got_entries(s1); + tcc_add_runtime(s1); + relocate_common_syms(); + tcc_add_linker_symbols(s1); + build_got_entries(s1); #endif - -#ifdef TCC_TARGET_X86_64 - { - /* If the distance of two sections are longer than 32bit, our - program will crash. Let's combine all sections which are - necessary to run the program into a single buffer in the - text section */ - unsigned char *p; - int size; - /* calculate the size of buffers we need */ - size = 0; - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (s->sh_flags & SHF_ALLOC) { - size += s->data_offset; - } - } - /* double the size of the buffer for got and plt entries - XXX: calculate exact size for them? */ - section_realloc(text_section, size * 2); - p = text_section->data + text_section->data_offset; - /* we will put got and plt after this offset */ - text_section->data_offset = size; - - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (s->sh_flags & SHF_ALLOC) { - if (s != text_section && s->data_offset) { - if (s->sh_type == SHT_NOBITS) { - /* for bss section */ - memset(p, 0, s->data_offset); - } else { - memcpy(p, s->data, s->data_offset); - tcc_free(s->data); - } - s->data = p; - /* we won't free s->data for this section */ - s->data_allocated = 0; - p += s->data_offset; - } - s->sh_addr = (unsigned long)s->data; - } - } + s1->runtime_added = 1; } -#else - /* compute relocation address : section are relocated in place. We - also alloc the bss space */ + + offset = 0; + mem = (unsigned long)ptr; for(i = 1; i < s1->nb_sections; i++) { s = s1->sections[i]; - if (s->sh_flags & SHF_ALLOC) { + if (0 == (s->sh_flags & SHF_ALLOC)) + continue; + length = s->data_offset; + if (0 == mem) { + s->sh_addr = 0; + } else if (1 == mem) { + /* section are relocated in place. + We also alloc the bss space */ if (s->sh_type == SHT_NOBITS) - s->data = tcc_mallocz(s->data_offset); + s->data = tcc_malloc(length); s->sh_addr = (unsigned long)s->data; + } else { + /* sections are relocated to new memory */ + s->sh_addr = (mem + offset + 15) & ~15; } + offset = (offset + length + 15) & ~15; } -#endif + /* relocate symbols */ relocate_syms(s1, 1); - - if (s1->nb_errors != 0) + if (s1->nb_errors) return -1; + if (0 == mem) + return offset + 15; + /* relocate each section */ for(i = 1; i < s1->nb_sections; i++) { s = s1->sections[i]; @@ -10366,12 +10342,20 @@ int tcc_relocate(TCCState *s1) relocate_section(s1, s); } - /* mark executable sections as executable in memory */ for(i = 1; i < s1->nb_sections; i++) { s = s1->sections[i]; - if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) == - (SHF_ALLOC | SHF_EXECINSTR)) - set_pages_executable(s->data, s->data_offset); + if (0 == (s->sh_flags & SHF_ALLOC)) + continue; + length = s->data_offset; + // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length); + ptr = (void*)s->sh_addr; + if (NULL == s->data || s->sh_type == SHT_NOBITS) + memset(ptr, 0, length); + else if (ptr != s->data) + memcpy(ptr, s->data, length); + /* mark executable sections as executable in memory */ + if (s->sh_flags & SHF_EXECINSTR) + set_pages_executable(ptr, length); } return 0; } @@ -10380,9 +10364,14 @@ int tcc_relocate(TCCState *s1) int tcc_run(TCCState *s1, int argc, char **argv) { int (*prog_main)(int, char **); + void *ptr; + int ret; - if (tcc_relocate(s1) < 0) + ret = tcc_relocate(s1, NULL); + if (ret < 0) return -1; + ptr = tcc_malloc(ret); + tcc_relocate(s1, ptr); prog_main = tcc_get_symbol_err(s1, "main"); @@ -10417,7 +10406,9 @@ int tcc_run(TCCState *s1, int argc, char **argv) bound_init(); } #endif - return (*prog_main)(argc, argv); + ret = (*prog_main)(argc, argv); + tcc_free(ptr); + return ret; } void tcc_memstats(void) -- 2.11.4.GIT