|
| 1 | +/* ------------------------------------------------------------- */ |
| 2 | +/* support for run_nostdlib() */ |
| 3 | + |
| 4 | +// FIXME: implement arm64 assembler |
| 5 | +#if defined(__aarch64__) |
| 6 | +#define USE_ARM64_ASM |
| 7 | +static void *alloca_arm64(unsigned long); |
| 8 | +__asm__( |
| 9 | +#ifdef __leading_underscore |
| 10 | + "_alloca_arm64:\n\t" |
| 11 | +#else |
| 12 | + "alloca_arm64:\n\t" |
| 13 | +#endif |
| 14 | + ".int 0x91003c00\n\t" // add x0, x0, #15 |
| 15 | + ".int 0x927cec00\n\t" // and x0, x0, #-16 |
| 16 | + ".int 0xcb2063ff\n\t" // sub sp, sp, x0 |
| 17 | + ".int 0x910003e0\n\t" // mov x0, sp |
| 18 | + ".int 0xd65f03c0" // ret |
| 19 | +); |
| 20 | +static void goto_arm64(void *start); |
| 21 | +__asm__( |
| 22 | +#ifdef __leading_underscore |
| 23 | + "_goto_arm64:\n\t" |
| 24 | +#else |
| 25 | + "goto_arm64:\n\t" |
| 26 | +#endif |
| 27 | + ".int 0xd61f0000" // br x0 |
| 28 | +); |
| 29 | +#endif |
| 30 | + |
| 31 | +void _run_nostdlib(void *start, int argc, char **argv, char **envp) |
| 32 | +{ |
| 33 | +#if !defined(_WIN32) |
| 34 | + int i, n = 1; |
| 35 | + unsigned long l; |
| 36 | + char **sp, **e = envp; |
| 37 | + |
| 38 | + if (envp) |
| 39 | + while (*e++) |
| 40 | + n++; |
| 41 | + l = (((unsigned long) argc + n + 2 + 1) & -2) * sizeof(char *); |
| 42 | + /* nostdlib so avoid alloca() */ |
| 43 | + /* also code below will be removed because compiler detects dead store */ |
| 44 | +#if defined(USE_ARM64_ASM) |
| 45 | + sp = alloca_arm64(l); |
| 46 | +#else |
| 47 | +#if defined(__aarch64__) |
| 48 | + __asm__("sub sp, sp, %1\n" |
| 49 | + "\tmov %0, sp" |
| 50 | +#elif defined(__arm__) |
| 51 | + __asm__("sub sp, sp, %1\n" |
| 52 | + "\tmov %0, sp" |
| 53 | +#elif defined(__i386__) |
| 54 | + __asm("sub %1, %%esp\n" |
| 55 | + "\tmov %%esp, %0" |
| 56 | +#elif defined(__riscv) |
| 57 | + __asm__("sub sp, sp, %1\n" |
| 58 | + "\tmv %0, sp" |
| 59 | +#elif defined(__x86_64__) |
| 60 | + __asm__("subq %1, %%rsp\n" |
| 61 | + "\tmovq %%rsp, %0" |
| 62 | +#endif |
| 63 | + : "=r" (sp) |
| 64 | + : "r" (l)); |
| 65 | +#endif |
| 66 | + /* create sysv memory layout: argc, argv[], NULL, envp[], NULL */ |
| 67 | + sp[0] = (char *) (__SIZE_TYPE__) argc; |
| 68 | + for (i = 0; i < argc; i++) |
| 69 | + sp[i + 1] = argv[i]; |
| 70 | + sp[argc + 1] = (char *) 0; |
| 71 | + if (envp) |
| 72 | + for (i = 0; i < n; i++) |
| 73 | + sp[i + argc + 2] = envp[i]; |
| 74 | + else |
| 75 | + sp[argc + 2] = (char *) 0; |
| 76 | +#endif |
| 77 | + |
| 78 | + /* goto *start does not work for clang. Use assembly. */ |
| 79 | +#if defined(USE_ARM64_ASM) |
| 80 | + goto_arm64(start); |
| 81 | +#else |
| 82 | +#if defined(__aarch64__) |
| 83 | + __asm__("br %0" : : "r" (start)); |
| 84 | +#elif defined(__arm__) |
| 85 | + __asm__("mov pc, %0" : : "r" (start)); |
| 86 | +#elif defined(__i386__) |
| 87 | + __asm__("jmp *%0" : : "r" (start)); |
| 88 | +#elif defined(__riscv) |
| 89 | + __asm__("jalr %0" : : "r" (start)); |
| 90 | +#elif defined(__x86_64__) |
| 91 | + __asm__("jmp *%0" : : "r" (start)); |
| 92 | +#endif |
| 93 | +#endif |
| 94 | +} |
0 commit comments