History

tccrun: review last changes

- LIBTCCAPI int tcc_set_backtrace_func(void *ud, ...) accept opaque user data pointer, - tcc -vv -run... : show section info - use memalign() to allocate runtime memory - printline_/dwarf : pass output to parent function - tccpe.c : fix -nostdlib -run - --config-backtrace=no : make it work again

grischka committed 2 years ago

Commit d2f8cea1 parent c88b19918 files · +402 −319Browse files

Unified · Split

18 files
  1. Makefile +3 −3
  2. configure +1 −1
  3. lib/Makefile +2 −3
  4. lib/bt-log.c +3 −3
  5. lib/runmain.c +5 −6
  6. libtcc.c +1 −1
  7. libtcc.h +5 −5
  8. tcc.h +5 −2
  9. tccelf.c +4 −4
  10. tccpe.c +3 −1
  11. tccrun.c +325 −270
  12. tests/Makefile +3 −1
  13. tests/libtcc_test_mt.c +36 −12
  14. tests/tcctest.c +1 −1
  15. win32/build-tcc.bat +1 −0
  16. win32/include/malloc.h +2 −2
  17. win32/include/stdlib.h +2 −2
  18. win32/lib/crt1.c +0 −2
Makefile+3−3
@@ -386,13 +386,13 @@ IR = $(IM) mkdir -p $2 && cp -r $1/. $2 · 385 unmodified lines
386IM = @echo "-> $2 : $1" ;386IM = @echo "-> $2 : $1" ;
387BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1)387BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1)
388 388
389B_O = runmain.o bt-exe.o bt-dll.o bcheck.o389EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
390 390
391# install progs & libs391# install progs & libs
392install-unx:392install-unx:
393 $(call BINCHECK)393 $(call BINCHECK)
394 $(call IBw,$(PROGS) *-tcc,"$(bindir)")394 $(call IBw,$(PROGS) *-tcc,"$(bindir)")
395 $(call IFw,$(LIBTCC1) $(B_O) $(LIBTCC1_U),"$(tccdir)")395 $(call IFw,$(LIBTCC1) $(EXTRA_O) $(LIBTCC1_U),"$(tccdir)")
396 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")396 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
397 $(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")397 $(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")
398 $(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")398 $(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")
@@ -419,7 +419,7 @@ install-win: · 20 unmodified lines
419 $(call BINCHECK)419 $(call BINCHECK)
420 $(call IBw,$(PROGS) *-tcc.exe libtcc.dll,"$(bindir)")420 $(call IBw,$(PROGS) *-tcc.exe libtcc.dll,"$(bindir)")
421 $(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")421 $(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")
422 $(call IFw,libtcc1.a $(B_O) $(LIBTCC1_W),"$(tccdir)/lib")422 $(call IFw,libtcc1.a $(EXTRA_O) $(LIBTCC1_W),"$(tccdir)/lib")
423 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")423 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
424 $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")424 $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")
425 $(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")425 $(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")
configure+1−1
@@ -365,7 +365,7 @@ case $targetos in · 364 unmodified lines
365 default tcc_libpaths "{B}:{R}/lib:/system/lib${S}"365 default tcc_libpaths "{B}:{R}/lib:/system/lib${S}"
366 default tcc_crtprefix "{R}/lib"366 default tcc_crtprefix "{R}/lib"
367 default tcc_elfinterp "/system/bin/linker${S}"367 default tcc_elfinterp "/system/bin/linker${S}"
368 default tcc_switches "-Wl,-rpath=$sysroot/lib,-section-alignment=0x1000"368 default tcc_switches "-Wl,-rpath=$sysroot/lib"
369 ;;369 ;;
370 WIN32)370 WIN32)
371 mingw32="yes"371 mingw32="yes"
lib/Makefile+2−3
@@ -40,7 +40,7 @@ endif · 39 unmodified lines
40$(X)BT_O = bt-exe.o bt-log.o40$(X)BT_O = bt-exe.o bt-log.o
41$(X)B_O = $(BCHECK_O) bt-exe.o bt-log.o bt-dll.o41$(X)B_O = $(BCHECK_O) bt-exe.o bt-log.o bt-dll.o
42endif42endif
43$(X)BT_O += tcov.o43$(X)BT_O += runmain.o tcov.o
44 44
45DSO_O = dsohandle.o45DSO_O = dsohandle.o
46 46
@@ -67,8 +67,7 @@ OBJ-arm-eabihf = $(ARM_O) $(DSO_O) · 20 unmodified lines
67OBJ-arm-wince = $(ARM_O) $(WIN_O)67OBJ-arm-wince = $(ARM_O) $(WIN_O)
68OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O)68OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O)
69 69
70OBJ-extra = $(filter-out bt-log.o,$(filter $(B_O),$(OBJ-$T)))70OBJ-extra = $(filter $(B_O) runmain.o,$(OBJ-$T))
71OBJ-extra += runmain.o
72OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))71OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
73 72
74ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra))73ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra))
lib/bt-log.c+3−3
@@ -23,19 +23,19 @@ typedef struct rt_frame { · 22 unmodified lines
23} rt_frame;23} rt_frame;
24 24
25__attribute__((weak))25__attribute__((weak))
26int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap);26int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap);
27 27
28DLL_EXPORT int tcc_backtrace(const char *fmt, ...)28DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
29{29{
30 va_list ap;30 va_list ap;
31 int ret;31 int ret;
32 32
33 if (__rt_dump) {33 if (_tcc_backtrace) {
34 rt_frame f;34 rt_frame f;
35 f.fp = __builtin_frame_address(1);35 f.fp = __builtin_frame_address(1);
36 f.ip = __builtin_return_address(0);36 f.ip = __builtin_return_address(0);
37 va_start(ap, fmt);37 va_start(ap, fmt);
38 ret = __rt_dump(&f, NULL, fmt, ap);38 ret = _tcc_backtrace(&f, fmt, ap);
39 va_end(ap);39 va_end(ap);
40 } else {40 } else {
41 const char *p, *nl = "\n";41 const char *p, *nl = "\n";
lib/runmain.c+5−6
@@ -29,7 +29,7 @@ static void run_dtors(void) · 28 unmodified lines
29 29
30static void *rt_exitfunc[32];30static void *rt_exitfunc[32];
31static void *rt_exitarg[32];31static void *rt_exitarg[32];
32int __rt_nr_exit;32static int __rt_nr_exit;
33 33
34void __run_on_exit(int ret)34void __run_on_exit(int ret)
35{35{
@@ -59,16 +59,16 @@ typedef struct rt_frame { · 23 unmodified lines
59 void *ip, *fp, *sp;59 void *ip, *fp, *sp;
60} rt_frame;60} rt_frame;
61 61
62void __rt_longjmp(rt_frame *, int);62void __rt_exit(rt_frame *, int);
63 63
64void exit(int code)64void exit(int code)
65{65{
66 rt_frame f;66 rt_frame f;
67 run_dtors();67 run_dtors();
68 __run_on_exit(code);68 __run_on_exit(code);
69 f.fp = __builtin_frame_address(1);69 f.fp = 0;
70 f.ip = __builtin_return_address(0);70 f.ip = exit;
71 __rt_longjmp(&f, code);71 __rt_exit(&f, code);
72}72}
73 73
74#ifndef _WIN3274#ifndef _WIN32
@@ -77,7 +77,6 @@ int main(int, char**, char**); · 2 unmodified lines
77int _runmain(int argc, char **argv, char **envp)77int _runmain(int argc, char **argv, char **envp)
78{78{
79 int ret;79 int ret;
80 __rt_nr_exit = 0;
81 run_ctors(argc, argv, envp);80 run_ctors(argc, argv, envp);
82 ret = main(argc, argv, envp);81 ret = main(argc, argv, envp);
83 run_dtors();82 run_dtors();
libtcc.c+1−1
@@ -229,7 +229,7 @@ static void *default_reallocator(void *ptr, unsigned long size) · 228 unmodified lines
229 return ptr1;229 return ptr1;
230}230}
231 231
232static void libc_free(void *ptr)232ST_FUNC void libc_free(void *ptr)
233{233{
234 free(ptr);234 free(ptr);
235}235}
libtcc.h+5−5
@@ -104,12 +104,12 @@ LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, · 103 unmodified lines
104 104
105/* catch runtime exceptions (optionally limit backtraces at top_func),105/* catch runtime exceptions (optionally limit backtraces at top_func),
106 when using tcc_set_options("-bt") and when not using tcc_run() */106 when using tcc_set_options("-bt") and when not using tcc_run() */
107LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *longjmp, void *jmp_buf, void *top_func);107LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp);
108#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, longjmp, jb, f))108#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp))
109 109
110/* set custom error printer for runtime exceptions */110/* custom error printer for runtime exceptions. Returning 0 stops backtrace */
111typedef void TCCBtFunc(void *pc, const char *file, int line, const char* func);111typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg);
112LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, TCCBtFunc*);112LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*);
113 113
114#ifdef __cplusplus114#ifdef __cplusplus
115}115}
tcc.h+5−2
@@ -1003,7 +1003,9 @@ struct TCCState { · 1002 unmodified lines
1003 struct TCCState *next;1003 struct TCCState *next;
1004 struct rt_context *rc; /* pointer to backtrace info block */1004 struct rt_context *rc; /* pointer to backtrace info block */
1005 void *run_lj, *run_jb; /* sj/lj for tcc_setjmp()/tcc_run() */1005 void *run_lj, *run_jb; /* sj/lj for tcc_setjmp()/tcc_run() */
1006 void (*bt_func)(void *, const char*, int, const char*);1006 TCCBtFunc *bt_func;
1007 void *bt_data;
1008 int run_tid;
1007#endif1009#endif
1008 1010
1009#ifdef CONFIG_TCC_BACKTRACE1011#ifdef CONFIG_TCC_BACKTRACE
@@ -1250,6 +1252,7 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file · 240 unmodified lines
1250PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);1252PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
1251#endif1253#endif
1252 1254
1255ST_FUNC void libc_free(void *ptr);
1253#define free(p) use_tcc_free(p)1256#define free(p) use_tcc_free(p)
1254#define malloc(s) use_tcc_malloc(s)1257#define malloc(s) use_tcc_malloc(s)
1255#define realloc(p, s) use_tcc_realloc(p, s)1258#define realloc(p, s) use_tcc_realloc(p, s)
@@ -1982,7 +1985,7 @@ ST_FUNC void wait_sem(TCCSem *p) · 726 unmodified lines
1982 sem_init(&p->sem, 0, 1), p->init = 1;1985 sem_init(&p->sem, 0, 1), p->init = 1;
1983 while (sem_wait(&p->sem) < 0 && errno == EINTR);1986 while (sem_wait(&p->sem) < 0 && errno == EINTR);
1984}1987}
1985ST_INLN void post_sem(TCCSem *p)1988ST_FUNC void post_sem(TCCSem *p)
1986{1989{
1987 sem_post(&p->sem);1990 sem_post(&p->sem);
1988}1991}
tccelf.c+4−4
@@ -1606,7 +1606,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 1605 unmodified lines
1606 (uint64_t)1 << 32);1606 (uint64_t)1 << 32);
1607#endif1607#endif
1608 }1608 }
1609 n = 4 * PTR_SIZE;1609 n = 3 * PTR_SIZE;
1610#ifdef CONFIG_TCC_BCHECK1610#ifdef CONFIG_TCC_BCHECK
1611 if (s1->do_bounds_check) {1611 if (s1->do_bounds_check) {
1612 put_ptr(s1, bounds_section, 0);1612 put_ptr(s1, bounds_section, 0);
@@ -1617,9 +1617,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 4 unmodified lines
1617 p = section_ptr_add(s, 2 * sizeof (int));1617 p = section_ptr_add(s, 2 * sizeof (int));
1618 p[0] = s1->rt_num_callers;1618 p[0] = s1->rt_num_callers;
1619 p[1] = s1->dwarf;1619 p[1] = s1->dwarf;
1620 1620 // if (s->data_offset - o != 10*PTR_SIZE + 2*sizeof (int)) exit(99);
1621 if (s->data_offset - o != 11 * PTR_SIZE + 2 * sizeof (int))
1622 exit(99);
1623 1621
1624 if (s1->output_type == TCC_OUTPUT_MEMORY) {1622 if (s1->output_type == TCC_OUTPUT_MEMORY) {
1625 set_global_sym(s1, __rt_info, s, o);1623 set_global_sym(s1, __rt_info, s, o);
@@ -1778,6 +1776,8 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 152 unmodified lines
1778 if (s1->do_backtrace) {1776 if (s1->do_backtrace) {
1779 if (s1->output_type & TCC_OUTPUT_EXE)1777 if (s1->output_type & TCC_OUTPUT_EXE)
1780 tcc_add_support(s1, "bt-exe.o");1778 tcc_add_support(s1, "bt-exe.o");
1779 if (s1->output_type != TCC_OUTPUT_DLL)
1780 tcc_add_support(s1, "bt-log.o");
1781 tcc_add_btstub(s1);1781 tcc_add_btstub(s1);
1782 lpthread = 1;1782 lpthread = 1;
1783 }1783 }
tccpe.c+3−1
@@ -1943,7 +1943,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 1942 unmodified lines
1943 pe_type = PE_EXE;1943 pe_type = PE_EXE;
1944 1944
1945 }1945 }
1946 if (TCC_OUTPUT_MEMORY == s1->output_type)1946 if (TCC_OUTPUT_MEMORY == s1->output_type && !s1->nostdlib)
1947 start_symbol = run_symbol;1947 start_symbol = run_symbol;
1948 }1948 }
1949 1949
@@ -1961,6 +1961,8 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 11 unmodified lines
1961 tcc_add_support(s1, "bt-exe.o");1961 tcc_add_support(s1, "bt-exe.o");
1962 if (s1->output_type == TCC_OUTPUT_DLL)1962 if (s1->output_type == TCC_OUTPUT_DLL)
1963 tcc_add_support(s1, "bt-dll.o");1963 tcc_add_support(s1, "bt-dll.o");
1964 if (s1->output_type != TCC_OUTPUT_DLL)
1965 tcc_add_support(s1, "bt-log.o");
1964 tcc_add_btstub(s1);1966 tcc_add_btstub(s1);
1965 }1967 }
1966#endif1968#endif
tccrun.c+325−270
@@ -24,6 +24,7 @@ · 23 unmodified lines
24#ifdef TCC_IS_NATIVE24#ifdef TCC_IS_NATIVE
25 25
26#ifdef CONFIG_TCC_BACKTRACE26#ifdef CONFIG_TCC_BACKTRACE
27/* runtime debug info block */
27typedef struct rt_context28typedef struct rt_context
28{29{
29 /* tccelf.c:tcc_add_btstub() wants these in that order: */30 /* tccelf.c:tcc_add_btstub() wants these in that order: */
@@ -42,32 +43,33 @@ typedef struct rt_context · 12 unmodified lines
42 ElfW(Sym) *esym_start;43 ElfW(Sym) *esym_start;
43 ElfW(Sym) *esym_end;44 ElfW(Sym) *esym_end;
44 char *elf_str;45 char *elf_str;
45 // 646 // 6 * PTR_SIZE
46 addr_t prog_base;47 addr_t prog_base;
47 void *bounds_start;48 void *bounds_start;
48 void *top_func;49 void *top_func;
49 TCCState *s1;
50 struct rt_context *next;50 struct rt_context *next;
51 // 1151 // 10 * PTR_SIZE
52 int num_callers;52 int num_callers;
53 int dwarf;53 int dwarf;
54} rt_context; /* size = 11 * PTR_SIZE + 2 * sizeof (int) */54} rt_context;
55
56/* linked list of rt_contexts */
57static rt_context *g_rc;
58static int signal_set;
59static void set_exception_handler(void);
60#endif /* def CONFIG_TCC_BACKTRACE */
55 61
56typedef struct rt_frame {62typedef struct rt_frame {
57 addr_t ip, fp, sp;63 addr_t ip, fp, sp;
58} rt_frame;64} rt_frame;
59 65
60/* linked list of rt_contexts */
61static rt_context *g_rc;
62static TCCState *g_s1;66static TCCState *g_s1;
63/* semaphore to protect it */67/* semaphore to protect it */
64TCC_SEM(static rt_sem);68TCC_SEM(static rt_sem);
65static int signal_set;
66static void set_exception_handler(void);
67static void rt_wait_sem(void) { WAIT_SEM(&rt_sem); }69static void rt_wait_sem(void) { WAIT_SEM(&rt_sem); }
68static void rt_post_sem(void) { POST_SEM(&rt_sem); }70static void rt_post_sem(void) { POST_SEM(&rt_sem); }
69static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level);71static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level);
70#endif /* def CONFIG_TCC_BACKTRACE */72static void rt_exit(rt_frame *f, int code);
71 73
72/* ------------------------------------------------------------- */74/* ------------------------------------------------------------- */
73/* defined when included from lib/bt-exe.c */75/* defined when included from lib/bt-exe.c */
@@ -79,73 +81,26 @@ static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level); · 5 unmodified lines
79 81
80static int protect_pages(void *ptr, unsigned long length, int mode);82static int protect_pages(void *ptr, unsigned long length, int mode);
81static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff);83static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff);
82static int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap);84static void st_link(TCCState *s1);
83static void rt_longjmp(rt_frame *f, int code);85static void st_unlink(TCCState *s1);
86#ifdef CONFIG_TCC_BACKTRACE
87static int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap);
88#endif
84#ifdef _WIN6489#ifdef _WIN64
85static void *win64_add_function_table(TCCState *s1);90static void *win64_add_function_table(TCCState *s1);
86static void win64_del_function_table(void *);91static void win64_del_function_table(void *);
87#endif92#endif
88 93
89static void bt_link(TCCState *s1)94#ifdef __APPLE__
90{95# define CONFIG_RUNMEM_ALIGNED 0
91#ifdef CONFIG_TCC_BACKTRACE96#else
92 rt_context *rc;97# ifndef CONFIG_RUNMEM_ALIGNED
93 void *p;98# define CONFIG_RUNMEM_ALIGNED 1
94 99# endif
95 if (!s1->do_backtrace)100# if CONFIG_RUNMEM_ALIGNED
96 return;101# include <malloc.h> /* memalign() */
97 rc = tcc_get_symbol(s1, "__rt_info");102# endif
98 if (!rc)
99 return;
100 rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
101 rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
102 rc->elf_str = (char *)symtab_section->link->data;
103 if (PTR_SIZE == 8 && !s1->dwarf)
104 rc->prog_base &= 0xffffffff00000000ULL;
105#ifdef CONFIG_TCC_BCHECK
106 if (s1->do_bounds_check) {
107 if ((p = tcc_get_symbol(s1, "__bound_init")))
108 ((void(*)(void*,int))p)(rc->bounds_start, 1);
109 }
110#endif
111 rc->next = g_rc, g_rc = rc, rc->s1 = s1, s1->rc = rc;
112 if (0 == signal_set)
113 set_exception_handler(), signal_set = 1;
114#endif
115}
116
117static void bt_unlink(TCCState *s1)
118{
119#ifdef CONFIG_TCC_BACKTRACE
120 rt_context *rc, **pp;
121 for (pp = &g_rc; rc = *pp, rc; pp = &rc->next)
122 if (rc->s1 == s1) {
123 *pp = rc->next;
124 break;
125 }
126#endif103#endif
127}
128
129static void st_link(TCCState *s1)
130{
131 rt_wait_sem();
132 s1->next = g_s1, g_s1 = s1;
133 bt_link(s1);
134 rt_post_sem();
135}
136
137static void st_unlink(TCCState *s1)
138{
139 TCCState *s2, **pp;
140 rt_wait_sem();
141 bt_unlink(s1);
142 for (pp = &g_s1; s2 = *pp, s2; pp = &s2->next)
143 if (s2 == s1) {
144 *pp = s2->next;
145 break;
146 }
147 rt_post_sem();
148}
149 104
150#if !_WIN32 && !__APPLE__105#if !_WIN32 && !__APPLE__
151//#define HAVE_SELINUX 1106//#define HAVE_SELINUX 1
@@ -172,7 +127,15 @@ static int rt_mem(TCCState *s1, int size) · 20 unmodified lines
172 ptr_diff = (char*)prw - (char*)ptr; /* = size; */127 ptr_diff = (char*)prw - (char*)ptr; /* = size; */
173 //printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff);128 //printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff);
174#else129#else
175 ptr = tcc_malloc(size);130# if !CONFIG_RUNMEM_ALIGNED
131 ptr = tcc_malloc(size += PAGESIZE);
132# elif _WIN32
133 ptr = _aligned_malloc(size, PAGESIZE);
134# else
135 ptr = memalign(PAGESIZE, size);
136# endif
137 if (NULL == ptr)
138 return tcc_error_noabort("tccrun: could not allocate memory");
176#endif139#endif
177 s1->run_ptr = ptr;140 s1->run_ptr = ptr;
178 s1->run_size = size;141 s1->run_size = size;
@@ -189,12 +152,10 @@ LIBTCCAPI int tcc_relocate(TCCState *s1) · 10 unmodified lines
189 152
190 if (s1->run_ptr)153 if (s1->run_ptr)
191 exit(tcc_error_noabort("'tcc_relocate()' twice is no longer supported"));154 exit(tcc_error_noabort("'tcc_relocate()' twice is no longer supported"));
192
193#ifdef CONFIG_TCC_BACKTRACE155#ifdef CONFIG_TCC_BACKTRACE
194 if (s1->do_backtrace)156 if (s1->do_backtrace)
195 tcc_add_symbol(s1, "__rt_dump", __rt_dump); /* for bt-log.c */157 tcc_add_symbol(s1, "_tcc_backtrace", _tcc_backtrace); /* for bt-log.c */
196#endif158#endif
197
198 size = tcc_relocate_ex(s1, NULL, 0);159 size = tcc_relocate_ex(s1, NULL, 0);
199 if (size < 0)160 if (size < 0)
200 return -1;161 return -1;
@@ -236,31 +197,24 @@ ST_FUNC void tcc_run_free(TCCState *s1) · 35 unmodified lines
236#else197#else
237 /* unprotect memory to make it usable for malloc again */198 /* unprotect memory to make it usable for malloc again */
238 protect_pages(ptr, size, 2 /*rw*/);199 protect_pages(ptr, size, 2 /*rw*/);
239#ifdef _WIN64200# ifdef _WIN64
240 win64_del_function_table(s1->run_function_table);201 win64_del_function_table(s1->run_function_table);
241#endif202# endif
203# if !CONFIG_RUNMEM_ALIGNED
242 tcc_free(ptr);204 tcc_free(ptr);
205# elif _WIN32
206 _aligned_free(ptr);
207# else
208 libc_free(ptr);
209# endif
243#endif210#endif
244}211}
245 212
246LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *p_longjmp, void *p_jmp_buf, void *func)
247{
248 s1->run_lj = p_longjmp;
249 s1->run_jb = p_jmp_buf;
250 if (func && s1->rc)
251 s1->rc->top_func = func;
252 return p_jmp_buf;
253}
254
255LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, TCCBtFunc *func)
256{
257 s1->bt_func = func;
258}
259
260/* launch the compiled program with the given arguments */213/* launch the compiled program with the given arguments */
261LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)214LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
262{215{
263 int (*prog_main)(int, char **, char **), ret;216 int (*prog_main)(int, char **, char **), ret;
217 const char *top_sym;
264 jmp_buf main_jb;218 jmp_buf main_jb;
265 219
266#if defined(__APPLE__) || defined(__FreeBSD__)220#if defined(__APPLE__) || defined(__FreeBSD__)
@@ -276,20 +230,25 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 9 unmodified lines
276 if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, "main", 0, 1))230 if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, "main", 0, 1))
277 return 0;231 return 0;
278 232
279 tcc_add_support(s1, "runmain.o");233 tcc_add_symbol(s1, "__rt_exit", rt_exit);
280 tcc_add_symbol(s1, "__rt_longjmp", rt_longjmp);234 if (s1->nostdlib) {
281 s1->run_main = (s1->nostdlib ? "_start" : "_runmain");235 s1->run_main = top_sym = "_start";
236 } else {
237 tcc_add_support(s1, "runmain.o");
238 s1->run_main = "_runmain";
239 top_sym = "main";
240 }
282 if (tcc_relocate(s1) < 0)241 if (tcc_relocate(s1) < 0)
283 return -1;242 return 1;
284 243
285 prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1);244 prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1);
286 if ((addr_t)-1 == (addr_t)prog_main)245 if ((addr_t)-1 == (addr_t)prog_main)
287 return -1;246 return 1;
288 errno = 0; /* clean errno value */247 errno = 0; /* clean errno value */
289 fflush(stdout);248 fflush(stdout);
290 fflush(stderr);249 fflush(stderr);
291 250
292 ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, "main"));251 ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym));
293 if (0 == ret)252 if (0 == ret)
294 ret = prog_main(argc, argv, envp);253 ret = prog_main(argc, argv, envp);
295 else if (256 == ret)254 else if (256 == ret)
@@ -344,8 +303,6 @@ static void cleanup_sections(TCCState *s1) · 48 unmodified lines
344# define CONFIG_RUNMEM_RO 1303# define CONFIG_RUNMEM_RO 1
345#endif304#endif
346 305
347#define DEBUG_RUNMEN 0
348
349/* relocate code. Return -1 on error, required size if ptr is NULL,306/* relocate code. Return -1 on error, required size if ptr is NULL,
350 otherwise copy code into buffer passed by the caller */307 otherwise copy code into buffer passed by the caller */
351static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff)308static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff)
@@ -367,16 +324,17 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff) · 15 unmodified lines
367 324
368 offset = copy = 0;325 offset = copy = 0;
369 mem = (addr_t)ptr;326 mem = (addr_t)ptr;
370
371#if DEBUG_RUNMEN
372 if (mem)
373 fprintf(stderr, "X: <base> %p len %5x\n",
374 ptr, s1->run_size);
375#endif
376
377redo:327redo:
328 if (s1->verbose == 2 && copy) {
329 printf(&"-----------------------------------------------------\n"[PTR_SIZE*2 - 8]);
330 if (1 == copy)
331 printf("memory %p len %05x\n", ptr, s1->run_size);
332 }
378 if (s1->nb_errors)333 if (s1->nb_errors)
379 return -1;334 return -1;
335 if (copy == 2)
336 return 0;
337
380 for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */338 for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
381 n = 0; addr = 0;339 n = 0; addr = 0;
382 for(i = 1; i < s1->nb_sections; i++) {340 for(i = 1; i < s1->nb_sections; i++) {
@@ -389,7 +347,9 @@ redo: · 6 unmodified lines
389 length = s->data_offset;347 length = s->data_offset;
390 348
391 if (copy) { /* final step: copy section data to memory */349 if (copy) { /* final step: copy section data to memory */
392 void *ptr;350 if (s1->verbose == 2)
351 printf("%d: %-16s %p len %05x align %04x\n",
352 k, s->name, (void*)s->sh_addr, length, s->sh_addralign);
393 if (addr == 0)353 if (addr == 0)
394 addr = s->sh_addr;354 addr = s->sh_addr;
395 n = (s->sh_addr - addr) + length;355 n = (s->sh_addr - addr) + length;
@@ -407,28 +367,25 @@ redo: · 11 unmodified lines
407 continue;367 continue;
408 }368 }
409 369
410 align = s->sh_addralign - 1;370 align = s->sh_addralign;
411 if (++n == 1) {371 if (++n == 1) {
412#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64372#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
413 /* To avoid that x86 processors would reload cached instructions373 /* To avoid that x86 processors would reload cached instructions
414 each time when data is written in the near, we need to make374 each time when data is written in the near, we need to make
415 sure that code and data do not share the same 64 byte unit */375 sure that code and data do not share the same 64 byte unit */
416 if (align < 63)376 if (align < 64)
417 align = 63;377 align = 64;
418#endif378#endif
419 /* start new page for different permissions */379 /* start new page for different permissions */
420 if (CONFIG_RUNMEM_RO || k < 2)380 if (CONFIG_RUNMEM_RO || k < 2)
421 align = PAGESIZE - 1;381 align = PAGESIZE;
422 }382 }
383 s->sh_addralign = align;
384
423 addr = k ? mem + ptr_diff : mem;385 addr = k ? mem + ptr_diff : mem;
424 offset += -(addr + offset) & align;386 offset += -(addr + offset) & (align - 1);
425 s->sh_addr = mem ? addr + offset : 0;387 s->sh_addr = mem ? addr + offset : 0;
426 offset += length;388 offset += length;
427#if DEBUG_RUNMEN
428 if (mem)
429 fprintf(stderr, "%d: %-16s %p len %5x align %04x\n",
430 k, s->name, (void*)s->sh_addr, length, align + 1);
431#endif
432 }389 }
433 if (copy) { /* set permissions */390 if (copy) { /* set permissions */
434 if (n == 0) /* no data */391 if (n == 0) /* no data */
@@ -443,30 +400,25 @@ redo: · 8 unmodified lines
443 continue;400 continue;
444 f = 3; /* change only SHF_EXECINSTR to rwx */401 f = 3; /* change only SHF_EXECINSTR to rwx */
445 }402 }
446#if DEBUG_RUNMEN403 n = (n + PAGESIZE-1) & ~(PAGESIZE-1);
447 fprintf(stderr, "protect %3s %p len %5x\n",404 if (s1->verbose == 2) {
448 &"rx\0r \0rw\0rwx"[f*3],405 printf("protect %3s %p len %05x\n",
449 (void*)addr, (unsigned)((n + PAGESIZE-1) & ~(PAGESIZE-1)));406 &"rx\0r \0rw\0rwx"[f*3], (void*)addr, (unsigned)n);
450#endif407 }
451 if (protect_pages((void*)addr, n, f) < 0)408 if (protect_pages((void*)addr, n, f) < 0)
452 return tcc_error_noabort(409 return tcc_error_noabort(
453 "mprotect failed (did you mean to configure --with-selinux?)");410 "mprotect failed (did you mean to configure --with-selinux?)");
454 }411 }
455 }412 }
456 413
457 if (0 == mem) {414 if (0 == mem)
458 offset = (offset + (PAGESIZE-1)) & ~(PAGESIZE-1);415 return (offset + (PAGESIZE-1)) & ~(PAGESIZE-1);
459#ifndef HAVE_SELINUX
460 offset += PAGESIZE; /* extra space to align malloc memory start */
461#endif
462 return offset;
463 }
464 416
465 if (copy) {417 if (++copy == 2) {
466 /* remove local symbols and free sections except symtab */418 /* remove local symbols and free sections except symtab */
467 cleanup_symbols(s1);419 cleanup_symbols(s1);
468 cleanup_sections(s1);420 cleanup_sections(s1);
469 return 0;421 goto redo;
470 }422 }
471 423
472 /* relocate symbols */424 /* relocate symbols */
@@ -478,7 +430,6 @@ redo: · 5 unmodified lines
478 relocate_plt(s1);430 relocate_plt(s1);
479#endif431#endif
480 relocate_sections(s1);432 relocate_sections(s1);
481 copy = 1;
482 goto redo;433 goto redo;
483}434}
484 435
@@ -546,6 +497,152 @@ static void win64_del_function_table(void *p) · 61 unmodified lines
546}497}
547#endif498#endif
548 499
500static void bt_link(TCCState *s1)
501{
502#ifdef CONFIG_TCC_BACKTRACE
503 rt_context *rc;
504 void *p;
505
506 if (!s1->do_backtrace)
507 return;
508 rc = tcc_get_symbol(s1, "__rt_info");
509 if (!rc)
510 return;
511 rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
512 rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
513 rc->elf_str = (char *)symtab_section->link->data;
514 if (PTR_SIZE == 8 && !s1->dwarf)
515 rc->prog_base &= 0xffffffff00000000ULL;
516#ifdef CONFIG_TCC_BCHECK
517 if (s1->do_bounds_check) {
518 if ((p = tcc_get_symbol(s1, "__bound_init")))
519 ((void(*)(void*,int))p)(rc->bounds_start, 1);
520 }
521#endif
522 rc->next = g_rc, g_rc = rc, s1->rc = rc;
523 if (0 == signal_set)
524 set_exception_handler(), signal_set = 1;
525#endif
526}
527
528static void st_link(TCCState *s1)
529{
530 rt_wait_sem();
531 s1->next = g_s1, g_s1 = s1;
532 bt_link(s1);
533 rt_post_sem();
534}
535
536/* remove 'el' from 'list' */
537static void ptr_unlink(void *list, void *e, unsigned next)
538{
539 void **pp, **nn, *p;
540 for (pp = list; !!(p = *pp); pp = nn) {
541 nn = (void*)((char*)p + next); /* nn = &p->next; */
542 if (p == e) {
543 *pp = *nn;
544 break;
545 }
546 }
547}
548
549static void st_unlink(TCCState *s1)
550{
551 rt_wait_sem();
552#ifdef CONFIG_TCC_BACKTRACE
553 ptr_unlink(&g_rc, s1->rc, offsetof(rt_context, next));
554#endif
555 ptr_unlink(&g_s1, s1, offsetof(TCCState, next));
556 rt_post_sem();
557}
558
559#ifdef _WIN32
560# define GETTID() GetCurrentThreadId()
561#elif defined __linux__
562# define GETTID() gettid()
563#elif 0
564# define GETTID() 1234 // threads not supported
565#endif
566
567LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *p_jmp_buf, void *func, void *p_longjmp)
568{
569#ifdef GETTID
570 int tid = GETTID();
571 TCCState *s;
572 rt_wait_sem();
573 for (s = g_s1; s; s = s->next)
574 if (s->run_tid == tid)
575 s->run_tid = -1;
576 s1->run_tid = (int)tid;
577 rt_post_sem();
578#endif
579 s1->run_lj = p_longjmp;
580 s1->run_jb = p_jmp_buf;
581#ifdef CONFIG_TCC_BACKTRACE
582 if (s1->rc)
583 s1->rc->top_func = func;
584#endif
585 return p_jmp_buf;
586}
587
588LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void *data, TCCBtFunc *func)
589{
590 s1->bt_func = func;
591 s1->bt_data = data;
592}
593
594static TCCState *rt_find_state(rt_frame *f)
595{
596#ifdef GETTID
597 int tid = GETTID();
598 TCCState *s;
599 for (s = g_s1; s; s = s->next)
600 if (s->run_tid == tid)
601 break;
602 return s;
603#else
604 TCCState *s;
605 int level;
606 addr_t pc;
607
608 s = g_s1;
609 if (NULL == s || NULL == s->next) {
610 /* play it safe in the simple case when there is only one state */
611 return s;
612 }
613 for (level = 0; level < 8; ++level) {
614 if (rt_get_caller_pc(&pc, f, level) < 0)
615 break;
616 for (s = g_s1; s; s = s->next) {
617 if (pc >= (addr_t)s->run_ptr
618 && pc < (addr_t)s->run_ptr + s->run_size)
619 return s;
620 }
621 }
622 return NULL;
623#endif
624}
625
626static void rt_exit(rt_frame *f, int code)
627{
628 TCCState *s;
629 rt_wait_sem();
630 s = rt_find_state(f);
631 rt_post_sem();
632 if (s && s->run_lj) {
633 if (code == 0)
634 code = 256;
635 ((void(*)(void*,int))s->run_lj)(s->run_jb, code);
636 }
637 exit(code);
638}
639
640/* ------------------------------------------------------------- */
641#else // if defined CONFIG_TCC_BACKTRACE_ONLY
642static void rt_exit(rt_frame *f, int code)
643{
644 exit(code);
645}
549#endif //ndef CONFIG_TCC_BACKTRACE_ONLY646#endif //ndef CONFIG_TCC_BACKTRACE_ONLY
550/* ------------------------------------------------------------- */647/* ------------------------------------------------------------- */
551#ifdef CONFIG_TCC_BACKTRACE648#ifdef CONFIG_TCC_BACKTRACE
@@ -582,11 +679,17 @@ static char *rt_elfsym(rt_context *rc, addr_t wanted_pc, addr_t *func_addr) · 30 unmodified lines
582 return NULL;679 return NULL;
583}680}
584 681
682typedef struct bt_info
683{
684 char file[100];
685 int line;
686 char func[100];
687 addr_t func_pc;
688} bt_info;
585 689
586/* print the position in the source file of PC value 'pc' by reading690/* print the position in the source file of PC value 'pc' by reading
587 the stabs debug information */691 the stabs debug information */
588static addr_t rt_printline (rt_context *rc, addr_t wanted_pc,692static addr_t rt_printline (rt_context *rc, addr_t wanted_pc, bt_info *bi)
589 rt_context** prc, const char *msg, const char *skip)
590{693{
591 char func_name[128];694 char func_name[128];
592 addr_t func_addr, last_pc, pc;695 addr_t func_addr, last_pc, pc;
@@ -595,15 +698,12 @@ static addr_t rt_printline (rt_context *rc, addr_t wanted_pc, · 2 unmodified lines
595 const char *str, *p;698 const char *str, *p;
596 Stab_Sym *sym;699 Stab_Sym *sym;
597 700
598next:
599 func_name[0] = '\0';701 func_name[0] = '\0';
600 func_addr = 0;702 func_addr = 0;
601 incl_index = 0;703 incl_index = 0;
602 last_pc = (addr_t)-1;704 last_pc = (addr_t)-1;
603 last_line_num = 1;705 last_line_num = 1;
604 last_incl_index = 0;706 last_incl_index = 0;
605 if (NULL == rc)
606 goto found;
607 707
608 for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) {708 for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) {
609 str = rc->stab_str + sym->n_strx;709 str = rc->stab_str + sym->n_strx;
@@ -680,50 +780,15 @@ next: · 70 unmodified lines
680 break;780 break;
681 }781 }
682 }782 }
683 783 last_incl_index = 0, func_name[0] = 0, func_addr = 0;
684 func_name[0] = '\0';
685 func_addr = 0;
686 last_incl_index = 0;
687
688 /* we try symtab symbols (no line number info) */
689 p = rt_elfsym(rc, wanted_pc, &func_addr);
690 if (p) {
691 pstrcpy(func_name, sizeof func_name, p);
692 goto found;
693 }
694 rc = rc->next;
695 goto next;
696
697found:784found:
698 i = last_incl_index;785 i = last_incl_index;
699 str = NULL;
700 if (i > 0) {786 if (i > 0) {
701 str = incl_files[--i];787 pstrcpy(bi->file, sizeof bi->file, incl_files[--i]);
702 if (skip[0] && strstr(str, skip))788 bi->line = last_line_num;
703 return (addr_t)-1;
704 }
705 if (rc && rc->s1 && rc->s1->bt_func) {
706 rc->s1->bt_func((void*)wanted_pc, str, last_line_num, func_name[0] ? func_name : NULL);
707 } else {
708 if (str)
709 rt_printf("%s:%d: ", str, last_line_num);
710 else
711 rt_printf("%08llx : ", (long long)wanted_pc);
712 rt_printf("%s %s", msg, func_name[0] ? func_name : "???");
713 }
714#if 0
715 if (--i >= 0) {
716 rt_printf(" (included from ");
717 for (;;) {
718 rt_printf("%s", incl_files[i]);
719 if (--i < 0)
720 break;
721 rt_printf(", ");
722 }
723 rt_printf(")");
724 }789 }
725#endif790 pstrcpy(bi->func, sizeof bi->func, func_name);
726 *prc = rc;791 bi->func_pc = func_addr;
727 return func_addr;792 return func_addr;
728}793}
729 794
@@ -793,8 +858,7 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end) · 63 unmodified lines
793 return retval;858 return retval;
794}859}
795 860
796static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,861static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc, bt_info *bi)
797 rt_context** prc, const char *msg, const char *skip)
798{862{
799 unsigned char *ln;863 unsigned char *ln;
800 unsigned char *cp;864 unsigned char *cp;
@@ -834,12 +898,10 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc, · 33 unmodified lines
834 char *filename;898 char *filename;
835 char *function;899 char *function;
836 900
837next:
838 filename = NULL;901 filename = NULL;
902 function = NULL;
839 func_addr = 0;903 func_addr = 0;
840 line = 0;904 line = 0;
841 if (NULL == rc)
842 goto found;
843 905
844 ln = rc->dwarf_line;906 ln = rc->dwarf_line;
845 while (ln < rc->dwarf_line_end) {907 while (ln < rc->dwarf_line_end) {
@@ -1070,44 +1132,28 @@ check_pc: · 224 unmodified lines
1070next_line:1132next_line:
1071 ln = end;1133 ln = end;
1072 }1134 }
1073 1135 filename = function = NULL, func_addr = 0;
1074 filename = NULL;
1075 func_addr = 0;
1076 /* we try symtab symbols (no line number info) */
1077 function = rt_elfsym(rc, wanted_pc, &func_addr);
1078 if (function)
1079 goto found;
1080 rc = rc->next;
1081 goto next;
1082
1083found:1136found:
1084 if (rc && rc->s1 && rc->s1->bt_func) {1137 if (filename)
1085 rc->s1->bt_func((void*)wanted_pc, filename, line, function);1138 pstrcpy(bi->file, sizeof bi->file, filename), bi->line = line;
1086 } else {1139 if (function)
1087 if (filename) {1140 pstrcpy(bi->func, sizeof bi->func, function);
1088 if (skip[0] && strstr(filename, skip))1141 bi->func_pc = func_addr;
1089 return (addr_t)-1;
1090 rt_printf("%s:%d: ", filename, line);
1091 }
1092 else
1093 rt_printf("0x%08llx : ", (long long)wanted_pc);
1094 rt_printf("%s %s", msg, function ? function : "???");
1095 }
1096 *prc = rc;
1097 return (addr_t)func_addr;1142 return (addr_t)func_addr;
1098}1143}
1099/* ------------------------------------------------------------- */1144/* ------------------------------------------------------------- */
1100#ifndef CONFIG_TCC_BACKTRACE_ONLY1145#ifndef CONFIG_TCC_BACKTRACE_ONLY
1101static1146static
1102#endif1147#endif
1103int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap)1148int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap)
1104{1149{
1105 rt_context *rc, *rd;1150 rt_context *rc, *rc2;
1106 addr_t pc = 0;1151 addr_t pc;
1107 char skip[100];1152 char skip[40], msg[200];
1108 int i, level, ret, n, one;1153 int i, level, ret, n, one;
1109 const char *a, *b;1154 const char *a, *b;
1110 addr_t (*printline)(rt_context*, addr_t, rt_context**, const char*, const char*);1155 bt_info bi;
1156 addr_t (*getinfo)(rt_context*, addr_t, bt_info*);
1111 1157
1112 skip[0] = 0;1158 skip[0] = 0;
1113 /* If fmt is like "^file.c^..." then skip calls from 'file.c' */1159 /* If fmt is like "^file.c^..." then skip calls from 'file.c' */
@@ -1119,41 +1165,73 @@ int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap) · 5 unmodified lines
1119 /* hack for bcheck.c:dprintf(): one level, no newline */1165 /* hack for bcheck.c:dprintf(): one level, no newline */
1120 if (fmt[0] == '\001')1166 if (fmt[0] == '\001')
1121 ++fmt, one = 1;1167 ++fmt, one = 1;
1168 vsnprintf(msg, sizeof msg, fmt, ap);
1122 1169
1123 rt_wait_sem();1170 rt_wait_sem();
1124 rc = g_rc;1171 rc = g_rc;
1125 printline = rt_printline, n = 6;1172 getinfo = rt_printline, n = 6;
1126 if (rc) {1173 if (rc) {
1127 if (rc->dwarf)1174 if (rc->dwarf)
1128 printline = rt_printline_dwarf;1175 getinfo = rt_printline_dwarf;
1129 if (rc->num_callers)1176 if (rc->num_callers)
1130 n = rc->num_callers;1177 n = rc->num_callers;
1131 }1178 }
1179
1132 for (i = level = 0; level < n; i++) {1180 for (i = level = 0; level < n; i++) {
1133 ret = rt_get_caller_pc(&pc, f, i);1181 ret = rt_get_caller_pc(&pc, f, i);
1134 if (ret != -1) {1182 if (ret == -1)
1135 pc = printline(rc, pc, &rd, level ? "by" : "at", skip);1183 break;
1136 if (pc == (addr_t)-1)1184 memset(&bi, 0, sizeof bi);
1137 continue;1185 for (rc2 = rc; rc2; rc2 = rc2->next) {
1186 if (getinfo(rc2, pc, &bi))
1187 break;
1188 /* we try symtab symbols (no line number info) */
1189 if (!!(a = rt_elfsym(rc2, pc, &bi.func_pc))) {
1190 pstrcpy(bi.func, sizeof bi.func, a);
1191 break;
1192 }
1193 }
1194 //fprintf(stderr, "%d rc %p %p\n", i, (void*)pcfunc, (void*)pc);
1195 if (skip[0] && strstr(bi.file, skip))
1196 continue;
1197#ifndef CONFIG_TCC_BACKTRACE_ONLY
1198 {
1199 TCCState *s = rt_find_state(f);
1200 if (s && s->bt_func) {
1201 ret = s->bt_func(
1202 s->bt_data,
1203 (void*)pc,
1204 bi.file[0] ? bi.file : NULL,
1205 bi.line,
1206 bi.func[0] ? bi.func : NULL,
1207 level == 0 ? msg : NULL
1208 );
1209 if (ret == 0)
1210 break;
1211 goto check_break;
1212 }
1213 }
1214#endif
1215 if (bi.file[0]) {
1216 rt_printf("%s:%d", bi.file, bi.line);
1217 } else {
1218 rt_printf("0x%08llx", (long long)pc);
1138 }1219 }
1220 rt_printf(": %s %s", level ? "by" : "at", bi.func[0] ? bi.func : "???");
1139 if (level == 0) {1221 if (level == 0) {
1140 if (rd && rd->s1 && rd->s1->bt_func)1222 rt_printf(": %s", msg);
1223 if (one)
1141 break;1224 break;
1142 if (ret != -1)1225 }
1143 rt_printf(": ");
1144 if (msg)
1145 rt_printf("%s: ", msg);
1146 rt_vprintf(fmt, ap);
1147 } else if (ret == -1)
1148 break;
1149 if (one)
1150 break;
1151 rt_printf("\n");1226 rt_printf("\n");
1152 if (ret == -1 || (rd && pc == (addr_t)rd->top_func && pc))1227
1228 check_break:
1229 if (rc2
1230 && bi.func_pc
1231 && bi.func_pc == (addr_t)rc2->top_func)
1153 break;1232 break;
1154 ++level;1233 ++level;
1155 }1234 }
1156
1157 rt_post_sem();1235 rt_post_sem();
1158 return 0;1236 return 0;
1159}1237}
@@ -1161,49 +1239,14 @@ int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap) · 1 unmodified line
1161/* emit a run time error at position 'pc' */1239/* emit a run time error at position 'pc' */
1162static int rt_error(rt_frame *f, const char *fmt, ...)1240static int rt_error(rt_frame *f, const char *fmt, ...)
1163{1241{
1164 va_list ap;1242 va_list ap; char msg[200]; int ret;
1165 int ret;
1166 va_start(ap, fmt);1243 va_start(ap, fmt);
1167 ret = __rt_dump(f, "RUNTIME ERROR", fmt, ap);1244 snprintf(msg, sizeof msg, "RUNTIME ERROR: %s", fmt);
1245 ret = _tcc_backtrace(f, msg, ap);
1168 va_end(ap);1246 va_end(ap);
1169 return ret;1247 return ret;
1170}1248}
1171 1249
1172static TCCState *rt_find_state(rt_frame *f)
1173{
1174 TCCState *s;
1175 int level;
1176 addr_t pc;
1177
1178 rt_wait_sem();
1179 for (s = g_s1; s; s = s->next) {
1180 if (0 == s->run_lj)
1181 continue;
1182 for (level = 0; level < 8; ++level) {
1183 if (rt_get_caller_pc(&pc, f, level) < 0)
1184 break;
1185 if (pc >= (addr_t)s->run_ptr
1186 && pc < (addr_t)s->run_ptr + s->run_size)
1187 goto found;
1188 }
1189 }
1190found:
1191 rt_post_sem();
1192 //fprintf(stderr, "\nrt_state found %s %p %p\n", s ? "YES" : "NO", s, s->rc->top_func), fflush(stderr);
1193 return s;
1194}
1195
1196static void rt_longjmp(rt_frame *f, int code)
1197{
1198 TCCState *s = rt_find_state(f);
1199 if (s && s->run_lj) {
1200 if (code == 0)
1201 code = 256;
1202 ((void(*)(void*,int))s->run_lj)(s->run_jb, code);
1203 }
1204 exit(code);
1205}
1206
1207/* ------------------------------------------------------------- */1250/* ------------------------------------------------------------- */
1208 1251
1209#ifndef _WIN321252#ifndef _WIN32
@@ -1338,8 +1381,13 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc) · 128 unmodified lines
1338 rt_error(&f, "caught signal %d", signum);1381 rt_error(&f, "caught signal %d", signum);
1339 break;1382 break;
1340 }1383 }
1341 set_exception_handler();1384 {
1342 rt_longjmp(&f, 255);1385 sigset_t s;
1386 sigemptyset(&s);
1387 sigaddset(&s, signum);
1388 sigprocmask(SIG_UNBLOCK, &s, NULL);
1389 }
1390 rt_exit(&f, 255);
1343}1391}
1344 1392
1345#ifndef SA_SIGINFO1393#ifndef SA_SIGINFO
@@ -1353,12 +1401,11 @@ static void set_exception_handler(void) · 7 unmodified lines
1353 /* install TCC signal handlers to print debug info on fatal1401 /* install TCC signal handlers to print debug info on fatal
1354 runtime errors */1402 runtime errors */
1355 sigemptyset (&sigact.sa_mask);1403 sigemptyset (&sigact.sa_mask);
1356 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND | SA_NODEFER;1404 sigact.sa_flags = SA_SIGINFO; //| SA_RESETHAND;
1357#if 0//def SIGSTKSZ // this causes signals not to work at all on some (older) linuxes1405#if 0//def SIGSTKSZ // this causes signals not to work at all on some (older) linuxes
1358 sigact.sa_flags |= SA_ONSTACK;1406 sigact.sa_flags |= SA_ONSTACK;
1359#endif1407#endif
1360 sigact.sa_sigaction = sig_error;1408 sigact.sa_sigaction = sig_error;
1361 sigemptyset(&sigact.sa_mask);
1362 sigaction(SIGFPE, &sigact, NULL);1409 sigaction(SIGFPE, &sigact, NULL);
1363 sigaction(SIGILL, &sigact, NULL);1410 sigaction(SIGILL, &sigact, NULL);
1364 sigaction(SIGSEGV, &sigact, NULL);1411 sigaction(SIGSEGV, &sigact, NULL);
@@ -1406,7 +1453,7 @@ static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info) · 41 unmodified lines
1406 rt_error(&f, "caught exception %08x", code);1453 rt_error(&f, "caught exception %08x", code);
1407 break;1454 break;
1408 }1455 }
1409 rt_longjmp(&f, 255);1456 rt_exit(&f, 255);
1410 return EXCEPTION_EXECUTE_HANDLER;1457 return EXCEPTION_EXECUTE_HANDLER;
1411}1458}
1412 1459
@@ -1506,6 +1553,14 @@ static int rt_get_caller_pc(addr_t *paddr, rt_frame *rc, int level) · 93 unmodified lines
1506}1553}
1507 1554
1508#endif1555#endif
1556#else // for runmain.c:exit(); when CONFIG_TCC_BACKTRACE == 0 */
1557static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level)
1558{
1559 if (level)
1560 return -1;
1561 *paddr = f->ip;
1562 return 0;
1563}
1509#endif /* CONFIG_TCC_BACKTRACE */1564#endif /* CONFIG_TCC_BACKTRACE */
1510/* ------------------------------------------------------------- */1565/* ------------------------------------------------------------- */
1511#ifdef CONFIG_TCC_STATIC1566#ifdef CONFIG_TCC_STATIC
tests/Makefile+3−1
@@ -26,7 +26,9 @@ TESTS = \ · 25 unmodified lines
26# test4_static -- Not all relocation types are implemented yet.26# test4_static -- Not all relocation types are implemented yet.
27# asmtest / asmtest2 -- minor differences with gcc27# asmtest / asmtest2 -- minor differences with gcc
28 28
29ifneq ($(CONFIG_bcheck),no)29ifeq ($(CONFIG_backtrace),no)
30 TESTS := $(filter-out libtest_mt, $(TESTS))
31else ifneq ($(CONFIG_bcheck),no)
30 TESTS += btest test1b tccb32 TESTS += btest test1b tccb
31endif33endif
32ifeq ($(CONFIG_dll),no)34ifeq ($(CONFIG_dll),no)
tests/libtcc_test_mt.c+36−12
@@ -83,11 +83,13 @@ PROG(my_program) · 82 unmodified lines
83" return add(fib(n-1),fib(n-2));\n"83" return add(fib(n-1),fib(n-2));\n"
84"}\n"84"}\n"
85"\n"85"\n"
86"void bar(void) { *(void**)0 = 0; }\n"
87"\n"
86"int foo(int n)\n"88"int foo(int n)\n"
87"{\n"89"{\n"
88" if (n >= N_CRASH && n < N_CRASH + 3)\n"
89" *(void**)0 = 0;\n"
90" printf(\" %d\", fib(n));\n"90" printf(\" %d\", fib(n));\n"
91" if (n >= N_CRASH && n < N_CRASH + 8)\n"
92" bar();\n"
91" return 0;\n"93" return 0;\n"
92"# warning is this the correct file:line...\n"94"# warning is this the correct file:line...\n"
93"}\n";95"}\n";
@@ -113,9 +115,27 @@ void parse_args(TCCState *s) · 19 unmodified lines
113 }115 }
114}116}
115 117
116void bt_func(void *pc, const char *file, int line, const char *func)118int backtrace_func(
119 void *ud,
120 void *pc,
121 const char *file,
122 int line,
123 const char *func,
124 const char *msg)
117{125{
118 printf(" *** at %s:%d in '%s'\n", file, line, func);126#if 0
127 printf("\n *** %p %s %s:%d in '%s'",
128 pc,
129 msg ? "at" : "by",
130 file ? file : "?",
131 line,
132 func ? func : "?");
133 return 1; // want more backtrace levels
134#else
135 //printf(" [%d]", *(int*)ud);
136 printf("!");
137 return 0; // cancel backtrace
138#endif
119}139}
120 140
121TCCState *new_state(int w)141TCCState *new_state(int w)
@@ -132,9 +152,8 @@ TCCState *new_state(int w) · 10 unmodified lines
132 if (w & 2) {152 if (w & 2) {
133 tcc_set_options(s, "-bt");153 tcc_set_options(s, "-bt");
134 tcc_define_symbol(s, "N_CRASH", str(M/2));154 tcc_define_symbol(s, "N_CRASH", str(M/2));
135 tcc_set_backtrace_func(s, bt_func);
136 } else155 } else
137 tcc_define_symbol(s, "N_CRASH", "99");156 tcc_define_symbol(s, "N_CRASH", "-1000");
138 tcc_set_output_type(s, TCC_OUTPUT_MEMORY);157 tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
139 return s;158 return s;
140}159}
@@ -171,8 +190,7 @@ int state_test(int w) · 30 unmodified lines
171 if (c < M)190 if (c < M)
172 funcs[c] = reloc_state(s[c], "foo");191 funcs[c] = reloc_state(s[c], "foo");
173 if (d < M && funcs[d]) {192 if (d < M && funcs[d]) {
174 if ((w & 2) && d == 8)193 tcc_set_backtrace_func(s[d], &d, backtrace_func);
175 printf("\n");
176 if (0 == tcc_setjmp(s[d], jb, funcs[d]))194 if (0 == tcc_setjmp(s[d], jb, funcs[d]))
177 funcs[d](F(d));195 funcs[d](F(d));
178 }196 }
@@ -189,15 +207,19 @@ TF_TYPE(thread_test_simple, vn) · 10 unmodified lines
189 int (*func)(int);207 int (*func)(int);
190 int ret;208 int ret;
191 int n = (size_t)vn;209 int n = (size_t)vn;
210 jmp_buf jb;
192 211
193 s = new_state(0);212 s = new_state(0); /* '2' for exceptions */
194 sleep_ms(1);213 sleep_ms(1);
195 ret = tcc_compile_string(s, my_program);214 ret = tcc_compile_string(s, my_program);
196 sleep_ms(1);215 sleep_ms(1);
197 if (ret >= 0) {216 if (ret >= 0) {
198 func = reloc_state(s, "foo");217 func = reloc_state(s, "foo");
199 if (func)218 tcc_set_backtrace_func(s, &n, backtrace_func);
200 func(F(n));219 if (func) {
220 if (0 == tcc_setjmp(s, jb, func))
221 func(F(n));
222 }
201 }223 }
202 tcc_delete(s);224 tcc_delete(s);
203 return 0;225 return 0;
@@ -281,18 +303,20 @@ int main(int argc, char **argv) · 77 unmodified lines
281 printf("\n (%u ms)\n", getclock_ms() - t);303 printf("\n (%u ms)\n", getclock_ms() - t);
282#endif304#endif
283#if 1305#if 1
284 printf("producing some exceptions\n "), fflush(stdout);306 printf("producing some exceptions (!)\n "), fflush(stdout);
285 t = getclock_ms();307 t = getclock_ms();
286 state_test(2);308 state_test(2);
287 printf("\n (%u ms)\n", getclock_ms() - t);309 printf("\n (%u ms)\n", getclock_ms() - t);
288#endif310#endif
289#if 1311#if 1
312 //{ int i; for (i = 0; i < 100; ++i) { printf("(%d) ", i);
290 printf("running fib in threads\n "), fflush(stdout);313 printf("running fib in threads\n "), fflush(stdout);
291 t = getclock_ms();314 t = getclock_ms();
292 for (n = 0; n < M; ++n)315 for (n = 0; n < M; ++n)
293 create_thread(thread_test_simple, n);316 create_thread(thread_test_simple, n);
294 wait_threads(n);317 wait_threads(n);
295 printf("\n (%u ms)\n", getclock_ms() - t);318 printf("\n (%u ms)\n", getclock_ms() - t);
319 //}}
296#endif320#endif
297#if 1321#if 1
298 printf("running tcc.c in threads to run fib\n "), fflush(stdout);322 printf("running tcc.c in threads to run fib\n "), fflush(stdout);
tests/tcctest.c+1−1
@@ -3889,7 +3889,7 @@ static void builtin_test_bits(unsigned long long x, int cnt[]) · 3888 unmodified lines
3889 if ((unsigned long) x) cnt[7] += __builtin_ctzl(x);3889 if ((unsigned long) x) cnt[7] += __builtin_ctzl(x);
3890 if ((unsigned long long) x) cnt[8] += __builtin_ctzll(x);3890 if ((unsigned long long) x) cnt[8] += __builtin_ctzll(x);
3891 3891
3892#if CC_NAME != CC_clang || GCC_MAJOR >= 113892#if GCC_MAJOR >= 6 && (CC_NAME != CC_clang || GCC_MAJOR >= 11)
3893/* Apple clang 10 does not have __builtin_clrsb[l[l]] */3893/* Apple clang 10 does not have __builtin_clrsb[l[l]] */
3894 cnt[9] += __builtin_clrsb(x);3894 cnt[9] += __builtin_clrsb(x);
3895 cnt[10] += __builtin_clrsbl(x);3895 cnt[10] += __builtin_clrsbl(x);
win32/build-tcc.bat+1−0
@@ -202,4 +202,5 @@ exit /B %ERRORLEVEL% · 201 unmodified lines
202.\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o202.\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o
203.\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o203.\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o
204.\tcc -B. -m%1 -c ../lib/bt-dll.c -o lib/%2bt-dll.o204.\tcc -B. -m%1 -c ../lib/bt-dll.c -o lib/%2bt-dll.o
205.\tcc -B. -m%1 -c ../lib/runmain.c -o lib/%2runmain.o
205exit /B %ERRORLEVEL%206exit /B %ERRORLEVEL%
win32/include/malloc.h+2−2
@@ -62,8 +62,8 @@ extern "C" { · 61 unmodified lines
62 void *__cdecl malloc(size_t _Size);62 void *__cdecl malloc(size_t _Size);
63 void *__cdecl realloc(void *_Memory,size_t _NewSize);63 void *__cdecl realloc(void *_Memory,size_t _NewSize);
64 _CRTIMP void *__cdecl _recalloc(void *_Memory,size_t _Count,size_t _Size);64 _CRTIMP void *__cdecl _recalloc(void *_Memory,size_t _Count,size_t _Size);
65 /* _CRTIMP void __cdecl _aligned_free(void *_Memory);65 _CRTIMP void __cdecl _aligned_free(void *_Memory);
66 _CRTIMP void *__cdecl _aligned_malloc(size_t _Size,size_t _Alignment); */66 _CRTIMP void *__cdecl _aligned_malloc(size_t _Size,size_t _Alignment);
67 _CRTIMP void *__cdecl _aligned_offset_malloc(size_t _Size,size_t _Alignment,size_t _Offset);67 _CRTIMP void *__cdecl _aligned_offset_malloc(size_t _Size,size_t _Alignment,size_t _Offset);
68 _CRTIMP void *__cdecl _aligned_realloc(void *_Memory,size_t _Size,size_t _Alignment);68 _CRTIMP void *__cdecl _aligned_realloc(void *_Memory,size_t _Size,size_t _Alignment);
69 _CRTIMP void *__cdecl _aligned_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment);69 _CRTIMP void *__cdecl _aligned_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment);
win32/include/stdlib.h+2−2
@@ -403,8 +403,8 @@ extern "C" { · 402 unmodified lines
403 void *__cdecl malloc(size_t _Size);403 void *__cdecl malloc(size_t _Size);
404 void *__cdecl realloc(void *_Memory,size_t _NewSize);404 void *__cdecl realloc(void *_Memory,size_t _NewSize);
405 _CRTIMP void *__cdecl _recalloc(void *_Memory,size_t _Count,size_t _Size);405 _CRTIMP void *__cdecl _recalloc(void *_Memory,size_t _Count,size_t _Size);
406 //_CRTIMP void __cdecl _aligned_free(void *_Memory);406 _CRTIMP void __cdecl _aligned_free(void *_Memory);
407 //_CRTIMP void *__cdecl _aligned_malloc(size_t _Size,size_t _Alignment);407 _CRTIMP void *__cdecl _aligned_malloc(size_t _Size,size_t _Alignment);
408 _CRTIMP void *__cdecl _aligned_offset_malloc(size_t _Size,size_t _Alignment,size_t _Offset);408 _CRTIMP void *__cdecl _aligned_offset_malloc(size_t _Size,size_t _Alignment,size_t _Offset);
409 _CRTIMP void *__cdecl _aligned_realloc(void *_Memory,size_t _Size,size_t _Alignment);409 _CRTIMP void *__cdecl _aligned_realloc(void *_Memory,size_t _Size,size_t _Alignment);
410 _CRTIMP void *__cdecl _aligned_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment);410 _CRTIMP void *__cdecl _aligned_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment);
win32/lib/crt1.c+0−2
@@ -70,7 +70,6 @@ void _tstart(void) · 69 unmodified lines
70// =============================================70// =============================================
71// for 'tcc -run ,,,'71// for 'tcc -run ,,,'
72 72
73__attribute__((weak)) extern int __rt_nr_exit;
74__attribute__((weak)) extern int __run_on_exit();73__attribute__((weak)) extern int __run_on_exit();
75 74
76int _runtmain(int argc, /* as tcc passed in */ char **argv)75int _runtmain(int argc, /* as tcc passed in */ char **argv)
@@ -92,7 +91,6 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv) · 15 unmodified lines
92#if defined __i386__ || defined __x86_64__91#if defined __i386__ || defined __x86_64__
93 _controlfp(_PC_53, _MCW_PC);92 _controlfp(_PC_53, _MCW_PC);
94#endif93#endif
95 __rt_nr_exit = 0;
96 run_ctors(__argc, __targv, _tenviron);94 run_ctors(__argc, __targv, _tenviron);
97 ret = _tmain(__argc, __targv, _tenviron);95 ret = _tmain(__argc, __targv, _tenviron);
98 run_dtors();96 run_dtors();

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