summaryrefslogtreecommitdiff
path: root/lib/libc/arch/x86_64/vdso_setup.c
diff options
context:
space:
mode:
authorKacper <kacper@mail.openlinux.dev>2025-12-07 20:10:31 +0100
committerKacper <kacper@mail.openlinux.dev>2025-12-07 20:10:31 +0100
commitfc00c656c96528112d05cf0edf8631bd5eaea446 (patch)
treea6e0e6c588191a8bd1c64afc3b7a258e3e66c236 /lib/libc/arch/x86_64/vdso_setup.c
Add build system scaffolding and libc headers
Diffstat (limited to 'lib/libc/arch/x86_64/vdso_setup.c')
-rw-r--r--lib/libc/arch/x86_64/vdso_setup.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/libc/arch/x86_64/vdso_setup.c b/lib/libc/arch/x86_64/vdso_setup.c
new file mode 100644
index 00000000..c410995d
--- /dev/null
+++ b/lib/libc/arch/x86_64/vdso_setup.c
@@ -0,0 +1,62 @@
+#include <linux/auxvec.h>
+#include <linux/elf.h>
+#include <string.h>
+#include <time.h>
+
+int (*__vdso_clock_gettime)(int, struct timespec *) = NULL;
+int (*__vdso_getcpu)(unsigned *, unsigned *, void *) = NULL;
+int (*__vdso_time)(long *) = NULL;
+
+static __inline __attribute__((used)) void vdso_setup(Elf64_Ehdr *vdso_addr)
+{
+ Elf64_Phdr *phdr =
+ (Elf64_Phdr *)((char *)vdso_addr + vdso_addr->e_phoff);
+
+ for (int i = 0; i < vdso_addr->e_phnum; i++) {
+ if (phdr[i].p_type == PT_DYNAMIC) {
+ Elf64_Dyn *dyn = (Elf64_Dyn *)((char *)vdso_addr +
+ phdr[i].p_offset);
+ const char *strtab = NULL;
+ Elf64_Sym *symtab = NULL;
+ for (; dyn->d_tag != DT_NULL; dyn++) {
+ if (dyn->d_tag == DT_STRTAB) {
+ strtab = (const char *)vdso_addr +
+ dyn->d_un.d_ptr;
+ } else if (dyn->d_tag == DT_SYMTAB) {
+ symtab =
+ (Elf64_Sym *)((char *)vdso_addr +
+ dyn->d_un.d_ptr);
+ }
+ }
+
+ if (strtab == NULL || symtab == NULL) {
+ return;
+ }
+
+ Elf64_Sym *sym = symtab;
+ while ((char *)sym < (char *)strtab) {
+ if (sym->st_name != 0 && sym->st_value != 0) {
+ const char *name =
+ strtab + sym->st_name;
+ if (strcmp(name,
+ "__vdso_clock_gettime") == 0)
+ __vdso_clock_gettime =
+ (void *)(vdso_addr +
+ sym->st_value);
+ else if (strcmp(name,
+ "__vdso_getcpu") == 0)
+ __vdso_getcpu =
+ (void *)(vdso_addr +
+ sym->st_value);
+ else if (strcmp(name, "__vdso_time") ==
+ 0)
+ __vdso_time =
+ (void *)(vdso_addr +
+ sym->st_value);
+ }
+ sym = (Elf64_Sym *)((char *)sym +
+ sizeof(Elf64_Sym));
+ }
+ }
+ }
+}