From 3db219477a6365d0f1d5214a345b3393a38e81d1 Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 19 Dec 2009 22:10:26 +0100 Subject: [PATCH] tccrun: new file factor out -run support --- libtcc.c | 506 +---------------------------------------------------- tccrun.c | 518 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 527 insertions(+), 497 deletions(-) create mode 100644 tccrun.c diff --git a/libtcc.c b/libtcc.c index 5b113963..2afe432d 100644 --- a/libtcc.c +++ b/libtcc.c @@ -352,6 +352,8 @@ static void asm_global_instr(void) #include "tccpe.c" #endif +#include "tccrun.c" + /********************************************************/ #ifdef _WIN32 char *normalize_slashes(char *path) @@ -389,72 +391,6 @@ BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) #endif #endif -/********************************************************/ -#ifdef CONFIG_TCC_STATIC - -#define RTLD_LAZY 0x001 -#define RTLD_NOW 0x002 -#define RTLD_GLOBAL 0x100 -#define RTLD_DEFAULT NULL - -/* dummy function for profiling */ -void *dlopen(const char *filename, int flag) -{ - return NULL; -} - -void dlclose(void *p) -{ -} - -const char *dlerror(void) -{ - return "error"; -} - -typedef struct TCCSyms { - char *str; - void *ptr; -} TCCSyms; - -#define TCCSYM(a) { #a, &a, }, - -/* add the symbol you want here if no dynamic linking is done */ -static TCCSyms tcc_syms[] = { -#if !defined(CONFIG_TCCBOOT) - TCCSYM(printf) - TCCSYM(fprintf) - TCCSYM(fopen) - TCCSYM(fclose) -#endif - { NULL, NULL }, -}; - -void *resolve_sym(TCCState *s1, const char *symbol) -{ - TCCSyms *p; - p = tcc_syms; - while (p->str != NULL) { - if (!strcmp(p->str, symbol)) - return p->ptr; - p++; - } - return NULL; -} - -#elif defined(_WIN32) -#define dlclose FreeLibrary - -#else -#include - -void *resolve_sym(TCCState *s1, const char *sym) -{ - return dlsym(RTLD_DEFAULT, sym); -} - -#endif - /********************************************************/ /* we use our own 'finite' function to avoid potential problems with @@ -512,20 +448,6 @@ char *tcc_fileextension (const char *name) return e ? e : strchr(b, 0); } -void set_pages_executable(void *ptr, unsigned long length) -{ -#ifdef _WIN32 - unsigned long old_protect; - VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); -#else - unsigned long start, end; - start = (unsigned long)ptr & ~(PAGESIZE - 1); - end = (unsigned long)ptr + length; - end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); - mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); -#endif -} - /* memory management */ #ifdef MEM_DEBUG int mem_cur_size; @@ -587,6 +509,13 @@ char *tcc_strdup(const char *str) return ptr; } +void tcc_memstats(void) +{ +#ifdef MEM_DEBUG + printf("memory in use: %d\n", mem_cur_size); +#endif +} + #define free(p) use_tcc_free(p) #define malloc(s) use_tcc_malloc(s) #define realloc(p, s) use_tcc_realloc(p, s) @@ -1409,423 +1338,6 @@ void tcc_undefine_symbol(TCCState *s1, const char *sym) define_undef(s); } - -#ifdef CONFIG_TCC_BACKTRACE -/* print the position in the source file of PC value 'pc' by reading - the stabs debug information */ -static unsigned long rt_printline(unsigned long wanted_pc) -{ - Stab_Sym *sym, *sym_end; - char func_name[128], last_func_name[128]; - unsigned long func_addr, last_pc, pc; - const char *incl_files[INCLUDE_STACK_SIZE]; - int incl_index, len, last_line_num, i; - const char *str, *p; - - fprintf(stderr, "0x%08lx:", wanted_pc); - - func_name[0] = '\0'; - func_addr = 0; - incl_index = 0; - last_func_name[0] = '\0'; - last_pc = 0xffffffff; - last_line_num = 1; - sym = (Stab_Sym *)stab_section->data + 1; - sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset); - while (sym < sym_end) { - switch(sym->n_type) { - /* function start or end */ - case N_FUN: - if (sym->n_strx == 0) { - /* we test if between last line and end of function */ - pc = sym->n_value + func_addr; - if (wanted_pc >= last_pc && wanted_pc < pc) - goto found; - func_name[0] = '\0'; - func_addr = 0; - } else { - str = stabstr_section->data + sym->n_strx; - p = strchr(str, ':'); - if (!p) { - pstrcpy(func_name, sizeof(func_name), str); - } else { - len = p - str; - if (len > sizeof(func_name) - 1) - len = sizeof(func_name) - 1; - memcpy(func_name, str, len); - func_name[len] = '\0'; - } - func_addr = sym->n_value; - } - break; - /* line number info */ - case N_SLINE: - pc = sym->n_value + func_addr; - if (wanted_pc >= last_pc && wanted_pc < pc) - goto found; - last_pc = pc; - last_line_num = sym->n_desc; - /* XXX: slow! */ - strcpy(last_func_name, func_name); - break; - /* include files */ - case N_BINCL: - str = stabstr_section->data + sym->n_strx; - add_incl: - if (incl_index < INCLUDE_STACK_SIZE) { - incl_files[incl_index++] = str; - } - break; - case N_EINCL: - if (incl_index > 1) - incl_index--; - break; - case N_SO: - if (sym->n_strx == 0) { - incl_index = 0; /* end of translation unit */ - } else { - str = stabstr_section->data + sym->n_strx; - /* do not add path */ - len = strlen(str); - if (len > 0 && str[len - 1] != '/') - goto add_incl; - } - break; - } - sym++; - } - - /* second pass: we try symtab symbols (no line number info) */ - incl_index = 0; - { - ElfW(Sym) *sym, *sym_end; - int type; - - sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset); - for(sym = (ElfW(Sym) *)symtab_section->data + 1; - sym < sym_end; - sym++) { - type = ELFW(ST_TYPE)(sym->st_info); - if (type == STT_FUNC) { - if (wanted_pc >= sym->st_value && - wanted_pc < sym->st_value + sym->st_size) { - pstrcpy(last_func_name, sizeof(last_func_name), - strtab_section->data + sym->st_name); - func_addr = sym->st_value; - goto found; - } - } - } - } - /* did not find any info: */ - fprintf(stderr, " ???\n"); - return 0; - found: - if (last_func_name[0] != '\0') { - fprintf(stderr, " %s()", last_func_name); - } - if (incl_index > 0) { - fprintf(stderr, " (%s:%d", - incl_files[incl_index - 1], last_line_num); - for(i = incl_index - 2; i >= 0; i--) - fprintf(stderr, ", included from %s", incl_files[i]); - fprintf(stderr, ")"); - } - fprintf(stderr, "\n"); - return func_addr; -} - -#ifdef __i386__ -/* fix for glibc 2.1 */ -#ifndef REG_EIP -#define REG_EIP EIP -#define REG_EBP EBP -#endif - -/* return the PC at frame level 'level'. Return non zero if not found */ -static int rt_get_caller_pc(unsigned long *paddr, - ucontext_t *uc, int level) -{ - unsigned long fp; - int i; - - if (level == 0) { -#if defined(__FreeBSD__) - *paddr = uc->uc_mcontext.mc_eip; -#elif defined(__dietlibc__) - *paddr = uc->uc_mcontext.eip; -#else - *paddr = uc->uc_mcontext.gregs[REG_EIP]; -#endif - return 0; - } else { -#if defined(__FreeBSD__) - fp = uc->uc_mcontext.mc_ebp; -#elif defined(__dietlibc__) - fp = uc->uc_mcontext.ebp; -#else - fp = uc->uc_mcontext.gregs[REG_EBP]; -#endif - for(i=1;i= 0xc0000000) - return -1; - fp = ((unsigned long *)fp)[0]; - } - *paddr = ((unsigned long *)fp)[1]; - return 0; - } -} -#elif defined(__x86_64__) -/* return the PC at frame level 'level'. Return non zero if not found */ -static int rt_get_caller_pc(unsigned long *paddr, - ucontext_t *uc, int level) -{ - unsigned long fp; - int i; - - if (level == 0) { - /* XXX: only support linux */ -#if defined(__FreeBSD__) - *paddr = uc->uc_mcontext.mc_rip; -#else - *paddr = uc->uc_mcontext.gregs[REG_RIP]; -#endif - return 0; - } else { -#if defined(__FreeBSD__) - fp = uc->uc_mcontext.mc_rbp; -#else - fp = uc->uc_mcontext.gregs[REG_RBP]; -#endif - for(i=1;isi_code) { - case FPE_INTDIV: - case FPE_FLTDIV: - rt_error(uc, "division by zero"); - break; - default: - rt_error(uc, "floating point exception"); - break; - } - break; - case SIGBUS: - case SIGSEGV: - if (rt_bound_error_msg && *rt_bound_error_msg) - rt_error(uc, *rt_bound_error_msg); - else - rt_error(uc, "dereferencing invalid pointer"); - break; - case SIGILL: - rt_error(uc, "illegal instruction"); - break; - case SIGABRT: - rt_error(uc, "abort() called"); - break; - default: - rt_error(uc, "caught signal %d", signum); - break; - } - exit(255); -} - -#endif - -/* 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; - uplong mem; - int i; - - if (0 == s1->runtime_added) { - s1->runtime_added = 1; - s1->nb_errors = 0; -#ifdef TCC_TARGET_PE - pe_output_file(s1, NULL); -#else - tcc_add_runtime(s1); - relocate_common_syms(); - tcc_add_linker_symbols(s1); - build_got_entries(s1); -#endif - if (s1->nb_errors) - return -1; - } - - offset = 0, mem = (uplong)ptr; - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (0 == (s->sh_flags & SHF_ALLOC)) - continue; - length = s->data_offset; - s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0; - offset = (offset + length + 15) & ~15; - } - - /* relocate symbols */ - relocate_syms(s1, 1); - if (s1->nb_errors) - return -1; - -#ifndef TCC_TARGET_PE -#ifdef TCC_TARGET_X86_64 - s1->runtime_plt_and_got_offset = 0; - s1->runtime_plt_and_got = (char *)(mem + offset); - /* double the size of the buffer for got and plt entries - XXX: calculate exact size for them? */ - offset *= 2; -#endif -#endif - - if (0 == mem) - return offset + 15; - - /* relocate each section */ - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (s->reloc) - relocate_section(s1, s); - } - - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - 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*)(uplong)s->sh_addr; - if (NULL == s->data || s->sh_type == SHT_NOBITS) - memset(ptr, 0, length); - else - memcpy(ptr, s->data, length); - /* mark executable sections as executable in memory */ - if (s->sh_flags & SHF_EXECINSTR) - set_pages_executable(ptr, length); - } -#ifndef TCC_TARGET_PE -#ifdef TCC_TARGET_X86_64 - set_pages_executable(s1->runtime_plt_and_got, - s1->runtime_plt_and_got_offset); -#endif -#endif - return 0; -} - -/* launch the compiled program with the given arguments */ -int tcc_run(TCCState *s1, int argc, char **argv) -{ - int (*prog_main)(int, char **); - void *ptr; - int ret; - - 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"); - - if (s1->do_debug) { -#ifdef CONFIG_TCC_BACKTRACE - struct sigaction sigact; - /* install TCC signal handlers to print debug info on fatal - runtime errors */ - sigact.sa_flags = SA_SIGINFO | SA_RESETHAND; - sigact.sa_sigaction = sig_error; - sigemptyset(&sigact.sa_mask); - sigaction(SIGFPE, &sigact, NULL); - sigaction(SIGILL, &sigact, NULL); - sigaction(SIGSEGV, &sigact, NULL); - sigaction(SIGBUS, &sigact, NULL); - sigaction(SIGABRT, &sigact, NULL); -#else - error("debug mode not available"); -#endif - } - -#ifdef CONFIG_TCC_BCHECK - if (s1->do_bounds_check) { - void (*bound_init)(void); - void (*bound_exit)(void); - /* set error function */ - rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg"); - rt_prog_main = (unsigned long)prog_main; - /* XXX: use .init section so that it also work in binary ? */ - bound_init = tcc_get_symbol_err(s1, "__bound_init"); - bound_exit = tcc_get_symbol_err(s1, "__bound_exit"); - bound_init(); - ret = (*prog_main)(argc, argv); - bound_exit(); - } else -#endif - ret = (*prog_main)(argc, argv); - tcc_free(ptr); - return ret; -} - -void tcc_memstats(void) -{ -#ifdef MEM_DEBUG - printf("memory in use: %d\n", mem_cur_size); -#endif -} - static void tcc_cleanup(void) { int i, n; diff --git a/tccrun.c b/tccrun.c new file mode 100644 index 00000000..c321c1ce --- /dev/null +++ b/tccrun.c @@ -0,0 +1,518 @@ +/* + * TCC - Tiny C Compiler + * + * Copyright (c) 2001-2004 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* tccrun.c - support for tcc -run */ + + +/********************************************************/ +#ifdef CONFIG_TCC_STATIC + +#define RTLD_LAZY 0x001 +#define RTLD_NOW 0x002 +#define RTLD_GLOBAL 0x100 +#define RTLD_DEFAULT NULL + +/* dummy function for profiling */ +void *dlopen(const char *filename, int flag) +{ + return NULL; +} + +void dlclose(void *p) +{ +} + +const char *dlerror(void) +{ + return "error"; +} + +typedef struct TCCSyms { + char *str; + void *ptr; +} TCCSyms; + +#define TCCSYM(a) { #a, &a, }, + +/* add the symbol you want here if no dynamic linking is done */ +static TCCSyms tcc_syms[] = { +#if !defined(CONFIG_TCCBOOT) + TCCSYM(printf) + TCCSYM(fprintf) + TCCSYM(fopen) + TCCSYM(fclose) +#endif + { NULL, NULL }, +}; + +void *resolve_sym(TCCState *s1, const char *symbol) +{ + TCCSyms *p; + p = tcc_syms; + while (p->str != NULL) { + if (!strcmp(p->str, symbol)) + return p->ptr; + p++; + } + return NULL; +} + +#elif defined(_WIN32) +#define dlclose FreeLibrary + +#else +#include + +void *resolve_sym(TCCState *s1, const char *sym) +{ + return dlsym(RTLD_DEFAULT, sym); +} + +#endif /* defined CONFIG_TCC_STATIC + +/********************************************************/ + +#ifdef CONFIG_TCC_BACKTRACE + +/* print the position in the source file of PC value 'pc' by reading + the stabs debug information */ +static unsigned long rt_printline(unsigned long wanted_pc) +{ + Stab_Sym *sym, *sym_end; + char func_name[128], last_func_name[128]; + unsigned long func_addr, last_pc, pc; + const char *incl_files[INCLUDE_STACK_SIZE]; + int incl_index, len, last_line_num, i; + const char *str, *p; + + fprintf(stderr, "0x%08lx:", wanted_pc); + + func_name[0] = '\0'; + func_addr = 0; + incl_index = 0; + last_func_name[0] = '\0'; + last_pc = 0xffffffff; + last_line_num = 1; + sym = (Stab_Sym *)stab_section->data + 1; + sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset); + while (sym < sym_end) { + switch(sym->n_type) { + /* function start or end */ + case N_FUN: + if (sym->n_strx == 0) { + /* we test if between last line and end of function */ + pc = sym->n_value + func_addr; + if (wanted_pc >= last_pc && wanted_pc < pc) + goto found; + func_name[0] = '\0'; + func_addr = 0; + } else { + str = stabstr_section->data + sym->n_strx; + p = strchr(str, ':'); + if (!p) { + pstrcpy(func_name, sizeof(func_name), str); + } else { + len = p - str; + if (len > sizeof(func_name) - 1) + len = sizeof(func_name) - 1; + memcpy(func_name, str, len); + func_name[len] = '\0'; + } + func_addr = sym->n_value; + } + break; + /* line number info */ + case N_SLINE: + pc = sym->n_value + func_addr; + if (wanted_pc >= last_pc && wanted_pc < pc) + goto found; + last_pc = pc; + last_line_num = sym->n_desc; + /* XXX: slow! */ + strcpy(last_func_name, func_name); + break; + /* include files */ + case N_BINCL: + str = stabstr_section->data + sym->n_strx; + add_incl: + if (incl_index < INCLUDE_STACK_SIZE) { + incl_files[incl_index++] = str; + } + break; + case N_EINCL: + if (incl_index > 1) + incl_index--; + break; + case N_SO: + if (sym->n_strx == 0) { + incl_index = 0; /* end of translation unit */ + } else { + str = stabstr_section->data + sym->n_strx; + /* do not add path */ + len = strlen(str); + if (len > 0 && str[len - 1] != '/') + goto add_incl; + } + break; + } + sym++; + } + + /* second pass: we try symtab symbols (no line number info) */ + incl_index = 0; + { + ElfW(Sym) *sym, *sym_end; + int type; + + sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset); + for(sym = (ElfW(Sym) *)symtab_section->data + 1; + sym < sym_end; + sym++) { + type = ELFW(ST_TYPE)(sym->st_info); + if (type == STT_FUNC) { + if (wanted_pc >= sym->st_value && + wanted_pc < sym->st_value + sym->st_size) { + pstrcpy(last_func_name, sizeof(last_func_name), + strtab_section->data + sym->st_name); + func_addr = sym->st_value; + goto found; + } + } + } + } + /* did not find any info: */ + fprintf(stderr, " ???\n"); + return 0; + found: + if (last_func_name[0] != '\0') { + fprintf(stderr, " %s()", last_func_name); + } + if (incl_index > 0) { + fprintf(stderr, " (%s:%d", + incl_files[incl_index - 1], last_line_num); + for(i = incl_index - 2; i >= 0; i--) + fprintf(stderr, ", included from %s", incl_files[i]); + fprintf(stderr, ")"); + } + fprintf(stderr, "\n"); + return func_addr; +} + +#ifdef __i386__ +/* fix for glibc 2.1 */ +#ifndef REG_EIP +#define REG_EIP EIP +#define REG_EBP EBP +#endif + +/* return the PC at frame level 'level'. Return non zero if not found */ +static int rt_get_caller_pc(unsigned long *paddr, + ucontext_t *uc, int level) +{ + unsigned long fp; + int i; + + if (level == 0) { +#if defined(__FreeBSD__) + *paddr = uc->uc_mcontext.mc_eip; +#elif defined(__dietlibc__) + *paddr = uc->uc_mcontext.eip; +#else + *paddr = uc->uc_mcontext.gregs[REG_EIP]; +#endif + return 0; + } else { +#if defined(__FreeBSD__) + fp = uc->uc_mcontext.mc_ebp; +#elif defined(__dietlibc__) + fp = uc->uc_mcontext.ebp; +#else + fp = uc->uc_mcontext.gregs[REG_EBP]; +#endif + for(i=1;i= 0xc0000000) + return -1; + fp = ((unsigned long *)fp)[0]; + } + *paddr = ((unsigned long *)fp)[1]; + return 0; + } +} +#elif defined(__x86_64__) +/* return the PC at frame level 'level'. Return non zero if not found */ +static int rt_get_caller_pc(unsigned long *paddr, + ucontext_t *uc, int level) +{ + unsigned long fp; + int i; + + if (level == 0) { + /* XXX: only support linux */ +#if defined(__FreeBSD__) + *paddr = uc->uc_mcontext.mc_rip; +#else + *paddr = uc->uc_mcontext.gregs[REG_RIP]; +#endif + return 0; + } else { +#if defined(__FreeBSD__) + fp = uc->uc_mcontext.mc_rbp; +#else + fp = uc->uc_mcontext.gregs[REG_RBP]; +#endif + for(i=1;isi_code) { + case FPE_INTDIV: + case FPE_FLTDIV: + rt_error(uc, "division by zero"); + break; + default: + rt_error(uc, "floating point exception"); + break; + } + break; + case SIGBUS: + case SIGSEGV: + if (rt_bound_error_msg && *rt_bound_error_msg) + rt_error(uc, *rt_bound_error_msg); + else + rt_error(uc, "dereferencing invalid pointer"); + break; + case SIGILL: + rt_error(uc, "illegal instruction"); + break; + case SIGABRT: + rt_error(uc, "abort() called"); + break; + default: + rt_error(uc, "caught signal %d", signum); + break; + } + exit(255); +} + +#endif /* defined CONFIG_TCC_BACKTRACE */ + +/********************************************************/ + +void set_pages_executable(void *ptr, unsigned long length) +{ +#ifdef _WIN32 + unsigned long old_protect; + VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); +#else + unsigned long start, end; + start = (unsigned long)ptr & ~(PAGESIZE - 1); + end = (unsigned long)ptr + length; + end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); + mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); +#endif +} + +/* 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; + uplong mem; + int i; + + if (0 == s1->runtime_added) { + s1->runtime_added = 1; + s1->nb_errors = 0; +#ifdef TCC_TARGET_PE + pe_output_file(s1, NULL); +#else + tcc_add_runtime(s1); + relocate_common_syms(); + tcc_add_linker_symbols(s1); + build_got_entries(s1); +#endif + if (s1->nb_errors) + return -1; + } + + offset = 0, mem = (uplong)ptr; + for(i = 1; i < s1->nb_sections; i++) { + s = s1->sections[i]; + if (0 == (s->sh_flags & SHF_ALLOC)) + continue; + length = s->data_offset; + s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0; + offset = (offset + length + 15) & ~15; + } + + /* relocate symbols */ + relocate_syms(s1, 1); + if (s1->nb_errors) + return -1; + +#ifndef TCC_TARGET_PE +#ifdef TCC_TARGET_X86_64 + s1->runtime_plt_and_got_offset = 0; + s1->runtime_plt_and_got = (char *)(mem + offset); + /* double the size of the buffer for got and plt entries + XXX: calculate exact size for them? */ + offset *= 2; +#endif +#endif + + if (0 == mem) + return offset + 15; + + /* relocate each section */ + for(i = 1; i < s1->nb_sections; i++) { + s = s1->sections[i]; + if (s->reloc) + relocate_section(s1, s); + } + + for(i = 1; i < s1->nb_sections; i++) { + s = s1->sections[i]; + 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*)(uplong)s->sh_addr; + if (NULL == s->data || s->sh_type == SHT_NOBITS) + memset(ptr, 0, length); + else + memcpy(ptr, s->data, length); + /* mark executable sections as executable in memory */ + if (s->sh_flags & SHF_EXECINSTR) + set_pages_executable(ptr, length); + } +#ifndef TCC_TARGET_PE +#ifdef TCC_TARGET_X86_64 + set_pages_executable(s1->runtime_plt_and_got, + s1->runtime_plt_and_got_offset); +#endif +#endif + return 0; +} + +/* launch the compiled program with the given arguments */ +int tcc_run(TCCState *s1, int argc, char **argv) +{ + int (*prog_main)(int, char **); + void *ptr; + int ret; + + 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"); + + if (s1->do_debug) { +#ifdef CONFIG_TCC_BACKTRACE + struct sigaction sigact; + /* install TCC signal handlers to print debug info on fatal + runtime errors */ + sigact.sa_flags = SA_SIGINFO | SA_RESETHAND; + sigact.sa_sigaction = sig_error; + sigemptyset(&sigact.sa_mask); + sigaction(SIGFPE, &sigact, NULL); + sigaction(SIGILL, &sigact, NULL); + sigaction(SIGSEGV, &sigact, NULL); + sigaction(SIGBUS, &sigact, NULL); + sigaction(SIGABRT, &sigact, NULL); +#else + error("debug mode not available"); +#endif + } + +#ifdef CONFIG_TCC_BCHECK + if (s1->do_bounds_check) { + void (*bound_init)(void); + void (*bound_exit)(void); + /* set error function */ + rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg"); + rt_prog_main = (unsigned long)prog_main; + /* XXX: use .init section so that it also work in binary ? */ + bound_init = tcc_get_symbol_err(s1, "__bound_init"); + bound_exit = tcc_get_symbol_err(s1, "__bound_exit"); + bound_init(); + ret = (*prog_main)(argc, argv); + bound_exit(); + } else +#endif + ret = (*prog_main)(argc, argv); + tcc_free(ptr); + return ret; +} + +/********************************************************/