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
5656 # use CC/AR from environment when set
5757 test -n "$CC" && cc="$CC"
5858 test -n "$AR" && ar="$AR"
59+test -n "CFLAGS" && CFLAGS="-Wall -O2"
5960
6061 # find source path
6162 source_path=${0%configure}
@@ -399,14 +400,6 @@ if test "$mingw32" = "no"; then · 337 unmodified lines
399400 default infodir "${sharedir}/info"
400401 fi
401402
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−
410403 if test x"$show_help" = "xyes" ; then
411404 show_help
412405 fi
@@ -464,6 +457,11 @@ if test "$bigendian" = "yes" ; then · 51 unmodified lines
464457 confvars="$confvars BIGENDIAN"
465458 fi
466459
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+
467465 if test "$cpu" = "arm"; then
468466 if test "${triplet%eabihf}" != "$triplet" ; then
469467 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
249249 #undef free
250250 #undef realloc
251251
252−static void *default_reallocator(void *ptr, size_t size)
252+static void *default_reallocator(void *ptr, unsigned long size)
253253 {
254254 void *ptr1;
255255 if (size == 0) {
@@ -275,18 +275,13 @@ static void libc_free(void *ptr) · 19 unmodified lines
275275 #define realloc(p, s) use_tcc_realloc(p, s)
276276
277277 /* 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;
279279
280−LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc)
280+LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *realloc)
281281 {
282282 reallocator = realloc;
283283 }
284284
285−LIBTCCAPI TCCReallocFunc tcc_get_realloc()
286−{
287− return reallocator;
288−}
289−
290285 /* in case MEM_DEBUG is #defined */
291286 #undef tcc_free
292287 #undef tcc_malloc
@@ -646,7 +641,7 @@ static void error1(int mode, const char *fmt, va_list ap) · 353 unmodified lines
646641 }
647642 cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
648643 cstr_vprintf(&cs, fmt, ap);
649− if (!s1 || !s1->error_func) {
644+ if (!s1->error_func) {
650645 /* default case: stderr */
651646 if (s1 && s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout)
652647 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
666661 }
667662 }
668663
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)
670665 {
671666 s->error_opaque = error_opaque;
672667 s->error_func = error_func;
673668 }
674669
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−
685670 /* error without aborting current compilation */
686671 PUB_FUNC int _tcc_error_noabort(const char *fmt, ...)
687672 {
@@ -2245,6 +2230,15 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) · 1557 unmodified lines
22452230 s1->total_output[3]
22462231 );
22472232 #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);
22492243 #endif
22502244 }
libtcc.h+14−25
@@ -9,18 +9,15 @@ · 8 unmodified lines
99 extern "C" {
1010 #endif
1111
12−struct TCCState;
13−
14−typedef struct TCCState TCCState;
12+/*****************************/
13+/* set custom allocator for all allocations (optional) */
1514
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);
1817
19−/* to be used for all allocation (including tcc_new()), otherwise malloc(), realloc(), free() */
20−LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc);
18+/*****************************/
2119
22−/* return current allocator */
23−LIBTCCAPI TCCReallocFunc tcc_get_realloc();
20+typedef struct TCCState TCCState;
2421
2522 /* create a new TCC compilation context */
2623 LIBTCCAPI TCCState *tcc_new(void);
@@ -31,14 +28,9 @@ LIBTCCAPI void tcc_delete(TCCState *s); · 4 unmodified lines
3128 /* set CONFIG_TCCDIR at runtime */
3229 LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
3330
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);
4234
4335 /* set options as from command line (multiple supported) */
4436 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
6759 /* compile a string containing a C source. Return -1 if error. */
6860 LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
6961
62+/* Tip: to have more specific errors/warnings from tcc_compile_string(),
63+ you can prefix the string with "#line <num> \"<filename>\"\n" */
64+
7065 /*****************************/
7166 /* linking commands */
7267
@@ -96,18 +91,12 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename); · 23 unmodified lines
9691 LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
9792
9893 /* 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);
10695
10796 /* return symbol value or NULL if not found */
10897 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
10998
110−/* return symbol value or NULL if not found */
99+/* list all (global) symbols and their values via 'symbol_cb()' */
111100 LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
112101 void (*symbol_cb)(void *ctx, const char *name, const void *val));
113102
tcc.h+11−6
@@ -923,13 +923,11 @@ struct TCCState { · 922 unmodified lines
923923 Section *lbounds_section; /* contains local data bound description */
924924 #endif
925925 /* symbol section */
926− Section *symtab_section;
926+ union { Section *symtab_section, *symtab; }; /* historical alias */
927927 /* temporary dynamic symbol sections (for dll loading) */
928928 Section *dynsymtab_section;
929929 /* exported dynamic symbol section */
930930 Section *dynsym;
931− /* copy of the global symtab_section variable */
932− Section *symtab;
933931 /* got & plt handling */
934932 Section *got, *plt;
935933 /* debug sections */
@@ -972,6 +970,8 @@ struct TCCState { · 36 unmodified lines
972970 int uw_sym;
973971 unsigned uw_offs;
974972 # endif
973+#else
974+ unsigned shf_RELRO; /* section flags for RELRO sections */
975975 #endif
976976
977977 #if defined TCC_TARGET_MACHO
@@ -991,9 +991,12 @@ struct TCCState { · 13 unmodified lines
991991 #endif
992992
993993 #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
9971000 #endif
9981001
9991002 #ifdef CONFIG_TCC_BACKTRACE
@@ -1542,7 +1545,9 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size); · 542 unmodified lines
15421545 ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
15431546 ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
15441547 ST_FUNC Section *find_section(TCCState *s1, const char *name);
1548+ST_FUNC void free_section(Section *s);
15451549 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);
15461551
15471552 ST_FUNC int put_elf_str(Section *s, const char *sym);
15481553 ST_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
714714 char buf[512];
715715 char *filename;
716716
717+ /* we might currently #include the <command-line> */
718+ filename = file->prev ? file->prev->filename : file->filename;
719+
717720 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
718721 symbols can be safely used */
719− filename = file->prev ? file->prev->filename : file->filename;
720722 put_elf_sym(symtab_section, 0, 0,
721723 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
722724 SHN_ABS, filename);
tccelf.c+29−19
@@ -48,10 +48,10 @@ struct sym_version { · 47 unmodified lines
4848 #define SHF_DYNSYM 0x40000000
4949
5050 #ifdef TCC_TARGET_PE
51−static const int shf_RELRO = SHF_ALLOC;
51+#define shf_RELRO SHF_ALLOC
5252 static const char rdata[] = ".rdata";
5353 #else
54−static const int shf_RELRO = SHF_ALLOC | SHF_WRITE;
54+#define shf_RELRO s1->shf_RELRO
5555 static const char rdata[] = ".data.ro";
5656 #endif
5757
@@ -60,6 +60,13 @@ static const char rdata[] = ".data.ro"; · 2 unmodified lines
6060 ST_FUNC void tccelf_new(TCCState *s)
6161 {
6262 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+
6370 /* no section zero */
6471 dynarray_add(&s->sections, &s->nb_sections, NULL);
6572
@@ -76,7 +83,6 @@ ST_FUNC void tccelf_new(TCCState *s) · 10 unmodified lines
7683 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
7784 ".strtab",
7885 ".hashtab", SHF_PRIVATE);
79− s->symtab = symtab_section;
8086
8187 /* private symbol table for dynamic symbols */
8288 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
99105 #endif
100106 }
101107
102−static void free_section(Section *s)
108+ST_FUNC void free_section(Section *s)
103109 {
110+ if (!s)
111+ return;
104112 tcc_free(s->data);
113+ s->data = NULL;
114+ s->data_allocated = s->data_offset = 0;
105115 }
106116
107117 ST_FUNC void tccelf_delete(TCCState *s1)
@@ -127,6 +137,9 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 19 unmodified lines
127137 free_section(s1->priv_sections[i]);
128138 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
129139
140+ tcc_free(s1->sym_attrs);
141+ symtab_section = NULL; /* for tccrun.c:rt_printline() */
142+
130143 /* free any loaded DLLs */
131144 #ifdef TCC_IS_NATIVE
132145 for ( i = 0; i < s1->nb_loaded_dlls; i++) {
@@ -141,9 +154,6 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 8 unmodified lines
141154 #endif
142155 /* free loaded dlls array */
143156 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() */
147157 }
148158
149159 /* 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
261271 return sec;
262272 }
263273
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+
264285 ST_FUNC Section *new_symtab(TCCState *s1,
265286 const char *symtab_name, int sh_type, int sh_flags,
266287 const char *strtab_name,
267288 const char *hash_name, int hash_sh_flags)
268289 {
269290 Section *symtab, *strtab, *hash;
270− int *ptr, nb_buckets;
271−
272291 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
273292 symtab->sh_entsize = sizeof(ElfW(Sym));
274293 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
275− put_elf_str(strtab, "");
276294 symtab->link = strtab;
277− put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
278−
279− nb_buckets = 1;
280−
281295 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
282296 hash->sh_entsize = sizeof(int);
283297 symtab->hash = hash;
284298 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);
290300 return symtab;
291301 }
292302
tccpe.c+3−3
@@ -1349,7 +1349,7 @@ static int pe_check_symbols(struct pe_info *pe) · 1348 unmodified lines
13491349 sprintf(buffer, "IAT.%s", name);
13501350 is->iat_index = put_elf_sym(
13511351 symtab_section, 0, sizeof(DWORD),
1352− ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1352+ ELFW(ST_INFO)(STB_LOCAL, STT_OBJECT),
13531353 0, SHN_UNDEF, buffer);
13541354
13551355 offset = text_section->data_offset;
@@ -1970,7 +1970,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 614 unmodified lines
19701970
19711971 /* grab the startup code from libtcc1.a */
19721972 #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)
19741974 #endif
19751975 set_global_sym(s1, start_symbol, NULL, 0);
19761976
@@ -2078,7 +2078,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 101 unmodified lines
20782078 #ifdef TCC_IS_NATIVE
20792079 pe.thunk = data_section;
20802080 pe_build_imports(&pe);
2081− s1->runtime_main = pe.start_symbol;
2081+ s1->run_main = pe.start_symbol;
20822082 #ifdef TCC_TARGET_X86_64
20832083 s1->uw_pdata = find_section(s1, ".pdata");
20842084 #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
7676 # include <sys/mman.h>
7777 #endif
7878
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);
8181
8282 #ifdef _WIN64
8383 static void *win64_add_function_table(TCCState *s1);
@@ -88,13 +88,11 @@ static void win64_del_function_table(void *); · 4 unmodified lines
8888 /* Do all relocations (needed before using tcc_get_symbol())
8989 Returns -1 on error. */
9090
91−LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
91+LIBTCCAPI int tcc_relocate(TCCState *s1)
9292 {
93+ void *ptr;
9394 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;
9896
9997 size = tcc_relocate_ex(s1, NULL, 0);
10098 if (size < 0)
@@ -103,51 +101,45 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) · 2 unmodified lines
103101 #ifdef HAVE_SELINUX
104102 {
105103 /* Using mmap instead of malloc */
106− void *prx;
104+ void *prw;
107105 char tmpfname[] = "/tmp/.tccrunXXXXXX";
108106 int fd = mkstemp(tmpfname);
109107 unlink(tmpfname);
110108 ftruncate(fd, size);
111109
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);
116113 close(fd);
117− if (ptr == MAP_FAILED || prx == MAP_FAILED)
114+ if (ptr == MAP_FAILED || prw == MAP_FAILED)
118115 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);
121118 }
122119 #else
123120 ptr = tcc_malloc(size);
124121 #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);
129125 return 0;
130126 }
131127
132128 ST_FUNC void tcc_run_free(TCCState *s1)
133129 {
134− int i;
130+ void *ptr = s1->run_ptr;
131+ unsigned size = s1->run_size;
135132
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];
139133 #ifdef HAVE_SELINUX
140− munmap(ptr, size * 2);
134+ munmap(ptr, size * 2);
141135 #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*/);
144138 #ifdef _WIN64
145− win64_del_function_table(*(void**)ptr);
139+ win64_del_function_table(s1->run_function_table);
146140 #endif
147− tcc_free(ptr);
141+ tcc_free(ptr);
148142 #endif
149− }
150− tcc_free(s1->runtime_mem);
151143 }
152144
153145 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
198190 char **envp = environ;
199191 #endif
200192
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))
203195 return 0;
204196
205197 tcc_add_symbol(s1, "exit", rt_exit);
206198 tcc_add_symbol(s1, "atexit", rt_atexit);
207199 tcc_add_symbol(s1, "on_exit", rt_on_exit);
208− if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
200+ if (tcc_relocate(s1) < 0)
209201 return -1;
210202
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);
212204 if ((addr_t)-1 == (addr_t)prog_main)
213205 return -1;
214206
@@ -275,28 +267,62 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 60 unmodified lines
275267 return ret;
276268 }
277269
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+}
279289
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+}
282310
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
292316 #endif
293317
318+#define DEBUG_RUNMEN 0
319+
294320 /* relocate code. Return -1 on error, required size if ptr is NULL,
295321 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)
297323 {
298324 Section *s;
299− unsigned offset, length, align, max_align, i, k, f;
325+ unsigned offset, length, align, i, k, f;
300326 unsigned n, copy;
301327 addr_t mem, addr;
302328
@@ -313,11 +339,15 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 10 unmodified lines
313339 return -1;
314340 }
315341
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);
319349 #endif
320− copy = 0;
350+
321351 redo:
322352 for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
323353 n = 0; addr = 0;
@@ -329,79 +359,98 @@ redo: · 5 unmodified lines
329359 if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
330360 continue;
331361 length = s->data_offset;
332− if (copy) {
362+
363+ if (copy) { /* final step: copy section data to memory */
364+ void *ptr;
333365 if (addr == 0)
334366 addr = s->sh_addr;
335367 n = (s->sh_addr - addr) + length;
336368 ptr = (void*)s->sh_addr;
337369 if (k == 0)
338− ptr = (void*)(s->sh_addr - ptr_diff);
370+ ptr = (void*)(s->sh_addr + ptr_diff);
339371 if (NULL == s->data || s->sh_type == SHT_NOBITS)
340372 memset(ptr, 0, length);
341373 else
342374 memcpy(ptr, s->data, length);
343375 #ifdef _WIN64
344376 if (s == s1->uw_pdata)
345− *(void**)mem = win64_add_function_table(s1);
377+ s1->run_function_table = win64_add_function_table(s1);
346378 #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);
353380 continue;
354381 }
382+
355383 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;
361397 offset += -(addr + offset) & align;
362398 s->sh_addr = mem ? addr + offset : 0;
363399 offset += length;
364400 #if DEBUG_RUNMEN
365401 if (mem)
366− printf("%d: %-16s %p len %04x align %04x\n",
402+ fprintf(stderr, "%d: %-16s %p len %5x align %04x\n",
367403 k, s->name, (void*)s->sh_addr, length, align + 1);
368404 #endif
369405 }
370406 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 */
376411 continue;
377− f = 3; /* change only SHF_EXECINSTR to rwx */
378412 #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+ }
379419 #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)));
381423 #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?)");
386428 }
387429 }
388430
389− if (copy)
431+ if (copy) {
432+ /* remove local symbols and free sections except symtab */
433+ cleanup_symbols(s1);
434+ cleanup_sections(s1);
390435 return 0;
436+ }
391437
392438 /* relocate symbols */
393439 relocate_syms(s1, s1->symtab, !(s1->nostdlib));
394440 if (s1->nb_errors)
395441 return -1;
396− if (0 == mem)
397− return offset + max_align;
398442
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 */
401447 #endif
448+ return offset;
449+ }
402450
403− /* relocate sections */
404−#ifndef TCC_TARGET_PE
451+#ifdef TCC_TARGET_PE
452+ s1->pe_imagebase = mem;
453+#else
405454 relocate_plt(s1);
406455 #endif
407456 relocate_sections(s1);
@@ -412,7 +461,7 @@ redo: · 4 unmodified lines
412461 /* ------------------------------------------------------------- */
413462 /* allow to run code in memory */
414463
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)
416465 {
417466 #ifdef _WIN32
418467 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
437486 end = (addr_t)ptr + length;
438487 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
439488 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;
441490 /* XXX: BSD sometimes dump core with bad system call */
442491 # if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64
443492 if (mode == 0 || mode == 3) {
@@ -472,6 +521,7 @@ static void win64_del_function_table(void *p) · 28 unmodified lines
472521 }
473522 }
474523 #endif
524+
475525 #endif //ndef CONFIG_TCC_BACKTRACE_ONLY
476526 /* ------------------------------------------------------------- */
477527 #ifdef CONFIG_TCC_BACKTRACE
tests/abitest.c+1−2
@@ -1,4 +1,3 @@
1−#include <unistd.h>
21 #include <libtcc.h>
32 #include <stdlib.h>
43 #include <stdio.h>
@@ -53,7 +52,7 @@ static int run_callback(const char *src, callback_type callback) { · 48 unmodified lines
5352 return -1;
5453 if (tcc_compile_string(s, src) == -1)
5554 return -1;
56− if (tcc_relocate(s, TCC_RELOCATE_AUTO) == -1)
55+ if (tcc_relocate(s) == -1)
5756 return -1;
5857
5958 ptr = tcc_get_symbol(s, "f");
tests/libtcc_test.c+2−9
@@ -6,8 +6,6 @@ · 5 unmodified lines
66 #include <stdlib.h>
77 #include <stdio.h>
88 #include <string.h>
9−#include <assert.h>
10−
119 #include "libtcc.h"
1210
1311 void handle_error(void *opaque, const char *msg)
@@ -59,14 +57,9 @@ int main(int argc, char **argv) · 45 unmodified lines
5957 exit(1);
6058 }
6159
62− assert(tcc_get_error_func(s) == NULL);
63− assert(tcc_get_error_opaque(s) == NULL);
64−
60+ /* set custom error/warning printer */
6561 tcc_set_error_func(s, stderr, handle_error);
6662
67− assert(tcc_get_error_func(s) == handle_error);
68− assert(tcc_get_error_opaque(s) == stderr);
69−
7063 /* if tcclib.h and libtcc1.a are not installed, where can we find them */
7164 for (i = 1; i < argc; ++i) {
7265 char *a = argv[i];
@@ -92,7 +85,7 @@ int main(int argc, char **argv) · 19 unmodified lines
9285 tcc_add_symbol(s, "hello", hello);
9386
9487 /* relocate the code */
95− if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
88+ if (tcc_relocate(s) < 0)
9689 return 1;
9790
9891 /* 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
128128 {
129129 void *func;
130130 tcc_add_symbol(s, "add", add);
131− if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
131+ if (tcc_relocate(s) < 0) {
132132 fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
133133 return NULL;
134134 }

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