mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-20 03:44:19 +08:00
Restore generic backtrace runtime path
This commit is contained in:
parent
a1da6220e3
commit
7e7917c3c9
@ -1171,7 +1171,7 @@ __bound_main_arg(int argc, char **argv, char **envp)
|
||||
}
|
||||
}
|
||||
|
||||
static void bound_exit_impl(void)
|
||||
void __attribute__((destructor)) __bound_exit(void)
|
||||
{
|
||||
int i;
|
||||
static const char * const alloc_type[] = {
|
||||
@ -1283,11 +1283,6 @@ static void bound_exit_impl(void)
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((destructor)) __bound_exit(void)
|
||||
{
|
||||
bound_exit_impl();
|
||||
}
|
||||
|
||||
void __bound_exit_dll(size_t *p)
|
||||
{
|
||||
dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
|
||||
|
||||
90
lib/bt-exe.c
90
lib/bt-exe.c
@ -11,6 +11,16 @@
|
||||
# define __declspec(n)
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64) && defined(__aarch64__)
|
||||
/* The bt-only Windows ARM64 build should not rely on importing this helper. */
|
||||
LONG InterlockedExchange(LONG volatile *Target, LONG Value)
|
||||
{
|
||||
LONG Old = *Target;
|
||||
*Target = Value;
|
||||
return Old;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
static void bt_init_pe_prog_base(rt_context *p)
|
||||
{
|
||||
@ -53,10 +63,88 @@ void __bt_init(rt_context *p, int is_exe)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static const char *bt_backtrace_format(const char *fmt, char *skip, int *one)
|
||||
{
|
||||
const char *a, *b;
|
||||
|
||||
skip[0] = 0;
|
||||
if (fmt[0] == '^' && (b = strchr(a = fmt + 1, fmt[0]))) {
|
||||
size_t len = b - a;
|
||||
if (len >= 40)
|
||||
len = 39;
|
||||
memcpy(skip, a, len);
|
||||
skip[len] = 0;
|
||||
fmt = b + 1;
|
||||
}
|
||||
*one = 0;
|
||||
if (fmt[0] == '\001')
|
||||
++fmt, *one = 1;
|
||||
return fmt;
|
||||
}
|
||||
|
||||
static int bt_backtrace_msg(rt_frame *f, const char *fmt, const char *msg)
|
||||
{
|
||||
rt_context *rc, *rc2;
|
||||
addr_t pc;
|
||||
char skip[40];
|
||||
int i, level, ret, n, one;
|
||||
const char *a;
|
||||
bt_info bi;
|
||||
addr_t (*getinfo)(rt_context*, addr_t, bt_info*);
|
||||
|
||||
bt_backtrace_format(fmt, skip, &one);
|
||||
|
||||
rt_wait_sem();
|
||||
rc = g_rc;
|
||||
getinfo = rt_printline, n = 6;
|
||||
if (rc) {
|
||||
if (rc->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)
|
||||
break;
|
||||
memset(&bi, 0, sizeof bi);
|
||||
for (rc2 = rc; rc2; rc2 = rc2->next) {
|
||||
if (getinfo(rc2, pc, &bi))
|
||||
break;
|
||||
if (!!(a = rt_elfsym(rc2, pc, &bi.func_pc))) {
|
||||
pstrcpy(bi.func, sizeof bi.func, a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip[0] && strstr(bi.file, skip))
|
||||
continue;
|
||||
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 (rc2
|
||||
&& bi.func_pc
|
||||
&& bi.func_pc == (addr_t)rc2->top_func)
|
||||
break;
|
||||
++level;
|
||||
}
|
||||
rt_post_sem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
__declspec(dllexport)
|
||||
int __bt_backtrace(rt_frame *f, const char *msg)
|
||||
{
|
||||
return _tcc_backtrace_msg(f, msg, msg);
|
||||
return bt_backtrace_msg(f, msg, msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
145
tccrun.c
145
tccrun.c
@ -21,17 +21,6 @@
|
||||
#include "tcc.h"
|
||||
#ifdef _WIN32
|
||||
#include <stdlib.h>
|
||||
#if defined(_WIN64) && defined(__aarch64__) && defined(CONFIG_TCC_BACKTRACE_ONLY)
|
||||
/* TCC's Windows ARM64 support objects may emit direct InterlockedExchange
|
||||
calls in the backtrace-only build; provide a local fallback so -b/-bt
|
||||
executables do not depend on the PE import for this helper. */
|
||||
LONG InterlockedExchange(LONG volatile *Target, LONG Value)
|
||||
{
|
||||
LONG Old = *Target;
|
||||
*Target = Value;
|
||||
return Old;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* only native compiler supports -run */
|
||||
@ -223,10 +212,6 @@ ST_FUNC void tcc_run_free(TCCState *s1)
|
||||
|
||||
#define RT_EXIT_ZERO 0xE0E00E0E /* passed from longjmp instead of '0' */
|
||||
|
||||
typedef struct TCCRunJmpBuf {
|
||||
jmp_buf jb;
|
||||
} TCCRunJmpBuf;
|
||||
|
||||
#ifdef _WIN32
|
||||
static char **rt_get_environ(void)
|
||||
{
|
||||
@ -265,25 +250,13 @@ static void rt_flush_target_io(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tcc_run_setjmp(TCCState *s1, TCCRunJmpBuf *jb, const char *top_sym)
|
||||
{
|
||||
_tcc_setjmp(s1, jb->jb, tcc_get_symbol(s1, top_sym), longjmp);
|
||||
return setjmp(jb->jb);
|
||||
}
|
||||
|
||||
/* launch the compiled program with the given arguments */
|
||||
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
int (*prog_main)(int, char **, char **), ret;
|
||||
const char *top_sym;
|
||||
TCCRunJmpBuf main_jb;
|
||||
#ifdef _WIN32
|
||||
int (*prog_main)(int, char **);
|
||||
#else
|
||||
int (*prog_main)(int, char **, char **);
|
||||
#endif
|
||||
jmp_buf main_jb;
|
||||
|
||||
#ifndef _WIN32
|
||||
#if defined(__APPLE__)
|
||||
extern char ***_NSGetEnviron(void);
|
||||
char **envp = *_NSGetEnviron();
|
||||
@ -292,7 +265,6 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
char **envp = environ;
|
||||
#else
|
||||
char **envp = environ;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* tcc -dt -run ... nothing to do if no main() */
|
||||
@ -330,13 +302,9 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
ret = tcc_run_setjmp(s1, &main_jb, top_sym);
|
||||
ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym));
|
||||
if (0 == ret) {
|
||||
#ifdef _WIN32
|
||||
ret = prog_main(argc, argv);
|
||||
#else
|
||||
ret = prog_main(argc, argv, envp);
|
||||
#endif
|
||||
} else if (RT_EXIT_ZERO == ret) {
|
||||
ret = 0;
|
||||
}
|
||||
@ -1178,113 +1146,6 @@ found:
|
||||
return (addr_t)func_addr;
|
||||
}
|
||||
/* ------------------------------------------------------------- */
|
||||
#if defined(_WIN32) && defined(CONFIG_TCC_BACKTRACE_ONLY)
|
||||
static const char *rt_backtrace_format(const char *fmt, char *skip, int *one)
|
||||
{
|
||||
const char *a, *b;
|
||||
|
||||
skip[0] = 0;
|
||||
if (fmt[0] == '^' && (b = strchr(a = fmt + 1, fmt[0]))) {
|
||||
size_t len = b - a;
|
||||
if (len >= 40)
|
||||
len = 39;
|
||||
memcpy(skip, a, len);
|
||||
skip[len] = 0;
|
||||
fmt = b + 1;
|
||||
}
|
||||
*one = 0;
|
||||
if (fmt[0] == '\001')
|
||||
++fmt, *one = 1;
|
||||
return fmt;
|
||||
}
|
||||
|
||||
/* Windows bt-dll.c needs a preformatted-message entry point because the
|
||||
ARM64 wrapper path cannot forward a va_list through the old trampoline
|
||||
mechanism. Keep this helper out of the generic runtime path. */
|
||||
static int _tcc_backtrace_msg(rt_frame *f, const char *fmt, const char *msg)
|
||||
{
|
||||
rt_context *rc, *rc2;
|
||||
addr_t pc;
|
||||
char skip[40];
|
||||
int i, level, ret, n, one;
|
||||
const char *a;
|
||||
bt_info bi;
|
||||
addr_t (*getinfo)(rt_context*, addr_t, bt_info*);
|
||||
|
||||
rt_backtrace_format(fmt, skip, &one);
|
||||
|
||||
rt_wait_sem();
|
||||
rc = g_rc;
|
||||
getinfo = rt_printline, n = 6;
|
||||
if (rc) {
|
||||
if (rc->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)
|
||||
break;
|
||||
memset(&bi, 0, sizeof bi);
|
||||
for (rc2 = rc; rc2; rc2 = rc2->next) {
|
||||
if (getinfo(rc2, pc, &bi))
|
||||
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");
|
||||
|
||||
#ifndef CONFIG_TCC_BACKTRACE_ONLY
|
||||
check_break:
|
||||
#endif
|
||||
if (rc2
|
||||
&& bi.func_pc
|
||||
&& bi.func_pc == (addr_t)rc2->top_func)
|
||||
break;
|
||||
++level;
|
||||
}
|
||||
rt_post_sem();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TCC_BACKTRACE_ONLY
|
||||
static
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user