mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
Move -run -nostdlib code to lib directory
tcc.h, arm-gen.c, arm64-gen.c, i386-gen.c, riscv64-gen.c, x86_64-gen.c: - remove old code tccrun.c: - update to use lib/run_nostdlib.c Makefile, lib/Makefile, lib/run_nostdlib.c: - new code tests/nostdlib_test.c: - testcode
This commit is contained in:
parent
829c848520
commit
8569427459
2
Makefile
2
Makefile
@ -367,7 +367,7 @@ 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)
|
||||
|
||||
EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
||||
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
||||
|
||||
# install progs & libs
|
||||
install-unx:
|
||||
|
||||
14
arm-gen.c
14
arm-gen.c
@ -1396,20 +1396,6 @@ void gfunc_call(int nb_args)
|
||||
float_abi = def_float_abi;
|
||||
}
|
||||
|
||||
void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var)
|
||||
{
|
||||
#ifdef __arm__
|
||||
void *sp;
|
||||
|
||||
__asm__("sub sp, sp, %1\n"
|
||||
"\tmov %0, sp"
|
||||
: "=r" (sp)
|
||||
: "r" ((((size_t) cnt + 1) & -2) * sizeof(char *)));
|
||||
memcpy(sp, var, cnt * sizeof(char *));
|
||||
__asm__("mov pc, %0" : : "r" (prog_main));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
void gfunc_prolog(Sym *func_sym)
|
||||
{
|
||||
|
||||
19
arm64-gen.c
19
arm64-gen.c
@ -1167,25 +1167,6 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
tcc_free(t);
|
||||
}
|
||||
|
||||
void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var)
|
||||
{
|
||||
#if defined(__aarch64__)
|
||||
#if defined(__TINYC__)
|
||||
// FIXME: immplement arm64 assembler
|
||||
fprintf(stderr, "tcc -nostdlib -run not implement for arm64\n");
|
||||
#else
|
||||
void *sp;
|
||||
|
||||
__asm__("sub sp, sp, %1\n"
|
||||
"\tmov %0, sp"
|
||||
: "=r" (sp)
|
||||
: "r" ((((size_t) cnt + 1) & -2) * sizeof(char *)));
|
||||
memcpy(sp, var, cnt * sizeof(char *));
|
||||
__asm__("br %0" : : "r" (prog_main));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned long arm64_func_va_list_stack;
|
||||
static int arm64_func_va_list_gr_offs;
|
||||
static int arm64_func_va_list_vr_offs;
|
||||
|
||||
18
i386-gen.c
18
i386-gen.c
@ -504,24 +504,6 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
vtop--;
|
||||
}
|
||||
|
||||
void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var)
|
||||
{
|
||||
#ifdef __i386__
|
||||
#ifdef TCC_TARGET_PE
|
||||
fprintf(stderr, "tcc -nostdlib -run not implement for TCC_TARGET_PE\n");
|
||||
#else
|
||||
void *sp;
|
||||
|
||||
__asm("sub %1, %%esp\n"
|
||||
"\tmov %%esp, %0"
|
||||
: "=r" (sp)
|
||||
: "r" ((((size_t) cnt + 1) & -2) * sizeof(char *)));
|
||||
memcpy(sp, var, cnt * sizeof(char *));
|
||||
__asm__("jmp *%0" : : "r" (prog_main));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
#define FUNC_PROLOG_SIZE (10 + USE_EBX)
|
||||
#else
|
||||
|
||||
@ -50,13 +50,13 @@ Nat = $(if $X,no,)
|
||||
Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace))
|
||||
Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck))
|
||||
|
||||
$(Nat)COMMON_O += runmain.o tcov.o
|
||||
$(Nat)COMMON_O += runmain.o run_nostdlib.o tcov.o
|
||||
$(Cbt)COMMON_O += bt-exe.o bt-log.o
|
||||
$(Cbt)WIN_O += bt-dll.o
|
||||
$(Cbc)COMMON_O += bcheck.o
|
||||
|
||||
# not in libtcc1.a
|
||||
EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
||||
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
||||
|
||||
OBJ-i386 = $(I386_O) $(LIN_O)
|
||||
OBJ-x86_64 = $(X86_64_O) $(LIN_O)
|
||||
|
||||
94
lib/run_nostdlib.c
Normal file
94
lib/run_nostdlib.c
Normal file
@ -0,0 +1,94 @@
|
||||
/* ------------------------------------------------------------- */
|
||||
/* support for run_nostdlib() */
|
||||
|
||||
// FIXME: implement arm64 assembler
|
||||
#if defined(__aarch64__)
|
||||
#define USE_ARM64_ASM
|
||||
static void *alloca_arm64(unsigned long);
|
||||
__asm__(
|
||||
#ifdef __leading_underscore
|
||||
"_alloca_arm64:\n\t"
|
||||
#else
|
||||
"alloca_arm64:\n\t"
|
||||
#endif
|
||||
".int 0x91003c00\n\t" // add x0, x0, #15
|
||||
".int 0x927cec00\n\t" // and x0, x0, #-16
|
||||
".int 0xcb2063ff\n\t" // sub sp, sp, x0
|
||||
".int 0x910003e0\n\t" // mov x0, sp
|
||||
".int 0xd65f03c0" // ret
|
||||
);
|
||||
static void goto_arm64(void *start);
|
||||
__asm__(
|
||||
#ifdef __leading_underscore
|
||||
"_goto_arm64:\n\t"
|
||||
#else
|
||||
"goto_arm64:\n\t"
|
||||
#endif
|
||||
".int 0xd61f0000" // br x0
|
||||
);
|
||||
#endif
|
||||
|
||||
void _run_nostdlib(void *start, int argc, char **argv, char **envp)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
int i, n = 1;
|
||||
unsigned long l;
|
||||
char **sp, **e = envp;
|
||||
|
||||
if (envp)
|
||||
while (*e++)
|
||||
n++;
|
||||
l = (((unsigned long) argc + n + 2 + 1) & -2) * sizeof(char *);
|
||||
/* nostdlib so avoid alloca() */
|
||||
/* also code below will be removed because compiler detects dead store */
|
||||
#if defined(USE_ARM64_ASM)
|
||||
sp = alloca_arm64(l);
|
||||
#else
|
||||
#if defined(__aarch64__)
|
||||
__asm__("sub sp, sp, %1\n"
|
||||
"\tmov %0, sp"
|
||||
#elif defined(__arm__)
|
||||
__asm__("sub sp, sp, %1\n"
|
||||
"\tmov %0, sp"
|
||||
#elif defined(__i386__)
|
||||
__asm("sub %1, %%esp\n"
|
||||
"\tmov %%esp, %0"
|
||||
#elif defined(__riscv)
|
||||
__asm__("sub sp, sp, %1\n"
|
||||
"\tmv %0, sp"
|
||||
#elif defined(__x86_64__)
|
||||
__asm__("subq %1, %%rsp\n"
|
||||
"\tmovq %%rsp, %0"
|
||||
#endif
|
||||
: "=r" (sp)
|
||||
: "r" (l));
|
||||
#endif
|
||||
/* create sysv memory layout: argc, argv[], NULL, envp[], NULL */
|
||||
sp[0] = (char *) (__SIZE_TYPE__) argc;
|
||||
for (i = 0; i < argc; i++)
|
||||
sp[i + 1] = argv[i];
|
||||
sp[argc + 1] = (char *) 0;
|
||||
if (envp)
|
||||
for (i = 0; i < n; i++)
|
||||
sp[i + argc + 2] = envp[i];
|
||||
else
|
||||
sp[argc + 2] = (char *) 0;
|
||||
#endif
|
||||
|
||||
/* goto *start does not work for clang. Use assembly. */
|
||||
#if defined(USE_ARM64_ASM)
|
||||
goto_arm64(start);
|
||||
#else
|
||||
#if defined(__aarch64__)
|
||||
__asm__("br %0" : : "r" (start));
|
||||
#elif defined(__arm__)
|
||||
__asm__("mov pc, %0" : : "r" (start));
|
||||
#elif defined(__i386__)
|
||||
__asm__("jmp *%0" : : "r" (start));
|
||||
#elif defined(__riscv)
|
||||
__asm__("jalr %0" : : "r" (start));
|
||||
#elif defined(__x86_64__)
|
||||
__asm__("jmp *%0" : : "r" (start));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@ -769,20 +769,6 @@ done:
|
||||
tcc_free(info);
|
||||
}
|
||||
|
||||
void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var)
|
||||
{
|
||||
#ifdef __riscv
|
||||
void *sp;
|
||||
|
||||
__asm__("sub sp, sp, %1\n"
|
||||
"\tmv %0, sp"
|
||||
: "=r" (sp)
|
||||
: "r" ((((size_t) cnt + 1) & -2) * sizeof(char *)));
|
||||
memcpy(sp, var, cnt * sizeof(char *));
|
||||
__asm__("jalr %0" : : "r" (prog_main));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int func_sub_sp_offset, num_va_regs, func_va_list_ofs;
|
||||
|
||||
ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
|
||||
1
tcc.h
1
tcc.h
@ -1797,7 +1797,6 @@ ST_FUNC const char *dlerror(void);
|
||||
ST_FUNC void *dlsym(void *handle, const char *symbol);
|
||||
#endif
|
||||
ST_FUNC void tcc_run_free(TCCState *s1);
|
||||
ST_FUNC void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var);
|
||||
#endif
|
||||
|
||||
/* ------------ tcctools.c ----------------- */
|
||||
|
||||
30
tccrun.c
30
tccrun.c
@ -206,9 +206,10 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
const char *top_sym;
|
||||
jmp_buf main_jb;
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
char **envp = NULL;
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#if defined(__APPLE__)
|
||||
extern char ***_NSGetEnviron(void);
|
||||
char **envp = *_NSGetEnviron();
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
extern char **environ;
|
||||
char **envp = environ;
|
||||
#else
|
||||
@ -221,6 +222,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
|
||||
tcc_add_symbol(s1, "__rt_exit", rt_exit);
|
||||
if (s1->nostdlib) {
|
||||
tcc_add_support(s1, "run_nostdlib.o");
|
||||
s1->run_main = top_sym = s1->elf_entryname ? s1->elf_entryname : "_start";
|
||||
} else {
|
||||
tcc_add_support(s1, "runmain.o");
|
||||
@ -251,24 +253,12 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym));
|
||||
if (0 == ret) {
|
||||
if (s1->nostdlib) {
|
||||
int n = 1;
|
||||
char **p, **e = envp;
|
||||
void (*run_nostdlib)(void *start, int argc, char **argv, char **envp);
|
||||
|
||||
/* create sysv memory layout: argc, argv[], NULL, envp[], NULL */
|
||||
if (envp)
|
||||
while (*e++)
|
||||
n++;
|
||||
p = tcc_malloc((argc + n + 2) * sizeof(char *));
|
||||
p[0] = (char *) (size_t) argc;
|
||||
memcpy(p + 1, argv, argc * sizeof(char *));
|
||||
p[argc + 1] = NULL;
|
||||
if (envp)
|
||||
memcpy(p + argc + 2, envp, n * sizeof(char *));
|
||||
else
|
||||
p[argc + 2] = NULL;
|
||||
/* Probably never returns */
|
||||
tcc_run_start(prog_main, argc + n + 2, p);
|
||||
tcc_free(p);
|
||||
run_nostdlib = (void *)get_sym_addr(s1, "_run_nostdlib", 1, 1);
|
||||
if ((addr_t)-1 == (addr_t)run_nostdlib)
|
||||
return -1;
|
||||
run_nostdlib(prog_main, argc, argv, envp); /* never returns */
|
||||
}
|
||||
else
|
||||
ret = prog_main(argc, argv, envp);
|
||||
|
||||
155
tests/nostdlib_test.c
Executable file
155
tests/nostdlib_test.c
Executable file
@ -0,0 +1,155 @@
|
||||
#!/usr/local/bin/tcc -run -nostdlib
|
||||
|
||||
// Not working on windows and apple because of different API.
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#if defined __x86_64__
|
||||
__asm__ ("syscall:\n\t"
|
||||
"mov %rdi,%rax\n\t"
|
||||
"mov %rsi,%rdi\n\t"
|
||||
"mov %rdx,%rsi\n\t"
|
||||
"mov %rcx,%rdx\n\t"
|
||||
"mov %r8,%r10\n\t"
|
||||
"mov %r9,%r8\n\t"
|
||||
"mov 0x8(%rsp),%r9\n\t"
|
||||
"syscall\n\t"
|
||||
"ret");
|
||||
__asm__ (".global _start\n\t"
|
||||
"_start:\n\t"
|
||||
"mov 0(%rsp), %rdi\n\t"
|
||||
"lea 8(%rsp), %rsi\n\t"
|
||||
"jmp print");
|
||||
#elif defined __i386__
|
||||
__asm__ ("syscall:\n\t"
|
||||
"push %ebp\n\t"
|
||||
"push %edi\n\t"
|
||||
"push %esi\n\t"
|
||||
"push %ebx\n\t"
|
||||
"mov 0x2c(%esp),%ebp\n\t"
|
||||
"mov 0x28(%esp),%edi\n\t"
|
||||
"mov 0x24(%esp),%esi\n\t"
|
||||
"mov 0x20(%esp),%edx\n\t"
|
||||
"mov 0x1c(%esp),%ecx\n\t"
|
||||
"mov 0x18(%esp),%ebx\n\t"
|
||||
"mov 0x14(%esp),%eax\n\t"
|
||||
// "call *%gs:0x10\n\t"
|
||||
".byte 0x65,0xff,0x15,0x10,0x00,0x00,0x00\n\t"
|
||||
"pop %ebx\n\t"
|
||||
"pop %esi\n\t"
|
||||
"pop %edi\n\t"
|
||||
"pop %ebp\n\t"
|
||||
"ret");
|
||||
__asm__ (".global _start\n\t"
|
||||
"_start:\n\t"
|
||||
"pop %esi\n\t"
|
||||
"mov %esp, %ecx\n\t"
|
||||
"and $0xfffffff0,%esp\n\t"
|
||||
"push %ecx\n\t"
|
||||
"push %esi\n\t"
|
||||
"call print");
|
||||
#elif defined __arm__
|
||||
__asm__ ("syscall:\n\t"
|
||||
"mov r12, sp\n\t"
|
||||
"push {r4, r5, r6, r7}\n\t"
|
||||
"mov r7, r0\n\t"
|
||||
"mov r0, r1\n\t"
|
||||
"mov r1, r2\n\t"
|
||||
"mov r2, r3\n\t"
|
||||
"ldm r12, {r3, r4, r5, r6}\n\t"
|
||||
"svc 0x00000000\n\t"
|
||||
"pop {r4, r5, r6, r7}\n\t"
|
||||
"mov pc, lr");
|
||||
__asm__ (".global _start\n\t"
|
||||
"_start:\n\t"
|
||||
"pop {r0}\n\t"
|
||||
"mov r1, sp\n\t"
|
||||
"bl print");
|
||||
#elif defined __aarch64__
|
||||
__asm__ ("syscall:\n\t"
|
||||
".int 0x2a0003e8\n\t" // mov w8, w0
|
||||
".int 0xaa0103e0\n\t" // x0, x1
|
||||
".int 0xaa0203e1\n\t" // mov x1, x2
|
||||
".int 0xaa0303e2\n\t" // mov x2, x3
|
||||
".int 0xaa0403e3\n\t" // mov x3, x4
|
||||
".int 0xaa0503e4\n\t" // mov x4, x5
|
||||
".int 0xaa0603e5\n\t" // mov x5, x6
|
||||
".int 0xaa0703e6\n\t" // mov x6, x7
|
||||
".int 0xd4000001\n\t" // svc #0x0
|
||||
".int 0xd65f03c0"); // ret
|
||||
__asm__ (".global _start\n\t"
|
||||
"_start:\n\t"
|
||||
".int 0xf94003e0\n\t" // ldr x0, [sp]
|
||||
".int 0x910023e1\n\t" // add x1, sp, #08
|
||||
".reloc .,R_AARCH64_CALL26,print\n\t"
|
||||
".int 0x94000000"); // bl print
|
||||
#elif defined __riscv
|
||||
__asm__ ("syscall:\n\t"
|
||||
"mv t1,a0\n\t"
|
||||
"mv a0,a1\n\t"
|
||||
"mv a1,a2\n\t"
|
||||
"mv a2,a3\n\t"
|
||||
"mv a3,a4\n\t"
|
||||
"mv a4,a5\n\t"
|
||||
"mv a5,a6\n\t"
|
||||
"mv a6,a7\n\t"
|
||||
"mv a7,t1\n\t"
|
||||
"ecall\n\t"
|
||||
"ret");
|
||||
__asm__ (".global _start\n\t"
|
||||
"_start:\n\t"
|
||||
"ld a0,0(sp)\n\t"
|
||||
"addi a1,sp,8\n\t"
|
||||
"jal print");
|
||||
#endif
|
||||
unsigned long strlen(const char *s)
|
||||
{
|
||||
unsigned long len = 0;
|
||||
|
||||
while (*s++)
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
static void pr_num(int num)
|
||||
{
|
||||
char val[20], *p = &val[20];
|
||||
|
||||
*--p = '\0';
|
||||
do {
|
||||
int a = num, b = 0;
|
||||
|
||||
while (a >= 10) {
|
||||
a -= 10;
|
||||
b++;
|
||||
}
|
||||
*--p = a + '0';
|
||||
num = b;
|
||||
} while (num);
|
||||
syscall(SYS_write, 1, p, strlen(p));
|
||||
}
|
||||
|
||||
static void pr_str(int n, char *s)
|
||||
{
|
||||
pr_num(n);
|
||||
syscall(SYS_write, 1, ": ", 2);
|
||||
syscall(SYS_write, 1, s, strlen(s));
|
||||
syscall(SYS_write, 1, "\n", 1);
|
||||
}
|
||||
|
||||
void print(int argc, char **argv) {
|
||||
int i;
|
||||
char **envp = &argv[argc + 1];
|
||||
|
||||
syscall(SYS_write, 1, "argc: ", 6);
|
||||
pr_num(argc);
|
||||
syscall(SYS_write, 1, "\n", 1);
|
||||
syscall(SYS_write, 1, "argv[]\n", 7);
|
||||
for (i = 0; i < argc; i++)
|
||||
pr_str(i, argv[i]);
|
||||
syscall(SYS_write, 1, "envp[]\n", 7);
|
||||
i = 0;
|
||||
while (*envp)
|
||||
pr_str(i++, *envp++);
|
||||
syscall(SYS_exit, 0);
|
||||
}
|
||||
19
x86_64-gen.c
19
x86_64-gen.c
@ -933,11 +933,6 @@ void gfunc_call(int nb_args)
|
||||
vtop--;
|
||||
}
|
||||
|
||||
void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var)
|
||||
{
|
||||
fprintf(stderr, "tcc -nostdlib -run not implement for TCC_TARGET_PE\n");
|
||||
}
|
||||
|
||||
#define FUNC_PROLOG_SIZE 11
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
@ -1438,20 +1433,6 @@ void gfunc_call(int nb_args)
|
||||
vtop--;
|
||||
}
|
||||
|
||||
void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
void *sp;
|
||||
|
||||
__asm__("subq %1, %%rsp\n"
|
||||
"\tmovq %%rsp, %0"
|
||||
: "=r" (sp)
|
||||
: "r" ((((size_t) cnt + 1) & -2) * sizeof(char *)));
|
||||
memcpy(sp, var, cnt * sizeof(char *));
|
||||
__asm__("jmp *%0" : : "r" (prog_main));
|
||||
#endif
|
||||
}
|
||||
|
||||
#define FUNC_PROLOG_SIZE 11
|
||||
|
||||
static void push_arg_reg(int i) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user