mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-04 18:38:41 +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;
|
int i;
|
||||||
static const char * const alloc_type[] = {
|
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)
|
void __bound_exit_dll(size_t *p)
|
||||||
{
|
{
|
||||||
dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
|
dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
|
||||||
|
|||||||
90
lib/bt-exe.c
90
lib/bt-exe.c
@ -11,6 +11,16 @@
|
|||||||
# define __declspec(n)
|
# define __declspec(n)
|
||||||
#endif
|
#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
|
#ifdef _WIN64
|
||||||
static void bt_init_pe_prog_base(rt_context *p)
|
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
|
#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)
|
__declspec(dllexport)
|
||||||
int __bt_backtrace(rt_frame *f, const char *msg)
|
int __bt_backtrace(rt_frame *f, const char *msg)
|
||||||
{
|
{
|
||||||
return _tcc_backtrace_msg(f, msg, msg);
|
return bt_backtrace_msg(f, msg, msg);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
145
tccrun.c
145
tccrun.c
@ -21,17 +21,6 @@
|
|||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <stdlib.h>
|
#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
|
#endif
|
||||||
|
|
||||||
/* only native compiler supports -run */
|
/* 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' */
|
#define RT_EXIT_ZERO 0xE0E00E0E /* passed from longjmp instead of '0' */
|
||||||
|
|
||||||
typedef struct TCCRunJmpBuf {
|
|
||||||
jmp_buf jb;
|
|
||||||
} TCCRunJmpBuf;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static char **rt_get_environ(void)
|
static char **rt_get_environ(void)
|
||||||
{
|
{
|
||||||
@ -265,25 +250,13 @@ static void rt_flush_target_io(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 */
|
/* launch the compiled program with the given arguments */
|
||||||
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
{
|
{
|
||||||
int ret;
|
int (*prog_main)(int, char **, char **), ret;
|
||||||
const char *top_sym;
|
const char *top_sym;
|
||||||
TCCRunJmpBuf main_jb;
|
jmp_buf main_jb;
|
||||||
#ifdef _WIN32
|
|
||||||
int (*prog_main)(int, char **);
|
|
||||||
#else
|
|
||||||
int (*prog_main)(int, char **, char **);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
extern char ***_NSGetEnviron(void);
|
extern char ***_NSGetEnviron(void);
|
||||||
char **envp = *_NSGetEnviron();
|
char **envp = *_NSGetEnviron();
|
||||||
@ -292,7 +265,6 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
char **envp = environ;
|
char **envp = environ;
|
||||||
#else
|
#else
|
||||||
char **envp = environ;
|
char **envp = environ;
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* tcc -dt -run ... nothing to do if no main() */
|
/* 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(stdout);
|
||||||
fflush(stderr);
|
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) {
|
if (0 == ret) {
|
||||||
#ifdef _WIN32
|
|
||||||
ret = prog_main(argc, argv);
|
|
||||||
#else
|
|
||||||
ret = prog_main(argc, argv, envp);
|
ret = prog_main(argc, argv, envp);
|
||||||
#endif
|
|
||||||
} else if (RT_EXIT_ZERO == ret) {
|
} else if (RT_EXIT_ZERO == ret) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
@ -1178,113 +1146,6 @@ found:
|
|||||||
return (addr_t)func_addr;
|
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
|
#ifndef CONFIG_TCC_BACKTRACE_ONLY
|
||||||
static
|
static
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user