diff --git a/red-system/runtime/start.reds b/red-system/runtime/start.reds index 3a53a8fc38..efa0a11f5b 100644 --- a/red-system/runtime/start.reds +++ b/red-system/runtime/start.reds @@ -23,9 +23,46 @@ system: declare struct! [ ;-- trimmed down temporary system definition #switch OS [ Windows [] ;-- nothing to do, initialization occurs in DLL init entry point Syllable [ - + #import [LIBC-file cdecl [ + libc-start: "__libc_start_main" [ + main [function! []] + argv [pointer! [integer!]] + envp [pointer! [integer!]] + init [function! []] + finish [function! []] + stack-end [pointer! [integer!]] + ] + ]] + + ;; Clear the frame pointer. The SVR4 ELF/i386 ABI suggests this, to + ;; mark the outermost frame. + system/stack/frame: as pointer! [integer!] 0 + + ;; Extract arguments from the call stack (which was setup by the + ;; kernel). + ;; esp: dummy value + ;; esp+4: **argv + ***__argv: system/stack/top + 1 + ***__argv: as [pointer! [integer!]] ***__argv/value + ;; esp+8: **envp + ***__envp: system/stack/top + 2 + ***__envp: as [pointer! [integer!]] ***__envp/value + + ;; Before pushing arguments for `libc-start`, align the stack to a + ;; 128-bit boundary, to prevent misaligned access penalities. + system/stack/top: as pointer! [integer!] (FFFFFFF0h and as integer! ***__argv) + + ;; The call to `libc-start` takes 6 4-byte arguments (passed on the + ;; stack). To keep the stack 128-bit aligned even after the call, we + ;; push some garbage. + push 0 + push 0 + + ;; Finally, call into libc's startup routine. + ***__stack_end: system/stack/top + libc-start :***_start ***__argv ***__envp null null ***__stack_end ] - #default [ + #default [ ;-- for SVR4 fully conforming UNIX platforms #import [LIBC-file cdecl [ libc-start: "__libc_start_main" [ main [function! []] diff --git a/red-system/runtime/syllable.reds b/red-system/runtime/syllable.reds index f7fb9c98a9..790a071cd8 100644 --- a/red-system/runtime/syllable.reds +++ b/red-system/runtime/syllable.reds @@ -34,11 +34,20 @@ Red/System [ ;------------------------------------------- ;-- Retrieve command-line information from stack ;------------------------------------------- -pop ;-- dummy value -system/args-list: as str-array! pop ;-- &argv -system/env-vars: as str-array! pop ;-- &envp -***-on-start: func [/local c argv][ +#either use-natives? = yes [ + pop ;-- dummy value + system/args-list: as str-array! pop ;-- &argv + system/env-vars: as str-array! pop ;-- &envp + +][ + ;-- the current stack is pointing to main(int argc, void **argv, void **envp) C layout + ;-- we avoid the double indirection by reusing our variables from %start.reds + system/args-list: as str-array! ***__argv + system/env-vars: as str-array! ***__envp +] + +***-get-argc: func [/local c argv][ argv: system/args-list c: 0 while [argv/item <> null][ @@ -47,6 +56,6 @@ system/env-vars: as str-array! pop ;-- &envp ] system/args-count: c ] -***-on-start - +***-get-argc + #include %POSIX.reds