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 | 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 | 1413 | /* generate function prolog of type 't' */ |
| 1400 | 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 | 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 | 1189 | static unsigned long arm64_func_va_list_stack; |
| 1171 | 1190 | static int arm64_func_va_list_gr_offs; |
| 1172 | 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 | 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 | 525 | #ifdef TCC_TARGET_PE |
| 508 | 526 | #define FUNC_PROLOG_SIZE (10 + USE_EBX) |
| 509 | 527 | #else |
| @@ -769,6 +769,20 @@ done: · 768 unmodified lines | ||
| 769 | 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 | 786 | static int func_sub_sp_offset, num_va_regs, func_va_list_ofs; |
| 773 | 787 | |
| 774 | 788 | ST_FUNC void gfunc_prolog(Sym *func_sym) |
| @@ -1797,6 +1797,7 @@ ST_FUNC const char *dlerror(void); · 1796 unmodified lines | ||
| 1797 | 1797 | ST_FUNC void *dlsym(void *handle, const char *symbol); |
| 1798 | 1798 | #endif |
| 1799 | 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 | 1801 | #endif |
| 1801 | 1802 | |
| 1802 | 1803 | /* ------------ tcctools.c ----------------- */ |
| @@ -249,8 +249,30 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 248 unmodified lines | ||
| 249 | 249 | fflush(stderr); |
| 250 | 250 | |
| 251 | 251 | ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym)); |
| 252 | − if (0 == ret) | |
| 253 | − ret = prog_main(argc, argv, envp); | |
| 252 | + if (0 == ret) { | |
| 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 | 276 | else if (RT_EXIT_ZERO == ret) |
| 255 | 277 | ret = 0; |
| 256 | 278 | |
| @@ -933,6 +933,10 @@ void gfunc_call(int nb_args) · 932 unmodified lines | ||
| 933 | 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 | 941 | #define FUNC_PROLOG_SIZE 11 |
| 938 | 942 | |
| @@ -1434,6 +1438,20 @@ void gfunc_call(int nb_args) · 495 unmodified lines | ||
| 1434 | 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 | 1455 | #define FUNC_PROLOG_SIZE 11 |
| 1438 | 1456 | |
| 1439 | 1457 | static void push_arg_reg(int i) { |