The -run option did not support -nostdlib correctly. The argc/argc/envp are now passed on stack according to sysv. This implementation does not work for TCC_TARGET_PE. Also arm64 does not work when running tcc compiled with itself. This is because arm64 assembly is not implemented yet. The following test code is used to check the code: #include <unistd.h> #include <sys/syscall.h> void _start() { syscall(SYS_write, 1, "hello world\n", 12); syscall(SYS_exit, 0); } Run this with: ./tcc -nostdlib -lc -run a.c make tcc_c ./tcc_c -nostdlib -lc -run a.c
Unified · Split
| @@ -1396,6 +1396,20 @@ void gfunc_call(int nb_args) · 1395 unmodified lines | |||
| 1396 | float_abi = def_float_abi; | 1396 | float_abi = def_float_abi; |
| 1397 | } | 1397 | } |
| 1398 | 1398 | ||
| 1399 | void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) | ||
| 1400 | { | ||
| 1401 | #ifdef __arm__ | ||
| 1402 | void *sp; | ||
| 1403 | |||
| 1404 | asm("sub sp, sp, %1\n" | ||
| 1405 | "\tmov %0, sp" | ||
| 1406 | : "=r" (sp) | ||
| 1407 | : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); | ||
| 1408 | memcpy(sp, var, cnt * sizeof(char *)); | ||
| 1409 | asm("mov pc, %0" : : "r" (prog_main)); | ||
| 1410 | #endif | ||
| 1411 | } | ||
| 1412 | |||
| 1399 | /* generate function prolog of type 't' */ | 1413 | /* generate function prolog of type 't' */ |
| 1400 | void gfunc_prolog(Sym *func_sym) | 1414 | void gfunc_prolog(Sym *func_sym) |
| 1401 | { | 1415 | { |
| @@ -1167,6 +1167,25 @@ ST_FUNC void gfunc_call(int nb_args) · 1166 unmodified lines | |||
| 1167 | tcc_free(t); | 1167 | tcc_free(t); |
| 1168 | } | 1168 | } |
| 1169 | 1169 | ||
| 1170 | void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) | ||
| 1171 | { | ||
| 1172 | #if defined(__aarch64__) | ||
| 1173 | #if defined(__TINYC__) | ||
| 1174 | // FIXME: immplement arm64 assembler | ||
| 1175 | fprintf(stderr, "tcc -nostdlib -run not implement for arm64\n"); | ||
| 1176 | #else | ||
| 1177 | void *sp; | ||
| 1178 | |||
| 1179 | asm("sub sp, sp, %1\n" | ||
| 1180 | "\tmov %0, sp" | ||
| 1181 | : "=r" (sp) | ||
| 1182 | : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); | ||
| 1183 | memcpy(sp, var, cnt * sizeof(char *)); | ||
| 1184 | asm("br %0" : : "r" (prog_main)); | ||
| 1185 | #endif | ||
| 1186 | #endif | ||
| 1187 | } | ||
| 1188 | |||
| 1170 | static unsigned long arm64_func_va_list_stack; | 1189 | static unsigned long arm64_func_va_list_stack; |
| 1171 | static int arm64_func_va_list_gr_offs; | 1190 | static int arm64_func_va_list_gr_offs; |
| 1172 | static int arm64_func_va_list_vr_offs; | 1191 | static int arm64_func_va_list_vr_offs; |
| @@ -504,6 +504,24 @@ ST_FUNC void gfunc_call(int nb_args) · 503 unmodified lines | |||
| 504 | vtop--; | 504 | vtop--; |
| 505 | } | 505 | } |
| 506 | 506 | ||
| 507 | void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) | ||
| 508 | { | ||
| 509 | #ifdef __i386__ | ||
| 510 | #ifdef TCC_TARGET_PE | ||
| 511 | fprintf(stderr, "tcc -nostdlib -run not implement for TCC_TARGET_PE\n"); | ||
| 512 | #else | ||
| 513 | void *sp; | ||
| 514 | |||
| 515 | asm("sub %1, %%esp\n" | ||
| 516 | "\tmov %%esp, %0" | ||
| 517 | : "=r" (sp) | ||
| 518 | : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); | ||
| 519 | memcpy(sp, var, cnt * sizeof(char *)); | ||
| 520 | asm("jmp *%0" : : "r" (prog_main)); | ||
| 521 | #endif | ||
| 522 | #endif | ||
| 523 | } | ||
| 524 | |||
| 507 | #ifdef TCC_TARGET_PE | 525 | #ifdef TCC_TARGET_PE |
| 508 | #define FUNC_PROLOG_SIZE (10 + USE_EBX) | 526 | #define FUNC_PROLOG_SIZE (10 + USE_EBX) |
| 509 | #else | 527 | #else |
| @@ -769,6 +769,20 @@ done: · 768 unmodified lines | |||
| 769 | tcc_free(info); | 769 | tcc_free(info); |
| 770 | } | 770 | } |
| 771 | 771 | ||
| 772 | void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) | ||
| 773 | { | ||
| 774 | #ifdef __riscv | ||
| 775 | void *sp; | ||
| 776 | |||
| 777 | asm("sub sp, sp, %1\n" | ||
| 778 | "\tmv %0, sp" | ||
| 779 | : "=r" (sp) | ||
| 780 | : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); | ||
| 781 | memcpy(sp, var, cnt * sizeof(char *)); | ||
| 782 | asm("jalr %0" : : "r" (prog_main)); | ||
| 783 | #endif | ||
| 784 | } | ||
| 785 | |||
| 772 | static int func_sub_sp_offset, num_va_regs, func_va_list_ofs; | 786 | static int func_sub_sp_offset, num_va_regs, func_va_list_ofs; |
| 773 | 787 | ||
| 774 | ST_FUNC void gfunc_prolog(Sym *func_sym) | 788 | ST_FUNC void gfunc_prolog(Sym *func_sym) |
| @@ -1797,6 +1797,7 @@ ST_FUNC const char *dlerror(void); · 1796 unmodified lines | |||
| 1797 | ST_FUNC void *dlsym(void *handle, const char *symbol); | 1797 | ST_FUNC void *dlsym(void *handle, const char *symbol); |
| 1798 | #endif | 1798 | #endif |
| 1799 | ST_FUNC void tcc_run_free(TCCState *s1); | 1799 | ST_FUNC void tcc_run_free(TCCState *s1); |
| 1800 | ST_FUNC void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var); | ||
| 1800 | #endif | 1801 | #endif |
| 1801 | 1802 | ||
| 1802 | /* ------------ tcctools.c ----------------- */ | 1803 | /* ------------ tcctools.c ----------------- */ |
| @@ -249,8 +249,30 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 248 unmodified lines | |||
| 249 | fflush(stderr); | 249 | fflush(stderr); |
| 250 | 250 | ||
| 251 | ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym)); | 251 | ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym)); |
| 252 | if (0 == ret) | 252 | if (0 == ret) { |
| 253 | ret = prog_main(argc, argv, envp); | 253 | if (s1->nostdlib) { |
| 254 | int n = 1; | ||
| 255 | char **p, **e = envp; | ||
| 256 | |||
| 257 | /* create sysv memory layout: argc, argv[], NULL, envp[], NULL */ | ||
| 258 | if (envp) | ||
| 259 | while (*e++) | ||
| 260 | n++; | ||
| 261 | p = tcc_malloc((argc + n + 2) * sizeof(char **)); | ||
| 262 | p[0] = (char *) (size_t) argc; | ||
| 263 | memcpy(p + 1, argv, argc * sizeof(char *)); | ||
| 264 | p[argc + 1] = NULL; | ||
| 265 | if (envp) | ||
| 266 | memcpy(p + argc + 2, envp, n * sizeof(char *)); | ||
| 267 | else | ||
| 268 | p[argc + 2] = NULL; | ||
| 269 | /* Probably never returns */ | ||
| 270 | tcc_run_start(prog_main, argc + n + 2, p); | ||
| 271 | tcc_free(p); | ||
| 272 | } | ||
| 273 | else | ||
| 274 | ret = prog_main(argc, argv, envp); | ||
| 275 | } | ||
| 254 | else if (RT_EXIT_ZERO == ret) | 276 | else if (RT_EXIT_ZERO == ret) |
| 255 | ret = 0; | 277 | ret = 0; |
| 256 | 278 | ||
| @@ -933,6 +933,10 @@ void gfunc_call(int nb_args) · 932 unmodified lines | |||
| 933 | vtop--; | 933 | vtop--; |
| 934 | } | 934 | } |
| 935 | 935 | ||
| 936 | void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) | ||
| 937 | { | ||
| 938 | fprintf(stderr, "tcc -nostdlib -run not implement for TCC_TARGET_PE\n"); | ||
| 939 | } | ||
| 936 | 940 | ||
| 937 | #define FUNC_PROLOG_SIZE 11 | 941 | #define FUNC_PROLOG_SIZE 11 |
| 938 | 942 | ||
| @@ -1434,6 +1438,20 @@ void gfunc_call(int nb_args) · 495 unmodified lines | |||
| 1434 | vtop--; | 1438 | vtop--; |
| 1435 | } | 1439 | } |
| 1436 | 1440 | ||
| 1441 | void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) | ||
| 1442 | { | ||
| 1443 | #ifdef __x86_64__ | ||
| 1444 | void *sp; | ||
| 1445 | |||
| 1446 | asm("subq %1, %%rsp\n" | ||
| 1447 | "\tmovq %%rsp, %0" | ||
| 1448 | : "=r" (sp) | ||
| 1449 | : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); | ||
| 1450 | memcpy(sp, var, cnt * sizeof(char *)); | ||
| 1451 | asm("jmp *%0" : : "r" (prog_main)); | ||
| 1452 | #endif | ||
| 1453 | } | ||
| 1454 | |||
| 1437 | #define FUNC_PROLOG_SIZE 11 | 1455 | #define FUNC_PROLOG_SIZE 11 |
| 1438 | 1456 | ||
| 1439 | static void push_arg_reg(int i) { | 1457 | static void push_arg_reg(int i) { |