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
This commit is contained in:
parent
c88b19966c
commit
d2f8ceac7a
18 changed files with 404 additions and 321 deletions
6
Makefile
6
Makefile
|
@ -386,13 +386,13 @@ IR = $(IM) mkdir -p $2 && cp -r $1/. $2
|
|||
IM = @echo "-> $2 : $1" ;
|
||||
BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1)
|
||||
|
||||
B_O = runmain.o bt-exe.o bt-dll.o bcheck.o
|
||||
EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
||||
|
||||
# install progs & libs
|
||||
install-unx:
|
||||
$(call BINCHECK)
|
||||
$(call IBw,$(PROGS) *-tcc,"$(bindir)")
|
||||
$(call IFw,$(LIBTCC1) $(B_O) $(LIBTCC1_U),"$(tccdir)")
|
||||
$(call IFw,$(LIBTCC1) $(EXTRA_O) $(LIBTCC1_U),"$(tccdir)")
|
||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
||||
$(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")
|
||||
$(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")
|
||||
|
@ -419,7 +419,7 @@ install-win:
|
|||
$(call BINCHECK)
|
||||
$(call IBw,$(PROGS) *-tcc.exe libtcc.dll,"$(bindir)")
|
||||
$(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")
|
||||
$(call IFw,libtcc1.a $(B_O) $(LIBTCC1_W),"$(tccdir)/lib")
|
||||
$(call IFw,libtcc1.a $(EXTRA_O) $(LIBTCC1_W),"$(tccdir)/lib")
|
||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
||||
$(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")
|
||||
$(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")
|
||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -365,7 +365,7 @@ case $targetos in
|
|||
default tcc_libpaths "{B}:{R}/lib:/system/lib${S}"
|
||||
default tcc_crtprefix "{R}/lib"
|
||||
default tcc_elfinterp "/system/bin/linker${S}"
|
||||
default tcc_switches "-Wl,-rpath=$sysroot/lib,-section-alignment=0x1000"
|
||||
default tcc_switches "-Wl,-rpath=$sysroot/lib"
|
||||
;;
|
||||
WIN32)
|
||||
mingw32="yes"
|
||||
|
|
|
@ -40,7 +40,7 @@ endif
|
|||
$(X)BT_O = bt-exe.o bt-log.o
|
||||
$(X)B_O = $(BCHECK_O) bt-exe.o bt-log.o bt-dll.o
|
||||
endif
|
||||
$(X)BT_O += tcov.o
|
||||
$(X)BT_O += runmain.o tcov.o
|
||||
|
||||
DSO_O = dsohandle.o
|
||||
|
||||
|
@ -67,8 +67,7 @@ OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
|
|||
OBJ-arm-wince = $(ARM_O) $(WIN_O)
|
||||
OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O)
|
||||
|
||||
OBJ-extra = $(filter-out bt-log.o,$(filter $(B_O),$(OBJ-$T)))
|
||||
OBJ-extra += runmain.o
|
||||
OBJ-extra = $(filter $(B_O) runmain.o,$(OBJ-$T))
|
||||
OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
|
||||
|
||||
ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra))
|
||||
|
|
|
@ -23,19 +23,19 @@ typedef struct rt_frame {
|
|||
} rt_frame;
|
||||
|
||||
__attribute__((weak))
|
||||
int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap);
|
||||
int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap);
|
||||
|
||||
DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
if (__rt_dump) {
|
||||
if (_tcc_backtrace) {
|
||||
rt_frame f;
|
||||
f.fp = __builtin_frame_address(1);
|
||||
f.ip = __builtin_return_address(0);
|
||||
va_start(ap, fmt);
|
||||
ret = __rt_dump(&f, NULL, fmt, ap);
|
||||
ret = _tcc_backtrace(&f, fmt, ap);
|
||||
va_end(ap);
|
||||
} else {
|
||||
const char *p, *nl = "\n";
|
||||
|
|
|
@ -29,7 +29,7 @@ static void run_dtors(void)
|
|||
|
||||
static void *rt_exitfunc[32];
|
||||
static void *rt_exitarg[32];
|
||||
int __rt_nr_exit;
|
||||
static int __rt_nr_exit;
|
||||
|
||||
void __run_on_exit(int ret)
|
||||
{
|
||||
|
@ -59,16 +59,16 @@ typedef struct rt_frame {
|
|||
void *ip, *fp, *sp;
|
||||
} rt_frame;
|
||||
|
||||
void __rt_longjmp(rt_frame *, int);
|
||||
void __rt_exit(rt_frame *, int);
|
||||
|
||||
void exit(int code)
|
||||
{
|
||||
rt_frame f;
|
||||
run_dtors();
|
||||
__run_on_exit(code);
|
||||
f.fp = __builtin_frame_address(1);
|
||||
f.ip = __builtin_return_address(0);
|
||||
__rt_longjmp(&f, code);
|
||||
f.fp = 0;
|
||||
f.ip = exit;
|
||||
__rt_exit(&f, code);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -77,7 +77,6 @@ int main(int, char**, char**);
|
|||
int _runmain(int argc, char **argv, char **envp)
|
||||
{
|
||||
int ret;
|
||||
__rt_nr_exit = 0;
|
||||
run_ctors(argc, argv, envp);
|
||||
ret = main(argc, argv, envp);
|
||||
run_dtors();
|
||||
|
|
2
libtcc.c
2
libtcc.c
|
@ -229,7 +229,7 @@ static void *default_reallocator(void *ptr, unsigned long size)
|
|||
return ptr1;
|
||||
}
|
||||
|
||||
static void libc_free(void *ptr)
|
||||
ST_FUNC void libc_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
|
10
libtcc.h
10
libtcc.h
|
@ -104,12 +104,12 @@ LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
|
|||
|
||||
/* catch runtime exceptions (optionally limit backtraces at top_func),
|
||||
when using tcc_set_options("-bt") and when not using tcc_run() */
|
||||
LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *longjmp, void *jmp_buf, void *top_func);
|
||||
#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, longjmp, jb, f))
|
||||
LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp);
|
||||
#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp))
|
||||
|
||||
/* set custom error printer for runtime exceptions */
|
||||
typedef void TCCBtFunc(void *pc, const char *file, int line, const char* func);
|
||||
LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, TCCBtFunc*);
|
||||
/* custom error printer for runtime exceptions. Returning 0 stops backtrace */
|
||||
typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg);
|
||||
LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
7
tcc.h
7
tcc.h
|
@ -1003,7 +1003,9 @@ struct TCCState {
|
|||
struct TCCState *next;
|
||||
struct rt_context *rc; /* pointer to backtrace info block */
|
||||
void *run_lj, *run_jb; /* sj/lj for tcc_setjmp()/tcc_run() */
|
||||
void (*bt_func)(void *, const char*, int, const char*);
|
||||
TCCBtFunc *bt_func;
|
||||
void *bt_data;
|
||||
int run_tid;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
|
@ -1250,6 +1252,7 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file
|
|||
PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
|
||||
#endif
|
||||
|
||||
ST_FUNC void libc_free(void *ptr);
|
||||
#define free(p) use_tcc_free(p)
|
||||
#define malloc(s) use_tcc_malloc(s)
|
||||
#define realloc(p, s) use_tcc_realloc(p, s)
|
||||
|
@ -1982,7 +1985,7 @@ ST_FUNC void wait_sem(TCCSem *p)
|
|||
sem_init(&p->sem, 0, 1), p->init = 1;
|
||||
while (sem_wait(&p->sem) < 0 && errno == EINTR);
|
||||
}
|
||||
ST_INLN void post_sem(TCCSem *p)
|
||||
ST_FUNC void post_sem(TCCSem *p)
|
||||
{
|
||||
sem_post(&p->sem);
|
||||
}
|
||||
|
|
8
tccelf.c
8
tccelf.c
|
@ -1606,7 +1606,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
|||
(uint64_t)1 << 32);
|
||||
#endif
|
||||
}
|
||||
n = 4 * PTR_SIZE;
|
||||
n = 3 * PTR_SIZE;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (s1->do_bounds_check) {
|
||||
put_ptr(s1, bounds_section, 0);
|
||||
|
@ -1617,9 +1617,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
|||
p = section_ptr_add(s, 2 * sizeof (int));
|
||||
p[0] = s1->rt_num_callers;
|
||||
p[1] = s1->dwarf;
|
||||
|
||||
if (s->data_offset - o != 11 * PTR_SIZE + 2 * sizeof (int))
|
||||
exit(99);
|
||||
// if (s->data_offset - o != 10*PTR_SIZE + 2*sizeof (int)) exit(99);
|
||||
|
||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
||||
set_global_sym(s1, __rt_info, s, o);
|
||||
|
@ -1778,6 +1776,8 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
|||
if (s1->do_backtrace) {
|
||||
if (s1->output_type & TCC_OUTPUT_EXE)
|
||||
tcc_add_support(s1, "bt-exe.o");
|
||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||
tcc_add_support(s1, "bt-log.o");
|
||||
tcc_add_btstub(s1);
|
||||
lpthread = 1;
|
||||
}
|
||||
|
|
4
tccpe.c
4
tccpe.c
|
@ -1943,7 +1943,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
|||
pe_type = PE_EXE;
|
||||
|
||||
}
|
||||
if (TCC_OUTPUT_MEMORY == s1->output_type)
|
||||
if (TCC_OUTPUT_MEMORY == s1->output_type && !s1->nostdlib)
|
||||
start_symbol = run_symbol;
|
||||
}
|
||||
|
||||
|
@ -1961,6 +1961,8 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
|||
tcc_add_support(s1, "bt-exe.o");
|
||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||
tcc_add_support(s1, "bt-dll.o");
|
||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||
tcc_add_support(s1, "bt-log.o");
|
||||
tcc_add_btstub(s1);
|
||||
}
|
||||
#endif
|
||||
|
|
599
tccrun.c
599
tccrun.c
|
@ -24,6 +24,7 @@
|
|||
#ifdef TCC_IS_NATIVE
|
||||
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
/* runtime debug info block */
|
||||
typedef struct rt_context
|
||||
{
|
||||
/* tccelf.c:tcc_add_btstub() wants these in that order: */
|
||||
|
@ -42,32 +43,33 @@ typedef struct rt_context
|
|||
ElfW(Sym) *esym_start;
|
||||
ElfW(Sym) *esym_end;
|
||||
char *elf_str;
|
||||
// 6
|
||||
// 6 * PTR_SIZE
|
||||
addr_t prog_base;
|
||||
void *bounds_start;
|
||||
void *top_func;
|
||||
TCCState *s1;
|
||||
struct rt_context *next;
|
||||
// 11
|
||||
// 10 * PTR_SIZE
|
||||
int num_callers;
|
||||
int dwarf;
|
||||
} rt_context; /* size = 11 * PTR_SIZE + 2 * sizeof (int) */
|
||||
} rt_context;
|
||||
|
||||
/* linked list of rt_contexts */
|
||||
static rt_context *g_rc;
|
||||
static int signal_set;
|
||||
static void set_exception_handler(void);
|
||||
#endif /* def CONFIG_TCC_BACKTRACE */
|
||||
|
||||
typedef struct rt_frame {
|
||||
addr_t ip, fp, sp;
|
||||
} rt_frame;
|
||||
|
||||
/* linked list of rt_contexts */
|
||||
static rt_context *g_rc;
|
||||
static TCCState *g_s1;
|
||||
/* semaphore to protect it */
|
||||
TCC_SEM(static rt_sem);
|
||||
static int signal_set;
|
||||
static void set_exception_handler(void);
|
||||
static void rt_wait_sem(void) { WAIT_SEM(&rt_sem); }
|
||||
static void rt_post_sem(void) { POST_SEM(&rt_sem); }
|
||||
static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level);
|
||||
#endif /* def CONFIG_TCC_BACKTRACE */
|
||||
static void rt_exit(rt_frame *f, int code);
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* 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);
|
|||
|
||||
static int protect_pages(void *ptr, unsigned long length, int mode);
|
||||
static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff);
|
||||
static int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap);
|
||||
static void rt_longjmp(rt_frame *f, int code);
|
||||
static void st_link(TCCState *s1);
|
||||
static void st_unlink(TCCState *s1);
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
static int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap);
|
||||
#endif
|
||||
#ifdef _WIN64
|
||||
static void *win64_add_function_table(TCCState *s1);
|
||||
static void win64_del_function_table(void *);
|
||||
#endif
|
||||
|
||||
static void bt_link(TCCState *s1)
|
||||
{
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
rt_context *rc;
|
||||
void *p;
|
||||
|
||||
if (!s1->do_backtrace)
|
||||
return;
|
||||
rc = tcc_get_symbol(s1, "__rt_info");
|
||||
if (!rc)
|
||||
return;
|
||||
rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
|
||||
rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
||||
rc->elf_str = (char *)symtab_section->link->data;
|
||||
if (PTR_SIZE == 8 && !s1->dwarf)
|
||||
rc->prog_base &= 0xffffffff00000000ULL;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (s1->do_bounds_check) {
|
||||
if ((p = tcc_get_symbol(s1, "__bound_init")))
|
||||
((void(*)(void*,int))p)(rc->bounds_start, 1);
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
# define CONFIG_RUNMEM_ALIGNED 0
|
||||
#else
|
||||
# ifndef CONFIG_RUNMEM_ALIGNED
|
||||
# define CONFIG_RUNMEM_ALIGNED 1
|
||||
# endif
|
||||
# if CONFIG_RUNMEM_ALIGNED
|
||||
# include <malloc.h> /* memalign() */
|
||||
# endif
|
||||
#endif
|
||||
rc->next = g_rc, g_rc = rc, rc->s1 = s1, s1->rc = rc;
|
||||
if (0 == signal_set)
|
||||
set_exception_handler(), signal_set = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void bt_unlink(TCCState *s1)
|
||||
{
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
rt_context *rc, **pp;
|
||||
for (pp = &g_rc; rc = *pp, rc; pp = &rc->next)
|
||||
if (rc->s1 == s1) {
|
||||
*pp = rc->next;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void st_link(TCCState *s1)
|
||||
{
|
||||
rt_wait_sem();
|
||||
s1->next = g_s1, g_s1 = s1;
|
||||
bt_link(s1);
|
||||
rt_post_sem();
|
||||
}
|
||||
|
||||
static void st_unlink(TCCState *s1)
|
||||
{
|
||||
TCCState *s2, **pp;
|
||||
rt_wait_sem();
|
||||
bt_unlink(s1);
|
||||
for (pp = &g_s1; s2 = *pp, s2; pp = &s2->next)
|
||||
if (s2 == s1) {
|
||||
*pp = s2->next;
|
||||
break;
|
||||
}
|
||||
rt_post_sem();
|
||||
}
|
||||
|
||||
#if !_WIN32 && !__APPLE__
|
||||
//#define HAVE_SELINUX 1
|
||||
|
@ -172,7 +127,15 @@ static int rt_mem(TCCState *s1, int size)
|
|||
ptr_diff = (char*)prw - (char*)ptr; /* = size; */
|
||||
//printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff);
|
||||
#else
|
||||
ptr = tcc_malloc(size);
|
||||
# if !CONFIG_RUNMEM_ALIGNED
|
||||
ptr = tcc_malloc(size += PAGESIZE);
|
||||
# elif _WIN32
|
||||
ptr = _aligned_malloc(size, PAGESIZE);
|
||||
# else
|
||||
ptr = memalign(PAGESIZE, size);
|
||||
# endif
|
||||
if (NULL == ptr)
|
||||
return tcc_error_noabort("tccrun: could not allocate memory");
|
||||
#endif
|
||||
s1->run_ptr = ptr;
|
||||
s1->run_size = size;
|
||||
|
@ -189,12 +152,10 @@ LIBTCCAPI int tcc_relocate(TCCState *s1)
|
|||
|
||||
if (s1->run_ptr)
|
||||
exit(tcc_error_noabort("'tcc_relocate()' twice is no longer supported"));
|
||||
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
if (s1->do_backtrace)
|
||||
tcc_add_symbol(s1, "__rt_dump", __rt_dump); /* for bt-log.c */
|
||||
tcc_add_symbol(s1, "_tcc_backtrace", _tcc_backtrace); /* for bt-log.c */
|
||||
#endif
|
||||
|
||||
size = tcc_relocate_ex(s1, NULL, 0);
|
||||
if (size < 0)
|
||||
return -1;
|
||||
|
@ -236,31 +197,24 @@ ST_FUNC void tcc_run_free(TCCState *s1)
|
|||
#else
|
||||
/* unprotect memory to make it usable for malloc again */
|
||||
protect_pages(ptr, size, 2 /*rw*/);
|
||||
#ifdef _WIN64
|
||||
# ifdef _WIN64
|
||||
win64_del_function_table(s1->run_function_table);
|
||||
#endif
|
||||
# endif
|
||||
# if !CONFIG_RUNMEM_ALIGNED
|
||||
tcc_free(ptr);
|
||||
# elif _WIN32
|
||||
_aligned_free(ptr);
|
||||
# else
|
||||
libc_free(ptr);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *p_longjmp, void *p_jmp_buf, void *func)
|
||||
{
|
||||
s1->run_lj = p_longjmp;
|
||||
s1->run_jb = p_jmp_buf;
|
||||
if (func && s1->rc)
|
||||
s1->rc->top_func = func;
|
||||
return p_jmp_buf;
|
||||
}
|
||||
|
||||
LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, TCCBtFunc *func)
|
||||
{
|
||||
s1->bt_func = func;
|
||||
}
|
||||
|
||||
/* launch the compiled program with the given arguments */
|
||||
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
{
|
||||
int (*prog_main)(int, char **, char **), ret;
|
||||
const char *top_sym;
|
||||
jmp_buf main_jb;
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
|
@ -276,20 +230,25 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||
if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, "main", 0, 1))
|
||||
return 0;
|
||||
|
||||
tcc_add_support(s1, "runmain.o");
|
||||
tcc_add_symbol(s1, "__rt_longjmp", rt_longjmp);
|
||||
s1->run_main = (s1->nostdlib ? "_start" : "_runmain");
|
||||
tcc_add_symbol(s1, "__rt_exit", rt_exit);
|
||||
if (s1->nostdlib) {
|
||||
s1->run_main = top_sym = "_start";
|
||||
} else {
|
||||
tcc_add_support(s1, "runmain.o");
|
||||
s1->run_main = "_runmain";
|
||||
top_sym = "main";
|
||||
}
|
||||
if (tcc_relocate(s1) < 0)
|
||||
return -1;
|
||||
return 1;
|
||||
|
||||
prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1);
|
||||
if ((addr_t)-1 == (addr_t)prog_main)
|
||||
return -1;
|
||||
return 1;
|
||||
errno = 0; /* clean errno value */
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, "main"));
|
||||
ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym));
|
||||
if (0 == ret)
|
||||
ret = prog_main(argc, argv, envp);
|
||||
else if (256 == ret)
|
||||
|
@ -344,8 +303,6 @@ static void cleanup_sections(TCCState *s1)
|
|||
# define CONFIG_RUNMEM_RO 1
|
||||
#endif
|
||||
|
||||
#define DEBUG_RUNMEN 0
|
||||
|
||||
/* relocate code. Return -1 on error, required size if ptr is NULL,
|
||||
otherwise copy code into buffer passed by the caller */
|
||||
static 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)
|
|||
|
||||
offset = copy = 0;
|
||||
mem = (addr_t)ptr;
|
||||
|
||||
#if DEBUG_RUNMEN
|
||||
if (mem)
|
||||
fprintf(stderr, "X: <base> %p len %5x\n",
|
||||
ptr, s1->run_size);
|
||||
#endif
|
||||
|
||||
redo:
|
||||
if (s1->verbose == 2 && copy) {
|
||||
printf(&"-----------------------------------------------------\n"[PTR_SIZE*2 - 8]);
|
||||
if (1 == copy)
|
||||
printf("memory %p len %05x\n", ptr, s1->run_size);
|
||||
}
|
||||
if (s1->nb_errors)
|
||||
return -1;
|
||||
if (copy == 2)
|
||||
return 0;
|
||||
|
||||
for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
|
||||
n = 0; addr = 0;
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
|
@ -389,7 +347,9 @@ redo:
|
|||
length = s->data_offset;
|
||||
|
||||
if (copy) { /* final step: copy section data to memory */
|
||||
void *ptr;
|
||||
if (s1->verbose == 2)
|
||||
printf("%d: %-16s %p len %05x align %04x\n",
|
||||
k, s->name, (void*)s->sh_addr, length, s->sh_addralign);
|
||||
if (addr == 0)
|
||||
addr = s->sh_addr;
|
||||
n = (s->sh_addr - addr) + length;
|
||||
|
@ -407,28 +367,25 @@ redo:
|
|||
continue;
|
||||
}
|
||||
|
||||
align = s->sh_addralign - 1;
|
||||
align = s->sh_addralign;
|
||||
if (++n == 1) {
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
/* To avoid that x86 processors would reload cached instructions
|
||||
each time when data is written in the near, we need to make
|
||||
sure that code and data do not share the same 64 byte unit */
|
||||
if (align < 63)
|
||||
align = 63;
|
||||
if (align < 64)
|
||||
align = 64;
|
||||
#endif
|
||||
/* start new page for different permissions */
|
||||
if (CONFIG_RUNMEM_RO || k < 2)
|
||||
align = PAGESIZE - 1;
|
||||
align = PAGESIZE;
|
||||
}
|
||||
s->sh_addralign = align;
|
||||
|
||||
addr = k ? mem + ptr_diff : mem;
|
||||
offset += -(addr + offset) & align;
|
||||
offset += -(addr + offset) & (align - 1);
|
||||
s->sh_addr = mem ? addr + offset : 0;
|
||||
offset += length;
|
||||
#if DEBUG_RUNMEN
|
||||
if (mem)
|
||||
fprintf(stderr, "%d: %-16s %p len %5x align %04x\n",
|
||||
k, s->name, (void*)s->sh_addr, length, align + 1);
|
||||
#endif
|
||||
}
|
||||
if (copy) { /* set permissions */
|
||||
if (n == 0) /* no data */
|
||||
|
@ -443,30 +400,25 @@ redo:
|
|||
continue;
|
||||
f = 3; /* change only SHF_EXECINSTR to rwx */
|
||||
}
|
||||
#if DEBUG_RUNMEN
|
||||
fprintf(stderr, "protect %3s %p len %5x\n",
|
||||
&"rx\0r \0rw\0rwx"[f*3],
|
||||
(void*)addr, (unsigned)((n + PAGESIZE-1) & ~(PAGESIZE-1)));
|
||||
#endif
|
||||
n = (n + PAGESIZE-1) & ~(PAGESIZE-1);
|
||||
if (s1->verbose == 2) {
|
||||
printf("protect %3s %p len %05x\n",
|
||||
&"rx\0r \0rw\0rwx"[f*3], (void*)addr, (unsigned)n);
|
||||
}
|
||||
if (protect_pages((void*)addr, n, f) < 0)
|
||||
return tcc_error_noabort(
|
||||
"mprotect failed (did you mean to configure --with-selinux?)");
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == mem) {
|
||||
offset = (offset + (PAGESIZE-1)) & ~(PAGESIZE-1);
|
||||
#ifndef HAVE_SELINUX
|
||||
offset += PAGESIZE; /* extra space to align malloc memory start */
|
||||
#endif
|
||||
return offset;
|
||||
}
|
||||
if (0 == mem)
|
||||
return (offset + (PAGESIZE-1)) & ~(PAGESIZE-1);
|
||||
|
||||
if (copy) {
|
||||
if (++copy == 2) {
|
||||
/* remove local symbols and free sections except symtab */
|
||||
cleanup_symbols(s1);
|
||||
cleanup_sections(s1);
|
||||
return 0;
|
||||
goto redo;
|
||||
}
|
||||
|
||||
/* relocate symbols */
|
||||
|
@ -478,7 +430,6 @@ redo:
|
|||
relocate_plt(s1);
|
||||
#endif
|
||||
relocate_sections(s1);
|
||||
copy = 1;
|
||||
goto redo;
|
||||
}
|
||||
|
||||
|
@ -546,6 +497,152 @@ static void win64_del_function_table(void *p)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void bt_link(TCCState *s1)
|
||||
{
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
rt_context *rc;
|
||||
void *p;
|
||||
|
||||
if (!s1->do_backtrace)
|
||||
return;
|
||||
rc = tcc_get_symbol(s1, "__rt_info");
|
||||
if (!rc)
|
||||
return;
|
||||
rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
|
||||
rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
||||
rc->elf_str = (char *)symtab_section->link->data;
|
||||
if (PTR_SIZE == 8 && !s1->dwarf)
|
||||
rc->prog_base &= 0xffffffff00000000ULL;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (s1->do_bounds_check) {
|
||||
if ((p = tcc_get_symbol(s1, "__bound_init")))
|
||||
((void(*)(void*,int))p)(rc->bounds_start, 1);
|
||||
}
|
||||
#endif
|
||||
rc->next = g_rc, g_rc = rc, s1->rc = rc;
|
||||
if (0 == signal_set)
|
||||
set_exception_handler(), signal_set = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void st_link(TCCState *s1)
|
||||
{
|
||||
rt_wait_sem();
|
||||
s1->next = g_s1, g_s1 = s1;
|
||||
bt_link(s1);
|
||||
rt_post_sem();
|
||||
}
|
||||
|
||||
/* remove 'el' from 'list' */
|
||||
static void ptr_unlink(void *list, void *e, unsigned next)
|
||||
{
|
||||
void **pp, **nn, *p;
|
||||
for (pp = list; !!(p = *pp); pp = nn) {
|
||||
nn = (void*)((char*)p + next); /* nn = &p->next; */
|
||||
if (p == e) {
|
||||
*pp = *nn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void st_unlink(TCCState *s1)
|
||||
{
|
||||
rt_wait_sem();
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
ptr_unlink(&g_rc, s1->rc, offsetof(rt_context, next));
|
||||
#endif
|
||||
ptr_unlink(&g_s1, s1, offsetof(TCCState, next));
|
||||
rt_post_sem();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
# define GETTID() GetCurrentThreadId()
|
||||
#elif defined __linux__
|
||||
# define GETTID() gettid()
|
||||
#elif 0
|
||||
# define GETTID() 1234 // threads not supported
|
||||
#endif
|
||||
|
||||
LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *p_jmp_buf, void *func, void *p_longjmp)
|
||||
{
|
||||
#ifdef GETTID
|
||||
int tid = GETTID();
|
||||
TCCState *s;
|
||||
rt_wait_sem();
|
||||
for (s = g_s1; s; s = s->next)
|
||||
if (s->run_tid == tid)
|
||||
s->run_tid = -1;
|
||||
s1->run_tid = (int)tid;
|
||||
rt_post_sem();
|
||||
#endif
|
||||
s1->run_lj = p_longjmp;
|
||||
s1->run_jb = p_jmp_buf;
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
if (s1->rc)
|
||||
s1->rc->top_func = func;
|
||||
#endif
|
||||
return p_jmp_buf;
|
||||
}
|
||||
|
||||
LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void *data, TCCBtFunc *func)
|
||||
{
|
||||
s1->bt_func = func;
|
||||
s1->bt_data = data;
|
||||
}
|
||||
|
||||
static TCCState *rt_find_state(rt_frame *f)
|
||||
{
|
||||
#ifdef GETTID
|
||||
int tid = GETTID();
|
||||
TCCState *s;
|
||||
for (s = g_s1; s; s = s->next)
|
||||
if (s->run_tid == tid)
|
||||
break;
|
||||
return s;
|
||||
#else
|
||||
TCCState *s;
|
||||
int level;
|
||||
addr_t pc;
|
||||
|
||||
s = g_s1;
|
||||
if (NULL == s || NULL == s->next) {
|
||||
/* play it safe in the simple case when there is only one state */
|
||||
return s;
|
||||
}
|
||||
for (level = 0; level < 8; ++level) {
|
||||
if (rt_get_caller_pc(&pc, f, level) < 0)
|
||||
break;
|
||||
for (s = g_s1; s; s = s->next) {
|
||||
if (pc >= (addr_t)s->run_ptr
|
||||
&& pc < (addr_t)s->run_ptr + s->run_size)
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rt_exit(rt_frame *f, int code)
|
||||
{
|
||||
TCCState *s;
|
||||
rt_wait_sem();
|
||||
s = rt_find_state(f);
|
||||
rt_post_sem();
|
||||
if (s && s->run_lj) {
|
||||
if (code == 0)
|
||||
code = 256;
|
||||
((void(*)(void*,int))s->run_lj)(s->run_jb, code);
|
||||
}
|
||||
exit(code);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#else // if defined CONFIG_TCC_BACKTRACE_ONLY
|
||||
static void rt_exit(rt_frame *f, int code)
|
||||
{
|
||||
exit(code);
|
||||
}
|
||||
#endif //ndef CONFIG_TCC_BACKTRACE_ONLY
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
|
@ -582,11 +679,17 @@ static char *rt_elfsym(rt_context *rc, addr_t wanted_pc, addr_t *func_addr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct bt_info
|
||||
{
|
||||
char file[100];
|
||||
int line;
|
||||
char func[100];
|
||||
addr_t func_pc;
|
||||
} bt_info;
|
||||
|
||||
/* print the position in the source file of PC value 'pc' by reading
|
||||
the stabs debug information */
|
||||
static addr_t rt_printline (rt_context *rc, addr_t wanted_pc,
|
||||
rt_context** prc, const char *msg, const char *skip)
|
||||
static addr_t rt_printline (rt_context *rc, addr_t wanted_pc, bt_info *bi)
|
||||
{
|
||||
char func_name[128];
|
||||
addr_t func_addr, last_pc, pc;
|
||||
|
@ -595,15 +698,12 @@ static addr_t rt_printline (rt_context *rc, addr_t wanted_pc,
|
|||
const char *str, *p;
|
||||
Stab_Sym *sym;
|
||||
|
||||
next:
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
incl_index = 0;
|
||||
last_pc = (addr_t)-1;
|
||||
last_line_num = 1;
|
||||
last_incl_index = 0;
|
||||
if (NULL == rc)
|
||||
goto found;
|
||||
|
||||
for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) {
|
||||
str = rc->stab_str + sym->n_strx;
|
||||
|
@ -680,50 +780,15 @@ next:
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
last_incl_index = 0;
|
||||
|
||||
/* we try symtab symbols (no line number info) */
|
||||
p = rt_elfsym(rc, wanted_pc, &func_addr);
|
||||
if (p) {
|
||||
pstrcpy(func_name, sizeof func_name, p);
|
||||
goto found;
|
||||
}
|
||||
rc = rc->next;
|
||||
goto next;
|
||||
|
||||
last_incl_index = 0, func_name[0] = 0, func_addr = 0;
|
||||
found:
|
||||
i = last_incl_index;
|
||||
str = NULL;
|
||||
if (i > 0) {
|
||||
str = incl_files[--i];
|
||||
if (skip[0] && strstr(str, skip))
|
||||
return (addr_t)-1;
|
||||
pstrcpy(bi->file, sizeof bi->file, incl_files[--i]);
|
||||
bi->line = last_line_num;
|
||||
}
|
||||
if (rc && rc->s1 && rc->s1->bt_func) {
|
||||
rc->s1->bt_func((void*)wanted_pc, str, last_line_num, func_name[0] ? func_name : NULL);
|
||||
} else {
|
||||
if (str)
|
||||
rt_printf("%s:%d: ", str, last_line_num);
|
||||
else
|
||||
rt_printf("%08llx : ", (long long)wanted_pc);
|
||||
rt_printf("%s %s", msg, func_name[0] ? func_name : "???");
|
||||
}
|
||||
#if 0
|
||||
if (--i >= 0) {
|
||||
rt_printf(" (included from ");
|
||||
for (;;) {
|
||||
rt_printf("%s", incl_files[i]);
|
||||
if (--i < 0)
|
||||
break;
|
||||
rt_printf(", ");
|
||||
}
|
||||
rt_printf(")");
|
||||
}
|
||||
#endif
|
||||
*prc = rc;
|
||||
pstrcpy(bi->func, sizeof bi->func, func_name);
|
||||
bi->func_pc = func_addr;
|
||||
return func_addr;
|
||||
}
|
||||
|
||||
|
@ -793,8 +858,7 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
||||
rt_context** prc, const char *msg, const char *skip)
|
||||
static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc, bt_info *bi)
|
||||
{
|
||||
unsigned char *ln;
|
||||
unsigned char *cp;
|
||||
|
@ -834,12 +898,10 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
|||
char *filename;
|
||||
char *function;
|
||||
|
||||
next:
|
||||
filename = NULL;
|
||||
function = NULL;
|
||||
func_addr = 0;
|
||||
line = 0;
|
||||
if (NULL == rc)
|
||||
goto found;
|
||||
|
||||
ln = rc->dwarf_line;
|
||||
while (ln < rc->dwarf_line_end) {
|
||||
|
@ -1070,44 +1132,28 @@ check_pc:
|
|||
next_line:
|
||||
ln = end;
|
||||
}
|
||||
|
||||
filename = NULL;
|
||||
func_addr = 0;
|
||||
/* we try symtab symbols (no line number info) */
|
||||
function = rt_elfsym(rc, wanted_pc, &func_addr);
|
||||
if (function)
|
||||
goto found;
|
||||
rc = rc->next;
|
||||
goto next;
|
||||
|
||||
filename = function = NULL, func_addr = 0;
|
||||
found:
|
||||
if (rc && rc->s1 && rc->s1->bt_func) {
|
||||
rc->s1->bt_func((void*)wanted_pc, filename, line, function);
|
||||
} else {
|
||||
if (filename) {
|
||||
if (skip[0] && strstr(filename, skip))
|
||||
return (addr_t)-1;
|
||||
rt_printf("%s:%d: ", filename, line);
|
||||
}
|
||||
else
|
||||
rt_printf("0x%08llx : ", (long long)wanted_pc);
|
||||
rt_printf("%s %s", msg, function ? function : "???");
|
||||
}
|
||||
*prc = rc;
|
||||
if (filename)
|
||||
pstrcpy(bi->file, sizeof bi->file, filename), bi->line = line;
|
||||
if (function)
|
||||
pstrcpy(bi->func, sizeof bi->func, function);
|
||||
bi->func_pc = func_addr;
|
||||
return (addr_t)func_addr;
|
||||
}
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifndef CONFIG_TCC_BACKTRACE_ONLY
|
||||
static
|
||||
#endif
|
||||
int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap)
|
||||
int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap)
|
||||
{
|
||||
rt_context *rc, *rd;
|
||||
addr_t pc = 0;
|
||||
char skip[100];
|
||||
rt_context *rc, *rc2;
|
||||
addr_t pc;
|
||||
char skip[40], msg[200];
|
||||
int i, level, ret, n, one;
|
||||
const char *a, *b;
|
||||
addr_t (*printline)(rt_context*, addr_t, rt_context**, const char*, const char*);
|
||||
bt_info bi;
|
||||
addr_t (*getinfo)(rt_context*, addr_t, bt_info*);
|
||||
|
||||
skip[0] = 0;
|
||||
/* 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)
|
|||
/* hack for bcheck.c:dprintf(): one level, no newline */
|
||||
if (fmt[0] == '\001')
|
||||
++fmt, one = 1;
|
||||
vsnprintf(msg, sizeof msg, fmt, ap);
|
||||
|
||||
rt_wait_sem();
|
||||
rc = g_rc;
|
||||
printline = rt_printline, n = 6;
|
||||
getinfo = rt_printline, n = 6;
|
||||
if (rc) {
|
||||
if (rc->dwarf)
|
||||
printline = rt_printline_dwarf;
|
||||
getinfo = rt_printline_dwarf;
|
||||
if (rc->num_callers)
|
||||
n = rc->num_callers;
|
||||
}
|
||||
|
||||
for (i = level = 0; level < n; i++) {
|
||||
ret = rt_get_caller_pc(&pc, f, i);
|
||||
if (ret != -1) {
|
||||
pc = printline(rc, pc, &rd, level ? "by" : "at", skip);
|
||||
if (pc == (addr_t)-1)
|
||||
continue;
|
||||
}
|
||||
if (level == 0) {
|
||||
if (rd && rd->s1 && rd->s1->bt_func)
|
||||
if (ret == -1)
|
||||
break;
|
||||
memset(&bi, 0, sizeof bi);
|
||||
for (rc2 = rc; rc2; rc2 = rc2->next) {
|
||||
if (getinfo(rc2, pc, &bi))
|
||||
break;
|
||||
if (ret != -1)
|
||||
rt_printf(": ");
|
||||
if (msg)
|
||||
rt_printf("%s: ", msg);
|
||||
rt_vprintf(fmt, ap);
|
||||
} else if (ret == -1)
|
||||
break;
|
||||
if (one)
|
||||
break;
|
||||
/* we try symtab symbols (no line number info) */
|
||||
if (!!(a = rt_elfsym(rc2, pc, &bi.func_pc))) {
|
||||
pstrcpy(bi.func, sizeof bi.func, a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//fprintf(stderr, "%d rc %p %p\n", i, (void*)pcfunc, (void*)pc);
|
||||
if (skip[0] && strstr(bi.file, skip))
|
||||
continue;
|
||||
#ifndef CONFIG_TCC_BACKTRACE_ONLY
|
||||
{
|
||||
TCCState *s = rt_find_state(f);
|
||||
if (s && s->bt_func) {
|
||||
ret = s->bt_func(
|
||||
s->bt_data,
|
||||
(void*)pc,
|
||||
bi.file[0] ? bi.file : NULL,
|
||||
bi.line,
|
||||
bi.func[0] ? bi.func : NULL,
|
||||
level == 0 ? msg : NULL
|
||||
);
|
||||
if (ret == 0)
|
||||
break;
|
||||
goto check_break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (bi.file[0]) {
|
||||
rt_printf("%s:%d", bi.file, bi.line);
|
||||
} else {
|
||||
rt_printf("0x%08llx", (long long)pc);
|
||||
}
|
||||
rt_printf(": %s %s", level ? "by" : "at", bi.func[0] ? bi.func : "???");
|
||||
if (level == 0) {
|
||||
rt_printf(": %s", msg);
|
||||
if (one)
|
||||
break;
|
||||
}
|
||||
rt_printf("\n");
|
||||
if (ret == -1 || (rd && pc == (addr_t)rd->top_func && pc))
|
||||
|
||||
check_break:
|
||||
if (rc2
|
||||
&& bi.func_pc
|
||||
&& bi.func_pc == (addr_t)rc2->top_func)
|
||||
break;
|
||||
++level;
|
||||
}
|
||||
|
||||
rt_post_sem();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1161,49 +1239,14 @@ int __rt_dump(rt_frame *f, const char *msg, const char *fmt, va_list ap)
|
|||
/* emit a run time error at position 'pc' */
|
||||
static int rt_error(rt_frame *f, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
va_list ap; char msg[200]; int ret;
|
||||
va_start(ap, fmt);
|
||||
ret = __rt_dump(f, "RUNTIME ERROR", fmt, ap);
|
||||
snprintf(msg, sizeof msg, "RUNTIME ERROR: %s", fmt);
|
||||
ret = _tcc_backtrace(f, msg, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static TCCState *rt_find_state(rt_frame *f)
|
||||
{
|
||||
TCCState *s;
|
||||
int level;
|
||||
addr_t pc;
|
||||
|
||||
rt_wait_sem();
|
||||
for (s = g_s1; s; s = s->next) {
|
||||
if (0 == s->run_lj)
|
||||
continue;
|
||||
for (level = 0; level < 8; ++level) {
|
||||
if (rt_get_caller_pc(&pc, f, level) < 0)
|
||||
break;
|
||||
if (pc >= (addr_t)s->run_ptr
|
||||
&& pc < (addr_t)s->run_ptr + s->run_size)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found:
|
||||
rt_post_sem();
|
||||
//fprintf(stderr, "\nrt_state found %s %p %p\n", s ? "YES" : "NO", s, s->rc->top_func), fflush(stderr);
|
||||
return s;
|
||||
}
|
||||
|
||||
static void rt_longjmp(rt_frame *f, int code)
|
||||
{
|
||||
TCCState *s = rt_find_state(f);
|
||||
if (s && s->run_lj) {
|
||||
if (code == 0)
|
||||
code = 256;
|
||||
((void(*)(void*,int))s->run_lj)(s->run_jb, code);
|
||||
}
|
||||
exit(code);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -1338,8 +1381,13 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc)
|
|||
rt_error(&f, "caught signal %d", signum);
|
||||
break;
|
||||
}
|
||||
set_exception_handler();
|
||||
rt_longjmp(&f, 255);
|
||||
{
|
||||
sigset_t s;
|
||||
sigemptyset(&s);
|
||||
sigaddset(&s, signum);
|
||||
sigprocmask(SIG_UNBLOCK, &s, NULL);
|
||||
}
|
||||
rt_exit(&f, 255);
|
||||
}
|
||||
|
||||
#ifndef SA_SIGINFO
|
||||
|
@ -1353,12 +1401,11 @@ static void set_exception_handler(void)
|
|||
/* install TCC signal handlers to print debug info on fatal
|
||||
runtime errors */
|
||||
sigemptyset (&sigact.sa_mask);
|
||||
sigact.sa_flags = SA_SIGINFO | SA_RESETHAND | SA_NODEFER;
|
||||
sigact.sa_flags = SA_SIGINFO; //| SA_RESETHAND;
|
||||
#if 0//def SIGSTKSZ // this causes signals not to work at all on some (older) linuxes
|
||||
sigact.sa_flags |= SA_ONSTACK;
|
||||
#endif
|
||||
sigact.sa_sigaction = sig_error;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigaction(SIGFPE, &sigact, NULL);
|
||||
sigaction(SIGILL, &sigact, NULL);
|
||||
sigaction(SIGSEGV, &sigact, NULL);
|
||||
|
@ -1406,7 +1453,7 @@ static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
|
|||
rt_error(&f, "caught exception %08x", code);
|
||||
break;
|
||||
}
|
||||
rt_longjmp(&f, 255);
|
||||
rt_exit(&f, 255);
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
|
@ -1506,6 +1553,14 @@ static int rt_get_caller_pc(addr_t *paddr, rt_frame *rc, int level)
|
|||
}
|
||||
|
||||
#endif
|
||||
#else // for runmain.c:exit(); when CONFIG_TCC_BACKTRACE == 0 */
|
||||
static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level)
|
||||
{
|
||||
if (level)
|
||||
return -1;
|
||||
*paddr = f->ip;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_TCC_BACKTRACE */
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef CONFIG_TCC_STATIC
|
||||
|
|
|
@ -26,7 +26,9 @@ TESTS = \
|
|||
# test4_static -- Not all relocation types are implemented yet.
|
||||
# asmtest / asmtest2 -- minor differences with gcc
|
||||
|
||||
ifneq ($(CONFIG_bcheck),no)
|
||||
ifeq ($(CONFIG_backtrace),no)
|
||||
TESTS := $(filter-out libtest_mt, $(TESTS))
|
||||
else ifneq ($(CONFIG_bcheck),no)
|
||||
TESTS += btest test1b tccb
|
||||
endif
|
||||
ifeq ($(CONFIG_dll),no)
|
||||
|
|
|
@ -83,11 +83,13 @@ PROG(my_program)
|
|||
" return add(fib(n-1),fib(n-2));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void bar(void) { *(void**)0 = 0; }\n"
|
||||
"\n"
|
||||
"int foo(int n)\n"
|
||||
"{\n"
|
||||
" if (n >= N_CRASH && n < N_CRASH + 3)\n"
|
||||
" *(void**)0 = 0;\n"
|
||||
" printf(\" %d\", fib(n));\n"
|
||||
" if (n >= N_CRASH && n < N_CRASH + 8)\n"
|
||||
" bar();\n"
|
||||
" return 0;\n"
|
||||
"# warning is this the correct file:line...\n"
|
||||
"}\n";
|
||||
|
@ -113,9 +115,27 @@ void parse_args(TCCState *s)
|
|||
}
|
||||
}
|
||||
|
||||
void bt_func(void *pc, const char *file, int line, const char *func)
|
||||
int backtrace_func(
|
||||
void *ud,
|
||||
void *pc,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *msg)
|
||||
{
|
||||
printf(" *** at %s:%d in '%s'\n", file, line, func);
|
||||
#if 0
|
||||
printf("\n *** %p %s %s:%d in '%s'",
|
||||
pc,
|
||||
msg ? "at" : "by",
|
||||
file ? file : "?",
|
||||
line,
|
||||
func ? func : "?");
|
||||
return 1; // want more backtrace levels
|
||||
#else
|
||||
//printf(" [%d]", *(int*)ud);
|
||||
printf("!");
|
||||
return 0; // cancel backtrace
|
||||
#endif
|
||||
}
|
||||
|
||||
TCCState *new_state(int w)
|
||||
|
@ -132,9 +152,8 @@ TCCState *new_state(int w)
|
|||
if (w & 2) {
|
||||
tcc_set_options(s, "-bt");
|
||||
tcc_define_symbol(s, "N_CRASH", str(M/2));
|
||||
tcc_set_backtrace_func(s, bt_func);
|
||||
} else
|
||||
tcc_define_symbol(s, "N_CRASH", "99");
|
||||
tcc_define_symbol(s, "N_CRASH", "-1000");
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
return s;
|
||||
}
|
||||
|
@ -171,8 +190,7 @@ int state_test(int w)
|
|||
if (c < M)
|
||||
funcs[c] = reloc_state(s[c], "foo");
|
||||
if (d < M && funcs[d]) {
|
||||
if ((w & 2) && d == 8)
|
||||
printf("\n");
|
||||
tcc_set_backtrace_func(s[d], &d, backtrace_func);
|
||||
if (0 == tcc_setjmp(s[d], jb, funcs[d]))
|
||||
funcs[d](F(d));
|
||||
}
|
||||
|
@ -189,15 +207,19 @@ TF_TYPE(thread_test_simple, vn)
|
|||
int (*func)(int);
|
||||
int ret;
|
||||
int n = (size_t)vn;
|
||||
jmp_buf jb;
|
||||
|
||||
s = new_state(0);
|
||||
s = new_state(0); /* '2' for exceptions */
|
||||
sleep_ms(1);
|
||||
ret = tcc_compile_string(s, my_program);
|
||||
sleep_ms(1);
|
||||
if (ret >= 0) {
|
||||
func = reloc_state(s, "foo");
|
||||
if (func)
|
||||
func(F(n));
|
||||
tcc_set_backtrace_func(s, &n, backtrace_func);
|
||||
if (func) {
|
||||
if (0 == tcc_setjmp(s, jb, func))
|
||||
func(F(n));
|
||||
}
|
||||
}
|
||||
tcc_delete(s);
|
||||
return 0;
|
||||
|
@ -281,18 +303,20 @@ int main(int argc, char **argv)
|
|||
printf("\n (%u ms)\n", getclock_ms() - t);
|
||||
#endif
|
||||
#if 1
|
||||
printf("producing some exceptions\n "), fflush(stdout);
|
||||
printf("producing some exceptions (!)\n "), fflush(stdout);
|
||||
t = getclock_ms();
|
||||
state_test(2);
|
||||
printf("\n (%u ms)\n", getclock_ms() - t);
|
||||
#endif
|
||||
#if 1
|
||||
//{ int i; for (i = 0; i < 100; ++i) { printf("(%d) ", i);
|
||||
printf("running fib in threads\n "), fflush(stdout);
|
||||
t = getclock_ms();
|
||||
for (n = 0; n < M; ++n)
|
||||
create_thread(thread_test_simple, n);
|
||||
wait_threads(n);
|
||||
printf("\n (%u ms)\n", getclock_ms() - t);
|
||||
//}}
|
||||
#endif
|
||||
#if 1
|
||||
printf("running tcc.c in threads to run fib\n "), fflush(stdout);
|
||||
|
|
|
@ -3889,7 +3889,7 @@ static void builtin_test_bits(unsigned long long x, int cnt[])
|
|||
if ((unsigned long) x) cnt[7] += __builtin_ctzl(x);
|
||||
if ((unsigned long long) x) cnt[8] += __builtin_ctzll(x);
|
||||
|
||||
#if CC_NAME != CC_clang || GCC_MAJOR >= 11
|
||||
#if GCC_MAJOR >= 6 && (CC_NAME != CC_clang || GCC_MAJOR >= 11)
|
||||
/* Apple clang 10 does not have __builtin_clrsb[l[l]] */
|
||||
cnt[9] += __builtin_clrsb(x);
|
||||
cnt[10] += __builtin_clrsbl(x);
|
||||
|
|
|
@ -202,4 +202,5 @@ exit /B %ERRORLEVEL%
|
|||
.\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o
|
||||
.\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o
|
||||
.\tcc -B. -m%1 -c ../lib/bt-dll.c -o lib/%2bt-dll.o
|
||||
.\tcc -B. -m%1 -c ../lib/runmain.c -o lib/%2runmain.o
|
||||
exit /B %ERRORLEVEL%
|
||||
|
|
|
@ -62,8 +62,8 @@ extern "C" {
|
|||
void *__cdecl malloc(size_t _Size);
|
||||
void *__cdecl realloc(void *_Memory,size_t _NewSize);
|
||||
_CRTIMP void *__cdecl _recalloc(void *_Memory,size_t _Count,size_t _Size);
|
||||
/* _CRTIMP void __cdecl _aligned_free(void *_Memory);
|
||||
_CRTIMP void *__cdecl _aligned_malloc(size_t _Size,size_t _Alignment); */
|
||||
_CRTIMP void __cdecl _aligned_free(void *_Memory);
|
||||
_CRTIMP void *__cdecl _aligned_malloc(size_t _Size,size_t _Alignment);
|
||||
_CRTIMP void *__cdecl _aligned_offset_malloc(size_t _Size,size_t _Alignment,size_t _Offset);
|
||||
_CRTIMP void *__cdecl _aligned_realloc(void *_Memory,size_t _Size,size_t _Alignment);
|
||||
_CRTIMP void *__cdecl _aligned_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment);
|
||||
|
|
|
@ -403,8 +403,8 @@ extern "C" {
|
|||
void *__cdecl malloc(size_t _Size);
|
||||
void *__cdecl realloc(void *_Memory,size_t _NewSize);
|
||||
_CRTIMP void *__cdecl _recalloc(void *_Memory,size_t _Count,size_t _Size);
|
||||
//_CRTIMP void __cdecl _aligned_free(void *_Memory);
|
||||
//_CRTIMP void *__cdecl _aligned_malloc(size_t _Size,size_t _Alignment);
|
||||
_CRTIMP void __cdecl _aligned_free(void *_Memory);
|
||||
_CRTIMP void *__cdecl _aligned_malloc(size_t _Size,size_t _Alignment);
|
||||
_CRTIMP void *__cdecl _aligned_offset_malloc(size_t _Size,size_t _Alignment,size_t _Offset);
|
||||
_CRTIMP void *__cdecl _aligned_realloc(void *_Memory,size_t _Size,size_t _Alignment);
|
||||
_CRTIMP void *__cdecl _aligned_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment);
|
||||
|
|
|
@ -70,7 +70,6 @@ void _tstart(void)
|
|||
// =============================================
|
||||
// for 'tcc -run ,,,'
|
||||
|
||||
__attribute__((weak)) extern int __rt_nr_exit;
|
||||
__attribute__((weak)) extern int __run_on_exit();
|
||||
|
||||
int _runtmain(int argc, /* as tcc passed in */ char **argv)
|
||||
|
@ -92,7 +91,6 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv)
|
|||
#if defined __i386__ || defined __x86_64__
|
||||
_controlfp(_PC_53, _MCW_PC);
|
||||
#endif
|
||||
__rt_nr_exit = 0;
|
||||
run_ctors(__argc, __targv, _tenviron);
|
||||
ret = _tmain(__argc, __targv, _tenviron);
|
||||
run_dtors();
|
||||
|
|
Loading…
Reference in a new issue