mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-13 05:10:07 +08:00
tccrun: 'tcc_relocate()' twice no longer supported
- abort with notice when tcc_relocate() is called with the former two-step method - support backtrace & bcheck not only with tcc_run() but also for directly called functions from tcc_get_symbol(); enable witn 'tcc_set_options("-bt/-b");' - move struct rt_context and debug sections into compiled code for TCC_OUTPUT_MEMORY also - protect access (g_rc) with semaphore Also: - add armv7/aarch4/riscv64 github tests (qemu emulated) - win32/build-tcc.bat: build cross compiler only with -x
This commit is contained in:
parent
7b9f19eaab
commit
a7cd016d71
54
.github/workflows/build.yml
vendored
54
.github/workflows/build.yml
vendored
@ -8,21 +8,21 @@ jobs:
|
|||||||
test-x86_64-linux:
|
test-x86_64-linux:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: make & test tcc
|
- name: make & test tcc
|
||||||
run: ./configure && make && make test -k
|
run: ./configure && make && make test -k
|
||||||
|
|
||||||
test-x86_64-osx:
|
test-x86_64-osx:
|
||||||
runs-on: macos-11
|
runs-on: macos-11
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: make & test tcc
|
- name: make & test tcc
|
||||||
run: ./configure --config-codesign=no && make && make test -k
|
run: ./configure --config-codesign=no && make && make test -k
|
||||||
|
|
||||||
test-x86_64-win32:
|
test-x86_64-win32:
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: make & test tcc
|
- name: make & test tcc
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
@ -30,3 +30,51 @@ jobs:
|
|||||||
set MSYSTEM=MINGW64
|
set MSYSTEM=MINGW64
|
||||||
set CHERE_INVOKING=yes
|
set CHERE_INVOKING=yes
|
||||||
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
|
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
|
||||||
|
|
||||||
|
test-armv7-linux:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: uraimo/run-on-arch-action@v2
|
||||||
|
with:
|
||||||
|
arch: armv7
|
||||||
|
distro: ubuntu20.04
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
install: |
|
||||||
|
apt-get update -q -y
|
||||||
|
apt-get install -q -y gcc make
|
||||||
|
run: |
|
||||||
|
echo "::endgroup::" && echo "::endgroup::" # missing in 'run-on-arch-action'
|
||||||
|
./configure && make && make test -k
|
||||||
|
|
||||||
|
test-aarch64-linux:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: uraimo/run-on-arch-action@v2
|
||||||
|
with:
|
||||||
|
arch: aarch64
|
||||||
|
distro: ubuntu20.04
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
install: |
|
||||||
|
apt-get update -q -y
|
||||||
|
apt-get install -q -y gcc make
|
||||||
|
run: |
|
||||||
|
echo "::endgroup::" && echo "::endgroup::" # missing in 'run-on-arch-action'
|
||||||
|
./configure && make && make test -k
|
||||||
|
|
||||||
|
test-riscv64-linux:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: uraimo/run-on-arch-action@v2
|
||||||
|
with:
|
||||||
|
arch: riscv64
|
||||||
|
distro: ubuntu20.04
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
install: |
|
||||||
|
apt-get update -q -y
|
||||||
|
apt-get install -q -y gcc make
|
||||||
|
run: |
|
||||||
|
echo "::endgroup::" && echo "::endgroup::" # missing in 'run-on-arch-action'
|
||||||
|
./configure && make && make test -k
|
||||||
|
3
Makefile
3
Makefile
@ -152,8 +152,7 @@ TCC_X += riscv64 arm64-osx
|
|||||||
# TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi
|
# TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi
|
||||||
|
|
||||||
# cross libtcc1.a targets to build
|
# cross libtcc1.a targets to build
|
||||||
LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince
|
LIBTCC1_X = $(filter-out c67,$(TCC_X))
|
||||||
LIBTCC1_X += riscv64 arm64-osx
|
|
||||||
|
|
||||||
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
|
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
|
||||||
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a)
|
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a)
|
||||||
|
4
configure
vendored
4
configure
vendored
@ -478,6 +478,10 @@ if test "$cpu" = "arm"; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test -n "$dwarf"; then
|
||||||
|
confvars="$confvars dwarf=$dwarf"
|
||||||
|
fi
|
||||||
|
|
||||||
# a final configuration tuning
|
# a final configuration tuning
|
||||||
if test "$cc_name" != "tcc"; then
|
if test "$cc_name" != "tcc"; then
|
||||||
OPT1="-Wdeclaration-after-statement -fno-strict-aliasing"
|
OPT1="-Wdeclaration-after-statement -fno-strict-aliasing"
|
||||||
|
63
lib/bt-exe.c
63
lib/bt-exe.c
@ -5,61 +5,56 @@
|
|||||||
#define CONFIG_TCC_BACKTRACE_ONLY
|
#define CONFIG_TCC_BACKTRACE_ONLY
|
||||||
#define ONE_SOURCE 1
|
#define ONE_SOURCE 1
|
||||||
#define pstrcpy tcc_pstrcpy
|
#define pstrcpy tcc_pstrcpy
|
||||||
|
#define TCC_SEM_IMPL 1
|
||||||
#include "../tccrun.c"
|
#include "../tccrun.c"
|
||||||
|
|
||||||
int (*__rt_error)(void*, void*, const char *, va_list);
|
|
||||||
__attribute__((weak)) void __bound_checking_lock(void);
|
|
||||||
__attribute__((weak)) void __bound_checking_unlock(void);
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# define __declspec(n)
|
# define __declspec(n)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__declspec(dllexport)
|
__declspec(dllexport)
|
||||||
void __bt_init(rt_context *p, int num_callers)
|
void __bt_init(rt_context *p, int is_exe)
|
||||||
{
|
{
|
||||||
__attribute__((weak)) int main();
|
__attribute__((weak)) int main();
|
||||||
__attribute__((weak)) void __bound_init(void*, int);
|
__attribute__((weak)) void __bound_init(void*, int);
|
||||||
struct rt_context *rc = &g_rtctxt;
|
|
||||||
//fprintf(stderr, "__bt_init %d %p %p\n", num_callers, p->stab_sym, p->bounds_start), fflush(stderr);
|
WAIT_SEM(&rt_sem);
|
||||||
|
//fprintf(stderr, "__bt_init %d %p %p %p\n", is_exe, p, p->stab_sym, p->bounds_start), fflush(stderr);
|
||||||
|
|
||||||
/* call __bound_init here due to redirection of sigaction */
|
/* call __bound_init here due to redirection of sigaction */
|
||||||
/* needed to add global symbols */
|
/* needed to add global symbols */
|
||||||
if (p->bounds_start) {
|
|
||||||
__bound_init(p->bounds_start, -1);
|
|
||||||
__bound_checking_lock();
|
|
||||||
}
|
|
||||||
if (num_callers) {
|
|
||||||
memcpy(rc, p, offsetof(rt_context, next));
|
|
||||||
rc->num_callers = num_callers - 1;
|
|
||||||
rc->top_func = main;
|
|
||||||
__rt_error = _rt_error;
|
|
||||||
set_exception_handler();
|
|
||||||
} else {
|
|
||||||
p->next = rc->next, rc->next = p;
|
|
||||||
}
|
|
||||||
if (p->bounds_start)
|
if (p->bounds_start)
|
||||||
__bound_checking_unlock();
|
__bound_init(p->bounds_start, -1);
|
||||||
|
|
||||||
|
/* add to chain */
|
||||||
|
p->next = g_rc, g_rc = p;
|
||||||
|
if (is_exe) {
|
||||||
|
/* we are the executable (not a dll) */
|
||||||
|
p->top_func = main;
|
||||||
|
set_exception_handler();
|
||||||
|
}
|
||||||
|
POST_SEM(&rt_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
__declspec(dllexport)
|
__declspec(dllexport)
|
||||||
void __bt_exit(rt_context *p)
|
void __bt_exit(rt_context *p)
|
||||||
{
|
{
|
||||||
|
struct rt_context *rc, **pp;
|
||||||
__attribute__((weak)) void __bound_exit_dll(void*);
|
__attribute__((weak)) void __bound_exit_dll(void*);
|
||||||
struct rt_context *rc = &g_rtctxt;
|
|
||||||
|
|
||||||
if (p->bounds_start) {
|
WAIT_SEM(&rt_sem);
|
||||||
__bound_exit_dll(p->bounds_start);
|
//fprintf(stderr, "__bt_exit %d %p\n", !!p->top_func, p);
|
||||||
__bound_checking_lock();
|
|
||||||
}
|
|
||||||
while (rc) {
|
|
||||||
if (rc->next == p) {
|
|
||||||
rc->next = rc->next->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rc = rc->next;
|
|
||||||
}
|
|
||||||
if (p->bounds_start)
|
if (p->bounds_start)
|
||||||
__bound_checking_unlock();
|
__bound_exit_dll(p->bounds_start);
|
||||||
|
|
||||||
|
/* remove from chain */
|
||||||
|
for (pp = &g_rc; rc = *pp, rc; pp = &rc->next)
|
||||||
|
if (rc == p) {
|
||||||
|
*pp = rc->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
POST_SEM(&rt_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy a string and truncate it. */
|
/* copy a string and truncate it. */
|
||||||
|
20
lib/bt-log.c
20
lib/bt-log.c
@ -4,8 +4,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#undef __attribute__
|
||||||
int (*__rt_error)(void*, void*, const char *, va_list);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define DLL_EXPORT __declspec(dllexport)
|
# define DLL_EXPORT __declspec(dllexport)
|
||||||
@ -19,16 +18,25 @@ int (*__rt_error)(void*, void*, const char *, va_list);
|
|||||||
#pragma GCC diagnostic ignored "-Wframe-address"
|
#pragma GCC diagnostic ignored "-Wframe-address"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct rt_frame
|
||||||
|
{
|
||||||
|
void *ip, *fp, *sp;
|
||||||
|
} rt_frame;
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
int _rt_error(rt_frame *f, const char *msg, const char *fmt, va_list ap);
|
||||||
|
|
||||||
DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
|
DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (__rt_error) {
|
if (_rt_error) {
|
||||||
void *fp = __builtin_frame_address(1);
|
rt_frame f;
|
||||||
void *ip = __builtin_return_address(0);
|
f.fp = __builtin_frame_address(1);
|
||||||
|
f.ip = __builtin_return_address(0);
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ret = __rt_error(fp, ip, fmt, ap);
|
ret = _rt_error(&f, "", fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
} else {
|
} else {
|
||||||
const char *p, *nl = "\n";
|
const char *p, *nl = "\n";
|
||||||
|
42
libtcc.c
42
libtcc.c
@ -60,6 +60,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif /* ONE_SOURCE */
|
#endif /* ONE_SOURCE */
|
||||||
|
|
||||||
|
#define TCC_SEM_IMPL 1
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
@ -110,7 +111,7 @@ static inline char *config_tccdir_w32(char *path)
|
|||||||
#define CONFIG_TCCDIR config_tccdir_w32(alloca(MAX_PATH))
|
#define CONFIG_TCCDIR config_tccdir_w32(alloca(MAX_PATH))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_IS_NATIVE
|
||||||
static void tcc_add_systemdir(TCCState *s)
|
static void tcc_add_systemdir(TCCState *s)
|
||||||
{
|
{
|
||||||
char buf[1000];
|
char buf[1000];
|
||||||
@ -121,44 +122,6 @@ static void tcc_add_systemdir(TCCState *s)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
#if CONFIG_TCC_SEMLOCK
|
|
||||||
#if defined _WIN32
|
|
||||||
ST_FUNC void wait_sem(TCCSem *p)
|
|
||||||
{
|
|
||||||
if (!p->init)
|
|
||||||
InitializeCriticalSection(&p->cr), p->init = 1;
|
|
||||||
EnterCriticalSection(&p->cr);
|
|
||||||
}
|
|
||||||
ST_FUNC void post_sem(TCCSem *p)
|
|
||||||
{
|
|
||||||
LeaveCriticalSection(&p->cr);
|
|
||||||
}
|
|
||||||
#elif defined __APPLE__
|
|
||||||
/* Half-compatible MacOS doesn't have non-shared (process local)
|
|
||||||
semaphores. Use the dispatch framework for lightweight locks. */
|
|
||||||
ST_FUNC void wait_sem(TCCSem *p)
|
|
||||||
{
|
|
||||||
if (!p->init)
|
|
||||||
p->sem = dispatch_semaphore_create(1), p->init = 1;
|
|
||||||
dispatch_semaphore_wait(p->sem, DISPATCH_TIME_FOREVER);
|
|
||||||
}
|
|
||||||
ST_FUNC void post_sem(TCCSem *p)
|
|
||||||
{
|
|
||||||
dispatch_semaphore_signal(p->sem);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ST_FUNC void wait_sem(TCCSem *p)
|
|
||||||
{
|
|
||||||
if (!p->init)
|
|
||||||
sem_init(&p->sem, 0, 1), p->init = 1;
|
|
||||||
while (sem_wait(&p->sem) < 0 && errno == EINTR);
|
|
||||||
}
|
|
||||||
ST_FUNC void post_sem(TCCSem *p)
|
|
||||||
{
|
|
||||||
sem_post(&p->sem);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PUB_FUNC void tcc_enter_state(TCCState *s1)
|
PUB_FUNC void tcc_enter_state(TCCState *s1)
|
||||||
{
|
{
|
||||||
@ -1959,6 +1922,7 @@ dorun:
|
|||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
case TCC_OPTION_bt:
|
case TCC_OPTION_bt:
|
||||||
s->rt_num_callers = atoi(optarg); /* zero = default (6) */
|
s->rt_num_callers = atoi(optarg); /* zero = default (6) */
|
||||||
|
goto enable_backtrace;
|
||||||
enable_backtrace:
|
enable_backtrace:
|
||||||
s->do_backtrace = 1;
|
s->do_backtrace = 1;
|
||||||
s->do_debug = s->do_debug ? s->do_debug : 1;
|
s->do_debug = s->do_debug ? s->do_debug : 1;
|
||||||
|
48
tcc.h
48
tcc.h
@ -1853,11 +1853,6 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
|
|||||||
#define dwarf_str_section s1->dwarf_str_section
|
#define dwarf_str_section s1->dwarf_str_section
|
||||||
#define dwarf_line_str_section s1->dwarf_line_str_section
|
#define dwarf_line_str_section s1->dwarf_line_str_section
|
||||||
|
|
||||||
/* default dwarf version for "-g". use 0 to emit stab debug infos */
|
|
||||||
#ifndef DWARF_VERSION
|
|
||||||
# define DWARF_VERSION 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* default dwarf version for "-gdwarf" */
|
/* default dwarf version for "-gdwarf" */
|
||||||
#ifdef TCC_TARGET_MACHO
|
#ifdef TCC_TARGET_MACHO
|
||||||
# define DEFAULT_DWARF_VERSION 2
|
# define DEFAULT_DWARF_VERSION 2
|
||||||
@ -1865,6 +1860,11 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
|
|||||||
# define DEFAULT_DWARF_VERSION 5
|
# define DEFAULT_DWARF_VERSION 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* default dwarf version for "-g". use 0 to emit stab debug infos */
|
||||||
|
#ifndef DWARF_VERSION
|
||||||
|
# define DWARF_VERSION 0 //DEFAULT_DWARF_VERSION
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined TCC_TARGET_PE
|
#if defined TCC_TARGET_PE
|
||||||
# define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */
|
# define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */
|
||||||
#elif defined TCC_TARGET_X86_64
|
#elif defined TCC_TARGET_X86_64
|
||||||
@ -1946,3 +1946,41 @@ PUB_FUNC void tcc_exit_state(TCCState *s1);
|
|||||||
# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
|
# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
|
||||||
# define _tcc_error use_tcc_error_noabort
|
# define _tcc_error use_tcc_error_noabort
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_TCC_SEMLOCK && TCC_SEM_IMPL
|
||||||
|
#undef TCC_SEM_IMPL
|
||||||
|
#if defined _WIN32
|
||||||
|
ST_FUNC void wait_sem(TCCSem *p)
|
||||||
|
{
|
||||||
|
if (!p->init)
|
||||||
|
InitializeCriticalSection(&p->cr), p->init = 1;
|
||||||
|
EnterCriticalSection(&p->cr);
|
||||||
|
}
|
||||||
|
ST_FUNC void post_sem(TCCSem *p)
|
||||||
|
{
|
||||||
|
LeaveCriticalSection(&p->cr);
|
||||||
|
}
|
||||||
|
#elif defined __APPLE__
|
||||||
|
ST_FUNC void wait_sem(TCCSem *p)
|
||||||
|
{
|
||||||
|
if (!p->init)
|
||||||
|
p->sem = dispatch_semaphore_create(1), p->init = 1;
|
||||||
|
dispatch_semaphore_wait(p->sem, DISPATCH_TIME_FOREVER);
|
||||||
|
}
|
||||||
|
ST_FUNC void post_sem(TCCSem *p)
|
||||||
|
{
|
||||||
|
dispatch_semaphore_signal(p->sem);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ST_FUNC void wait_sem(TCCSem *p)
|
||||||
|
{
|
||||||
|
if (!p->init)
|
||||||
|
sem_init(&p->sem, 0, 1), p->init = 1;
|
||||||
|
while (sem_wait(&p->sem) < 0 && errno == EINTR);
|
||||||
|
}
|
||||||
|
ST_INLN void post_sem(TCCSem *p)
|
||||||
|
{
|
||||||
|
sem_post(&p->sem);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
7
tccdbg.c
7
tccdbg.c
@ -416,12 +416,15 @@ ST_FUNC void tcc_debug_new(TCCState *s1)
|
|||||||
int shf = 0;
|
int shf = 0;
|
||||||
if (!s1->dState)
|
if (!s1->dState)
|
||||||
s1->dState = tcc_mallocz(sizeof *s1->dState);
|
s1->dState = tcc_mallocz(sizeof *s1->dState);
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
/* include stab info with standalone backtrace support */
|
/* include stab info with standalone backtrace support */
|
||||||
if (s1->do_backtrace
|
if (s1->do_debug && s1->output_type == TCC_OUTPUT_MEMORY)
|
||||||
&& (s1->output_type & (TCC_OUTPUT_EXE | TCC_OUTPUT_DLL)))
|
s1->do_backtrace = 1;
|
||||||
|
if (s1->do_backtrace)
|
||||||
shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX
|
shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (s1->dwarf) {
|
if (s1->dwarf) {
|
||||||
s1->dwlo = s1->nb_sections;
|
s1->dwlo = s1->nb_sections;
|
||||||
dwarf_info_section =
|
dwarf_info_section =
|
||||||
|
61
tccelf.c
61
tccelf.c
@ -139,21 +139,6 @@ ST_FUNC void tccelf_delete(TCCState *s1)
|
|||||||
|
|
||||||
tcc_free(s1->sym_attrs);
|
tcc_free(s1->sym_attrs);
|
||||||
symtab_section = NULL; /* for tccrun.c:rt_printline() */
|
symtab_section = NULL; /* for tccrun.c:rt_printline() */
|
||||||
|
|
||||||
/* free any loaded DLLs */
|
|
||||||
#ifdef TCC_IS_NATIVE
|
|
||||||
for ( i = 0; i < s1->nb_loaded_dlls; i++) {
|
|
||||||
DLLReference *ref = s1->loaded_dlls[i];
|
|
||||||
if ( ref->handle )
|
|
||||||
# ifdef _WIN32
|
|
||||||
FreeLibrary((HMODULE)ref->handle);
|
|
||||||
# else
|
|
||||||
dlclose(ref->handle);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* free loaded dlls array */
|
|
||||||
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save section data state */
|
/* save section data state */
|
||||||
@ -1582,14 +1567,15 @@ static void put_ptr(TCCState *s1, Section *s, int offs)
|
|||||||
ST_FUNC void tcc_add_btstub(TCCState *s1)
|
ST_FUNC void tcc_add_btstub(TCCState *s1)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
int n, o;
|
int n, o, *p;
|
||||||
CString cstr;
|
CString cstr;
|
||||||
|
const char *__rt_info = &"___rt_info"[!s1->leading_underscore];
|
||||||
|
|
||||||
s = data_section;
|
s = data_section;
|
||||||
/* Align to PTR_SIZE */
|
/* Align to PTR_SIZE */
|
||||||
section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
|
section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
|
||||||
o = s->data_offset;
|
o = s->data_offset;
|
||||||
/* create (part of) a struct rt_context (see tccrun.c) */
|
/* create a struct rt_context (see tccrun.c) */
|
||||||
if (s1->dwarf) {
|
if (s1->dwarf) {
|
||||||
put_ptr(s1, dwarf_line_section, 0);
|
put_ptr(s1, dwarf_line_section, 0);
|
||||||
put_ptr(s1, dwarf_line_section, -1);
|
put_ptr(s1, dwarf_line_section, -1);
|
||||||
@ -1604,18 +1590,23 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
|||||||
put_ptr(s1, stab_section, -1);
|
put_ptr(s1, stab_section, -1);
|
||||||
put_ptr(s1, stab_section->link, 0);
|
put_ptr(s1, stab_section->link, 0);
|
||||||
}
|
}
|
||||||
*(addr_t *)section_ptr_add(s, PTR_SIZE) = s1->dwarf;
|
|
||||||
/* skip esym_start/esym_end/elf_str (not loaded) */
|
/* skip esym_start/esym_end/elf_str (not loaded) */
|
||||||
section_ptr_add(s, 3 * PTR_SIZE);
|
section_ptr_add(s, 3 * PTR_SIZE);
|
||||||
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
|
|
||||||
put_ptr(s1, NULL, 0);
|
if (s1->output_type == TCC_OUTPUT_MEMORY && 0 == s1->dwarf) {
|
||||||
|
put_ptr(s1, text_section, 0);
|
||||||
|
} else {
|
||||||
|
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
|
||||||
|
put_ptr(s1, NULL, 0);
|
||||||
#if defined TCC_TARGET_MACHO
|
#if defined TCC_TARGET_MACHO
|
||||||
/* adjust for __PAGEZERO */
|
/* adjust for __PAGEZERO */
|
||||||
if (s1->dwarf == 0 && s1->output_type == TCC_OUTPUT_EXE)
|
if (s1->dwarf == 0 && s1->output_type == TCC_OUTPUT_EXE)
|
||||||
write64le(data_section->data + data_section->data_offset - PTR_SIZE,
|
write64le(data_section->data + data_section->data_offset - PTR_SIZE,
|
||||||
(uint64_t)1 << 32);
|
(uint64_t)1 << 32);
|
||||||
#endif
|
#endif
|
||||||
n = 2 * PTR_SIZE;
|
}
|
||||||
|
n = 4 * PTR_SIZE;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (s1->do_bounds_check) {
|
if (s1->do_bounds_check) {
|
||||||
put_ptr(s1, bounds_section, 0);
|
put_ptr(s1, bounds_section, 0);
|
||||||
@ -1623,6 +1614,18 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
section_ptr_add(s, n);
|
section_ptr_add(s, n);
|
||||||
|
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 (s1->output_type == TCC_OUTPUT_MEMORY) {
|
||||||
|
set_global_sym(s1, __rt_info, s, o);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cstr_new(&cstr);
|
cstr_new(&cstr);
|
||||||
cstr_printf(&cstr,
|
cstr_printf(&cstr,
|
||||||
"extern void __bt_init(),__bt_exit(),__bt_init_dll();"
|
"extern void __bt_init(),__bt_exit(),__bt_init_dll();"
|
||||||
@ -1637,14 +1640,14 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
|
cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
|
||||||
s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1);
|
s1->output_type != TCC_OUTPUT_DLL);
|
||||||
/* In case dlcose is called by application */
|
/* In case dlcose is called by application */
|
||||||
cstr_printf(&cstr,
|
cstr_printf(&cstr,
|
||||||
"__attribute__((destructor)) static void __bt_exit_rt(){"
|
"__attribute__((destructor)) static void __bt_exit_rt(){"
|
||||||
"__bt_exit(__rt_info);}");
|
"__bt_exit(__rt_info);}");
|
||||||
tcc_compile_string_no_debug(s1, cstr.data);
|
tcc_compile_string_no_debug(s1, cstr.data);
|
||||||
cstr_free(&cstr);
|
cstr_free(&cstr);
|
||||||
set_local_sym(s1, &"___rt_info"[!s1->leading_underscore], s, o);
|
set_local_sym(s1, __rt_info, s, o);
|
||||||
}
|
}
|
||||||
#endif /* def CONFIG_TCC_BACKTRACE */
|
#endif /* def CONFIG_TCC_BACKTRACE */
|
||||||
|
|
||||||
@ -1777,8 +1780,8 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
|||||||
tcc_add_support(s1, "bt-exe.o");
|
tcc_add_support(s1, "bt-exe.o");
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||||
tcc_add_support(s1, "bt-log.o");
|
tcc_add_support(s1, "bt-log.o");
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
tcc_add_btstub(s1);
|
||||||
tcc_add_btstub(s1);
|
lpthread = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (lpthread)
|
if (lpthread)
|
||||||
|
3
tccpe.c
3
tccpe.c
@ -1963,8 +1963,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
|||||||
tcc_add_support(s1, "bt-dll.o");
|
tcc_add_support(s1, "bt-dll.o");
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||||
tcc_add_support(s1, "bt-log.o");
|
tcc_add_support(s1, "bt-log.o");
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
tcc_add_btstub(s1);
|
||||||
tcc_add_btstub(s1);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
405
tccrun.c
405
tccrun.c
@ -23,52 +23,69 @@
|
|||||||
/* only native compiler supports -run */
|
/* only native compiler supports -run */
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
|
|
||||||
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
typedef struct rt_context
|
typedef struct rt_context
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
/* --> tccelf.c:tcc_add_btstub wants those below in that order: */
|
/* --> tccelf.c:tcc_add_btstub wants those below in that order: */
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
Stab_Sym *stab_sym, *stab_sym_end;
|
Stab_Sym *stab_sym;
|
||||||
char *stab_str;
|
Stab_Sym *stab_sym_end;
|
||||||
|
char *stab_str;
|
||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
unsigned char *dwarf_line, *dwarf_line_end, *dwarf_line_str;
|
unsigned char *dwarf_line;
|
||||||
|
unsigned char *dwarf_line_end;
|
||||||
|
unsigned char *dwarf_line_str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
addr_t dwarf;
|
ElfW(Sym) *esym_start;
|
||||||
ElfW(Sym) *esym_start, *esym_end;
|
ElfW(Sym) *esym_end;
|
||||||
char *elf_str;
|
char *elf_str;
|
||||||
|
|
||||||
addr_t prog_base;
|
addr_t prog_base;
|
||||||
void *bounds_start;
|
void *bounds_start;
|
||||||
struct rt_context *next;
|
|
||||||
/* <-- */
|
|
||||||
int num_callers;
|
|
||||||
addr_t ip, fp, sp;
|
|
||||||
void *top_func;
|
void *top_func;
|
||||||
#endif
|
TCCState *s1;
|
||||||
jmp_buf jb;
|
struct rt_context *next;
|
||||||
int do_jmp;
|
|
||||||
# define NR_AT_EXIT 32
|
int num_callers;
|
||||||
int nr_exit;
|
int dwarf;
|
||||||
void *exitfunc[NR_AT_EXIT];
|
/* <-- */
|
||||||
void *exitarg[NR_AT_EXIT];
|
} rt_context; /* size = 11 * PTR_SIZE + 2 * sizeof (int) */
|
||||||
} rt_context;
|
|
||||||
|
typedef struct rt_frame
|
||||||
|
{
|
||||||
|
addr_t ip, fp, sp;
|
||||||
|
} rt_frame;
|
||||||
|
|
||||||
|
/* linked list of rt_contexts */
|
||||||
|
static rt_context *g_rc;
|
||||||
|
/* semaphore to protect it */
|
||||||
|
TCC_SEM(static rt_sem);
|
||||||
|
static int signal_set;
|
||||||
|
static void set_exception_handler(void);
|
||||||
|
|
||||||
|
int _rt_error(rt_frame *f, const char *msg, const char *fmt, va_list ap);
|
||||||
|
void rt_wait_sem(void) { WAIT_SEM(&rt_sem); }
|
||||||
|
void rt_post_sem(void) { POST_SEM(&rt_sem); }
|
||||||
|
#endif /* def CONFIG_TCC_BACKTRACE */
|
||||||
|
|
||||||
|
/* handle exit/atexit for tcc_run() -- thread-unsafe */
|
||||||
|
static jmp_buf rt_jb;
|
||||||
|
static int rt_do_jmp;
|
||||||
|
static int rt_nr_exit;
|
||||||
|
static void *rt_exitfunc[32];
|
||||||
|
static void *rt_exitarg[32];
|
||||||
|
|
||||||
static rt_context g_rtctxt;
|
|
||||||
static void rt_exit(int code)
|
static void rt_exit(int code)
|
||||||
{
|
{
|
||||||
rt_context *rc = &g_rtctxt;
|
if (rt_do_jmp)
|
||||||
if (rc->do_jmp)
|
longjmp(rt_jb, code ? code : 256);
|
||||||
longjmp(rc->jb, code ? code : 256);
|
|
||||||
exit(code);
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
/* ------------------------------------------------------------- */
|
||||||
static void set_exception_handler(void);
|
|
||||||
static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap);
|
|
||||||
#endif /* CONFIG_TCC_BACKTRACE */
|
|
||||||
|
|
||||||
/* defined when included from lib/bt-exe.c */
|
/* defined when included from lib/bt-exe.c */
|
||||||
#ifndef CONFIG_TCC_BACKTRACE_ONLY
|
#ifndef CONFIG_TCC_BACKTRACE_ONLY
|
||||||
|
|
||||||
@ -84,22 +101,60 @@ static void *win64_add_function_table(TCCState *s1);
|
|||||||
static void win64_del_function_table(void *);
|
static void win64_del_function_table(void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
static void bt_link(TCCState *s1)
|
||||||
/* Do all relocations (needed before using tcc_get_symbol())
|
{
|
||||||
Returns -1 on error. */
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
|
rt_context *rc;
|
||||||
|
void *p;
|
||||||
|
|
||||||
LIBTCCAPI int tcc_relocate(TCCState *s1)
|
if (!s1->do_backtrace)
|
||||||
|
return;
|
||||||
|
rc = tcc_get_symbol(s1, "__rt_info");
|
||||||
|
if (!rc)
|
||||||
|
return;
|
||||||
|
rt_wait_sem();
|
||||||
|
rc->next = g_rc, g_rc = rc, rc->s1 = s1;
|
||||||
|
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;
|
||||||
|
rc->top_func = tcc_get_symbol(s1, "main");
|
||||||
|
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
|
||||||
|
rt_post_sem();
|
||||||
|
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;
|
||||||
|
rt_wait_sem();
|
||||||
|
for (pp = &g_rc; rc = *pp, rc; pp = &rc->next)
|
||||||
|
if (rc->s1 == s1) {
|
||||||
|
*pp = rc->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rt_post_sem();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !_WIN32 && !__APPLE__
|
||||||
|
//#define HAVE_SELINUX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int rt_mem(TCCState *s1, int size)
|
||||||
{
|
{
|
||||||
void *ptr;
|
void *ptr;
|
||||||
int size;
|
int ptr_diff = 0;
|
||||||
unsigned ptr_diff = 0;
|
|
||||||
|
|
||||||
size = tcc_relocate_ex(s1, NULL, 0);
|
|
||||||
if (size < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
{
|
|
||||||
/* Using mmap instead of malloc */
|
/* Using mmap instead of malloc */
|
||||||
void *prw;
|
void *prw;
|
||||||
char tmpfname[] = "/tmp/.tccrunXXXXXX";
|
char tmpfname[] = "/tmp/.tccrunXXXXXX";
|
||||||
@ -115,21 +170,68 @@ LIBTCCAPI int tcc_relocate(TCCState *s1)
|
|||||||
return tcc_error_noabort("tccrun: could not map memory");
|
return tcc_error_noabort("tccrun: could not map memory");
|
||||||
ptr_diff = (char*)prw - (char*)ptr; /* = size; */
|
ptr_diff = (char*)prw - (char*)ptr; /* = size; */
|
||||||
//printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff);
|
//printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff);
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
ptr = tcc_malloc(size);
|
ptr = tcc_malloc(size);
|
||||||
#endif
|
#endif
|
||||||
s1->run_ptr = ptr;
|
s1->run_ptr = ptr;
|
||||||
s1->run_size = size;
|
s1->run_size = size;
|
||||||
tcc_relocate_ex(s1, ptr, ptr_diff);
|
return ptr_diff;
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/* Do all relocations (needed before using tcc_get_symbol())
|
||||||
|
Returns -1 on error. */
|
||||||
|
|
||||||
|
LIBTCCAPI int tcc_relocate(TCCState *s1)
|
||||||
|
{
|
||||||
|
int size, ret, ptr_diff;
|
||||||
|
|
||||||
|
if (s1->run_ptr)
|
||||||
|
exit(tcc_error_noabort("'tcc_relocate()' twice is no longer supported"));
|
||||||
|
|
||||||
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
|
/* for bt-log.c (but not when 'tcc -bt -run tcc.c') */
|
||||||
|
if (s1->do_backtrace && !tcc_get_symbol(s1, "_rt_error"))
|
||||||
|
tcc_add_symbol(s1, "_rt_error", _rt_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size = tcc_relocate_ex(s1, NULL, 0);
|
||||||
|
if (size < 0)
|
||||||
|
return -1;
|
||||||
|
ptr_diff = rt_mem(s1, size);
|
||||||
|
if (ptr_diff < 0)
|
||||||
|
return -1;
|
||||||
|
ret = tcc_relocate_ex(s1, s1->run_ptr, ptr_diff);
|
||||||
|
if (ret == 0)
|
||||||
|
bt_link(s1);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tcc_run_free(TCCState *s1)
|
ST_FUNC void tcc_run_free(TCCState *s1)
|
||||||
{
|
{
|
||||||
void *ptr = s1->run_ptr;
|
unsigned size;
|
||||||
unsigned size = s1->run_size;
|
void *ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* free any loaded DLLs */
|
||||||
|
for ( i = 0; i < s1->nb_loaded_dlls; i++) {
|
||||||
|
DLLReference *ref = s1->loaded_dlls[i];
|
||||||
|
if ( ref->handle )
|
||||||
|
#ifdef _WIN32
|
||||||
|
FreeLibrary((HMODULE)ref->handle);
|
||||||
|
#else
|
||||||
|
dlclose(ref->handle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/* free loaded dlls array */
|
||||||
|
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
||||||
|
|
||||||
|
/* unmap or unprotect and free memory */
|
||||||
|
ptr = s1->run_ptr;
|
||||||
|
if (NULL == ptr)
|
||||||
|
return;
|
||||||
|
bt_unlink(s1);
|
||||||
|
size = s1->run_size;
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
munmap(ptr, size * 2);
|
munmap(ptr, size * 2);
|
||||||
#else
|
#else
|
||||||
@ -153,18 +255,16 @@ static void run_cdtors(TCCState *s1, const char *start, const char *end,
|
|||||||
|
|
||||||
static void run_on_exit(int ret)
|
static void run_on_exit(int ret)
|
||||||
{
|
{
|
||||||
rt_context *rc = &g_rtctxt;
|
int n = rt_nr_exit;
|
||||||
int n = rc->nr_exit;
|
|
||||||
while (n)
|
while (n)
|
||||||
--n, ((void(*)(int,void*))rc->exitfunc[n])(ret, rc->exitarg[n]);
|
--n, ((void(*)(int,void*))rt_exitfunc[n])(ret, rt_exitarg[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rt_on_exit(void *function, void *arg)
|
static int rt_on_exit(void *function, void *arg)
|
||||||
{
|
{
|
||||||
rt_context *rc = &g_rtctxt;
|
if (rt_nr_exit < countof(rt_exitfunc)) {
|
||||||
if (rc->nr_exit < NR_AT_EXIT) {
|
rt_exitfunc[rt_nr_exit] = function;
|
||||||
rc->exitfunc[rc->nr_exit] = function;
|
rt_exitarg[rt_nr_exit++] = arg;
|
||||||
rc->exitarg[rc->nr_exit++] = arg;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -179,7 +279,6 @@ static int rt_atexit(void *function)
|
|||||||
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
{
|
{
|
||||||
int (*prog_main)(int, char **, char **), ret;
|
int (*prog_main)(int, char **, char **), ret;
|
||||||
rt_context *rc = &g_rtctxt;
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
char **envp = NULL;
|
char **envp = NULL;
|
||||||
@ -204,58 +303,15 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
if ((addr_t)-1 == (addr_t)prog_main)
|
if ((addr_t)-1 == (addr_t)prog_main)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
memset(rc, 0, sizeof *rc);
|
|
||||||
rc->do_jmp = 1;
|
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
if (s1->do_debug) {
|
|
||||||
void *p;
|
|
||||||
if (s1->dwarf) {
|
|
||||||
rc->dwarf_line = dwarf_line_section->data;
|
|
||||||
rc->dwarf_line_end = dwarf_line_section->data + dwarf_line_section->data_offset;
|
|
||||||
if (dwarf_line_str_section)
|
|
||||||
rc->dwarf_line_str = dwarf_line_str_section->data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc->stab_sym = (Stab_Sym *)stab_section->data;
|
|
||||||
rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
|
|
||||||
rc->stab_str = (char *)stab_section->link->data;
|
|
||||||
}
|
|
||||||
rc->dwarf = s1->dwarf;
|
|
||||||
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
|
|
||||||
rc->prog_base = text_section->sh_addr & 0xffffffff00000000ULL;
|
|
||||||
#if defined TCC_TARGET_MACHO
|
|
||||||
if (s1->dwarf)
|
|
||||||
rc->prog_base = (addr_t) -1;
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
rc->top_func = tcc_get_symbol(s1, "main");
|
|
||||||
rc->num_callers = s1->rt_num_callers;
|
|
||||||
if ((p = tcc_get_symbol(s1, "__rt_error")))
|
|
||||||
*(void**)p = _rt_error;
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (s1->do_bounds_check) {
|
|
||||||
rc->bounds_start = (void*)bounds_section->sh_addr;
|
|
||||||
if ((p = tcc_get_symbol(s1, "__bound_init")))
|
|
||||||
((void(*)(void*,int))p)(rc->bounds_start, 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
set_exception_handler();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
errno = 0; /* clean errno value */
|
errno = 0; /* clean errno value */
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
rt_do_jmp = 1;
|
||||||
|
rt_nr_exit = 0;
|
||||||
|
|
||||||
/* These aren't C symbols, so don't need leading underscore handling. */
|
/* These aren't C symbols, so don't need leading underscore handling. */
|
||||||
run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
|
run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
|
||||||
ret = setjmp(rc->jb);
|
ret = setjmp(rt_jb);
|
||||||
if (0 == ret)
|
if (0 == ret)
|
||||||
ret = prog_main(argc, argv, envp);
|
ret = prog_main(argc, argv, envp);
|
||||||
else if (256 == ret)
|
else if (256 == ret)
|
||||||
@ -276,7 +332,7 @@ static void cleanup_symbols(TCCState *s1)
|
|||||||
/* reset symtab */
|
/* reset symtab */
|
||||||
s->data_offset = s->link->data_offset = s->hash->data_offset = 0;
|
s->data_offset = s->link->data_offset = s->hash->data_offset = 0;
|
||||||
init_symtab(s);
|
init_symtab(s);
|
||||||
/* re-add symbols except STB_LOCAL */
|
/* add global symbols again */
|
||||||
for (sym_index = 1; sym_index < end_sym; ++sym_index) {
|
for (sym_index = 1; sym_index < end_sym; ++sym_index) {
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)s->data)[sym_index];
|
ElfW(Sym) *sym = &((ElfW(Sym) *)s->data)[sym_index];
|
||||||
const char *name = (char *)s->link->data + sym->st_name;
|
const char *name = (char *)s->link->data + sym->st_name;
|
||||||
@ -295,14 +351,10 @@ static void cleanup_sections(TCCState *s1)
|
|||||||
do {
|
do {
|
||||||
for (i = --f; i < p->nb_secs; i++) {
|
for (i = --f; i < p->nb_secs; i++) {
|
||||||
Section *s = p->secs[i];
|
Section *s = p->secs[i];
|
||||||
if (s == s1->symtab || s == s1->symtab->link || s == s1->symtab->hash
|
if (s == s1->symtab || s == s1->symtab->link || s == s1->symtab->hash) {
|
||||||
|| 0 == memcmp(s->name, ".stab", 5)
|
|
||||||
|| 0 == memcmp(s->name, ".debug_", 7)) {
|
|
||||||
s->data = tcc_realloc(s->data, s->data_allocated = s->data_offset);
|
s->data = tcc_realloc(s->data, s->data_allocated = s->data_offset);
|
||||||
} else {
|
} else {
|
||||||
free_section(s);
|
free_section(s), tcc_free(s), p->secs[i] = NULL;
|
||||||
if (0 == (s->sh_flags & SHF_ALLOC))
|
|
||||||
tcc_free(s), p->secs[i] = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++p, f);
|
} while (++p, f);
|
||||||
@ -335,8 +387,6 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff)
|
|||||||
resolve_common_syms(s1);
|
resolve_common_syms(s1);
|
||||||
build_got_entries(s1, 0);
|
build_got_entries(s1, 0);
|
||||||
#endif
|
#endif
|
||||||
if (s1->nb_errors)
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = copy = 0;
|
offset = copy = 0;
|
||||||
@ -349,6 +399,8 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
redo:
|
redo:
|
||||||
|
if (s1->nb_errors)
|
||||||
|
return -1;
|
||||||
for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
|
for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
|
||||||
n = 0; addr = 0;
|
n = 0; addr = 0;
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
@ -376,7 +428,6 @@ redo:
|
|||||||
if (s == s1->uw_pdata)
|
if (s == s1->uw_pdata)
|
||||||
s1->run_function_table = win64_add_function_table(s1);
|
s1->run_function_table = win64_add_function_table(s1);
|
||||||
#endif
|
#endif
|
||||||
free_section(s);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,11 +474,18 @@ redo:
|
|||||||
#endif
|
#endif
|
||||||
if (protect_pages((void*)addr, n, f) < 0)
|
if (protect_pages((void*)addr, n, f) < 0)
|
||||||
return tcc_error_noabort(
|
return tcc_error_noabort(
|
||||||
"mprotect failed "
|
"mprotect failed (did you mean to configure --with-selinux?)");
|
||||||
"(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 (copy) {
|
if (copy) {
|
||||||
/* remove local symbols and free sections except symtab */
|
/* remove local symbols and free sections except symtab */
|
||||||
cleanup_symbols(s1);
|
cleanup_symbols(s1);
|
||||||
@ -437,17 +495,7 @@ redo:
|
|||||||
|
|
||||||
/* relocate symbols */
|
/* relocate symbols */
|
||||||
relocate_syms(s1, s1->symtab, !(s1->nostdlib));
|
relocate_syms(s1, s1->symtab, !(s1->nostdlib));
|
||||||
if (s1->nb_errors)
|
/* relocate sections */
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (0 == mem) {
|
|
||||||
offset = (offset + (PAGESIZE-1)) & ~(PAGESIZE-1);
|
|
||||||
#ifndef HAVE_SELINUX
|
|
||||||
offset += PAGESIZE; /* extra space to align malloc memory start */
|
|
||||||
#endif
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
s1->pe_imagebase = mem;
|
s1->pe_imagebase = mem;
|
||||||
#else
|
#else
|
||||||
@ -578,6 +626,8 @@ next:
|
|||||||
last_pc = (addr_t)-1;
|
last_pc = (addr_t)-1;
|
||||||
last_line_num = 1;
|
last_line_num = 1;
|
||||||
last_incl_index = 0;
|
last_incl_index = 0;
|
||||||
|
if (NULL == rc)
|
||||||
|
goto found;
|
||||||
|
|
||||||
for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) {
|
for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) {
|
||||||
str = rc->stab_str + sym->n_strx;
|
str = rc->stab_str + sym->n_strx;
|
||||||
@ -658,14 +708,16 @@ next:
|
|||||||
func_name[0] = '\0';
|
func_name[0] = '\0';
|
||||||
func_addr = 0;
|
func_addr = 0;
|
||||||
last_incl_index = 0;
|
last_incl_index = 0;
|
||||||
|
|
||||||
/* we try symtab symbols (no line number info) */
|
/* we try symtab symbols (no line number info) */
|
||||||
p = rt_elfsym(rc, wanted_pc, &func_addr);
|
p = rt_elfsym(rc, wanted_pc, &func_addr);
|
||||||
if (p) {
|
if (p) {
|
||||||
pstrcpy(func_name, sizeof func_name, p);
|
pstrcpy(func_name, sizeof func_name, p);
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
if ((rc = rc->next))
|
rc = rc->next;
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
i = last_incl_index;
|
i = last_incl_index;
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
@ -799,6 +851,11 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
|||||||
char *function;
|
char *function;
|
||||||
|
|
||||||
next:
|
next:
|
||||||
|
filename = NULL;
|
||||||
|
func_addr = 0;
|
||||||
|
if (NULL == rc)
|
||||||
|
goto found;
|
||||||
|
|
||||||
ln = rc->dwarf_line;
|
ln = rc->dwarf_line;
|
||||||
while (ln < rc->dwarf_line_end) {
|
while (ln < rc->dwarf_line_end) {
|
||||||
dir_size = 0;
|
dir_size = 0;
|
||||||
@ -953,8 +1010,7 @@ check_pc:
|
|||||||
pc = dwarf_read_8(cp, end);
|
pc = dwarf_read_8(cp, end);
|
||||||
#endif
|
#endif
|
||||||
#if defined TCC_TARGET_MACHO
|
#if defined TCC_TARGET_MACHO
|
||||||
if (rc->prog_base != (addr_t) -1)
|
pc += rc->prog_base;
|
||||||
pc += rc->prog_base;
|
|
||||||
#endif
|
#endif
|
||||||
opindex = 0;
|
opindex = 0;
|
||||||
break;
|
break;
|
||||||
@ -1036,8 +1092,9 @@ next_line:
|
|||||||
function = rt_elfsym(rc, wanted_pc, &func_addr);
|
function = rt_elfsym(rc, wanted_pc, &func_addr);
|
||||||
if (function)
|
if (function)
|
||||||
goto found;
|
goto found;
|
||||||
if ((rc = rc->next))
|
rc = rc->next;
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
if (filename) {
|
if (filename) {
|
||||||
if (skip[0] && strstr(filename, skip))
|
if (skip[0] && strstr(filename, skip))
|
||||||
@ -1051,25 +1108,17 @@ found:
|
|||||||
}
|
}
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
|
|
||||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level);
|
static int rt_get_caller_pc(addr_t *paddr, rt_frame *f, int level);
|
||||||
|
|
||||||
static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
|
int _rt_error(rt_frame *f, const char *msg, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
rt_context *rc = &g_rtctxt;
|
rt_context *rc;
|
||||||
addr_t pc = 0;
|
addr_t pc = 0;
|
||||||
char skip[100];
|
char skip[100];
|
||||||
int i, level, ret, n, one;
|
int i, level, ret, n, one;
|
||||||
const char *a, *b, *msg;
|
const char *a, *b;
|
||||||
|
addr_t (*printline)(rt_context*, addr_t, const char*, const char*);
|
||||||
if (fp) {
|
addr_t top_func = 0;
|
||||||
/* we're called from tcc_backtrace. */
|
|
||||||
rc->fp = (addr_t)fp;
|
|
||||||
rc->ip = (addr_t)ip;
|
|
||||||
msg = "";
|
|
||||||
} else {
|
|
||||||
/* we're called from signal/exception handler */
|
|
||||||
msg = "RUNTIME ERROR: ";
|
|
||||||
}
|
|
||||||
|
|
||||||
skip[0] = 0;
|
skip[0] = 0;
|
||||||
/* If fmt is like "^file.c^..." then skip calls from 'file.c' */
|
/* If fmt is like "^file.c^..." then skip calls from 'file.c' */
|
||||||
@ -1082,15 +1131,22 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
|
|||||||
if (fmt[0] == '\001')
|
if (fmt[0] == '\001')
|
||||||
++fmt, one = 1;
|
++fmt, one = 1;
|
||||||
|
|
||||||
n = rc->num_callers ? rc->num_callers : 6;
|
rt_wait_sem();
|
||||||
|
rc = g_rc;
|
||||||
|
printline = rt_printline, n = 6;
|
||||||
|
if (rc) {
|
||||||
|
if (rc->dwarf)
|
||||||
|
printline = rt_printline_dwarf;
|
||||||
|
if (rc->num_callers)
|
||||||
|
n = rc->num_callers;
|
||||||
|
top_func = (addr_t)rc->top_func;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = level = 0; level < n; i++) {
|
for (i = level = 0; level < n; i++) {
|
||||||
ret = rt_get_caller_pc(&pc, rc, i);
|
ret = rt_get_caller_pc(&pc, f, i);
|
||||||
a = "%s";
|
a = "%s";
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
if (rc->dwarf)
|
pc = printline(rc, pc, level ? "by" : "at", skip);
|
||||||
pc = rt_printline_dwarf(rc, pc, level ? "by" : "at", skip);
|
|
||||||
else
|
|
||||||
pc = rt_printline(rc, pc, level ? "by" : "at", skip);
|
|
||||||
if (pc == (addr_t)-1)
|
if (pc == (addr_t)-1)
|
||||||
continue;
|
continue;
|
||||||
a = ": %s";
|
a = ": %s";
|
||||||
@ -1103,22 +1159,22 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
|
|||||||
if (one)
|
if (one)
|
||||||
break;
|
break;
|
||||||
rt_printf("\n");
|
rt_printf("\n");
|
||||||
if (ret == -1 || (pc == (addr_t)rc->top_func && pc))
|
if (ret == -1 || (pc == top_func && pc))
|
||||||
break;
|
break;
|
||||||
++level;
|
++level;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc->ip = rc->fp = 0;
|
rt_post_sem();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* emit a run time error at position 'pc' */
|
/* emit a run time error at position 'pc' */
|
||||||
static int rt_error(const char *fmt, ...)
|
static int rt_error(rt_frame *f, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int ret;
|
int ret;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ret = _rt_error(0, 0, fmt, ap);
|
ret = _rt_error(f, "RUNTIME ERROR: ", fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1135,7 +1191,7 @@ static int rt_error(const char *fmt, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* translate from ucontext_t* to internal rt_context * */
|
/* translate from ucontext_t* to internal rt_context * */
|
||||||
static void rt_getcontext(ucontext_t *uc, rt_context *rc)
|
static void rt_getcontext(ucontext_t *uc, rt_frame *rc)
|
||||||
{
|
{
|
||||||
#if defined _WIN64
|
#if defined _WIN64
|
||||||
rc->ip = uc->Rip;
|
rc->ip = uc->Rip;
|
||||||
@ -1228,33 +1284,33 @@ static void rt_getcontext(ucontext_t *uc, rt_context *rc)
|
|||||||
/* signal handler for fatal errors */
|
/* signal handler for fatal errors */
|
||||||
static void sig_error(int signum, siginfo_t *siginf, void *puc)
|
static void sig_error(int signum, siginfo_t *siginf, void *puc)
|
||||||
{
|
{
|
||||||
rt_context *rc = &g_rtctxt;
|
rt_frame f;
|
||||||
rt_getcontext(puc, rc);
|
rt_getcontext(puc, &f);
|
||||||
|
|
||||||
switch(signum) {
|
switch(signum) {
|
||||||
case SIGFPE:
|
case SIGFPE:
|
||||||
switch(siginf->si_code) {
|
switch(siginf->si_code) {
|
||||||
case FPE_INTDIV:
|
case FPE_INTDIV:
|
||||||
case FPE_FLTDIV:
|
case FPE_FLTDIV:
|
||||||
rt_error("division by zero");
|
rt_error(&f, "division by zero");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rt_error("floating point exception");
|
rt_error(&f, "floating point exception");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SIGBUS:
|
case SIGBUS:
|
||||||
case SIGSEGV:
|
case SIGSEGV:
|
||||||
rt_error("invalid memory access");
|
rt_error(&f, "invalid memory access");
|
||||||
break;
|
break;
|
||||||
case SIGILL:
|
case SIGILL:
|
||||||
rt_error("illegal instruction");
|
rt_error(&f, "illegal instruction");
|
||||||
break;
|
break;
|
||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
rt_error("abort() called");
|
rt_error(&f, "abort() called");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rt_error("caught signal %d", signum);
|
rt_error(&f, "caught signal %d", signum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rt_exit(255);
|
rt_exit(255);
|
||||||
@ -1301,30 +1357,31 @@ static void set_exception_handler(void)
|
|||||||
/* signal handler for fatal errors */
|
/* signal handler for fatal errors */
|
||||||
static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
|
static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
|
||||||
{
|
{
|
||||||
rt_context *rc = &g_rtctxt;
|
rt_frame f;
|
||||||
unsigned code;
|
unsigned code;
|
||||||
rt_getcontext(ex_info->ContextRecord, rc);
|
|
||||||
|
rt_getcontext(ex_info->ContextRecord, &f);
|
||||||
|
|
||||||
switch (code = ex_info->ExceptionRecord->ExceptionCode) {
|
switch (code = ex_info->ExceptionRecord->ExceptionCode) {
|
||||||
case EXCEPTION_ACCESS_VIOLATION:
|
case EXCEPTION_ACCESS_VIOLATION:
|
||||||
rt_error("invalid memory access");
|
rt_error(&f, "invalid memory access");
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_STACK_OVERFLOW:
|
case EXCEPTION_STACK_OVERFLOW:
|
||||||
rt_error("stack overflow");
|
rt_error(&f, "stack overflow");
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||||
rt_error("division by zero");
|
rt_error(&f, "division by zero");
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_BREAKPOINT:
|
case EXCEPTION_BREAKPOINT:
|
||||||
case EXCEPTION_SINGLE_STEP:
|
case EXCEPTION_SINGLE_STEP:
|
||||||
rc->ip = *(addr_t*)rc->sp;
|
f.ip = *(addr_t*)f.sp;
|
||||||
rt_error("breakpoint/single-step exception:");
|
rt_error(&f, "breakpoint/single-step exception:");
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
default:
|
default:
|
||||||
rt_error("caught exception %08x", code);
|
rt_error(&f, "caught exception %08x", code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (rc->do_jmp)
|
if (rt_do_jmp)
|
||||||
rt_exit(255);
|
rt_exit(255);
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
}
|
}
|
||||||
@ -1340,7 +1397,7 @@ static void set_exception_handler(void)
|
|||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
/* return the PC at frame level 'level'. Return negative if not found */
|
/* return the PC at frame level 'level'. Return negative if not found */
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
static int rt_get_caller_pc(addr_t *paddr, rt_frame *rc, int level)
|
||||||
{
|
{
|
||||||
addr_t ip, fp;
|
addr_t ip, fp;
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
@ -1364,7 +1421,7 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
static int rt_get_caller_pc(addr_t *paddr, rt_frame *rc, int level)
|
||||||
{
|
{
|
||||||
/* XXX: only supports linux/bsd */
|
/* XXX: only supports linux/bsd */
|
||||||
#if !defined(__linux__) && \
|
#if !defined(__linux__) && \
|
||||||
@ -1384,7 +1441,7 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
static int rt_get_caller_pc(addr_t *paddr, rt_frame *rc, int level)
|
||||||
{
|
{
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
*paddr = rc->ip;
|
*paddr = rc->ip;
|
||||||
@ -1398,7 +1455,7 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__riscv)
|
#elif defined(__riscv)
|
||||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
static int rt_get_caller_pc(addr_t *paddr, rt_frame *rc, int level)
|
||||||
{
|
{
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
*paddr = rc->ip;
|
*paddr = rc->ip;
|
||||||
@ -1415,7 +1472,7 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
#warning add arch specific rt_get_caller_pc()
|
#warning add arch specific rt_get_caller_pc()
|
||||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
|
static int rt_get_caller_pc(addr_t *paddr, rt_frame *rc, int level)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,8 @@ DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
all test :
|
all test :
|
||||||
|
@echo ------------ version ------------
|
||||||
|
@$(TCC_LOCAL) -v
|
||||||
@$(MAKE) --no-print-directory -s clean
|
@$(MAKE) --no-print-directory -s clean
|
||||||
@$(MAKE) --no-print-directory -s -r $(TESTS)
|
@$(MAKE) --no-print-directory -s -r $(TESTS)
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ set /p VERSION= < ..\VERSION
|
|||||||
set TCCDIR=
|
set TCCDIR=
|
||||||
set BINDIR=
|
set BINDIR=
|
||||||
set DOC=no
|
set DOC=no
|
||||||
set EXES_ONLY=no
|
set XCC=no
|
||||||
goto :a0
|
goto :a0
|
||||||
:a2
|
:a2
|
||||||
shift
|
shift
|
||||||
@ -27,7 +27,7 @@ if (%1)==(-v) set VERSION=%~2&& goto :a2
|
|||||||
if (%1)==(-i) set TCCDIR=%2&& goto :a2
|
if (%1)==(-i) set TCCDIR=%2&& goto :a2
|
||||||
if (%1)==(-b) set BINDIR=%2&& goto :a2
|
if (%1)==(-b) set BINDIR=%2&& goto :a2
|
||||||
if (%1)==(-d) set DOC=yes&& goto :a3
|
if (%1)==(-d) set DOC=yes&& goto :a3
|
||||||
if (%1)==(-x) set EXES_ONLY=yes&& goto :a3
|
if (%1)==(-x) set XCC=yes&& goto :a3
|
||||||
if (%1)==() goto :p1
|
if (%1)==() goto :p1
|
||||||
:usage
|
:usage
|
||||||
echo usage: build-tcc.bat [ options ... ]
|
echo usage: build-tcc.bat [ options ... ]
|
||||||
@ -39,7 +39,7 @@ echo -v "version" set tcc version
|
|||||||
echo -i tccdir install tcc into tccdir
|
echo -i tccdir install tcc into tccdir
|
||||||
echo -b bindir but install tcc.exe and libtcc.dll into bindir
|
echo -b bindir but install tcc.exe and libtcc.dll into bindir
|
||||||
echo -d create tcc-doc.html too (needs makeinfo)
|
echo -d create tcc-doc.html too (needs makeinfo)
|
||||||
echo -x just create the executables
|
echo -x build the cross compiler too
|
||||||
echo -clean delete all previously produced files and directories
|
echo -clean delete all previously produced files and directories
|
||||||
exit /B 1
|
exit /B 1
|
||||||
|
|
||||||
@ -144,6 +144,7 @@ for %%f in (*tcc.exe *tcc.dll) do @del %%f
|
|||||||
%CC% -o libtcc.dll -shared %LIBTCC_C% %D% -DLIBTCC_AS_DLL
|
%CC% -o libtcc.dll -shared %LIBTCC_C% %D% -DLIBTCC_AS_DLL
|
||||||
@if errorlevel 1 goto :the_end
|
@if errorlevel 1 goto :the_end
|
||||||
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0"
|
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0"
|
||||||
|
if not _%XCC%_==_yes_ goto :compiler_done
|
||||||
%CC% -o %PX%-tcc.exe ..\tcc.c %DX%
|
%CC% -o %PX%-tcc.exe ..\tcc.c %DX%
|
||||||
:compiler_done
|
:compiler_done
|
||||||
@if (%EXES_ONLY%)==(yes) goto :files_done
|
@if (%EXES_ONLY%)==(yes) goto :files_done
|
||||||
|
Loading…
Reference in New Issue
Block a user