summaryrefslogtreecommitdiff
path: root/lib/libc/internal/init
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/internal/init')
-rw-r--r--lib/libc/internal/init/Kbuild1
-rw-r--r--lib/libc/internal/init/init.c35
-rw-r--r--lib/libc/internal/init/io.c42
-rw-r--r--lib/libc/internal/init/tls.c43
-rw-r--r--lib/libc/internal/init/vdso.c13
5 files changed, 112 insertions, 22 deletions
diff --git a/lib/libc/internal/init/Kbuild b/lib/libc/internal/init/Kbuild
index 361f220a..3c1bab0b 100644
--- a/lib/libc/internal/init/Kbuild
+++ b/lib/libc/internal/init/Kbuild
@@ -1,3 +1,4 @@
obj-y += init.o
+obj-y += io.o
obj-y += tls.o
obj-y += vdso.o
diff --git a/lib/libc/internal/init/init.c b/lib/libc/internal/init/init.c
index b2dd8487..62678dce 100644
--- a/lib/libc/internal/init/init.c
+++ b/lib/libc/internal/init/init.c
@@ -1,11 +1,15 @@
+#include <alloca.h>
#include <libc.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/cdefs.h>
-extern void __init_vdso(void);
-extern void __init_tls(void);
+#define BUFSIZ 4096
+
+extern void __libc_init_vdso(void) __attribute__((weak));
+extern void __libc_init_tls(void) __attribute__((weak));
+extern void __libc_init_io(void) __attribute__((weak));
extern int main(int, char **, char **);
@@ -13,10 +17,9 @@ struct libc __libc = { 0 };
char **environ;
char *__progname;
-__used void __init(uintptr_t *rsp)
+__used void __libc_init(uintptr_t *rsp)
{
char **argv;
- size_t *auxv;
int argc;
argc = (int)(*rsp);
@@ -30,13 +33,27 @@ __used void __init(uintptr_t *rsp)
while (*rsp)
rsp++;
- auxv = (size_t *)++rsp;
+ __libc.auxv = (size_t *)++rsp;
+
+ if (__libc_init_io) {
+ __libc_init_io();
+
+ __libc.stdout.buf = alloca(BUFSIZ);
+ __libc.stdout.buf_size = BUFSIZ;
+ __libc.stdout.buf_len = 0;
+ __libc.stdout.buf_pos = 0;
+
+ __libc.stdin.buf = alloca(BUFSIZ);
+ __libc.stdin.buf_size = BUFSIZ;
+ __libc.stdin.buf_len = 0;
+ __libc.stdin.buf_pos = 0;
+ }
- for (size_t i = 0; auxv[i]; i += 2)
- __libc.auxv[auxv[i]] = auxv[i + 1];
+ if (__libc_init_tls)
+ __libc_init_tls();
- __init_tls();
- __init_vdso();
+ if (__libc_init_vdso)
+ __libc_init_vdso();
exit(main(argc, argv, environ));
}
diff --git a/lib/libc/internal/init/io.c b/lib/libc/internal/init/io.c
new file mode 100644
index 00000000..4790af89
--- /dev/null
+++ b/lib/libc/internal/init/io.c
@@ -0,0 +1,42 @@
+#include <atomic.h>
+#include <fcntl.h>
+#include <libc.h>
+#include <stdio.h>
+#include <unistd.h>
+
+struct __FILE *const stdout = (struct __FILE *)&__libc.stdout;
+struct __FILE *const stdin = (struct __FILE *)&__libc.stdin;
+struct __FILE *const stderr = (struct __FILE *)&__libc.stderr;
+
+void __libc_init_io(void)
+{
+ /* stdout */
+ memset(&__libc.stdout, 0, sizeof(struct __FILE));
+ __libc.stdout.fd = STDOUT_FILENO;
+ __libc.stdout.flags = O_WRONLY;
+ __libc.stdout.type = _IOLBF;
+ __libc.stdout.buf = NULL;
+ __libc.stdout.buf_size = 0;
+ __libc.stdout.buf_len = 0;
+ __libc.stdout.buf_pos = 0;
+
+ /* stdin */
+ memset(&__libc.stdin, 0, sizeof(struct __FILE));
+ __libc.stdin.fd = STDIN_FILENO;
+ __libc.stdin.flags = O_RDONLY;
+ __libc.stdin.type = _IONBF;
+ __libc.stdin.buf = NULL;
+ __libc.stdin.buf_size = 0;
+ __libc.stdin.buf_len = 0;
+ __libc.stdin.buf_pos = 0;
+
+ /* stderr */
+ memset(&__libc.stderr, 0, sizeof(struct __FILE));
+ __libc.stderr.fd = STDERR_FILENO;
+ __libc.stderr.flags = O_WRONLY;
+ __libc.stderr.type = _IONBF;
+ __libc.stderr.buf = NULL;
+ __libc.stderr.buf_size = 0;
+ __libc.stderr.buf_len = 0;
+ __libc.stderr.buf_pos = 0;
+}
diff --git a/lib/libc/internal/init/tls.c b/lib/libc/internal/init/tls.c
index f6ccde35..302edd9d 100644
--- a/lib/libc/internal/init/tls.c
+++ b/lib/libc/internal/init/tls.c
@@ -6,14 +6,31 @@
#include <sys/mman.h>
#include <syscall.h>
-#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
-#define ALIGN_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#include <libc/tcb.h>
+#include <stdio.h>
+
+// TODO: remove this thing
static struct tls __libc_tls = { 0 };
+
static struct __thread_self __libc_thread;
volatile int __libc_tid;
-void __init_tls(void)
+void __libc_tls_copy(void *dest)
+{
+ if (__libc_tls.size == 0)
+ return;
+
+ if (__libc_tls.length > 0) {
+ memcpy(dest, __libc_tls.data, __libc_tls.length);
+
+ memset((unsigned char *)dest + __libc_tls.length, 0, __libc_tls.size - __libc_tls.length);
+ } else {
+ memset(dest, 0, __libc_tls.size);
+ }
+}
+
+void __libc_init_tls(void)
{
int r;
void *mem;
@@ -40,6 +57,7 @@ void __init_tls(void)
__libc_tls.length = tls_phdr->p_filesz;
__libc_tls.size = tls_phdr->p_memsz;
__libc_tls.align = tls_phdr->p_align;
+ __libc.tls.align = __libc_tls.align;
}
if (__libc_tls.size != 0) {
@@ -56,21 +74,22 @@ void __init_tls(void)
thrd = (struct __thread_self *)mem;
tls_mem = (unsigned char *)mem + sizeof(struct __thread_self);
- if (tls_phdr->p_filesz > 0) {
- memcpy(tls_mem, (void *)tls_phdr->p_vaddr, tls_phdr->p_filesz);
- memset(tls_mem + tls_phdr->p_filesz, 0, tls_phdr->p_memsz - tls_phdr->p_filesz);
- } else {
- memset(tls_mem, 0, tls_phdr->p_memsz);
- }
+ __libc_tls_copy(tls_mem);
- r = syscall(arch_prctl, ARCH_SET_FS, mem + sizeof(struct __thread_self));
- panic_if(r < 0, "arch_prctl(SET_FS) failed");
+ __libc.tls.base = tls_mem;
+ __libc.tls.size = __libc_tls.size;
} else {
- __libc.tls.base = NULL;
thrd = &__libc_thread;
+ __libc.tls.base = &__libc_thread;
+ __libc.tls.size = 0;
}
r = syscall(set_tid_address, &__libc_tid);
panic_if(r < 0, "set_tid_address failed");
+
+ thrd->self = thrd;
thrd->tid = r;
+ thrd->dtv = NULL;
+
+ __libc_tcb_set((uint64_t)thrd);
}
diff --git a/lib/libc/internal/init/vdso.c b/lib/libc/internal/init/vdso.c
index de8d0e2f..73bfb46b 100644
--- a/lib/libc/internal/init/vdso.c
+++ b/lib/libc/internal/init/vdso.c
@@ -3,7 +3,18 @@
#include <string.h>
#include <sys/auxv.h>
-void __init_vdso(void)
+int (*__vdso_clock_gettime)(int, struct timespec *) = 0;
+int (*__vdso_getcpu)(unsigned *, unsigned *, void *) = 0;
+int (*__vdso_time)(long *) = 0;
+
+struct __vdso_sym __vdso_symtab[] = {
+ { "__vdso_clock_gettime", (void *)&__vdso_clock_gettime },
+ { "__vdso_getcpu", (void *)&__vdso_getcpu },
+ { "__vdso_time", (void *)&__vdso_time },
+ { 0, 0 },
+};
+
+void __libc_init_vdso(void)
{
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR);