[libc-commits] [libc] [libc] implement vdso (PR #91572)
Schrodinger ZHU Yifan via libc-commits
libc-commits at lists.llvm.org
Tue May 21 20:15:15 PDT 2024
https://github.com/SchrodingerZhu updated https://github.com/llvm/llvm-project/pull/91572
>From a4f2eb97fe463e8ca0b2e8080ba82dea17c2df32 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Thu, 9 May 2024 04:26:55 -0400
Subject: [PATCH 1/8] [libc] implement vdso
---
libc/src/__support/OSUtil/CMakeLists.txt | 8 +
libc/src/__support/OSUtil/fuchsia/vdso.h | 12 ++
.../src/__support/OSUtil/linux/CMakeLists.txt | 16 ++
.../OSUtil/linux/aarch64/CMakeLists.txt | 9 +
.../src/__support/OSUtil/linux/aarch64/vdso.h | 47 +++++
.../__support/OSUtil/linux/arm/CMakeLists.txt | 9 +
libc/src/__support/OSUtil/linux/arm/vdso.h | 36 ++++
.../OSUtil/linux/riscv/CMakeLists.txt | 9 +
libc/src/__support/OSUtil/linux/riscv/vdso.h | 55 +++++
libc/src/__support/OSUtil/linux/vdso.cpp | 198 ++++++++++++++++++
libc/src/__support/OSUtil/linux/vdso.h | 29 +++
.../OSUtil/linux/x86_64/CMakeLists.txt | 9 +
libc/src/__support/OSUtil/linux/x86_64/vdso.h | 41 ++++
libc/src/__support/OSUtil/vdso.h | 18 ++
14 files changed, 496 insertions(+)
create mode 100644 libc/src/__support/OSUtil/fuchsia/vdso.h
create mode 100644 libc/src/__support/OSUtil/linux/aarch64/vdso.h
create mode 100644 libc/src/__support/OSUtil/linux/arm/vdso.h
create mode 100644 libc/src/__support/OSUtil/linux/riscv/vdso.h
create mode 100644 libc/src/__support/OSUtil/linux/vdso.cpp
create mode 100644 libc/src/__support/OSUtil/linux/vdso.h
create mode 100644 libc/src/__support/OSUtil/linux/x86_64/vdso.h
create mode 100644 libc/src/__support/OSUtil/vdso.h
diff --git a/libc/src/__support/OSUtil/CMakeLists.txt b/libc/src/__support/OSUtil/CMakeLists.txt
index 94d1042ccbb4a..78285c960c0a4 100644
--- a/libc/src/__support/OSUtil/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/CMakeLists.txt
@@ -15,3 +15,11 @@ add_object_library(
DEPENDS
${target_os_util}
)
+
+add_header_library(
+ vdso
+ HDRS
+ vdso.h
+ DEPENDS
+ .${LIBC_TARGET_OS}.vdso
+)
diff --git a/libc/src/__support/OSUtil/fuchsia/vdso.h b/libc/src/__support/OSUtil/fuchsia/vdso.h
new file mode 100644
index 0000000000000..177d29f879693
--- /dev/null
+++ b/libc/src/__support/OSUtil/fuchsia/vdso.h
@@ -0,0 +1,12 @@
+//===------------- Fuchsia VDSO Header --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_FUCHSIA_VDSO_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_FUCHSIA_VDSO_H
+/// TODO: implement fuchsia VDSO
+/// https://fuchsia.dev/fuchsia-src/concepts/kernel/vdso
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_FUCHSIA_VDSO_H
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index 239d115704927..e7411c14711d2 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -16,3 +16,19 @@ add_object_library(
libc.src.__support.common
libc.src.__support.CPP.string_view
)
+
+add_object_library(
+ vdso
+ HDRS
+ vdso.h
+ SRCS
+ vdso.cpp
+ DEPENDS
+ .${LIBC_TARGET_ARCHITECTURE}.vdso
+ libc.src.__support.CPP.array
+ libc.src.__support.CPP.string_view
+ libc.src.__support.threads.callonce
+ libc.src.__support.threads.linux.futex_word_type
+ libc.src.errno.errno
+ libc.src.sys.auxv.getauxval
+)
diff --git a/libc/src/__support/OSUtil/linux/aarch64/CMakeLists.txt b/libc/src/__support/OSUtil/linux/aarch64/CMakeLists.txt
index eea9badc46cae..68ce1d74c2099 100644
--- a/libc/src/__support/OSUtil/linux/aarch64/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/aarch64/CMakeLists.txt
@@ -5,3 +5,12 @@ add_header_library(
DEPENDS
libc.src.__support.common
)
+
+add_header_library(
+ vdso
+ HDRS
+ vdso.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.CPP.string_view
+)
diff --git a/libc/src/__support/OSUtil/linux/aarch64/vdso.h b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
new file mode 100644
index 0000000000000..55024e61ee914
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
@@ -0,0 +1,47 @@
+//===---------- aarch64 vdso configuration ------------------------* C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "src/__support/CPP/string_view.h"
+namespace LIBC_NAMESPACE {
+namespace vdso {
+// macro definitions
+#define LIBC_VDSO_HAS_RT_SIGRETURN
+#define LIBC_VDSO_HAS_GETTIMEOFDAY
+#define LIBC_VDSO_HAS_CLOCK_GETTIME
+#define LIBC_VDSO_HAS_CLOCK_GETRES
+
+// list of VDSO symbols
+enum class VDSOSym {
+ RTSigReturn,
+ GetTimeOfDay,
+ ClockGetTime,
+ ClockGetRes,
+ VDSOSymCount
+};
+
+// translate VDSOSym to symbol names
+LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
+ switch (sym) {
+ case VDSOSym::RTSigReturn:
+ return "__kernel_rt_sigreturn";
+ case VDSOSym::GetTimeOfDay:
+ return "__kernel_gettimeofday";
+ case VDSOSym::ClockGetTime:
+ return "__kernel_clock_gettime";
+ case VDSOSym::ClockGetRes:
+ return "__kernel_clock_getres";
+ default:
+ return "";
+ }
+}
+
+// symbol versions
+LIBC_INLINE constexpr cpp::string_view symbol_version(VDSOSym) {
+ return "LINUX_2.6.39";
+}
+} // namespace vdso
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/linux/arm/CMakeLists.txt b/libc/src/__support/OSUtil/linux/arm/CMakeLists.txt
index 733366f6d4a2e..36c991425e603 100644
--- a/libc/src/__support/OSUtil/linux/arm/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/arm/CMakeLists.txt
@@ -5,3 +5,12 @@ add_header_library(
DEPENDS
libc.src.__support.common
)
+
+add_header_library(
+ vdso
+ HDRS
+ vdso.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.CPP.string_view
+)
diff --git a/libc/src/__support/OSUtil/linux/arm/vdso.h b/libc/src/__support/OSUtil/linux/arm/vdso.h
new file mode 100644
index 0000000000000..5d9ff5d929ab6
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/arm/vdso.h
@@ -0,0 +1,36 @@
+//===---------- arm vdso configuration ----------------------------* C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "src/__support/CPP/string_view.h"
+namespace LIBC_NAMESPACE {
+namespace vdso {
+// macro definitions
+#define LIBC_VDSO_HAS_GETTIMEOFDAY
+#define LIBC_VDSO_HAS_CLOCK_GETTIME
+
+// list of VDSO symbols
+enum class VDSOSym {
+ GetTimeOfDay,
+ ClockGetTime,
+};
+
+// translate VDSOSym to symbol names
+LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
+ switch (sym) {
+ case VDSOSym::GetTimeOfDay:
+ return "__vdso_gettimeofday";
+ case VDSOSym::ClockGetTime:
+ return "__vdso_clock_gettime";
+ }
+}
+
+// symbol versions
+LIBC_INLINE constexpr cpp::string_view symbol_version(VDSOSym) {
+ return "LINUX_2.6";
+}
+} // namespace vdso
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/linux/riscv/CMakeLists.txt b/libc/src/__support/OSUtil/linux/riscv/CMakeLists.txt
index e271204f51982..b2e2401ece1ac 100644
--- a/libc/src/__support/OSUtil/linux/riscv/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/riscv/CMakeLists.txt
@@ -5,3 +5,12 @@ add_header_library(
DEPENDS
libc.src.__support.common
)
+
+add_header_library(
+ vdso
+ HDRS
+ vdso.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.CPP.string_view
+)
diff --git a/libc/src/__support/OSUtil/linux/riscv/vdso.h b/libc/src/__support/OSUtil/linux/riscv/vdso.h
new file mode 100644
index 0000000000000..394c06e6a5a72
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/riscv/vdso.h
@@ -0,0 +1,55 @@
+//===---------- RISC-V vdso configuration -------------------------* C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "src/__support/CPP/string_view.h"
+namespace LIBC_NAMESPACE {
+namespace vdso {
+// macro definitions
+#define LIBC_VDSO_HAS_RT_SIGRETURN
+#define LIBC_VDSO_HAS_GETTIMEOFDAY
+#define LIBC_VDSO_HAS_CLOCK_GETTIME
+#define LIBC_VDSO_HAS_CLOCK_GETRES
+#define LIBC_VDSO_HAS_GETCPU
+#define LIBC_VDSO_HAS_FLUSH_ICACHE
+
+// list of VDSO symbols
+enum class VDSOSym {
+ RTSigReturn,
+ GetTimeOfDay,
+ ClockGetTime,
+ ClockGetRes,
+ GetCpu,
+ FlushICache,
+ VDSOSymCount
+};
+
+// translate VDSOSym to symbol names
+LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
+ switch (sym) {
+ case VDSOSym::RTSigReturn:
+ return "__vdso_rt_sigreturn";
+ case VDSOSym::GetTimeOfDay:
+ return "__vdso_gettimeofday";
+ case VDSOSym::ClockGetTime:
+ return "__vdso_clock_gettime";
+ case VDSOSym::ClockGetRes:
+ return "__vdso_clock_getres";
+ case VDSOSym::GetCpu:
+ return "__vdso_getcpu";
+ case VDSOSym::FlushICache:
+ return "__vdso_flush_icache";
+ default:
+ return "";
+ }
+}
+
+// symbol versions
+LIBC_INLINE constexpr cpp::string_view symbol_version(VDSOSym) {
+ return "LINUX_4.15";
+}
+} // namespace vdso
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
new file mode 100644
index 0000000000000..2b2c02ec69fef
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -0,0 +1,198 @@
+//===------------- Linux VDSO Implementation --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "src/__support/OSUtil/linux/vdso.h"
+#include "src/__support/CPP/array.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/threads/callonce.h"
+#include "src/__support/threads/linux/futex_word.h"
+#include "src/errno/libc_errno.h"
+#include "src/sys/auxv/getauxval.h"
+#include <linux/auxvec.h>
+#include <linux/elf.h>
+
+#ifndef ElfW
+#if __POINTER_WIDTH__ == 32
+#define ElfW(type) Elf32_##type
+#else
+#define ElfW(type) Elf64_##type
+#endif
+#endif
+
+namespace LIBC_NAMESPACE {
+namespace vdso {
+
+// See https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
+struct Verdaux {
+ ElfW(Word) vda_name; /* Version or dependency names */
+ ElfW(Word) vda_next; /* Offset in bytes to next verdaux
+ entry */
+};
+struct Verdef {
+ ElfW(Half) vd_version; /* Version revision */
+ ElfW(Half) vd_flags; /* Version information */
+ ElfW(Half) vd_ndx; /* Version Index */
+ ElfW(Half) vd_cnt; /* Number of associated aux entries */
+ ElfW(Word) vd_hash; /* Version name hash value */
+ ElfW(Word) vd_aux; /* Offset in bytes to verdaux array */
+ ElfW(Word) vd_next; /* Offset in bytes to next verdef
+ entry */
+ Verdef *next() const {
+ if (vd_next == 0)
+ return nullptr;
+ return reinterpret_cast<Verdef *>(reinterpret_cast<uintptr_t>(this) +
+ vd_next);
+ }
+ Verdaux *aux() const {
+ return reinterpret_cast<Verdaux *>(reinterpret_cast<uintptr_t>(this) +
+ vd_aux);
+ }
+};
+
+// version search procedure specified by
+// https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symversion.html#SYMVERTBL
+cpp::string_view find_version(Verdef *verdef, ElfW(Half) * versym,
+ const char *strtab, size_t idx) {
+ static constexpr ElfW(Half) VER_FLG_BASE = 0x1;
+ ElfW(Half) identifier = versym[idx] & 0x7FFF;
+ // iterate through all version definitions
+ for (Verdef *def = verdef; def != nullptr; def = def->next()) {
+ // skip if this is a file-level version
+ if (def->vd_flags & VER_FLG_BASE)
+ continue;
+ // check if the version identifier matches
+ if ((def->vd_ndx & 0x7FFF) == identifier) {
+ Verdaux *aux = def->aux();
+ return strtab + aux->vda_name;
+ }
+ }
+ return "";
+}
+
+using VDSOArray =
+ cpp::array<void *, static_cast<size_t>(VDSOSym::VDSOSymCount)>;
+
+static VDSOArray symbol_table;
+
+void *get_symbol(VDSOSym sym) {
+ // if sym is invalid, return nullptr
+ const size_t index = static_cast<size_t>(sym);
+ if (index >= symbol_table.size())
+ return nullptr;
+
+ static FutexWordType once_flag = 0;
+ callonce(reinterpret_cast<CallOnceFlag *>(&once_flag), [] {
+ // first clear the symbol table
+ for (auto &i : symbol_table) {
+ i = nullptr;
+ }
+
+ // get the address of the VDSO, protect errno since getauxval may change it
+ int errno_backup = libc_errno;
+ uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
+ // Get the memory address of the vDSO ELF header.
+ auto vdso_ehdr = reinterpret_cast<ElfW(Ehdr) *>(vdso_ehdr_addr);
+ // leave the table unpopulated if we don't have vDSO
+ if (vdso_ehdr == nullptr) {
+ libc_errno = errno_backup;
+ return;
+ }
+
+ // count entries
+ size_t symbol_count = 0;
+ // locate the section header inside the elf using the section header offset
+ auto vdso_shdr =
+ reinterpret_cast<ElfW(Shdr) *>(vdso_ehdr_addr + vdso_ehdr->e_shoff);
+ // iterate all sections until we locate the dynamic symbol section
+ for (size_t i = 0; i < vdso_ehdr->e_shnum; ++i) {
+ if (vdso_shdr[i].sh_type == SHT_DYNSYM) {
+ // dynamic symbol section is a table section
+ // therefore, the number of entries can be computed as the ratio
+ // of the section size to the size of a single entry
+ symbol_count = vdso_shdr[i].sh_size / vdso_shdr[i].sh_entsize;
+ break;
+ }
+ }
+
+ // early return if no symbol is found
+ if (symbol_count == 0)
+ return;
+
+ // We need to find both the loadable segment and the dynamic linking of the
+ // vDSO.
+ auto vdso_addr = static_cast<ElfW(Addr)>(-1);
+ ElfW(Dyn) *vdso_dyn = nullptr;
+ // compute vdso_phdr as the program header using the program header offset
+ ElfW(Phdr) *vdso_phdr =
+ reinterpret_cast<ElfW(Phdr) *>(vdso_ehdr_addr + vdso_ehdr->e_phoff);
+ // iterate through all the program headers until we get the desired pieces
+ for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
+ if (vdso_phdr[i].p_type == PT_DYNAMIC)
+ vdso_dyn = reinterpret_cast<ElfW(Dyn) *>(vdso_ehdr_addr +
+ vdso_phdr[i].p_offset);
+
+ if (vdso_phdr[i].p_type == PT_LOAD)
+ vdso_addr =
+ vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
+
+ if (vdso_addr && vdso_dyn)
+ break;
+ }
+ // early return if either the dynamic linking or the loadable segment is not
+ // found
+ if (vdso_dyn == nullptr || vdso_addr == static_cast<ElfW(Addr)>(-1))
+ return;
+
+ // now, locate several more tables inside the dynmaic linking section
+ const char *strtab = nullptr;
+ ElfW(Sym) *symtab = nullptr;
+ ElfW(Half) *versym = nullptr;
+ Verdef *verdef = nullptr;
+ for (ElfW(Dyn) *d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
+ switch (d->d_tag) {
+ case DT_STRTAB:
+ strtab = reinterpret_cast<const char *>(vdso_addr + d->d_un.d_ptr);
+ break;
+ case DT_SYMTAB:
+ symtab = reinterpret_cast<ElfW(Sym) *>(vdso_addr + d->d_un.d_ptr);
+ break;
+ case DT_VERSYM:
+ versym = reinterpret_cast<uint16_t *>(vdso_addr + d->d_un.d_ptr);
+ break;
+ case DT_VERDEF:
+ verdef = reinterpret_cast<Verdef *>(vdso_addr + d->d_un.d_ptr);
+ break;
+ }
+ if (strtab && symtab && versym && verdef) {
+ break;
+ }
+ }
+ if (strtab == nullptr || symtab == nullptr)
+ return;
+
+ for (size_t i = 0; i < symbol_table.size(); ++i) {
+ for (size_t j = 0; j < symbol_count; ++j) {
+ auto sym = static_cast<VDSOSym>(i);
+ if (symbol_name(sym) == strtab + symtab[j].st_name) {
+ // we find a symbol with desired name
+ // now we need to check if it has the right version
+ if (versym && verdef)
+ if (symbol_version(sym) != find_version(verdef, versym, strtab, j))
+ continue;
+
+ // put the symbol address into the symbol table
+ symbol_table[i] =
+ reinterpret_cast<void *>(vdso_addr + symtab[j].st_value);
+ }
+ }
+ }
+ });
+
+ return symbol_table[index];
+}
+} // namespace vdso
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/linux/vdso.h b/libc/src/__support/OSUtil/linux/vdso.h
new file mode 100644
index 0000000000000..2d71db13303f0
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/vdso.h
@@ -0,0 +1,29 @@
+//===------------- Linux VDSO Header ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H
+#include "src/__support/common.h"
+#include "src/__support/macros/properties/architectures.h"
+
+#if defined(LIBC_TARGET_ARCH_IS_X86)
+#include "x86_64/vdso.h"
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64)
+#include "aarch64/vdso.h"
+#elif defined(LIBC_TARGET_ARCH_IS_ARM)
+#include "arm/vdso.h"
+#elif defined(LIBC_TARGET_ARCH_IS_RISCV)
+#include "riscv/vdso.h"
+#endif
+
+namespace LIBC_NAMESPACE {
+namespace vdso {
+void *get_symbol(VDSOSym);
+} // namespace vdso
+
+} // namespace LIBC_NAMESPACE
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H
diff --git a/libc/src/__support/OSUtil/linux/x86_64/CMakeLists.txt b/libc/src/__support/OSUtil/linux/x86_64/CMakeLists.txt
index a7f2d74e6353e..cb5938ef94d7d 100644
--- a/libc/src/__support/OSUtil/linux/x86_64/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/x86_64/CMakeLists.txt
@@ -5,3 +5,12 @@ add_header_library(
DEPENDS
libc.src.__support.common
)
+
+add_header_library(
+ vdso
+ HDRS
+ vdso.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.CPP.string_view
+)
diff --git a/libc/src/__support/OSUtil/linux/x86_64/vdso.h b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
new file mode 100644
index 0000000000000..13b8e3d8cc6f4
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
@@ -0,0 +1,41 @@
+//===---------- x86/x86_64 vdso configuration ---------------------* C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "src/__support/CPP/string_view.h"
+namespace LIBC_NAMESPACE {
+namespace vdso {
+// macro definitions
+#define LIBC_VDSO_HAS_CLOCK_GETTIME
+#define LIBC_VDSO_HAS_GETCPU
+#define LIBC_VDSO_HAS_GETTIMEOFDAY
+#define LIBC_VDSO_HAS_TIME
+
+// list of VDSO symbols
+enum class VDSOSym { ClockGetTime, GetCpu, GetTimeOfDay, Time, VDSOSymCount };
+
+// translate VDSOSym to symbol names
+LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
+ switch (sym) {
+ case VDSOSym::ClockGetTime:
+ return "__vdso_clock_gettime";
+ case VDSOSym::GetCpu:
+ return "__vdso_getcpu";
+ case VDSOSym::GetTimeOfDay:
+ return "__vdso_gettimeofday";
+ case VDSOSym::Time:
+ return "__vdso_time";
+ default:
+ return "";
+ }
+}
+
+// symbol versions
+LIBC_INLINE constexpr cpp::string_view symbol_version(VDSOSym) {
+ return "LINUX_2.6";
+}
+} // namespace vdso
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/vdso.h b/libc/src/__support/OSUtil/vdso.h
new file mode 100644
index 0000000000000..93bbc98da19b4
--- /dev/null
+++ b/libc/src/__support/OSUtil/vdso.h
@@ -0,0 +1,18 @@
+//===--------------- Virtual DSO Support ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_VDSO_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_VDSO_H
+
+#if defined(__linux__)
+#include "linux/vdso.h"
+#elif defined(__Fuchsia__)
+#include "fuchsia/vdso.h"
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_VDSO_H
>From ac0e09e786d47d0c23a18f502998a1473fcdccc2 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Thu, 9 May 2024 12:18:53 -0400
Subject: [PATCH 2/8] [libc] add simple tests for vDSO symbols
---
.../src/__support/OSUtil/linux/CMakeLists.txt | 9 +++++
.../src/__support/OSUtil/linux/vdso_test.cpp | 33 +++++++++++++++++++
2 files changed, 42 insertions(+)
create mode 100644 libc/test/src/__support/OSUtil/linux/vdso_test.cpp
diff --git a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
index bfb072c03e971..29c95ea27d70b 100644
--- a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
@@ -1,3 +1,12 @@
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
add_subdirectory(${LIBC_TARGET_ARCHITECTURE})
endif()
+
+add_libc_test(
+ vdso_test
+ SUITE libc-osutil-tests
+ SRCS vdso_test.cpp
+ DEPENDS
+ libc.src.__support.OSUtil.vdso
+ libc.include.llvm-libc-types.struct_timeval # TODO: update this to proxy header once available
+)
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
new file mode 100644
index 0000000000000..f1148daaccc1a
--- /dev/null
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -0,0 +1,33 @@
+//===-- Unittests for x86_64 syscalls -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-libc-types/struct_timeval.h"
+#include "src/__support/OSUtil/vdso.h"
+#include "test/UnitTest/Test.h"
+
+namespace LIBC_NAMESPACE {
+TEST(LlvmLibcOSUtilVDSOTest, SymbolsDefined) {
+ // for now, we simply test all symbols are provided.
+ for (size_t i = 0; i < static_cast<size_t>(vdso::VDSOSym::VDSOSymCount); ++i)
+ EXPECT_NE(vdso::get_symbol(static_cast<vdso::VDSOSym>(i)),
+ static_cast<void *>(nullptr));
+}
+
+#ifdef LIBC_VDSO_HAS_GETTIMEOFDAY
+TEST(LlvmLibcOSUtilVDSOTest, GetTimeOfDay) {
+ using FuncTy = int (*)(timeval *, struct timezone *);
+ auto func =
+ reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::GetTimeOfDay));
+ timeval tv;
+ EXPECT_EQ(func(&tv, nullptr), 0);
+ // hopefully people are not building time machines using our libc.
+ EXPECT_GT(tv.tv_sec, static_cast<decltype(tv.tv_sec)>(0));
+}
+#endif
+
+} // namespace LIBC_NAMESPACE
>From 62a91df574ed52093cfdc6685cfe091fd31928c2 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Thu, 9 May 2024 12:23:42 -0400
Subject: [PATCH 3/8] [libc] fix header
---
libc/test/src/__support/OSUtil/linux/vdso_test.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
index f1148daaccc1a..6dc35589938f6 100644
--- a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -1,4 +1,4 @@
-//===-- Unittests for x86_64 syscalls -------------------------------------===//
+//===-- Unittests for VDSO ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From a525b6d130a86015fa577e1cc2fb8dc349e50246 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Thu, 9 May 2024 14:04:52 -0400
Subject: [PATCH 4/8] [libc] add missing header guards
---
libc/src/__support/OSUtil/linux/aarch64/vdso.h | 3 +++
libc/src/__support/OSUtil/linux/arm/vdso.h | 3 +++
libc/src/__support/OSUtil/linux/riscv/vdso.h | 3 +++
libc/src/__support/OSUtil/linux/x86_64/vdso.h | 3 +++
4 files changed, 12 insertions(+)
diff --git a/libc/src/__support/OSUtil/linux/aarch64/vdso.h b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
index 55024e61ee914..14783b065069a 100644
--- a/libc/src/__support/OSUtil/linux/aarch64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
@@ -5,6 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_AARCH64_VDSO_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_AARCH64_VDSO_H
#include "src/__support/CPP/string_view.h"
namespace LIBC_NAMESPACE {
namespace vdso {
@@ -45,3 +47,4 @@ LIBC_INLINE constexpr cpp::string_view symbol_version(VDSOSym) {
}
} // namespace vdso
} // namespace LIBC_NAMESPACE
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_AARCH64_VDSO_H
diff --git a/libc/src/__support/OSUtil/linux/arm/vdso.h b/libc/src/__support/OSUtil/linux/arm/vdso.h
index 5d9ff5d929ab6..e1495df89d9ad 100644
--- a/libc/src/__support/OSUtil/linux/arm/vdso.h
+++ b/libc/src/__support/OSUtil/linux/arm/vdso.h
@@ -5,6 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_ARM_VDSO_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_ARM_VDSO_H
#include "src/__support/CPP/string_view.h"
namespace LIBC_NAMESPACE {
namespace vdso {
@@ -34,3 +36,4 @@ LIBC_INLINE constexpr cpp::string_view symbol_version(VDSOSym) {
}
} // namespace vdso
} // namespace LIBC_NAMESPACE
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_ARM_VDSO_H
diff --git a/libc/src/__support/OSUtil/linux/riscv/vdso.h b/libc/src/__support/OSUtil/linux/riscv/vdso.h
index 394c06e6a5a72..41681856037c8 100644
--- a/libc/src/__support/OSUtil/linux/riscv/vdso.h
+++ b/libc/src/__support/OSUtil/linux/riscv/vdso.h
@@ -5,6 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_RISCV_VDSO_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_RISCV_VDSO_H
#include "src/__support/CPP/string_view.h"
namespace LIBC_NAMESPACE {
namespace vdso {
@@ -53,3 +55,4 @@ LIBC_INLINE constexpr cpp::string_view symbol_version(VDSOSym) {
}
} // namespace vdso
} // namespace LIBC_NAMESPACE
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_RISCV_VDSO_H
diff --git a/libc/src/__support/OSUtil/linux/x86_64/vdso.h b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
index 13b8e3d8cc6f4..37580b0201f2c 100644
--- a/libc/src/__support/OSUtil/linux/x86_64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
@@ -5,6 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_X86_64_VDSO_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_X86_64_VDSO_H
#include "src/__support/CPP/string_view.h"
namespace LIBC_NAMESPACE {
namespace vdso {
@@ -39,3 +41,4 @@ LIBC_INLINE constexpr cpp::string_view symbol_version(VDSOSym) {
}
} // namespace vdso
} // namespace LIBC_NAMESPACE
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_X86_64_VDSO_H
>From 770e052259dd762627e139b7d990494a55f9af35 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Thu, 9 May 2024 14:16:50 -0400
Subject: [PATCH 5/8] [libc] fix overlay build problems
---
libc/src/__support/OSUtil/linux/vdso.cpp | 7 ++++++-
libc/test/src/__support/OSUtil/linux/CMakeLists.txt | 2 +-
libc/test/src/__support/OSUtil/linux/vdso_test.cpp | 2 +-
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index 2b2c02ec69fef..98372f0ee00e3 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -11,7 +11,6 @@
#include "src/__support/threads/callonce.h"
#include "src/__support/threads/linux/futex_word.h"
#include "src/errno/libc_errno.h"
-#include "src/sys/auxv/getauxval.h"
#include <linux/auxvec.h>
#include <linux/elf.h>
@@ -24,6 +23,12 @@
#endif
namespace LIBC_NAMESPACE {
+
+// we don't include getauxval.h as it may forcibly pull in elf.h (via
+// sys/auxv.h) in overlay mode instead, we provide a separate declaration for
+// getauxval
+unsigned long getauxval(unsigned long id);
+
namespace vdso {
// See https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
diff --git a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
index 29c95ea27d70b..eef7a48255300 100644
--- a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
@@ -8,5 +8,5 @@ add_libc_test(
SRCS vdso_test.cpp
DEPENDS
libc.src.__support.OSUtil.vdso
- libc.include.llvm-libc-types.struct_timeval # TODO: update this to proxy header once available
+ libc.hdr.types.struct_timeval
)
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
index 6dc35589938f6..dcc1c5747b47a 100644
--- a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm-libc-types/struct_timeval.h"
+#include "hdr/types/struct_timeval.h"
#include "src/__support/OSUtil/vdso.h"
#include "test/UnitTest/Test.h"
>From 36aa78bfe4adf744a94a3e22bb63bd15012d7556 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Fri, 10 May 2024 17:04:58 -0400
Subject: [PATCH 6/8] [libc] remove toplevel vdso and non-linux vdso
---
libc/src/__support/OSUtil/CMakeLists.txt | 8 --------
libc/src/__support/OSUtil/fuchsia/vdso.h | 12 ------------
libc/src/__support/OSUtil/vdso.h | 18 ------------------
.../src/__support/OSUtil/linux/CMakeLists.txt | 2 +-
.../src/__support/OSUtil/linux/vdso_test.cpp | 2 +-
5 files changed, 2 insertions(+), 40 deletions(-)
delete mode 100644 libc/src/__support/OSUtil/fuchsia/vdso.h
delete mode 100644 libc/src/__support/OSUtil/vdso.h
diff --git a/libc/src/__support/OSUtil/CMakeLists.txt b/libc/src/__support/OSUtil/CMakeLists.txt
index 78285c960c0a4..94d1042ccbb4a 100644
--- a/libc/src/__support/OSUtil/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/CMakeLists.txt
@@ -15,11 +15,3 @@ add_object_library(
DEPENDS
${target_os_util}
)
-
-add_header_library(
- vdso
- HDRS
- vdso.h
- DEPENDS
- .${LIBC_TARGET_OS}.vdso
-)
diff --git a/libc/src/__support/OSUtil/fuchsia/vdso.h b/libc/src/__support/OSUtil/fuchsia/vdso.h
deleted file mode 100644
index 177d29f879693..0000000000000
--- a/libc/src/__support/OSUtil/fuchsia/vdso.h
+++ /dev/null
@@ -1,12 +0,0 @@
-//===------------- Fuchsia VDSO Header --------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_FUCHSIA_VDSO_H
-#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_FUCHSIA_VDSO_H
-/// TODO: implement fuchsia VDSO
-/// https://fuchsia.dev/fuchsia-src/concepts/kernel/vdso
-#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_FUCHSIA_VDSO_H
diff --git a/libc/src/__support/OSUtil/vdso.h b/libc/src/__support/OSUtil/vdso.h
deleted file mode 100644
index 93bbc98da19b4..0000000000000
--- a/libc/src/__support/OSUtil/vdso.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//===--------------- Virtual DSO Support ------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_VDSO_H
-#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_VDSO_H
-
-#if defined(__linux__)
-#include "linux/vdso.h"
-#elif defined(__Fuchsia__)
-#include "fuchsia/vdso.h"
-#endif
-
-#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_VDSO_H
diff --git a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
index eef7a48255300..34c6c755a39eb 100644
--- a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
@@ -7,6 +7,6 @@ add_libc_test(
SUITE libc-osutil-tests
SRCS vdso_test.cpp
DEPENDS
- libc.src.__support.OSUtil.vdso
+ libc.src.__support.OSUtil.linux.vdso
libc.hdr.types.struct_timeval
)
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
index dcc1c5747b47a..28cf8bd1c297a 100644
--- a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "hdr/types/struct_timeval.h"
-#include "src/__support/OSUtil/vdso.h"
+#include "src/__support/OSUtil/linux/vdso.h"
#include "test/UnitTest/Test.h"
namespace LIBC_NAMESPACE {
>From 379ade6c6fcd0f7bd67163212c4e3972304b38a4 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Mon, 13 May 2024 17:34:03 -0400
Subject: [PATCH 7/8] wrap vDSO parsing utilities in unnamed namespace
---
libc/src/__support/OSUtil/linux/vdso.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index 98372f0ee00e3..970308eeaa855 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -31,6 +31,7 @@ unsigned long getauxval(unsigned long id);
namespace vdso {
+namespace {
// See https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
struct Verdaux {
ElfW(Word) vda_name; /* Version or dependency names */
@@ -82,6 +83,7 @@ using VDSOArray =
cpp::array<void *, static_cast<size_t>(VDSOSym::VDSOSymCount)>;
static VDSOArray symbol_table;
+} // namespace
void *get_symbol(VDSOSym sym) {
// if sym is invalid, return nullptr
>From 37582b649aa55bea736fb7403a5c827980a2d405 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 21 May 2024 20:15:06 -0700
Subject: [PATCH 8/8] use `auto` after explicit casting
Co-authored-by: Nick Desaulniers (paternity leave) <nickdesaulniers at users.noreply.github.com>
---
libc/src/__support/OSUtil/linux/vdso.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index 970308eeaa855..a1110323a91c9 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -87,7 +87,7 @@ static VDSOArray symbol_table;
void *get_symbol(VDSOSym sym) {
// if sym is invalid, return nullptr
- const size_t index = static_cast<size_t>(sym);
+ const auto index = static_cast<size_t>(sym);
if (index >= symbol_table.size())
return nullptr;
More information about the libc-commits
mailing list