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