From 69e6fe89fa9baafeca3e3515bb50897cd8ee7c35 Mon Sep 17 00:00:00 2001 From: Kacper Date: Mon, 15 Dec 2025 18:24:54 +0100 Subject: Add getauxval and cleanup libc startup --- lib/libc/internal/Kbuild | 2 ++ lib/libc/internal/init/Kbuild | 1 + lib/libc/internal/init/vdso.c | 56 +++++++++++++++++++++++++++++++++++++++++++ lib/libc/internal/libc_main.c | 40 +++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 lib/libc/internal/Kbuild create mode 100644 lib/libc/internal/init/Kbuild create mode 100644 lib/libc/internal/init/vdso.c create mode 100644 lib/libc/internal/libc_main.c (limited to 'lib/libc/internal') diff --git a/lib/libc/internal/Kbuild b/lib/libc/internal/Kbuild new file mode 100644 index 00000000..5015f987 --- /dev/null +++ b/lib/libc/internal/Kbuild @@ -0,0 +1,2 @@ +obj-y += init/ +obj-y += libc_main.o diff --git a/lib/libc/internal/init/Kbuild b/lib/libc/internal/init/Kbuild new file mode 100644 index 00000000..dd27261a --- /dev/null +++ b/lib/libc/internal/init/Kbuild @@ -0,0 +1 @@ +obj-y += vdso.o diff --git a/lib/libc/internal/init/vdso.c b/lib/libc/internal/init/vdso.c new file mode 100644 index 00000000..f94401f6 --- /dev/null +++ b/lib/libc/internal/init/vdso.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +void __init_vdso(void) +{ + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR); + Elf64_Phdr *phdr = (Elf64_Phdr *)(ehdr + ehdr->e_phoff); + + for (int i = 0; i < ehdr->e_phnum; i++) { + Elf64_Dyn *dyn; + Elf64_Sym *symtab; + const char *strtab; + + if (phdr[i].p_type == PT_DYNAMIC) { + Elf64_Sym *sym; + + dyn = (Elf64_Dyn *)((char *)ehdr + phdr[i].p_offset); + symtab = 0; + strtab = 0; + + while (dyn->d_tag != DT_NULL) { + if (dyn->d_tag == DT_STRTAB) { + strtab = (const char *)(ehdr + dyn->d_un.d_ptr); + } else if (dyn->d_tag == DT_SYMTAB) { + symtab = (Elf64_Sym *)(ehdr + dyn->d_un.d_ptr); + } + + if (strtab && symtab) { + break; + } + + dyn++; + } + + sym = symtab; + while ((char *)sym < strtab) { + if (sym->st_name != 0 && sym->st_value != 0) { + const char *name = strtab + sym->st_name; + + for (int i = 0; __vdso_symtab[i].name != 0; i++) { + if (strcmp(name, __vdso_symtab[i].name) == 0) { + __vdso_symtab[i].func = (void *)(ehdr + sym->st_value); + break; + } + } + } + + sym = (Elf64_Sym *)((char *)sym + sizeof(Elf64_Sym)); + } + + break; + } + } +} diff --git a/lib/libc/internal/libc_main.c b/lib/libc/internal/libc_main.c new file mode 100644 index 00000000..7ac15ab4 --- /dev/null +++ b/lib/libc/internal/libc_main.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +extern void __init_vdso(void); + +struct libc __libc; +char **environ; +char *__progname; + +extern int main(int, char **, char **); + +__used void __libc_main(uintptr_t *rsp) +{ + char **argv; + size_t *auxv; + int argc; + + argc = (int)(*rsp); + argv = (char **)(++rsp); + + rsp += argc; + + environ = (char **)(++rsp); + __progname = argv[0]; + + while (*rsp) + rsp++; + + auxv = (size_t *)++rsp; + + for (size_t i = 0; auxv[i]; i += 2) + __libc.auxv[auxv[i]] = auxv[i + 1]; + + __init_vdso(); + + exit(main(argc, argv, environ)); +} -- cgit v1.2.3