diff options
Diffstat (limited to 'sys/rt')
-rw-r--r-- | sys/rt/amd64/crt1.s | 21 | ||||
-rw-r--r-- | sys/rt/amd64/crti.s | 17 | ||||
-rw-r--r-- | sys/rt/amd64/crtn.s | 9 | ||||
-rw-r--r-- | sys/rt/boot.c | 34 | ||||
-rw-r--r-- | sys/rt/env.c | 3 | ||||
-rw-r--r-- | sys/rt/exit.c | 15 | ||||
-rw-r--r-- | sys/rt/include/rt.h | 12 |
7 files changed, 111 insertions, 0 deletions
diff --git a/sys/rt/amd64/crt1.s b/sys/rt/amd64/crt1.s new file mode 100644 index 0000000..aaad0ba --- /dev/null +++ b/sys/rt/amd64/crt1.s @@ -0,0 +1,21 @@ +global _start + +; NOTE: assumes program loader has put argc, argv, envc, envp on stack +section .text +_start: + xor rbp,rbp ; base pointer undefined: set to 0 + mov r9,rdx ; 6th arg: function to register with atexit() + pop rsi ; 2nd arg: argc + mov rdx,rsp ; 3rd arg: argv + and rsp,$-16 ; align stack pointer to 16 bytes + mov $_fini,r8 ; 5th arg: fini + mov $_init,rcx ; 4th arg: init + mov $main,rdi ; 1st arg: main + + call rt·boot ; int boot( + ; int(*main)(int,char*[],char*[]), + ; int argc, + ; char *argv[], + ; init, fini, atexit); + +.loop: jmp .loop ; should never reach... diff --git a/sys/rt/amd64/crti.s b/sys/rt/amd64/crti.s new file mode 100644 index 0000000..eeba8b1 --- /dev/null +++ b/sys/rt/amd64/crti.s @@ -0,0 +1,17 @@ +global _init +global _fini + +section .init +_init: + ; call pushes an 8 byte return address on the stack + ; 64 bit ABI requires stack to be aligned to 16 bytes + ; we realign with another 8 byte address + push rbp + mov rbp, rsp + ;; compiler inserts the rest here + +section .fini +_fini: + push rbp ; see above + mov rbp, rsp + ;; compiler inserts the rest here diff --git a/sys/rt/amd64/crtn.s b/sys/rt/amd64/crtn.s new file mode 100644 index 0000000..45d1a29 --- /dev/null +++ b/sys/rt/amd64/crtn.s @@ -0,0 +1,9 @@ +section .init + ;; compiler inserts here + pop rbp ;; undo our push + ret + +section .fini + ;; compiler inserts here + pop rbp ;; undo our push + ret diff --git a/sys/rt/boot.c b/sys/rt/boot.c new file mode 100644 index 0000000..197e861 --- /dev/null +++ b/sys/rt/boot.c @@ -0,0 +1,34 @@ +#include <rt.h> + +int +rt·boot( + int (*main)(int,char **,char **), int argc, char **argv, + int (*init)(int, char **, char **), void (*fini)(void), + void (*exit)(void) +) +{ + char **envp = argv+argc+1; + rt·environ = envp; + + if(exit) + rt·context.exit = exit; + + if(fini) + rt·context.fini = fini; + + if(init){ + rt·context.init = init; + init(argc, argv, envp); + } + + /* XXX: + * we could call __libc_start_main of musl here: + * this would give us the normal C runtime along with ours + * which would allow seamless linking to other libraries + * or we can implement a compatibility layer + */ + rt·exit(main(argc, argv, envp)); + + /* should never get here */ + return 0; +} diff --git a/sys/rt/env.c b/sys/rt/env.c new file mode 100644 index 0000000..ddd559d --- /dev/null +++ b/sys/rt/env.c @@ -0,0 +1,3 @@ +#include <rt.h> + +char *rt·environ = 0; diff --git a/sys/rt/exit.c b/sys/rt/exit.c new file mode 100644 index 0000000..55a684a --- /dev/null +++ b/sys/rt/exit.c @@ -0,0 +1,15 @@ +#include <rt.h> +#include <sys.h> + +void +rt·exit(int code) +{ + if(rt·context.fini) + rt·context.fini(); + if(rt·context.exit) + rt·context.exit(); + + /* call exit syscalls here */ + + for(;;); +} diff --git a/sys/rt/include/rt.h b/sys/rt/include/rt.h new file mode 100644 index 0000000..dd1598b --- /dev/null +++ b/sys/rt/include/rt.h @@ -0,0 +1,12 @@ +#pragma once + +extern struct rt·context +{ + void (*init)(void); + void (*fini)(void); + void (*exit)(void); +} rt·context; + +extern char **rt·environ; + +void rt·exit(int code); |