diff options
| author | Kacper <kacper@mail.openlinux.dev> | 2025-12-07 20:10:31 +0100 |
|---|---|---|
| committer | Kacper <kacper@mail.openlinux.dev> | 2025-12-07 20:10:31 +0100 |
| commit | fc00c656c96528112d05cf0edf8631bd5eaea446 (patch) | |
| tree | a6e0e6c588191a8bd1c64afc3b7a258e3e66c236 /lib/libc/arch/x86_64/crt0.c | |
Add build system scaffolding and libc headers
Diffstat (limited to 'lib/libc/arch/x86_64/crt0.c')
| -rw-r--r-- | lib/libc/arch/x86_64/crt0.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/libc/arch/x86_64/crt0.c b/lib/libc/arch/x86_64/crt0.c new file mode 100644 index 00000000..2c7943ff --- /dev/null +++ b/lib/libc/arch/x86_64/crt0.c @@ -0,0 +1,59 @@ +#include <linux/auxvec.h> +#include <linux/elf.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/time.h> +#include <thread.h> +#include <unistd.h> + +#define weak_reference(old, new) \ + extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) + +extern int main(int, char *[]); +char **environ; + +static struct __thread_self thread = { .tid = 0, ._errno = 0 }; + +struct __attribute__((packed)) auxv_t { + uintptr_t a_type; + uintptr_t a_val; +} *__auxv; + +static void __vdso_setup(Elf64_Ehdr *vdso_addr __attribute__((unused))) +{ +} + +weak_reference(__vdso_setup, vdso_setup); + +__attribute__((used)) void __libc_start(uintptr_t *sp) +{ + char **argv; + int argc; + + argc = (int)(*sp); + argv = (char **)(++sp); + sp += argc; + environ = (char **)(++sp); + + while (*sp) + sp++; + + __auxv = (struct auxv_t *)(++sp); + while (__auxv->a_type != AT_NULL) { + if (__auxv->a_type == AT_SYSINFO_EHDR) { + vdso_setup((Elf64_Ehdr *)__auxv->a_val); + } + + __auxv++; + } + + __asm__ volatile("wrfsbase %0" ::"r"(thread)); + + exit(main(argc, argv)); +} + +__attribute__((noreturn, naked)) void _start(void) +{ + __asm__ __volatile__("mov %rsp, %rdi\n" + "call __libc_start\n"); +} |
