History

LIBTCCAPI tcc_relocate(s) : REMOVED 2nd argument

removed second argument for tcc_relocate(s). previous 'TCC_RELOCATE_AUTO' is now default and only behavior. Rationale: In the past, the option to compile into memory provided by the user was introduced because only one TCCState could exist at a time. This is no longer a limitation. As such it is also possible now to keep any number of compiled code snippets around together with their state in order to run them as needed. - Also - LIBTCCAPI tcc_get_error_func/opaque() removed - tccrun/SELINUX: switch rx/rw mappings such that rx comes first (risc64-link.c:relocate_plt() does not like got < plt) - tcc_relocate_ex(): free local symbols and obsolete sections to reduce memory after tcc_relocate()

grischka committed 2 years ago

Commit b671fc01 parent a0ab99111 files · +222 −182Browse files

Unified · Split

11 files
  1. configure +6 −8
  2. libtcc.c +15 −21
  3. libtcc.h +14 −25
  4. tcc.h +11 −6
  5. tccdbg.c +3 −1
  6. tccelf.c +29 −19
  7. tccpe.c +3 −3
  8. tccrun.c +137 −87
  9. tests/abitest.c +1 −2
  10. tests/libtcc_test.c +2 −9
  11. tests/libtcc_test_mt.c +1 −1
configure+6−8
@@ -56,6 +56,7 @@ build_cross= · 55 unmodified lines
56# use CC/AR from environment when set56# use CC/AR from environment when set
57test -n "$CC" && cc="$CC"57test -n "$CC" && cc="$CC"
58test -n "$AR" && ar="$AR"58test -n "$AR" && ar="$AR"
59test -n "CFLAGS" && CFLAGS="-Wall -O2"
59 60
60# find source path61# find source path
61source_path=${0%configure}62source_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"
400fi401fi
401 402
402# set default CFLAGS
403default CFLAGS "-Wall -O2"
404
405if test "$mingw32" = "yes" -a "$cc_name" = "gcc"; then
406 # avoid mingw dependencies such as 'libgcc_s_dw2-1.dll'
407 default LDFLAGS "-static"
408fi
409
410if test x"$show_help" = "xyes" ; then403if test x"$show_help" = "xyes" ; then
411 show_help404 show_help
412fi405fi
@@ -464,6 +457,11 @@ if test "$bigendian" = "yes" ; then · 51 unmodified lines
464 confvars="$confvars BIGENDIAN"457 confvars="$confvars BIGENDIAN"
465fi458fi
466 459
460if test "$mingw32" = "yes" -a "$cc_name" = "gcc"; then
461 # avoid mingw dependencies such as 'libgcc_s_dw2-1.dll'
462 default LDFLAGS "-static"
463fi
464
467if test "$cpu" = "arm"; then465if test "$cpu" = "arm"; then
468 if test "${triplet%eabihf}" != "$triplet" ; then466 if test "${triplet%eabihf}" != "$triplet" ; then
469 confvars="$confvars arm_eabihf arm_vfp"467 confvars="$confvars arm_eabihf arm_vfp"
libtcc.c+15−21
@@ -249,7 +249,7 @@ ST_FUNC char *tcc_load_text(int fd) · 248 unmodified lines
249#undef free249#undef free
250#undef realloc250#undef realloc
251 251
252static void *default_reallocator(void *ptr, size_t size)252static 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 */
278static TCCReallocFunc reallocator = default_reallocator;278static void *(*reallocator)(void*, unsigned long) = default_reallocator;
279 279
280LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc)280LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *realloc)
281{281{
282 reallocator = realloc;282 reallocator = realloc;
283}283}
284 284
285LIBTCCAPI 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_free286#undef tcc_free
292#undef tcc_malloc287#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
669LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func)664LIBTCCAPI 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
675LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s)
676{
677 return s->error_func;
678}
679
680LIBTCCAPI 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 */
686PUB_FUNC int _tcc_error_noabort(const char *fmt, ...)671PUB_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_DEBUG2232#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#endif2243#endif
2250}2244}
libtcc.h+14−25
@@ -9,18 +9,15 @@ · 8 unmodified lines
9extern "C" {9extern "C" {
10#endif10#endif
11 11
12struct TCCState;12/*****************************/
13 13/* set custom allocator for all allocations (optional) */
14typedef struct TCCState TCCState;
15 14
16typedef void (*TCCErrorFunc)(void *opaque, const char *msg);15typedef void *TCCReallocFunc(void *ptr, unsigned long size);
17typedef void *(*TCCReallocFunc)(void *ptr, size_t size);16LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *my_realloc);
18 17
19/* to be used for all allocation (including tcc_new()), otherwise malloc(), realloc(), free() */18/*****************************/
20LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc);
21 19
22/* return current allocator */20typedef struct TCCState TCCState;
23LIBTCCAPI TCCReallocFunc tcc_get_realloc();
24 21
25/* create a new TCC compilation context */22/* create a new TCC compilation context */
26LIBTCCAPI TCCState *tcc_new(void);23LIBTCCAPI 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 */
32LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);29LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
33 30
34/* set error/warning display callback */31/* set error/warning callback (optional) */
35LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func);32typedef void TCCErrorFunc(void *opaque, const char *msg);
36 33LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func);
37/* return error/warning callback */
38LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s);
39
40/* return error/warning callback opaque pointer */
41LIBTCCAPI 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) */
44LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);36LIBTCCAPI 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. */
68LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);60LIBTCCAPI 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
96LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);91LIBTCCAPI 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()) */
99LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);94LIBTCCAPI 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 */
108LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);97LIBTCCAPI 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()' */
111LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,100LIBTCCAPI 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
tcc.h+11−6
@@ -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#endif924#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# endif972# endif
973#else
974 unsigned shf_RELRO; /* section flags for RELRO sections */
975#endif975#endif
976 976
977#if defined TCC_TARGET_MACHO977#if defined TCC_TARGET_MACHO
@@ -991,9 +991,12 @@ struct TCCState { · 13 unmodified lines
991#endif991#endif
992 992
993#ifdef TCC_IS_NATIVE993#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#endif1000#endif
998 1001
999#ifdef CONFIG_TCC_BACKTRACE1002#ifdef CONFIG_TCC_BACKTRACE
@@ -1542,7 +1545,9 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size); · 542 unmodified lines
1542ST_FUNC size_t section_add(Section *sec, addr_t size, int align);1545ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
1543ST_FUNC void *section_ptr_add(Section *sec, addr_t size);1546ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
1544ST_FUNC Section *find_section(TCCState *s1, const char *name);1547ST_FUNC Section *find_section(TCCState *s1, const char *name);
1548ST_FUNC void free_section(Section *s);
1545ST_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);1549ST_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);
1550ST_FUNC void init_symtab(Section *s);
1546 1551
1547ST_FUNC int put_elf_str(Section *s, const char *sym);1552ST_FUNC int put_elf_str(Section *s, const char *sym);
1548ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);1553ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
tccdbg.c+3−1
@@ -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_LOCAL720 /* 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);
tccelf.c+29−19
@@ -48,10 +48,10 @@ struct sym_version { · 47 unmodified lines
48#define SHF_DYNSYM 0x4000000048#define SHF_DYNSYM 0x40000000
49 49
50#ifdef TCC_TARGET_PE50#ifdef TCC_TARGET_PE
51static const int shf_RELRO = SHF_ALLOC;51#define shf_RELRO SHF_ALLOC
52static const char rdata[] = ".rdata";52static const char rdata[] = ".rdata";
53#else53#else
54static const int shf_RELRO = SHF_ALLOC | SHF_WRITE;54#define shf_RELRO s1->shf_RELRO
55static const char rdata[] = ".data.ro";55static const char rdata[] = ".data.ro";
56#endif56#endif
57 57
@@ -60,6 +60,13 @@ static const char rdata[] = ".data.ro"; · 2 unmodified lines
60ST_FUNC void tccelf_new(TCCState *s)60ST_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#endif105#endif
100}106}
101 107
102static void free_section(Section *s)108ST_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
107ST_FUNC void tccelf_delete(TCCState *s1)117ST_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_NATIVE144#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#endif154#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
274ST_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
264ST_FUNC Section *new_symtab(TCCState *s1,285ST_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
tccpe.c+3−3
@@ -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_NATIVE1972#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#endif1974#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_NATIVE2078#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_642082#ifdef TCC_TARGET_X86_64
2083 s1->uw_pdata = find_section(s1, ".pdata");2083 s1->uw_pdata = find_section(s1, ".pdata");
2084#endif2084#endif
tccrun.c+137−87
@@ -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#endif77#endif
78 78
79static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length);79static int protect_pages(void *ptr, unsigned long length, int mode);
80static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff);80static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff);
81 81
82#ifdef _WIN6482#ifdef _WIN64
83static void *win64_add_function_table(TCCState *s1);83static 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
91LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)91LIBTCCAPI 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_SELINUX101#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#else119#else
123 ptr = tcc_malloc(size);120 ptr = tcc_malloc(size);
124#endif121#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
132ST_FUNC void tcc_run_free(TCCState *s1)128ST_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_SELINUX133#ifdef HAVE_SELINUX
140 munmap(ptr, size * 2);134 munmap(ptr, size * 2);
141#else135#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 _WIN64138#ifdef _WIN64
145 win64_del_function_table(*(void**)ptr);139 win64_del_function_table(s1->run_function_table);
146#endif140#endif
147 tcc_free(ptr);141 tcc_free(ptr);
148#endif142#endif
149 }
150 tcc_free(s1->runtime_mem);
151}143}
152 144
153static void run_cdtors(TCCState *s1, const char *start, const char *end,145static 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#endif191#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 0270/* ------------------------------------------------------------- */
271/* remove all STB_LOCAL symbols */
272static 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 1291static 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_RO311/* ------------------------------------------------------------- */
284# define PAGE_ALIGN PAGESIZE312/* 0 = .text rwx other rw */
285#elif defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64313/* 1 = .text rx .rdata r .data/.bss rw */
286/* To avoid that x86 processors would reload cached instructions314#ifndef CONFIG_RUNMEM_RO
287 each time when data is written in the near, we need to make315# 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#endif316#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 */
296static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)322static 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 _WIN64343 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#endif349#endif
320 copy = 0;350
321redo:351redo:
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 else373 else
342 memcpy(ptr, s->data, length);374 memcpy(ptr, s->data, length);
343#ifdef _WIN64375#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#endif378#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_RUNMEN400#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#endif404#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_RO410 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#endif412#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_RUNMEN419#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#endif423#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_PE443 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#endif447#endif
448 return offset;
449 }
402 450
403 /* relocate sections */451#ifdef TCC_TARGET_PE
404#ifndef TCC_TARGET_PE452 s1->pe_imagebase = mem;
453#else
405 relocate_plt(s1);454 relocate_plt(s1);
406#endif455#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
415static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length)464static int protect_pages(void *ptr, unsigned long length, int mode)
416{465{
417#ifdef _WIN32466#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_ARM64491# 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#endif523#endif
524
475#endif //ndef CONFIG_TCC_BACKTRACE_ONLY525#endif //ndef CONFIG_TCC_BACKTRACE_ONLY
476/* ------------------------------------------------------------- */526/* ------------------------------------------------------------- */
477#ifdef CONFIG_TCC_BACKTRACE527#ifdef CONFIG_TCC_BACKTRACE
tests/abitest.c+1−2
@@ -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");
tests/libtcc_test.c+2−9
@@ -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
13void handle_error(void *opaque, const char *msg)11void 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 */
tests/libtcc_test_mt.c+1−1
@@ -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 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t