aboutsummaryrefslogtreecommitdiff
path: root/sys/rt
diff options
context:
space:
mode:
Diffstat (limited to 'sys/rt')
-rw-r--r--sys/rt/amd64/crt1.s21
-rw-r--r--sys/rt/amd64/crti.s17
-rw-r--r--sys/rt/amd64/crtn.s9
-rw-r--r--sys/rt/boot.c34
-rw-r--r--sys/rt/env.c3
-rw-r--r--sys/rt/exit.c15
-rw-r--r--sys/rt/include/rt.h12
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);