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()
Unified · Split
| @@ -56,6 +56,7 @@ build_cross= · 55 unmodified lines | |||
| 56 | # use CC/AR from environment when set | 56 | # use CC/AR from environment when set |
| 57 | test -n "$CC" && cc="$CC" | 57 | test -n "$CC" && cc="$CC" |
| 58 | test -n "$AR" && ar="$AR" | 58 | test -n "$AR" && ar="$AR" |
| 59 | test -n "CFLAGS" && CFLAGS="-Wall -O2" | ||
| 59 | 60 | ||
| 60 | # find source path | 61 | # find source path |
| 61 | source_path=${0%configure} | 62 | source_path=${0%configure} |
| @@ -399,14 +400,6 @@ if test "$mingw32" = "no"; then · 337 unmodified lines | |||
| 399 | default infodir "${sharedir}/info" | 400 | default infodir "${sharedir}/info" |
| 400 | fi | 401 | fi |
| 401 | 402 | ||
| 402 | # set default CFLAGS | ||
| 403 | default CFLAGS "-Wall -O2" | ||
| 404 | |||
| 405 | if test "$mingw32" = "yes" -a "$cc_name" = "gcc"; then | ||
| 406 | # avoid mingw dependencies such as 'libgcc_s_dw2-1.dll' | ||
| 407 | default LDFLAGS "-static" | ||
| 408 | fi | ||
| 409 | |||
| 410 | if test x"$show_help" = "xyes" ; then | 403 | if test x"$show_help" = "xyes" ; then |
| 411 | show_help | 404 | show_help |
| 412 | fi | 405 | fi |
| @@ -464,6 +457,11 @@ if test "$bigendian" = "yes" ; then · 51 unmodified lines | |||
| 464 | confvars="$confvars BIGENDIAN" | 457 | confvars="$confvars BIGENDIAN" |
| 465 | fi | 458 | fi |
| 466 | 459 | ||
| 460 | if test "$mingw32" = "yes" -a "$cc_name" = "gcc"; then | ||
| 461 | # avoid mingw dependencies such as 'libgcc_s_dw2-1.dll' | ||
| 462 | default LDFLAGS "-static" | ||
| 463 | fi | ||
| 464 | |||
| 467 | if test "$cpu" = "arm"; then | 465 | if test "$cpu" = "arm"; then |
| 468 | if test "${triplet%eabihf}" != "$triplet" ; then | 466 | if test "${triplet%eabihf}" != "$triplet" ; then |
| 469 | confvars="$confvars arm_eabihf arm_vfp" | 467 | confvars="$confvars arm_eabihf arm_vfp" |
| @@ -249,7 +249,7 @@ ST_FUNC char *tcc_load_text(int fd) · 248 unmodified lines | |||
| 249 | #undef free | 249 | #undef free |
| 250 | #undef realloc | 250 | #undef realloc |
| 251 | 251 | ||
| 252 | static void *default_reallocator(void *ptr, size_t size) | 252 | static void *default_reallocator(void *ptr, unsigned long size) |
| 253 | { | 253 | { |
| 254 | void *ptr1; | 254 | void *ptr1; |
| 255 | if (size == 0) { | 255 | if (size == 0) { |
| @@ -275,18 +275,13 @@ static void libc_free(void *ptr) · 19 unmodified lines | |||
| 275 | #define realloc(p, s) use_tcc_realloc(p, s) | 275 | #define realloc(p, s) use_tcc_realloc(p, s) |
| 276 | 276 | ||
| 277 | /* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */ | 277 | /* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */ |
| 278 | static TCCReallocFunc reallocator = default_reallocator; | 278 | static void *(*reallocator)(void*, unsigned long) = default_reallocator; |
| 279 | 279 | ||
| 280 | LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc) | 280 | LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *realloc) |
| 281 | { | 281 | { |
| 282 | reallocator = realloc; | 282 | reallocator = realloc; |
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | LIBTCCAPI TCCReallocFunc tcc_get_realloc() | ||
| 286 | { | ||
| 287 | return reallocator; | ||
| 288 | } | ||
| 289 | |||
| 290 | /* in case MEM_DEBUG is #defined */ | 285 | /* in case MEM_DEBUG is #defined */ |
| 291 | #undef tcc_free | 286 | #undef tcc_free |
| 292 | #undef tcc_malloc | 287 | #undef tcc_malloc |
| @@ -646,7 +641,7 @@ static void error1(int mode, const char *fmt, va_list ap) · 353 unmodified lines | |||
| 646 | } | 641 | } |
| 647 | cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: "); | 642 | cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: "); |
| 648 | cstr_vprintf(&cs, fmt, ap); | 643 | cstr_vprintf(&cs, fmt, ap); |
| 649 | if (!s1 || !s1->error_func) { | 644 | if (!s1->error_func) { |
| 650 | /* default case: stderr */ | 645 | /* default case: stderr */ |
| 651 | if (s1 && s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout) | 646 | if (s1 && s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout) |
| 652 | printf("\n"); /* print a newline during tcc -E */ | 647 | printf("\n"); /* print a newline during tcc -E */ |
| @@ -666,22 +661,12 @@ static void error1(int mode, const char *fmt, va_list ap) · 13 unmodified lines | |||
| 666 | } | 661 | } |
| 667 | } | 662 | } |
| 668 | 663 | ||
| 669 | LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func) | 664 | LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func) |
| 670 | { | 665 | { |
| 671 | s->error_opaque = error_opaque; | 666 | s->error_opaque = error_opaque; |
| 672 | s->error_func = error_func; | 667 | s->error_func = error_func; |
| 673 | } | 668 | } |
| 674 | 669 | ||
| 675 | LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s) | ||
| 676 | { | ||
| 677 | return s->error_func; | ||
| 678 | } | ||
| 679 | |||
| 680 | LIBTCCAPI void *tcc_get_error_opaque(TCCState *s) | ||
| 681 | { | ||
| 682 | return s->error_opaque; | ||
| 683 | } | ||
| 684 | |||
| 685 | /* error without aborting current compilation */ | 670 | /* error without aborting current compilation */ |
| 686 | PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) | 671 | PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) |
| 687 | { | 672 | { |
| @@ -2245,6 +2230,15 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) · 1557 unmodified lines | |||
| 2245 | s1->total_output[3] | 2230 | s1->total_output[3] |
| 2246 | ); | 2231 | ); |
| 2247 | #ifdef MEM_DEBUG | 2232 | #ifdef MEM_DEBUG |
| 2248 | fprintf(stderr, "# %d bytes memory used\n", mem_max_size); | 2233 | fprintf(stderr, "# memory usage"); |
| 2234 | #ifdef TCC_IS_NATIVE | ||
| 2235 | if (s1->run_size) { | ||
| 2236 | Section *s = s1->symtab; | ||
| 2237 | int ms = s->data_offset + s->link->data_offset + s->hash->data_offset; | ||
| 2238 | fprintf(stderr, ": %d to run, %d symbols, %d other,", | ||
| 2239 | s1->run_size, ms, mem_cur_size - s1->run_size - ms); | ||
| 2240 | } | ||
| 2241 | #endif | ||
| 2242 | fprintf(stderr, " %d max (bytes)\n", mem_max_size); | ||
| 2249 | #endif | 2243 | #endif |
| 2250 | } | 2244 | } |
| @@ -9,18 +9,15 @@ · 8 unmodified lines | |||
| 9 | extern "C" { | 9 | extern "C" { |
| 10 | #endif | 10 | #endif |
| 11 | 11 | ||
| 12 | struct TCCState; | 12 | /*****************************/ |
| 13 | 13 | /* set custom allocator for all allocations (optional) */ | |
| 14 | typedef struct TCCState TCCState; | ||
| 15 | 14 | ||
| 16 | typedef void (*TCCErrorFunc)(void *opaque, const char *msg); | 15 | typedef void *TCCReallocFunc(void *ptr, unsigned long size); |
| 17 | typedef void *(*TCCReallocFunc)(void *ptr, size_t size); | 16 | LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *my_realloc); |
| 18 | 17 | ||
| 19 | /* to be used for all allocation (including tcc_new()), otherwise malloc(), realloc(), free() */ | 18 | /*****************************/ |
| 20 | LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc); | ||
| 21 | 19 | ||
| 22 | /* return current allocator */ | 20 | typedef struct TCCState TCCState; |
| 23 | LIBTCCAPI TCCReallocFunc tcc_get_realloc(); | ||
| 24 | 21 | ||
| 25 | /* create a new TCC compilation context */ | 22 | /* create a new TCC compilation context */ |
| 26 | LIBTCCAPI TCCState *tcc_new(void); | 23 | LIBTCCAPI TCCState *tcc_new(void); |
| @@ -31,14 +28,9 @@ LIBTCCAPI void tcc_delete(TCCState *s); · 4 unmodified lines | |||
| 31 | /* set CONFIG_TCCDIR at runtime */ | 28 | /* set CONFIG_TCCDIR at runtime */ |
| 32 | LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); | 29 | LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); |
| 33 | 30 | ||
| 34 | /* set error/warning display callback */ | 31 | /* set error/warning callback (optional) */ |
| 35 | LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func); | 32 | typedef void TCCErrorFunc(void *opaque, const char *msg); |
| 36 | 33 | LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func); | |
| 37 | /* return error/warning callback */ | ||
| 38 | LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s); | ||
| 39 | |||
| 40 | /* return error/warning callback opaque pointer */ | ||
| 41 | LIBTCCAPI void *tcc_get_error_opaque(TCCState *s); | ||
| 42 | 34 | ||
| 43 | /* set options as from command line (multiple supported) */ | 35 | /* set options as from command line (multiple supported) */ |
| 44 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str); | 36 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str); |
| @@ -67,6 +59,9 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename); · 22 unmodified lines | |||
| 67 | /* compile a string containing a C source. Return -1 if error. */ | 59 | /* compile a string containing a C source. Return -1 if error. */ |
| 68 | LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf); | 60 | LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf); |
| 69 | 61 | ||
| 62 | /* Tip: to have more specific errors/warnings from tcc_compile_string(), | ||
| 63 | you can prefix the string with "#line <num> \"<filename>\"\n" */ | ||
| 64 | |||
| 70 | /*****************************/ | 65 | /*****************************/ |
| 71 | /* linking commands */ | 66 | /* linking commands */ |
| 72 | 67 | ||
| @@ -96,18 +91,12 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename); · 23 unmodified lines | |||
| 96 | LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv); | 91 | LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv); |
| 97 | 92 | ||
| 98 | /* do all relocations (needed before using tcc_get_symbol()) */ | 93 | /* do all relocations (needed before using tcc_get_symbol()) */ |
| 99 | LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr); | 94 | LIBTCCAPI int tcc_relocate(TCCState *s1); |
| 100 | /* possible values for 'ptr': | ||
| 101 | - TCC_RELOCATE_AUTO : Allocate and manage memory internally | ||
| 102 | - NULL : return required memory size for the step below | ||
| 103 | - memory address : copy code to memory passed by the caller | ||
| 104 | returns -1 if error. */ | ||
| 105 | #define TCC_RELOCATE_AUTO (void*)1 | ||
| 106 | 95 | ||
| 107 | /* return symbol value or NULL if not found */ | 96 | /* return symbol value or NULL if not found */ |
| 108 | LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name); | 97 | LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name); |
| 109 | 98 | ||
| 110 | /* return symbol value or NULL if not found */ | 99 | /* list all (global) symbols and their values via 'symbol_cb()' */ |
| 111 | LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, | 100 | LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, |
| 112 | void (*symbol_cb)(void *ctx, const char *name, const void *val)); | 101 | void (*symbol_cb)(void *ctx, const char *name, const void *val)); |
| 113 | 102 | ||
| @@ -923,13 +923,11 @@ struct TCCState { · 922 unmodified lines | |||
| 923 | Section *lbounds_section; /* contains local data bound description */ | 923 | Section *lbounds_section; /* contains local data bound description */ |
| 924 | #endif | 924 | #endif |
| 925 | /* symbol section */ | 925 | /* symbol section */ |
| 926 | Section *symtab_section; | 926 | union { Section *symtab_section, *symtab; }; /* historical alias */ |
| 927 | /* temporary dynamic symbol sections (for dll loading) */ | 927 | /* temporary dynamic symbol sections (for dll loading) */ |
| 928 | Section *dynsymtab_section; | 928 | Section *dynsymtab_section; |
| 929 | /* exported dynamic symbol section */ | 929 | /* exported dynamic symbol section */ |
| 930 | Section *dynsym; | 930 | Section *dynsym; |
| 931 | /* copy of the global symtab_section variable */ | ||
| 932 | Section *symtab; | ||
| 933 | /* got & plt handling */ | 931 | /* got & plt handling */ |
| 934 | Section *got, *plt; | 932 | Section *got, *plt; |
| 935 | /* debug sections */ | 933 | /* debug sections */ |
| @@ -972,6 +970,8 @@ struct TCCState { · 36 unmodified lines | |||
| 972 | int uw_sym; | 970 | int uw_sym; |
| 973 | unsigned uw_offs; | 971 | unsigned uw_offs; |
| 974 | # endif | 972 | # endif |
| 973 | #else | ||
| 974 | unsigned shf_RELRO; /* section flags for RELRO sections */ | ||
| 975 | #endif | 975 | #endif |
| 976 | 976 | ||
| 977 | #if defined TCC_TARGET_MACHO | 977 | #if defined TCC_TARGET_MACHO |
| @@ -991,9 +991,12 @@ struct TCCState { · 13 unmodified lines | |||
| 991 | #endif | 991 | #endif |
| 992 | 992 | ||
| 993 | #ifdef TCC_IS_NATIVE | 993 | #ifdef TCC_IS_NATIVE |
| 994 | const char *runtime_main; | 994 | const char *run_main; /* entry for tcc_run() */ |
| 995 | void **runtime_mem; | 995 | void *run_ptr; /* ptr to runtime_memory */ |
| 996 | int nb_runtime_mem; | 996 | unsigned run_size; /* size of runtime_memory */ |
| 997 | #ifdef _WIN64 | ||
| 998 | void *run_function_table; /* unwind data */ | ||
| 999 | #endif | ||
| 997 | #endif | 1000 | #endif |
| 998 | 1001 | ||
| 999 | #ifdef CONFIG_TCC_BACKTRACE | 1002 | #ifdef CONFIG_TCC_BACKTRACE |
| @@ -1542,7 +1545,9 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size); · 542 unmodified lines | |||
| 1542 | ST_FUNC size_t section_add(Section *sec, addr_t size, int align); | 1545 | ST_FUNC size_t section_add(Section *sec, addr_t size, int align); |
| 1543 | ST_FUNC void *section_ptr_add(Section *sec, addr_t size); | 1546 | ST_FUNC void *section_ptr_add(Section *sec, addr_t size); |
| 1544 | ST_FUNC Section *find_section(TCCState *s1, const char *name); | 1547 | ST_FUNC Section *find_section(TCCState *s1, const char *name); |
| 1548 | ST_FUNC void free_section(Section *s); | ||
| 1545 | 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); | 1549 | 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); |
| 1550 | ST_FUNC void init_symtab(Section *s); | ||
| 1546 | 1551 | ||
| 1547 | ST_FUNC int put_elf_str(Section *s, const char *sym); | 1552 | ST_FUNC int put_elf_str(Section *s, const char *sym); |
| 1548 | ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); | 1553 | ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); |
| @@ -714,9 +714,11 @@ ST_FUNC void tcc_debug_start(TCCState *s1) · 713 unmodified lines | |||
| 714 | char buf[512]; | 714 | char buf[512]; |
| 715 | char *filename; | 715 | char *filename; |
| 716 | 716 | ||
| 717 | /* we might currently #include the <command-line> */ | ||
| 718 | filename = file->prev ? file->prev->filename : file->filename; | ||
| 719 | |||
| 717 | /* an elf symbol of type STT_FILE must be put so that STB_LOCAL | 720 | /* an elf symbol of type STT_FILE must be put so that STB_LOCAL |
| 718 | symbols can be safely used */ | 721 | symbols can be safely used */ |
| 719 | filename = file->prev ? file->prev->filename : file->filename; | ||
| 720 | put_elf_sym(symtab_section, 0, 0, | 722 | put_elf_sym(symtab_section, 0, 0, |
| 721 | ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, | 723 | ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, |
| 722 | SHN_ABS, filename); | 724 | SHN_ABS, filename); |
| @@ -48,10 +48,10 @@ struct sym_version { · 47 unmodified lines | |||
| 48 | #define SHF_DYNSYM 0x40000000 | 48 | #define SHF_DYNSYM 0x40000000 |
| 49 | 49 | ||
| 50 | #ifdef TCC_TARGET_PE | 50 | #ifdef TCC_TARGET_PE |
| 51 | static const int shf_RELRO = SHF_ALLOC; | 51 | #define shf_RELRO SHF_ALLOC |
| 52 | static const char rdata[] = ".rdata"; | 52 | static const char rdata[] = ".rdata"; |
| 53 | #else | 53 | #else |
| 54 | static const int shf_RELRO = SHF_ALLOC | SHF_WRITE; | 54 | #define shf_RELRO s1->shf_RELRO |
| 55 | static const char rdata[] = ".data.ro"; | 55 | static const char rdata[] = ".data.ro"; |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| @@ -60,6 +60,13 @@ static const char rdata[] = ".data.ro"; · 2 unmodified lines | |||
| 60 | ST_FUNC void tccelf_new(TCCState *s) | 60 | ST_FUNC void tccelf_new(TCCState *s) |
| 61 | { | 61 | { |
| 62 | TCCState *s1 = s; | 62 | TCCState *s1 = s; |
| 63 | |||
| 64 | #ifndef TCC_TARGET_PE | ||
| 65 | shf_RELRO = SHF_ALLOC; | ||
| 66 | if (s1->output_type != TCC_OUTPUT_MEMORY) | ||
| 67 | shf_RELRO |= SHF_WRITE; /* the ELF loader will set it to RO at runtime */ | ||
| 68 | #endif | ||
| 69 | |||
| 63 | /* no section zero */ | 70 | /* no section zero */ |
| 64 | dynarray_add(&s->sections, &s->nb_sections, NULL); | 71 | dynarray_add(&s->sections, &s->nb_sections, NULL); |
| 65 | 72 | ||
| @@ -76,7 +83,6 @@ ST_FUNC void tccelf_new(TCCState *s) · 10 unmodified lines | |||
| 76 | symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, | 83 | symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, |
| 77 | ".strtab", | 84 | ".strtab", |
| 78 | ".hashtab", SHF_PRIVATE); | 85 | ".hashtab", SHF_PRIVATE); |
| 79 | s->symtab = symtab_section; | ||
| 80 | 86 | ||
| 81 | /* private symbol table for dynamic symbols */ | 87 | /* private symbol table for dynamic symbols */ |
| 82 | s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM, | 88 | s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM, |
| @@ -99,9 +105,13 @@ ST_FUNC void tccelf_new(TCCState *s) · 16 unmodified lines | |||
| 99 | #endif | 105 | #endif |
| 100 | } | 106 | } |
| 101 | 107 | ||
| 102 | static void free_section(Section *s) | 108 | ST_FUNC void free_section(Section *s) |
| 103 | { | 109 | { |
| 110 | if (!s) | ||
| 111 | return; | ||
| 104 | tcc_free(s->data); | 112 | tcc_free(s->data); |
| 113 | s->data = NULL; | ||
| 114 | s->data_allocated = s->data_offset = 0; | ||
| 105 | } | 115 | } |
| 106 | 116 | ||
| 107 | ST_FUNC void tccelf_delete(TCCState *s1) | 117 | ST_FUNC void tccelf_delete(TCCState *s1) |
| @@ -127,6 +137,9 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 19 unmodified lines | |||
| 127 | free_section(s1->priv_sections[i]); | 137 | free_section(s1->priv_sections[i]); |
| 128 | dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections); | 138 | dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections); |
| 129 | 139 | ||
| 140 | tcc_free(s1->sym_attrs); | ||
| 141 | symtab_section = NULL; /* for tccrun.c:rt_printline() */ | ||
| 142 | |||
| 130 | /* free any loaded DLLs */ | 143 | /* free any loaded DLLs */ |
| 131 | #ifdef TCC_IS_NATIVE | 144 | #ifdef TCC_IS_NATIVE |
| 132 | for ( i = 0; i < s1->nb_loaded_dlls; i++) { | 145 | for ( i = 0; i < s1->nb_loaded_dlls; i++) { |
| @@ -141,9 +154,6 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 8 unmodified lines | |||
| 141 | #endif | 154 | #endif |
| 142 | /* free loaded dlls array */ | 155 | /* free loaded dlls array */ |
| 143 | dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); | 156 | dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); |
| 144 | tcc_free(s1->sym_attrs); | ||
| 145 | |||
| 146 | symtab_section = NULL; /* for tccrun.c:rt_printline() */ | ||
| 147 | } | 157 | } |
| 148 | 158 | ||
| 149 | /* save section data state */ | 159 | /* save section data state */ |
| @@ -261,32 +271,32 @@ ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh · 111 unmodified lines | |||
| 261 | return sec; | 271 | return sec; |
| 262 | } | 272 | } |
| 263 | 273 | ||
| 274 | ST_FUNC void init_symtab(Section *s) | ||
| 275 | { | ||
| 276 | int *ptr, nb_buckets = 1; | ||
| 277 | put_elf_str(s->link, ""); | ||
| 278 | section_ptr_add(s, sizeof (ElfW(Sym))); | ||
| 279 | ptr = section_ptr_add(s->hash, (2 + nb_buckets + 1) * sizeof(int)); | ||
| 280 | ptr[0] = nb_buckets; | ||
| 281 | ptr[1] = 1; | ||
| 282 | memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int)); | ||
| 283 | } | ||
| 284 | |||
| 264 | ST_FUNC Section *new_symtab(TCCState *s1, | 285 | ST_FUNC Section *new_symtab(TCCState *s1, |
| 265 | const char *symtab_name, int sh_type, int sh_flags, | 286 | const char *symtab_name, int sh_type, int sh_flags, |
| 266 | const char *strtab_name, | 287 | const char *strtab_name, |
| 267 | const char *hash_name, int hash_sh_flags) | 288 | const char *hash_name, int hash_sh_flags) |
| 268 | { | 289 | { |
| 269 | Section *symtab, *strtab, *hash; | 290 | Section *symtab, *strtab, *hash; |
| 270 | int *ptr, nb_buckets; | ||
| 271 | |||
| 272 | symtab = new_section(s1, symtab_name, sh_type, sh_flags); | 291 | symtab = new_section(s1, symtab_name, sh_type, sh_flags); |
| 273 | symtab->sh_entsize = sizeof(ElfW(Sym)); | 292 | symtab->sh_entsize = sizeof(ElfW(Sym)); |
| 274 | strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags); | 293 | strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags); |
| 275 | put_elf_str(strtab, ""); | ||
| 276 | symtab->link = strtab; | 294 | symtab->link = strtab; |
| 277 | put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL); | ||
| 278 | |||
| 279 | nb_buckets = 1; | ||
| 280 | |||
| 281 | hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags); | 295 | hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags); |
| 282 | hash->sh_entsize = sizeof(int); | 296 | hash->sh_entsize = sizeof(int); |
| 283 | symtab->hash = hash; | 297 | symtab->hash = hash; |
| 284 | hash->link = symtab; | 298 | hash->link = symtab; |
| 285 | 299 | init_symtab(symtab); | |
| 286 | ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int)); | ||
| 287 | ptr[0] = nb_buckets; | ||
| 288 | ptr[1] = 1; | ||
| 289 | memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int)); | ||
| 290 | return symtab; | 300 | return symtab; |
| 291 | } | 301 | } |
| 292 | 302 | ||
| @@ -1349,7 +1349,7 @@ static int pe_check_symbols(struct pe_info *pe) · 1348 unmodified lines | |||
| 1349 | sprintf(buffer, "IAT.%s", name); | 1349 | sprintf(buffer, "IAT.%s", name); |
| 1350 | is->iat_index = put_elf_sym( | 1350 | is->iat_index = put_elf_sym( |
| 1351 | symtab_section, 0, sizeof(DWORD), | 1351 | symtab_section, 0, sizeof(DWORD), |
| 1352 | ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT), | 1352 | ELFW(ST_INFO)(STB_LOCAL, STT_OBJECT), |
| 1353 | 0, SHN_UNDEF, buffer); | 1353 | 0, SHN_UNDEF, buffer); |
| 1354 | 1354 | ||
| 1355 | offset = text_section->data_offset; | 1355 | offset = text_section->data_offset; |
| @@ -1970,7 +1970,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 614 unmodified lines | |||
| 1970 | 1970 | ||
| 1971 | /* grab the startup code from libtcc1.a */ | 1971 | /* grab the startup code from libtcc1.a */ |
| 1972 | #ifdef TCC_IS_NATIVE | 1972 | #ifdef TCC_IS_NATIVE |
| 1973 | if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main) | 1973 | if (TCC_OUTPUT_MEMORY != s1->output_type || s1->run_main) |
| 1974 | #endif | 1974 | #endif |
| 1975 | set_global_sym(s1, start_symbol, NULL, 0); | 1975 | set_global_sym(s1, start_symbol, NULL, 0); |
| 1976 | 1976 | ||
| @@ -2078,7 +2078,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 101 unmodified lines | |||
| 2078 | #ifdef TCC_IS_NATIVE | 2078 | #ifdef TCC_IS_NATIVE |
| 2079 | pe.thunk = data_section; | 2079 | pe.thunk = data_section; |
| 2080 | pe_build_imports(&pe); | 2080 | pe_build_imports(&pe); |
| 2081 | s1->runtime_main = pe.start_symbol; | 2081 | s1->run_main = pe.start_symbol; |
| 2082 | #ifdef TCC_TARGET_X86_64 | 2082 | #ifdef TCC_TARGET_X86_64 |
| 2083 | s1->uw_pdata = find_section(s1, ".pdata"); | 2083 | s1->uw_pdata = find_section(s1, ".pdata"); |
| 2084 | #endif | 2084 | #endif |
| @@ -76,8 +76,8 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap); · 75 unmodified lines | |||
| 76 | # include <sys/mman.h> | 76 | # include <sys/mman.h> |
| 77 | #endif | 77 | #endif |
| 78 | 78 | ||
| 79 | static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length); | 79 | static int protect_pages(void *ptr, unsigned long length, int mode); |
| 80 | static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); | 80 | static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff); |
| 81 | 81 | ||
| 82 | #ifdef _WIN64 | 82 | #ifdef _WIN64 |
| 83 | static void *win64_add_function_table(TCCState *s1); | 83 | static void *win64_add_function_table(TCCState *s1); |
| @@ -88,13 +88,11 @@ static void win64_del_function_table(void *); · 4 unmodified lines | |||
| 88 | /* Do all relocations (needed before using tcc_get_symbol()) | 88 | /* Do all relocations (needed before using tcc_get_symbol()) |
| 89 | Returns -1 on error. */ | 89 | Returns -1 on error. */ |
| 90 | 90 | ||
| 91 | LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) | 91 | LIBTCCAPI int tcc_relocate(TCCState *s1) |
| 92 | { | 92 | { |
| 93 | void *ptr; | ||
| 93 | int size; | 94 | int size; |
| 94 | addr_t ptr_diff = 0; | 95 | unsigned ptr_diff = 0; |
| 95 | |||
| 96 | if (TCC_RELOCATE_AUTO != ptr) | ||
| 97 | return tcc_relocate_ex(s1, ptr, 0); | ||
| 98 | 96 | ||
| 99 | size = tcc_relocate_ex(s1, NULL, 0); | 97 | size = tcc_relocate_ex(s1, NULL, 0); |
| 100 | if (size < 0) | 98 | if (size < 0) |
| @@ -103,51 +101,45 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) · 2 unmodified lines | |||
| 103 | #ifdef HAVE_SELINUX | 101 | #ifdef HAVE_SELINUX |
| 104 | { | 102 | { |
| 105 | /* Using mmap instead of malloc */ | 103 | /* Using mmap instead of malloc */ |
| 106 | void *prx; | 104 | void *prw; |
| 107 | char tmpfname[] = "/tmp/.tccrunXXXXXX"; | 105 | char tmpfname[] = "/tmp/.tccrunXXXXXX"; |
| 108 | int fd = mkstemp(tmpfname); | 106 | int fd = mkstemp(tmpfname); |
| 109 | unlink(tmpfname); | 107 | unlink(tmpfname); |
| 110 | ftruncate(fd, size); | 108 | ftruncate(fd, size); |
| 111 | 109 | ||
| 112 | size = (size + (PAGESIZE-1)) & ~(PAGESIZE-1); | 110 | ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0); |
| 113 | ptr = mmap(NULL, size * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | 111 | /* mmap RW memory at fixed distance */ |
| 114 | /* mmap RX memory at a fixed distance */ | 112 | prw = mmap((char*)ptr + size, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0); |
| 115 | prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0); | ||
| 116 | close(fd); | 113 | close(fd); |
| 117 | if (ptr == MAP_FAILED || prx == MAP_FAILED) | 114 | if (ptr == MAP_FAILED || prw == MAP_FAILED) |
| 118 | return tcc_error_noabort("tccrun: could not map memory"); | 115 | return tcc_error_noabort("tccrun: could not map memory"); |
| 119 | ptr_diff = (char*)prx - (char*)ptr; | 116 | ptr_diff = (char*)prw - (char*)ptr; /* = size; */ |
| 120 | //printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff); | 117 | //printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff); |
| 121 | } | 118 | } |
| 122 | #else | 119 | #else |
| 123 | ptr = tcc_malloc(size); | 120 | ptr = tcc_malloc(size); |
| 124 | #endif | 121 | #endif |
| 125 | if (tcc_relocate_ex(s1, ptr, ptr_diff)) | 122 | s1->run_ptr = ptr; |
| 126 | return -1; | 123 | s1->run_size = size; |
| 127 | dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size); | 124 | tcc_relocate_ex(s1, ptr, ptr_diff); |
| 128 | dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr); | ||
| 129 | return 0; | 125 | return 0; |
| 130 | } | 126 | } |
| 131 | 127 | ||
| 132 | ST_FUNC void tcc_run_free(TCCState *s1) | 128 | ST_FUNC void tcc_run_free(TCCState *s1) |
| 133 | { | 129 | { |
| 134 | int i; | 130 | void *ptr = s1->run_ptr; |
| 131 | unsigned size = s1->run_size; | ||
| 135 | 132 | ||
| 136 | for (i = 0; i < s1->nb_runtime_mem; i += 2) { | ||
| 137 | unsigned size = (unsigned)(addr_t)s1->runtime_mem[i]; | ||
| 138 | void *ptr = s1->runtime_mem[i+1]; | ||
| 139 | #ifdef HAVE_SELINUX | 133 | #ifdef HAVE_SELINUX |
| 140 | munmap(ptr, size * 2); | 134 | munmap(ptr, size * 2); |
| 141 | #else | 135 | #else |
| 142 | /* unprotect memory to make it usable for malloc again */ | 136 | /* unprotect memory to make it usable for malloc again */ |
| 143 | set_pages_executable(s1, 2, ptr, size); | 137 | protect_pages(ptr, size, 2 /*rw*/); |
| 144 | #ifdef _WIN64 | 138 | #ifdef _WIN64 |
| 145 | win64_del_function_table(*(void**)ptr); | 139 | win64_del_function_table(s1->run_function_table); |
| 146 | #endif | 140 | #endif |
| 147 | tcc_free(ptr); | 141 | tcc_free(ptr); |
| 148 | #endif | 142 | #endif |
| 149 | } | ||
| 150 | tcc_free(s1->runtime_mem); | ||
| 151 | } | 143 | } |
| 152 | 144 | ||
| 153 | static void run_cdtors(TCCState *s1, const char *start, const char *end, | 145 | 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) · 44 unmodified lines | |||
| 198 | char **envp = environ; | 190 | char **envp = environ; |
| 199 | #endif | 191 | #endif |
| 200 | 192 | ||
| 201 | s1->runtime_main = s1->nostdlib ? "_start" : "main"; | 193 | s1->run_main = s1->nostdlib ? "_start" : "main"; |
| 202 | if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->runtime_main, 0, 1)) | 194 | if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->run_main, 0, 1)) |
| 203 | return 0; | 195 | return 0; |
| 204 | 196 | ||
| 205 | tcc_add_symbol(s1, "exit", rt_exit); | 197 | tcc_add_symbol(s1, "exit", rt_exit); |
| 206 | tcc_add_symbol(s1, "atexit", rt_atexit); | 198 | tcc_add_symbol(s1, "atexit", rt_atexit); |
| 207 | tcc_add_symbol(s1, "on_exit", rt_on_exit); | 199 | tcc_add_symbol(s1, "on_exit", rt_on_exit); |
| 208 | if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) | 200 | if (tcc_relocate(s1) < 0) |
| 209 | return -1; | 201 | return -1; |
| 210 | 202 | ||
| 211 | prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1); | 203 | prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1); |
| 212 | if ((addr_t)-1 == (addr_t)prog_main) | 204 | if ((addr_t)-1 == (addr_t)prog_main) |
| 213 | return -1; | 205 | return -1; |
| 214 | 206 | ||
| @@ -275,28 +267,62 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 60 unmodified lines | |||
| 275 | return ret; | 267 | return ret; |
| 276 | } | 268 | } |
| 277 | 269 | ||
| 278 | #define DEBUG_RUNMEN 0 | 270 | /* ------------------------------------------------------------- */ |
| 271 | /* remove all STB_LOCAL symbols */ | ||
| 272 | static void cleanup_symbols(TCCState *s1) | ||
| 273 | { | ||
| 274 | Section *s = s1->symtab; | ||
| 275 | int sym_index, end_sym = s->data_offset / sizeof (ElfSym); | ||
| 276 | /* reset symtab */ | ||
| 277 | s->data_offset = s->link->data_offset = s->hash->data_offset = 0; | ||
| 278 | init_symtab(s); | ||
| 279 | /* re-add symbols except STB_LOCAL */ | ||
| 280 | for (sym_index = 1; sym_index < end_sym; ++sym_index) { | ||
| 281 | ElfW(Sym) *sym = &((ElfW(Sym) *)s->data)[sym_index]; | ||
| 282 | const char *name = (char *)s->link->data + sym->st_name; | ||
| 283 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) | ||
| 284 | continue; | ||
| 285 | //printf("sym %s\n", name); | ||
| 286 | put_elf_sym(s, sym->st_value, sym->st_size, sym->st_info, sym->st_other, sym->st_shndx, name); | ||
| 287 | } | ||
| 288 | } | ||
| 279 | 289 | ||
| 280 | /* enable rx/ro/rw permissions */ | 290 | /* free all sections except symbols */ |
| 281 | #define CONFIG_RUNMEM_RO 1 | 291 | static void cleanup_sections(TCCState *s1) |
| 292 | { | ||
| 293 | struct { Section **secs; int nb_secs; } *p = (void*)&s1->sections; | ||
| 294 | int i, f = 2; | ||
| 295 | do { | ||
| 296 | for (i = --f; i < p->nb_secs; i++) { | ||
| 297 | Section *s = p->secs[i]; | ||
| 298 | if (s == s1->symtab || s == s1->symtab->link || s == s1->symtab->hash | ||
| 299 | || 0 == memcmp(s->name, ".stab", 5) | ||
| 300 | || 0 == memcmp(s->name, ".debug_", 7)) { | ||
| 301 | s->data = tcc_realloc(s->data, s->data_allocated = s->data_offset); | ||
| 302 | } else { | ||
| 303 | free_section(s); | ||
| 304 | if (0 == (s->sh_flags & SHF_ALLOC)) | ||
| 305 | tcc_free(s), p->secs[i] = NULL; | ||
| 306 | } | ||
| 307 | } | ||
| 308 | } while (++p, f); | ||
| 309 | } | ||
| 282 | 310 | ||
| 283 | #if CONFIG_RUNMEM_RO | 311 | /* ------------------------------------------------------------- */ |
| 284 | # define PAGE_ALIGN PAGESIZE | 312 | /* 0 = .text rwx other rw */ |
| 285 | #elif defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | 313 | /* 1 = .text rx .rdata r .data/.bss rw */ |
| 286 | /* To avoid that x86 processors would reload cached instructions | 314 | #ifndef CONFIG_RUNMEM_RO |
| 287 | each time when data is written in the near, we need to make | 315 | # define CONFIG_RUNMEM_RO 1 |
| 288 | sure that code and data do not share the same 64 byte unit */ | ||
| 289 | # define PAGE_ALIGN 64 | ||
| 290 | #else | ||
| 291 | # define PAGE_ALIGN 1 | ||
| 292 | #endif | 316 | #endif |
| 293 | 317 | ||
| 318 | #define DEBUG_RUNMEN 0 | ||
| 319 | |||
| 294 | /* relocate code. Return -1 on error, required size if ptr is NULL, | 320 | /* relocate code. Return -1 on error, required size if ptr is NULL, |
| 295 | otherwise copy code into buffer passed by the caller */ | 321 | otherwise copy code into buffer passed by the caller */ |
| 296 | static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) | 322 | static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff) |
| 297 | { | 323 | { |
| 298 | Section *s; | 324 | Section *s; |
| 299 | unsigned offset, length, align, max_align, i, k, f; | 325 | unsigned offset, length, align, i, k, f; |
| 300 | unsigned n, copy; | 326 | unsigned n, copy; |
| 301 | addr_t mem, addr; | 327 | addr_t mem, addr; |
| 302 | 328 | ||
| @@ -313,11 +339,15 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 10 unmodified lines | |||
| 313 | return -1; | 339 | return -1; |
| 314 | } | 340 | } |
| 315 | 341 | ||
| 316 | offset = max_align = 0, mem = (addr_t)ptr; | 342 | offset = copy = 0; |
| 317 | #ifdef _WIN64 | 343 | mem = (addr_t)ptr; |
| 318 | offset += sizeof (void*); /* space for function_table pointer */ | 344 | |
| 345 | #if DEBUG_RUNMEN | ||
| 346 | if (mem) | ||
| 347 | fprintf(stderr, "X: <base> %p len %5x\n", | ||
| 348 | ptr, s1->run_size); | ||
| 319 | #endif | 349 | #endif |
| 320 | copy = 0; | 350 | |
| 321 | redo: | 351 | redo: |
| 322 | for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */ | 352 | for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */ |
| 323 | n = 0; addr = 0; | 353 | n = 0; addr = 0; |
| @@ -329,79 +359,98 @@ redo: · 5 unmodified lines | |||
| 329 | if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR))) | 359 | if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR))) |
| 330 | continue; | 360 | continue; |
| 331 | length = s->data_offset; | 361 | length = s->data_offset; |
| 332 | if (copy) { | 362 | |
| 363 | if (copy) { /* final step: copy section data to memory */ | ||
| 364 | void *ptr; | ||
| 333 | if (addr == 0) | 365 | if (addr == 0) |
| 334 | addr = s->sh_addr; | 366 | addr = s->sh_addr; |
| 335 | n = (s->sh_addr - addr) + length; | 367 | n = (s->sh_addr - addr) + length; |
| 336 | ptr = (void*)s->sh_addr; | 368 | ptr = (void*)s->sh_addr; |
| 337 | if (k == 0) | 369 | if (k == 0) |
| 338 | ptr = (void*)(s->sh_addr - ptr_diff); | 370 | ptr = (void*)(s->sh_addr + ptr_diff); |
| 339 | if (NULL == s->data || s->sh_type == SHT_NOBITS) | 371 | if (NULL == s->data || s->sh_type == SHT_NOBITS) |
| 340 | memset(ptr, 0, length); | 372 | memset(ptr, 0, length); |
| 341 | else | 373 | else |
| 342 | memcpy(ptr, s->data, length); | 374 | memcpy(ptr, s->data, length); |
| 343 | #ifdef _WIN64 | 375 | #ifdef _WIN64 |
| 344 | if (s == s1->uw_pdata) | 376 | if (s == s1->uw_pdata) |
| 345 | *(void**)mem = win64_add_function_table(s1); | 377 | s1->run_function_table = win64_add_function_table(s1); |
| 346 | #endif | 378 | #endif |
| 347 | if (s->data) { | 379 | free_section(s); |
| 348 | tcc_free(s->data); | ||
| 349 | s->data = NULL; | ||
| 350 | s->data_allocated = 0; | ||
| 351 | } | ||
| 352 | s->data_offset = 0; | ||
| 353 | continue; | 380 | continue; |
| 354 | } | 381 | } |
| 382 | |||
| 355 | align = s->sh_addralign - 1; | 383 | align = s->sh_addralign - 1; |
| 356 | if (++n == 1 && align < (PAGE_ALIGN - 1)) | 384 | if (++n == 1) { |
| 357 | align = (PAGE_ALIGN - 1); | 385 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 |
| 358 | if (max_align < align) | 386 | /* To avoid that x86 processors would reload cached instructions |
| 359 | max_align = align; | 387 | each time when data is written in the near, we need to make |
| 360 | addr = k ? mem : mem + ptr_diff; | 388 | sure that code and data do not share the same 64 byte unit */ |
| 389 | if (align < 63) | ||
| 390 | align = 63; | ||
| 391 | #endif | ||
| 392 | /* start new page for different permissions */ | ||
| 393 | if (CONFIG_RUNMEM_RO || k < 2) | ||
| 394 | align = PAGESIZE - 1; | ||
| 395 | } | ||
| 396 | addr = k ? mem + ptr_diff : mem; | ||
| 361 | offset += -(addr + offset) & align; | 397 | offset += -(addr + offset) & align; |
| 362 | s->sh_addr = mem ? addr + offset : 0; | 398 | s->sh_addr = mem ? addr + offset : 0; |
| 363 | offset += length; | 399 | offset += length; |
| 364 | #if DEBUG_RUNMEN | 400 | #if DEBUG_RUNMEN |
| 365 | if (mem) | 401 | if (mem) |
| 366 | printf("%d: %-16s %p len %04x align %04x\n", | 402 | fprintf(stderr, "%d: %-16s %p len %5x align %04x\n", |
| 367 | k, s->name, (void*)s->sh_addr, length, align + 1); | 403 | k, s->name, (void*)s->sh_addr, length, align + 1); |
| 368 | #endif | 404 | #endif |
| 369 | } | 405 | } |
| 370 | if (copy) { /* set permissions */ | 406 | if (copy) { /* set permissions */ |
| 371 | if (k == 0 && ptr_diff) | 407 | if (n == 0) /* no data */ |
| 372 | continue; /* not with HAVE_SELINUX */ | 408 | continue; |
| 373 | f = k; | 409 | #ifdef HAVE_SELINUX |
| 374 | #if !CONFIG_RUNMEM_RO | 410 | if (k == 0) /* SHF_EXECINSTR has its own mapping */ |
| 375 | if (f != 0) | ||
| 376 | continue; | 411 | continue; |
| 377 | f = 3; /* change only SHF_EXECINSTR to rwx */ | ||
| 378 | #endif | 412 | #endif |
| 413 | f = k; | ||
| 414 | if (CONFIG_RUNMEM_RO == 0) { | ||
| 415 | if (f != 0) | ||
| 416 | continue; | ||
| 417 | f = 3; /* change only SHF_EXECINSTR to rwx */ | ||
| 418 | } | ||
| 379 | #if DEBUG_RUNMEN | 419 | #if DEBUG_RUNMEN |
| 380 | printf("protect %d %p %04x\n", f, (void*)addr, n); | 420 | fprintf(stderr, "protect %3s %p len %5x\n", |
| 421 | &"rx\0r \0rw\0rwx"[f*3], | ||
| 422 | (void*)addr, (unsigned)((n + PAGESIZE-1) & ~(PAGESIZE-1))); | ||
| 381 | #endif | 423 | #endif |
| 382 | if (n) { | 424 | if (protect_pages((void*)addr, n, f) < 0) |
| 383 | if (set_pages_executable(s1, f, (void*)addr, n)) | 425 | return tcc_error_noabort( |
| 384 | return -1; | 426 | "mprotect failed " |
| 385 | } | 427 | "(did you mean to configure --with-selinux?)"); |
| 386 | } | 428 | } |
| 387 | } | 429 | } |
| 388 | 430 | ||
| 389 | if (copy) | 431 | if (copy) { |
| 432 | /* remove local symbols and free sections except symtab */ | ||
| 433 | cleanup_symbols(s1); | ||
| 434 | cleanup_sections(s1); | ||
| 390 | return 0; | 435 | return 0; |
| 436 | } | ||
| 391 | 437 | ||
| 392 | /* relocate symbols */ | 438 | /* relocate symbols */ |
| 393 | relocate_syms(s1, s1->symtab, !(s1->nostdlib)); | 439 | relocate_syms(s1, s1->symtab, !(s1->nostdlib)); |
| 394 | if (s1->nb_errors) | 440 | if (s1->nb_errors) |
| 395 | return -1; | 441 | return -1; |
| 396 | if (0 == mem) | ||
| 397 | return offset + max_align; | ||
| 398 | 442 | ||
| 399 | #ifdef TCC_TARGET_PE | 443 | if (0 == mem) { |
| 400 | s1->pe_imagebase = mem; | 444 | offset = (offset + (PAGESIZE-1)) & ~(PAGESIZE-1); |
| 445 | #ifndef HAVE_SELINUX | ||
| 446 | offset += PAGESIZE; /* extra space to align malloc memory start */ | ||
| 401 | #endif | 447 | #endif |
| 448 | return offset; | ||
| 449 | } | ||
| 402 | 450 | ||
| 403 | /* relocate sections */ | 451 | #ifdef TCC_TARGET_PE |
| 404 | #ifndef TCC_TARGET_PE | 452 | s1->pe_imagebase = mem; |
| 453 | #else | ||
| 405 | relocate_plt(s1); | 454 | relocate_plt(s1); |
| 406 | #endif | 455 | #endif |
| 407 | relocate_sections(s1); | 456 | relocate_sections(s1); |
| @@ -412,7 +461,7 @@ redo: · 4 unmodified lines | |||
| 412 | /* ------------------------------------------------------------- */ | 461 | /* ------------------------------------------------------------- */ |
| 413 | /* allow to run code in memory */ | 462 | /* allow to run code in memory */ |
| 414 | 463 | ||
| 415 | static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length) | 464 | static int protect_pages(void *ptr, unsigned long length, int mode) |
| 416 | { | 465 | { |
| 417 | #ifdef _WIN32 | 466 | #ifdef _WIN32 |
| 418 | static const unsigned char protect[] = { | 467 | static const unsigned char protect[] = { |
| @@ -437,7 +486,7 @@ static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long · 18 unmodified lines | |||
| 437 | end = (addr_t)ptr + length; | 486 | end = (addr_t)ptr + length; |
| 438 | end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); | 487 | end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); |
| 439 | if (mprotect((void *)start, end - start, protect[mode])) | 488 | if (mprotect((void *)start, end - start, protect[mode])) |
| 440 | return tcc_error_noabort("mprotect failed: did you mean to configure --with-selinux?"); | 489 | return -1; |
| 441 | /* XXX: BSD sometimes dump core with bad system call */ | 490 | /* XXX: BSD sometimes dump core with bad system call */ |
| 442 | # if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64 | 491 | # if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64 |
| 443 | if (mode == 0 || mode == 3) { | 492 | if (mode == 0 || mode == 3) { |
| @@ -472,6 +521,7 @@ static void win64_del_function_table(void *p) · 28 unmodified lines | |||
| 472 | } | 521 | } |
| 473 | } | 522 | } |
| 474 | #endif | 523 | #endif |
| 524 | |||
| 475 | #endif //ndef CONFIG_TCC_BACKTRACE_ONLY | 525 | #endif //ndef CONFIG_TCC_BACKTRACE_ONLY |
| 476 | /* ------------------------------------------------------------- */ | 526 | /* ------------------------------------------------------------- */ |
| 477 | #ifdef CONFIG_TCC_BACKTRACE | 527 | #ifdef CONFIG_TCC_BACKTRACE |
| @@ -1,4 +1,3 @@ | |||
| 1 | #include <unistd.h> | ||
| 2 | #include <libtcc.h> | 1 | #include <libtcc.h> |
| 3 | #include <stdlib.h> | 2 | #include <stdlib.h> |
| 4 | #include <stdio.h> | 3 | #include <stdio.h> |
| @@ -53,7 +52,7 @@ static int run_callback(const char *src, callback_type callback) { · 48 unmodified lines | |||
| 53 | return -1; | 52 | return -1; |
| 54 | if (tcc_compile_string(s, src) == -1) | 53 | if (tcc_compile_string(s, src) == -1) |
| 55 | return -1; | 54 | return -1; |
| 56 | if (tcc_relocate(s, TCC_RELOCATE_AUTO) == -1) | 55 | if (tcc_relocate(s) == -1) |
| 57 | return -1; | 56 | return -1; |
| 58 | 57 | ||
| 59 | ptr = tcc_get_symbol(s, "f"); | 58 | ptr = tcc_get_symbol(s, "f"); |
| @@ -6,8 +6,6 @@ · 5 unmodified lines | |||
| 6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
| 7 | #include <stdio.h> | 7 | #include <stdio.h> |
| 8 | #include <string.h> | 8 | #include <string.h> |
| 9 | #include <assert.h> | ||
| 10 | |||
| 11 | #include "libtcc.h" | 9 | #include "libtcc.h" |
| 12 | 10 | ||
| 13 | void handle_error(void *opaque, const char *msg) | 11 | void handle_error(void *opaque, const char *msg) |
| @@ -59,14 +57,9 @@ int main(int argc, char **argv) · 45 unmodified lines | |||
| 59 | exit(1); | 57 | exit(1); |
| 60 | } | 58 | } |
| 61 | 59 | ||
| 62 | assert(tcc_get_error_func(s) == NULL); | 60 | /* set custom error/warning printer */ |
| 63 | assert(tcc_get_error_opaque(s) == NULL); | ||
| 64 | |||
| 65 | tcc_set_error_func(s, stderr, handle_error); | 61 | tcc_set_error_func(s, stderr, handle_error); |
| 66 | 62 | ||
| 67 | assert(tcc_get_error_func(s) == handle_error); | ||
| 68 | assert(tcc_get_error_opaque(s) == stderr); | ||
| 69 | |||
| 70 | /* if tcclib.h and libtcc1.a are not installed, where can we find them */ | 63 | /* if tcclib.h and libtcc1.a are not installed, where can we find them */ |
| 71 | for (i = 1; i < argc; ++i) { | 64 | for (i = 1; i < argc; ++i) { |
| 72 | char *a = argv[i]; | 65 | char *a = argv[i]; |
| @@ -92,7 +85,7 @@ int main(int argc, char **argv) · 19 unmodified lines | |||
| 92 | tcc_add_symbol(s, "hello", hello); | 85 | tcc_add_symbol(s, "hello", hello); |
| 93 | 86 | ||
| 94 | /* relocate the code */ | 87 | /* relocate the code */ |
| 95 | if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) | 88 | if (tcc_relocate(s) < 0) |
| 96 | return 1; | 89 | return 1; |
| 97 | 90 | ||
| 98 | /* get entry symbol */ | 91 | /* get entry symbol */ |
| @@ -128,7 +128,7 @@ void *reloc_state(TCCState *s, const char *entry) · 127 unmodified lines | |||
| 128 | { | 128 | { |
| 129 | void *func; | 129 | void *func; |
| 130 | tcc_add_symbol(s, "add", add); | 130 | tcc_add_symbol(s, "add", add); |
| 131 | if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) { | 131 | if (tcc_relocate(s) < 0) { |
| 132 | fprintf(stderr, __FILE__ ": could not relocate tcc state.\n"); | 132 | fprintf(stderr, __FILE__ ": could not relocate tcc state.\n"); |
| 133 | return NULL; | 133 | return NULL; |
| 134 | } | 134 | } |