[libc-commits] [libc] [libc] implement vdso (PR #91572)
Schrodinger ZHU Yifan via libc-commits
libc-commits at lists.llvm.org
Sat Jun 8 17:49:29 PDT 2024
https://github.com/SchrodingerZhu updated https://github.com/llvm/llvm-project/pull/91572
>From 777853f974854425e0372fe2bead66d4a992c6bd 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 01/21] [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 9a55232d532fe..9d50d0a98d3bc 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 351847739067d7fbc07b011bf5315a674b787661 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 02/21] [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 e60ba0eea43f80c11be1c11d073a293cef82ca9f 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 03/21] [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 a12de75846962d4912d17fb7a9e65b5abbfa7355 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 04/21] [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 0f1b5dc0d95f90452e1698d771022f8f765fdf02 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 05/21] [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 a894f619939d0e778f0d56fd3ba1e26ac2ce74d6 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 06/21] [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 6326a8539ca98ccfd8700ecf554a6e9ca24878fc 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 07/21] 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 353c9827811db77561910c1e2cde629791dc34df 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 08/21] 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;
>From e6bfe3d5669b4adbfcbfe4f007ba88830b3acb60 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 21 May 2024 20:18:11 -0700
Subject: [PATCH 09/21] error on failure of arch resolution.
Co-authored-by: Nick Desaulniers (paternity leave) <nickdesaulniers at users.noreply.github.com>
---
libc/src/__support/OSUtil/linux/vdso.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libc/src/__support/OSUtil/linux/vdso.h b/libc/src/__support/OSUtil/linux/vdso.h
index 2d71db13303f0..31d3e413e242d 100644
--- a/libc/src/__support/OSUtil/linux/vdso.h
+++ b/libc/src/__support/OSUtil/linux/vdso.h
@@ -18,6 +18,8 @@
#include "arm/vdso.h"
#elif defined(LIBC_TARGET_ARCH_IS_RISCV)
#include "riscv/vdso.h"
+#else
+#error "unknown arch"
#endif
namespace LIBC_NAMESPACE {
>From e261c60b635c23453c93edf85dcc825f8f2c821d Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Sat, 25 May 2024 21:24:12 -0700
Subject: [PATCH 10/21] remove extra brace
Co-authored-by: Nick Desaulniers (paternity leave) <nickdesaulniers at users.noreply.github.com>
---
libc/src/__support/OSUtil/linux/vdso.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index a1110323a91c9..f5166bc193487 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -94,9 +94,8 @@ void *get_symbol(VDSOSym sym) {
static FutexWordType once_flag = 0;
callonce(reinterpret_cast<CallOnceFlag *>(&once_flag), [] {
// first clear the symbol table
- for (auto &i : 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;
>From ef06acd32c29d96240de75cbb76dd2a8750df44c Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sat, 25 May 2024 22:15:06 -0700
Subject: [PATCH 11/21] restructure vdso initialization routine
---
.../src/__support/OSUtil/linux/CMakeLists.txt | 1 +
libc/src/__support/OSUtil/linux/vdso.cpp | 188 +++++++++++-------
2 files changed, 118 insertions(+), 71 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index 9d50d0a98d3bc..a8fedf3e956ea 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -26,6 +26,7 @@ add_object_library(
DEPENDS
.${LIBC_TARGET_ARCHITECTURE}.vdso
libc.src.__support.CPP.array
+ libc.src.__support.CPP.optional
libc.src.__support.CPP.string_view
libc.src.__support.threads.callonce
libc.src.__support.threads.linux.futex_word_type
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index f5166bc193487..af1ef8630d846 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "src/__support/OSUtil/linux/vdso.h"
#include "src/__support/CPP/array.h"
+#include "src/__support/CPP/optional.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/threads/callonce.h"
#include "src/__support/threads/linux/futex_word.h"
@@ -70,7 +71,9 @@ cpp::string_view find_version(Verdef *verdef, ElfW(Half) * versym,
// skip if this is a file-level version
if (def->vd_flags & VER_FLG_BASE)
continue;
- // check if the version identifier matches
+ // check if the version identifier matches. Highest bit is used to determine
+ // whether the symbol is local. Only lower 15 bits are used for version
+ // identifier.
if ((def->vd_ndx & 0x7FFF) == identifier) {
Verdaux *aux = def->aux();
return strtab + aux->vda_name;
@@ -82,61 +85,58 @@ cpp::string_view find_version(Verdef *verdef, ElfW(Half) * versym,
using VDSOArray =
cpp::array<void *, static_cast<size_t>(VDSOSym::VDSOSymCount)>;
-static VDSOArray symbol_table;
-} // namespace
+VDSOArray symbol_table;
-void *get_symbol(VDSOSym sym) {
- // if sym is invalid, return nullptr
- const auto index = static_cast<size_t>(sym);
- if (index >= symbol_table.size())
- return nullptr;
+size_t shdr_get_symbol_count(ElfW(Shdr) * vdso_shdr, size_t e_shnum) {
+ // iterate all sections until we locate the dynamic symbol section
+ for (size_t i = 0; i < e_shnum; ++i) {
+ // 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
+ if (vdso_shdr[i].sh_type == SHT_DYNSYM)
+ return vdso_shdr[i].sh_size / vdso_shdr[i].sh_entsize;
+ }
+ return 0;
+}
- 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;
- }
+struct VDSOSymbolTable {
+ const char *strtab;
+ ElfW(Sym) * symtab;
+ ElfW(Half) * versym;
+ Verdef *verdef;
- // 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;
+ void populate_symbol_cache(size_t symbol_count, ElfW(Addr) vdso_addr) {
+ for (size_t i = 0; i < symbol_table.size(); ++i) {
+ auto sym = static_cast<VDSOSym>(i);
+ cpp::string_view name = symbol_name(sym);
+ cpp::string_view version = symbol_version(sym);
+ for (size_t j = 0; j < symbol_count; ++j) {
+ if (name == 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 (version != 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);
+ }
}
}
+ }
+};
- // 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);
+struct PhdrInfo {
+ ElfW(Addr) vdso_addr;
+ ElfW(Dyn) * vdso_dyn;
+ static cpp::optional<PhdrInfo> from(ElfW(Phdr) * vdso_phdr, size_t e_phnum,
+ uintptr_t vdso_ehdr_addr) {
+ static constexpr ElfW(Addr) INVALID_ADDR = static_cast<ElfW(Addr)>(-1);
+ ElfW(Addr) vdso_addr = INVALID_ADDR;
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) {
+ for (size_t i = 0; i < 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);
@@ -146,14 +146,13 @@ void *get_symbol(VDSOSym sym) {
vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
if (vdso_addr && vdso_dyn)
- break;
+ return PhdrInfo{vdso_addr, vdso_dyn};
}
- // 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
+ return cpp::nullopt;
+ }
+
+ cpp::optional<VDSOSymbolTable> populate_symbol_table() {
const char *strtab = nullptr;
ElfW(Sym) *symtab = nullptr;
ElfW(Half) *versym = nullptr;
@@ -178,26 +177,73 @@ void *get_symbol(VDSOSym sym) {
}
}
if (strtab == nullptr || symtab == nullptr)
- return;
+ return cpp::nullopt;
- 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;
+ return VDSOSymbolTable{strtab, symtab, versym, verdef};
+ }
+};
- // put the symbol address into the symbol table
- symbol_table[i] =
- reinterpret_cast<void *>(vdso_addr + symtab[j].st_value);
- }
- }
- }
- });
+void initialize_vdso_global_cache() {
+ // 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;
+ }
+ // 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);
+ size_t symbol_count = shdr_get_symbol_count(vdso_shdr, vdso_ehdr->e_shnum);
+
+ // 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. 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);
+ cpp::optional<PhdrInfo> phdr_info =
+ PhdrInfo::from(vdso_phdr, vdso_ehdr->e_phnum, vdso_ehdr_addr);
+ // early return if either the dynamic linking or the loadable segment is
+ // not found
+ if (!phdr_info.has_value())
+ return;
+
+ // now, locate several more tables inside the dynmaic linking section
+ cpp::optional<VDSOSymbolTable> vdso_symbol_table =
+ phdr_info->populate_symbol_table();
+
+ // early return if we can't find any required fields of the symbol table
+ if (!vdso_symbol_table.has_value())
+ return;
+
+ // finally, populate the global symbol table cache
+ vdso_symbol_table->populate_symbol_cache(symbol_count, phdr_info->vdso_addr);
+}
+} // namespace
+
+void *get_symbol(VDSOSym sym) {
+ // if sym is invalid, return nullptr
+ const auto index = static_cast<size_t>(sym);
+ if (index >= symbol_table.size())
+ return nullptr;
+
+ static FutexWordType once_flag = 0;
+ callonce(reinterpret_cast<CallOnceFlag *>(&once_flag),
+ initialize_vdso_global_cache);
return symbol_table[index];
}
} // namespace vdso
>From 6dfd57f57f139db6d932fa0472c9cf7acf49b656 Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sun, 26 May 2024 13:30:36 -0700
Subject: [PATCH 12/21] adjust vDSO definitions
---
.../src/__support/OSUtil/linux/aarch64/vdso.h | 1 +
libc/src/__support/OSUtil/linux/arm/vdso.h | 20 +++++++++++++++----
libc/src/__support/OSUtil/linux/riscv/vdso.h | 5 +++++
libc/src/__support/OSUtil/linux/x86_64/vdso.h | 19 ++++++++++++++----
.../src/__support/OSUtil/linux/vdso_test.cpp | 10 ++++++++--
5 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/aarch64/vdso.h b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
index 14783b065069a..27659e686506d 100644
--- a/libc/src/__support/OSUtil/linux/aarch64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
@@ -17,6 +17,7 @@ namespace vdso {
#define LIBC_VDSO_HAS_CLOCK_GETRES
// list of VDSO symbols
+// following the order in arch/arm64/kernel/vdso/vdso.lds.S
enum class VDSOSym {
RTSigReturn,
GetTimeOfDay,
diff --git a/libc/src/__support/OSUtil/linux/arm/vdso.h b/libc/src/__support/OSUtil/linux/arm/vdso.h
index e1495df89d9ad..17d09a69db03b 100644
--- a/libc/src/__support/OSUtil/linux/arm/vdso.h
+++ b/libc/src/__support/OSUtil/linux/arm/vdso.h
@@ -11,22 +11,34 @@
namespace LIBC_NAMESPACE {
namespace vdso {
// macro definitions
-#define LIBC_VDSO_HAS_GETTIMEOFDAY
+// following the order in arch/arm/vdso/vdso.lds.S
#define LIBC_VDSO_HAS_CLOCK_GETTIME
+#define LIBC_VDSO_HAS_GETTIMEOFDAY
+#define LIBC_VDSO_HAS_CLOCK_GETRES
+#define LIBC_VDSO_HAS_CLOCK_GETTIME64
// list of VDSO symbols
enum class VDSOSym {
- GetTimeOfDay,
ClockGetTime,
+ GetTimeOfDay,
+ ClockGetRes,
+ ClockGetTime64,
+ VDSOSymCount
};
// 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";
+ case VDSOSym::GetTimeOfDay:
+ return "__vdso_gettimeofday";
+ case VDSOSym::ClockGetRes:
+ return "__vdso_clock_getres";
+ case VDSOSym::ClockGetTime64:
+ return "__vdso_clock_gettime64";
+ default:
+ return "";
}
}
diff --git a/libc/src/__support/OSUtil/linux/riscv/vdso.h b/libc/src/__support/OSUtil/linux/riscv/vdso.h
index 41681856037c8..10e5c9a54a982 100644
--- a/libc/src/__support/OSUtil/linux/riscv/vdso.h
+++ b/libc/src/__support/OSUtil/linux/riscv/vdso.h
@@ -11,12 +11,14 @@
namespace LIBC_NAMESPACE {
namespace vdso {
// macro definitions
+// following the order in arch/riscv/kernel/vdso/vdso.lds.S
#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
+#define LIBC_VDSO_HAS_RISCV_HWPROBE
// list of VDSO symbols
enum class VDSOSym {
@@ -26,6 +28,7 @@ enum class VDSOSym {
ClockGetRes,
GetCpu,
FlushICache,
+ RiscvHwProbe,
VDSOSymCount
};
@@ -44,6 +47,8 @@ LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
return "__vdso_getcpu";
case VDSOSym::FlushICache:
return "__vdso_flush_icache";
+ case VDSOSym::RiscvHwProbe:
+ return "__vdso_riscv_hwprobe";
default:
return "";
}
diff --git a/libc/src/__support/OSUtil/linux/x86_64/vdso.h b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
index 37580b0201f2c..96e50c25aab8a 100644
--- a/libc/src/__support/OSUtil/linux/x86_64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
@@ -11,25 +11,36 @@
namespace LIBC_NAMESPACE {
namespace vdso {
// macro definitions
+// following the order in arch/x86/entry/vdso/vdso.lds.S
#define LIBC_VDSO_HAS_CLOCK_GETTIME
-#define LIBC_VDSO_HAS_GETCPU
#define LIBC_VDSO_HAS_GETTIMEOFDAY
+#define LIBC_VDSO_HAS_GETCPU
#define LIBC_VDSO_HAS_TIME
+#define LIBC_VDSO_HAS_CLOCK_GETRES
// list of VDSO symbols
-enum class VDSOSym { ClockGetTime, GetCpu, GetTimeOfDay, Time, VDSOSymCount };
+enum class VDSOSym {
+ ClockGetTime,
+ GetTimeOfDay,
+ GetCpu,
+ Time,
+ ClockGetRes,
+ 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::GetCpu:
+ return "__vdso_getcpu";
case VDSOSym::Time:
return "__vdso_time";
+ case VDSOSym::ClockGetRes:
+ return "__vdso_clock_getres";
default:
return "";
}
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
index 28cf8bd1c297a..543292bae7223 100644
--- a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -12,10 +12,16 @@
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)
+ for (size_t i = 0; i < static_cast<size_t>(vdso::VDSOSym::VDSOSymCount);
+ ++i) {
+ // RiscvHwProbe is provided only on >=6.4 kernels. Skip it for now.
+#ifdef LIBC_VDSO_HAS_RISCV_HWPROBE
+ if (static_cast<vdso::VDSOSym>(i) == vdso::VDSOSym::RiscvHwProbe)
+ continue;
+#endif
EXPECT_NE(vdso::get_symbol(static_cast<vdso::VDSOSym>(i)),
static_cast<void *>(nullptr));
+ }
}
#ifdef LIBC_VDSO_HAS_GETTIMEOFDAY
>From fe7bdc25359d553ce4504f0afa0bb5082c01c575 Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sun, 26 May 2024 13:40:05 -0700
Subject: [PATCH 13/21] add more tests
---
.../src/__support/OSUtil/linux/CMakeLists.txt | 3 ++
.../src/__support/OSUtil/linux/vdso_test.cpp | 34 ++++++++++++++++++-
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
index 34c6c755a39eb..c2363927e0ec3 100644
--- a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
@@ -9,4 +9,7 @@ add_libc_test(
DEPENDS
libc.src.__support.OSUtil.linux.vdso
libc.hdr.types.struct_timeval
+ libc.hdr.types.struct_timespec
+ libc.hdr.types.clockid_t
+ libc.hdr.time_macros
)
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
index 543292bae7223..0c937c0cd8658 100644
--- a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -6,15 +6,20 @@
//
//===----------------------------------------------------------------------===//
+#include "hdr/time_macros.h"
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_timespec.h"
#include "hdr/types/struct_timeval.h"
+#include "include/llvm-libc-macros/linux/time-macros.h"
#include "src/__support/OSUtil/linux/vdso.h"
+#include "test/UnitTest/LibcTest.h"
#include "test/UnitTest/Test.h"
namespace LIBC_NAMESPACE {
TEST(LlvmLibcOSUtilVDSOTest, SymbolsDefined) {
for (size_t i = 0; i < static_cast<size_t>(vdso::VDSOSym::VDSOSymCount);
++i) {
- // RiscvHwProbe is provided only on >=6.4 kernels. Skip it for now.
+ // riscv_hwprobe is provided only on >=6.4 kernels. Skip it for now.
#ifdef LIBC_VDSO_HAS_RISCV_HWPROBE
if (static_cast<vdso::VDSOSym>(i) == vdso::VDSOSym::RiscvHwProbe)
continue;
@@ -36,4 +41,31 @@ TEST(LlvmLibcOSUtilVDSOTest, GetTimeOfDay) {
}
#endif
+#ifdef LIBC_VDSO_HAS_CLOCK_GETTIME
+TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime) {
+ using FuncTy = int (*)(clockid_t, timespec *);
+ auto func =
+ reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetTime));
+ timespec a, b;
+ EXPECT_EQ(func(CLOCK_MONOTONIC, &a), 0);
+ EXPECT_EQ(func(CLOCK_MONOTONIC, &b), 0);
+ if (a.tv_sec == b.tv_sec) {
+ EXPECT_LT(a.tv_nsec, b.tv_nsec);
+ } else {
+ EXPECT_LT(a.tv_sec, b.tv_sec);
+ }
+}
+#endif
+
+#ifdef LIBC_VDSO_HAS_CLOCK_GETRES
+TEST(LlvmLibcOSUtilVDSOTest, ClockGetRes) {
+ using FuncTy = int (*)(clockid_t, timespec *);
+ auto func =
+ reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetRes));
+ timespec res{};
+ EXPECT_EQ(func(CLOCK_MONOTONIC, &res), 0);
+ EXPECT_TRUE(res.tv_sec > 0 || res.tv_nsec > 0);
+}
+#endif
+
} // namespace LIBC_NAMESPACE
>From 8270eccc3b81432e24fa0d0bf8fc5680b42ea5d0 Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Tue, 28 May 2024 23:27:50 -0700
Subject: [PATCH 14/21] address CRs
---
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/vdso.cpp | 18 +++++++++++++-----
libc/src/__support/OSUtil/linux/x86_64/vdso.h | 3 ++-
5 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/aarch64/vdso.h b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
index 27659e686506d..cf14ed724a186 100644
--- a/libc/src/__support/OSUtil/linux/aarch64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
@@ -17,7 +17,8 @@ namespace vdso {
#define LIBC_VDSO_HAS_CLOCK_GETRES
// list of VDSO symbols
-// following the order in arch/arm64/kernel/vdso/vdso.lds.S
+// following the order in
+// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/kernel/vdso/vdso.lds.S
enum class VDSOSym {
RTSigReturn,
GetTimeOfDay,
diff --git a/libc/src/__support/OSUtil/linux/arm/vdso.h b/libc/src/__support/OSUtil/linux/arm/vdso.h
index 17d09a69db03b..4cc5bbbb6777e 100644
--- a/libc/src/__support/OSUtil/linux/arm/vdso.h
+++ b/libc/src/__support/OSUtil/linux/arm/vdso.h
@@ -11,7 +11,8 @@
namespace LIBC_NAMESPACE {
namespace vdso {
// macro definitions
-// following the order in arch/arm/vdso/vdso.lds.S
+// following the order in
+// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/vdso/vdso.lds.S
#define LIBC_VDSO_HAS_CLOCK_GETTIME
#define LIBC_VDSO_HAS_GETTIMEOFDAY
#define LIBC_VDSO_HAS_CLOCK_GETRES
diff --git a/libc/src/__support/OSUtil/linux/riscv/vdso.h b/libc/src/__support/OSUtil/linux/riscv/vdso.h
index 10e5c9a54a982..313a94a8af00f 100644
--- a/libc/src/__support/OSUtil/linux/riscv/vdso.h
+++ b/libc/src/__support/OSUtil/linux/riscv/vdso.h
@@ -11,7 +11,8 @@
namespace LIBC_NAMESPACE {
namespace vdso {
// macro definitions
-// following the order in arch/riscv/kernel/vdso/vdso.lds.S
+// following the order in
+// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/kernel/vdso/vdso.lds.S
#define LIBC_VDSO_HAS_RT_SIGRETURN
#define LIBC_VDSO_HAS_GETTIMEOFDAY
#define LIBC_VDSO_HAS_CLOCK_GETTIME
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index af1ef8630d846..46b8d897d99f6 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -12,6 +12,8 @@
#include "src/__support/threads/callonce.h"
#include "src/__support/threads/linux/futex_word.h"
#include "src/errno/libc_errno.h"
+#include "x86_64/vdso.h"
+#include <cstddef>
#include <linux/auxvec.h>
#include <linux/elf.h>
@@ -33,6 +35,13 @@ unsigned long getauxval(unsigned long id);
namespace vdso {
namespace {
+
+// Helper functions to convert between VDSOSym and its index
+constexpr VDSOSym symbolize(size_t index) {
+ return static_cast<VDSOSym>(index);
+}
+constexpr size_t numeralize(VDSOSym sym) { return static_cast<size_t>(sym); }
+
// See https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
struct Verdaux {
ElfW(Word) vda_name; /* Version or dependency names */
@@ -82,8 +91,7 @@ cpp::string_view find_version(Verdef *verdef, ElfW(Half) * versym,
return "";
}
-using VDSOArray =
- cpp::array<void *, static_cast<size_t>(VDSOSym::VDSOSymCount)>;
+using VDSOArray = cpp::array<void *, numeralize(VDSOSym::VDSOSymCount)>;
VDSOArray symbol_table;
@@ -106,8 +114,8 @@ struct VDSOSymbolTable {
Verdef *verdef;
void populate_symbol_cache(size_t symbol_count, ElfW(Addr) vdso_addr) {
- for (size_t i = 0; i < symbol_table.size(); ++i) {
- auto sym = static_cast<VDSOSym>(i);
+ for (size_t i = 0, e = symbol_table.size(); i < e; ++i) {
+ VDSOSym sym = symbolize(i);
cpp::string_view name = symbol_name(sym);
cpp::string_view version = symbol_version(sym);
for (size_t j = 0; j < symbol_count; ++j) {
@@ -237,7 +245,7 @@ void initialize_vdso_global_cache() {
void *get_symbol(VDSOSym sym) {
// if sym is invalid, return nullptr
- const auto index = static_cast<size_t>(sym);
+ const size_t index = numeralize(sym);
if (index >= symbol_table.size())
return nullptr;
diff --git a/libc/src/__support/OSUtil/linux/x86_64/vdso.h b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
index 96e50c25aab8a..95a43d4fa070a 100644
--- a/libc/src/__support/OSUtil/linux/x86_64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
@@ -11,7 +11,8 @@
namespace LIBC_NAMESPACE {
namespace vdso {
// macro definitions
-// following the order in arch/x86/entry/vdso/vdso.lds.S
+// following the order in
+// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/vdso/vdso.lds.S
#define LIBC_VDSO_HAS_CLOCK_GETTIME
#define LIBC_VDSO_HAS_GETTIMEOFDAY
#define LIBC_VDSO_HAS_GETCPU
>From 4233ad7e12447f298a018c0476ed73d99a9875f4 Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sat, 1 Jun 2024 14:19:55 -0700
Subject: [PATCH 15/21] [libc] add comment for x86 vdso
---
libc/src/__support/OSUtil/linux/x86_64/vdso.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libc/src/__support/OSUtil/linux/x86_64/vdso.h b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
index 95a43d4fa070a..c5b5c45b5b01f 100644
--- a/libc/src/__support/OSUtil/linux/x86_64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
@@ -30,6 +30,10 @@ enum class VDSOSym {
};
// translate VDSOSym to symbol names
+// On x86, there are symbols defined without the __vdso_ prefix, however,
+// it is suggested that one should use the __vdso_ prefix.
+// Additionally, there is also an __vdso_sgx_enter_enclave, it is for the SGX
+// support, we do not include it here for now.
LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
switch (sym) {
case VDSOSym::ClockGetTime:
>From 116f2e6812fdeadd8032b54db76fc261c827d9ef Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sat, 1 Jun 2024 14:33:43 -0700
Subject: [PATCH 16/21] [libc] fix
---
libc/src/__support/OSUtil/linux/vdso.cpp | 36 +++++++++++++++---------
1 file changed, 22 insertions(+), 14 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index 46b8d897d99f6..377648fb9a353 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -12,8 +12,6 @@
#include "src/__support/threads/callonce.h"
#include "src/__support/threads/linux/futex_word.h"
#include "src/errno/libc_errno.h"
-#include "x86_64/vdso.h"
-#include <cstddef>
#include <linux/auxvec.h>
#include <linux/elf.h>
@@ -36,11 +34,21 @@ namespace vdso {
namespace {
-// Helper functions to convert between VDSOSym and its index
-constexpr VDSOSym symbolize(size_t index) {
- return static_cast<VDSOSym>(index);
-}
-constexpr size_t numeralize(VDSOSym sym) { return static_cast<size_t>(sym); }
+// This class is an internal helper for symbol <-> index conversion and
+// improve the readability of the code.
+// We keep this class internal on purpose to avoid users from implicitly
+// converting between size_t and VDSOSym.
+class Symbol {
+ VDSOSym sym;
+
+public:
+ static constexpr size_t COUNT = static_cast<size_t>(VDSOSym::VDSOSymCount);
+ constexpr Symbol(VDSOSym sym) : sym(sym) {}
+ constexpr Symbol(size_t idx) : sym(static_cast<VDSOSym>(idx)) {}
+ constexpr cpp::string_view name() const { return symbol_name(sym); }
+ constexpr cpp::string_view version() const { return symbol_version(sym); }
+ operator size_t() const { return static_cast<size_t>(sym); }
+};
// See https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
struct Verdaux {
@@ -91,7 +99,7 @@ cpp::string_view find_version(Verdef *verdef, ElfW(Half) * versym,
return "";
}
-using VDSOArray = cpp::array<void *, numeralize(VDSOSym::VDSOSymCount)>;
+using VDSOArray = cpp::array<void *, Symbol::COUNT>;
VDSOArray symbol_table;
@@ -115,9 +123,9 @@ struct VDSOSymbolTable {
void populate_symbol_cache(size_t symbol_count, ElfW(Addr) vdso_addr) {
for (size_t i = 0, e = symbol_table.size(); i < e; ++i) {
- VDSOSym sym = symbolize(i);
- cpp::string_view name = symbol_name(sym);
- cpp::string_view version = symbol_version(sym);
+ Symbol sym = i;
+ cpp::string_view name = sym.name();
+ cpp::string_view version = sym.version();
for (size_t j = 0; j < symbol_count; ++j) {
if (name == strtab + symtab[j].st_name) {
// we find a symbol with desired name
@@ -245,14 +253,14 @@ void initialize_vdso_global_cache() {
void *get_symbol(VDSOSym sym) {
// if sym is invalid, return nullptr
- const size_t index = numeralize(sym);
- if (index >= symbol_table.size())
+ Symbol symbol(sym);
+ if (symbol >= symbol_table.size())
return nullptr;
static FutexWordType once_flag = 0;
callonce(reinterpret_cast<CallOnceFlag *>(&once_flag),
initialize_vdso_global_cache);
- return symbol_table[index];
+ return symbol_table[symbol];
}
} // namespace vdso
} // namespace LIBC_NAMESPACE
>From 92661d61c4f48a379613ea8fc968a01fef8241e6 Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sat, 1 Jun 2024 14:36:21 -0700
Subject: [PATCH 17/21] [libc] fix
---
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 377648fb9a353..615b6cd3de5e2 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -47,7 +47,7 @@ class Symbol {
constexpr Symbol(size_t idx) : sym(static_cast<VDSOSym>(idx)) {}
constexpr cpp::string_view name() const { return symbol_name(sym); }
constexpr cpp::string_view version() const { return symbol_version(sym); }
- operator size_t() const { return static_cast<size_t>(sym); }
+ constexpr operator size_t() const { return static_cast<size_t>(sym); }
};
// See https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
>From 22e1b46c66f54df7271f003184b990f29c41cc76 Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sat, 1 Jun 2024 14:57:55 -0700
Subject: [PATCH 18/21] [libc] fix
---
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 615b6cd3de5e2..d1ea951f22ae9 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -15,6 +15,8 @@
#include <linux/auxvec.h>
#include <linux/elf.h>
+// TODO: This is a temporary workaround to avoid including elf.h
+// Include our own headers for ElfW and friends once we have them.
#ifndef ElfW
#if __POINTER_WIDTH__ == 32
#define ElfW(type) Elf32_##type
>From e8d80be579969c5c7870b24aa69b3d3405c27172 Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sat, 1 Jun 2024 16:32:48 -0700
Subject: [PATCH 19/21] [libc] fix
---
libc/hdr/types/CMakeLists.txt | 9 +
libc/hdr/types/struct_sigaction.h | 21 +++
libc/src/sched/linux/CMakeLists.txt | 2 +-
libc/src/signal/linux/CMakeLists.txt | 1 +
libc/src/signal/sigaction.h | 2 +-
.../src/__support/OSUtil/linux/CMakeLists.txt | 6 +
.../src/__support/OSUtil/linux/vdso_test.cpp | 162 ++++++++++++++++--
7 files changed, 187 insertions(+), 16 deletions(-)
create mode 100644 libc/hdr/types/struct_sigaction.h
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 9b3373a0ca390..1cab1d3b812cf 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -126,3 +126,12 @@ add_proxy_header_library(
libc.include.llvm-libc-types.atexithandler_t
libc.include.stdlib
)
+
+add_proxy_header_library(
+ struct_sigaction
+ HDRS
+ struct_sigaction.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.struct_sigaction
+ libc.include.signal
+)
diff --git a/libc/hdr/types/struct_sigaction.h b/libc/hdr/types/struct_sigaction.h
new file mode 100644
index 0000000000000..60f6caeb4af10
--- /dev/null
+++ b/libc/hdr/types/struct_sigaction.h
@@ -0,0 +1,21 @@
+//===-- Proxy for struct sigaction ---------------------------------------===//
+//
+// 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_HDR_TYPES_STRUCT_SIGACTION_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_SIGACTION_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_sigaction.h"
+
+#else
+
+#include <signal.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_SIGACTION_H
diff --git a/libc/src/sched/linux/CMakeLists.txt b/libc/src/sched/linux/CMakeLists.txt
index ac95bf85da534..03f513cac644a 100644
--- a/libc/src/sched/linux/CMakeLists.txt
+++ b/libc/src/sched/linux/CMakeLists.txt
@@ -29,7 +29,7 @@ add_entrypoint_object(
HDRS
../sched_getcpucount.h
DEPENDS
- libc.include.sched
+ libc.hdr.types.cpu_set_t
)
add_entrypoint_object(
diff --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt
index 7606b4b21d3dd..b03d06a0bc4c7 100644
--- a/libc/src/signal/linux/CMakeLists.txt
+++ b/libc/src/signal/linux/CMakeLists.txt
@@ -60,6 +60,7 @@ add_entrypoint_object(
DEPENDS
.__restore
libc.hdr.types.sigset_t
+ libc.hdr.types.struct_sigaction
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
diff --git a/libc/src/signal/sigaction.h b/libc/src/signal/sigaction.h
index c36a3ec9fedfa..293093f6a0751 100644
--- a/libc/src/signal/sigaction.h
+++ b/libc/src/signal/sigaction.h
@@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_SIGNAL_SIGACTION_H
#define LLVM_LIBC_SRC_SIGNAL_SIGACTION_H
-#include <signal.h>
+#include <hdr/types/struct_sigaction.h>
namespace LIBC_NAMESPACE {
diff --git a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
index c2363927e0ec3..ff82616cc4a70 100644
--- a/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/test/src/__support/OSUtil/linux/CMakeLists.txt
@@ -8,8 +8,14 @@ add_libc_test(
SRCS vdso_test.cpp
DEPENDS
libc.src.__support.OSUtil.linux.vdso
+ libc.src.__support.OSUtil.osutil
+ libc.hdr.types.struct_sigaction
libc.hdr.types.struct_timeval
libc.hdr.types.struct_timespec
libc.hdr.types.clockid_t
+ libc.hdr.types.time_t
libc.hdr.time_macros
+ libc.hdr.signal_macros
+ libc.src.signal.sigaction
+ libc.src.signal.raise
)
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
index 0c937c0cd8658..f023acff5642f 100644
--- a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -6,34 +6,31 @@
//
//===----------------------------------------------------------------------===//
+#include "hdr/signal_macros.h"
#include "hdr/time_macros.h"
#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_sigaction.h"
#include "hdr/types/struct_timespec.h"
#include "hdr/types/struct_timeval.h"
-#include "include/llvm-libc-macros/linux/time-macros.h"
+#include "hdr/types/time_t.h"
#include "src/__support/OSUtil/linux/vdso.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/signal/raise.h"
+#include "src/signal/sigaction.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/LibcTest.h"
#include "test/UnitTest/Test.h"
+#include <linux/time_types.h>
+#include <sys/syscall.h>
namespace LIBC_NAMESPACE {
-TEST(LlvmLibcOSUtilVDSOTest, SymbolsDefined) {
- for (size_t i = 0; i < static_cast<size_t>(vdso::VDSOSym::VDSOSymCount);
- ++i) {
- // riscv_hwprobe is provided only on >=6.4 kernels. Skip it for now.
-#ifdef LIBC_VDSO_HAS_RISCV_HWPROBE
- if (static_cast<vdso::VDSOSym>(i) == vdso::VDSOSym::RiscvHwProbe)
- continue;
-#endif
- 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));
+ if (func == nullptr)
+ return;
timeval tv;
EXPECT_EQ(func(&tv, nullptr), 0);
// hopefully people are not building time machines using our libc.
@@ -41,11 +38,26 @@ TEST(LlvmLibcOSUtilVDSOTest, GetTimeOfDay) {
}
#endif
+#ifdef LIBC_VDSO_HAS_TIME
+TEST(LlvmLibcOSUtilVDSOTest, Time) {
+ using FuncTy = time_t (*)(time_t *);
+ auto func = reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::Time));
+ if (func == nullptr)
+ return;
+ time_t a, b;
+ EXPECT_GT(func(&a), static_cast<time_t>(0));
+ EXPECT_GT(func(&b), static_cast<time_t>(0));
+ EXPECT_GE(b, a);
+}
+#endif
+
#ifdef LIBC_VDSO_HAS_CLOCK_GETTIME
TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime) {
using FuncTy = int (*)(clockid_t, timespec *);
auto func =
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetTime));
+ if (func == nullptr)
+ return;
timespec a, b;
EXPECT_EQ(func(CLOCK_MONOTONIC, &a), 0);
EXPECT_EQ(func(CLOCK_MONOTONIC, &b), 0);
@@ -57,15 +69,137 @@ TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime) {
}
#endif
+#ifdef LIBC_VDSO_HAS_CLOCK_GETTIME64
+TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime64) {
+ using FuncTy = int (*)(clockid_t, __kernel_timespec *);
+ auto func =
+ reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetTime64));
+ if (func == nullptr)
+ return;
+ // See kernel API at
+ // https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/vDSO/vdso_test_correctness.c#L155
+ __kernel_timespec a, b;
+ EXPECT_EQ(func(CLOCK_MONOTONIC, &a), 0);
+ EXPECT_EQ(func(CLOCK_MONOTONIC, &b), 0);
+ if (a.tv_sec == b.tv_sec) {
+ EXPECT_LT(a.tv_nsec, b.tv_nsec);
+ } else {
+ EXPECT_LT(a.tv_sec, b.tv_sec);
+ }
+}
+#endif
+
#ifdef LIBC_VDSO_HAS_CLOCK_GETRES
TEST(LlvmLibcOSUtilVDSOTest, ClockGetRes) {
using FuncTy = int (*)(clockid_t, timespec *);
auto func =
reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetRes));
+ if (func == nullptr)
+ return;
timespec res{};
EXPECT_EQ(func(CLOCK_MONOTONIC, &res), 0);
EXPECT_TRUE(res.tv_sec > 0 || res.tv_nsec > 0);
}
#endif
+#ifdef LIBC_VDSO_HAS_GETCPU
+TEST(LlvmLibcOSUtilVDSOTest, GetCpu) {
+ // The kernel system call has a third argument, which should be passed as
+ // nullptr.
+ using FuncTy = int (*)(int *, int *, void *);
+ auto func = reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::GetCpu));
+ if (func == nullptr)
+ return;
+ int cpu = -1, node = -1;
+ EXPECT_EQ(func(&cpu, &node, nullptr), 0);
+ EXPECT_GE(cpu, 0);
+ EXPECT_GE(node, 0);
+}
+#endif
+
+// TODO: apply this change to __restore_rt in
+// libc/src/signal/linux/sigaction.cpp
+// Caution: user application typically should not play with the trampoline.
+// Let the libc handle it.
+[[gnu::noreturn]] static void __restore_rt() {
+#ifdef LIBC_VDSO_HAS_RT_SIGRETURN
+ using FuncTy = void (*)();
+ auto func =
+ reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::RTSigReturn));
+ if (func) {
+ func();
+ __builtin_trap();
+ }
+#endif
+ LIBC_NAMESPACE::syscall_impl<long>(SYS_rt_sigreturn);
+ __builtin_trap();
+}
+
+static bool flag = false;
+
+static void sigprof_handler [[gnu::used]] (int) { flag = true; }
+
+TEST(LlvmLibcOSUtilVDSOTest, RtSigReturn) {
+ using namespace testing::ErrnoSetterMatcher;
+ // must use struct since there is a function of the same name in the same
+ // scope.
+ struct sigaction sa{};
+ struct sigaction old_sa{};
+ sa.sa_handler = sigprof_handler;
+ sa.sa_flags = SA_RESTORER;
+ sa.sa_restorer = __restore_rt;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGPROF, &sa, &old_sa), Succeeds());
+ raise(SIGPROF);
+ ASSERT_TRUE(flag);
+ flag = false;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGPROF, &old_sa, nullptr), Succeeds());
+}
+
+#ifdef LIBC_VDSO_HAS_FLUSH_ICACHE
+TEST(LlvmLibcOSUtilVDSOTest, FlushICache) {
+ using FuncTy = void (*)(void *, void *, unsigned long);
+ auto func =
+ reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::FlushICache));
+ if (func == nullptr)
+ return;
+ char buf[512];
+ // we just check that the flush will not panic the program.
+ // the flags part only take 0/1 as up to kernel 6.10, which is used to
+ // indicate whether the flush is local to the core or global.
+ func(buf, buf + sizeof(buf), 0);
+ func(buf, buf + sizeof(buf), 1);
+}
+#endif
+
+// https://docs.kernel.org/6.5/riscv/hwprobe.html
+
+#ifdef LIBC_VDSO_HAS_RISCV_HWPROBE
+TEST(LlvmLibcOSUtilVDSOTest, RiscvHwProbe) {
+ using namespace testing::ErrnoSetterMatcher;
+ struct riscv_hwprobe {
+ int64_t key;
+ uint64_t value;
+ };
+ using FuncTy =
+ long (*)(riscv_hwprobe *, size_t, size_t, struct cpu_set_t *, unsigned);
+ auto func =
+ reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::RiscvHwProbe));
+ if (func == nullptr)
+ return;
+ // If a key is unknown to the kernel, its key field will be cleared to -1, and
+ // its value set to 0. We expect probes.value are all 0.
+ // Usermode can supply NULL for cpus and 0 for cpu_count as a shortcut for all
+ // online CPUs
+ riscv_hwprobe probes[2] = {{-1, 1}, {-1, 1}};
+ ASSERT_THAT(func(/*pairs=*/probes, /*count=*/2, /*cpusetsize=*/0,
+ /*cpuset=*/nullptr,
+ /*flags=*/0),
+ Succeeds());
+ for (auto &probe : probes) {
+ EXPECT_EQ(probe.key, static_cast<decltype(probe.key)>(-1));
+ EXPECT_EQ(probe.value, static_cast<decltype(probe.value)>(0));
+ }
+}
+#endif
+
} // namespace LIBC_NAMESPACE
>From 22be062f461a0425e7555a4fc0c144d32ce0389c Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sat, 1 Jun 2024 16:36:15 -0700
Subject: [PATCH 20/21] [libc] undo extra changes
---
libc/src/sched/linux/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/sched/linux/CMakeLists.txt b/libc/src/sched/linux/CMakeLists.txt
index 03f513cac644a..ac95bf85da534 100644
--- a/libc/src/sched/linux/CMakeLists.txt
+++ b/libc/src/sched/linux/CMakeLists.txt
@@ -29,7 +29,7 @@ add_entrypoint_object(
HDRS
../sched_getcpucount.h
DEPENDS
- libc.hdr.types.cpu_set_t
+ libc.include.sched
)
add_entrypoint_object(
>From 67e0f01ffe12c1830aba158438225de3cb47dc31 Mon Sep 17 00:00:00 2001
From: Yifan Zhu <yifzhu at nvidia.com>
Date: Sat, 8 Jun 2024 17:21:10 -0700
Subject: [PATCH 21/21] address CRs and improve inlining of fastpaths
---
.../src/__support/OSUtil/linux/aarch64/vdso.h | 17 ----
libc/src/__support/OSUtil/linux/arm/vdso.h | 17 ----
libc/src/__support/OSUtil/linux/riscv/vdso.h | 23 ------
libc/src/__support/OSUtil/linux/vdso.cpp | 50 +++--------
libc/src/__support/OSUtil/linux/vdso.h | 59 ++++++++++++-
libc/src/__support/OSUtil/linux/x86_64/vdso.h | 19 -----
libc/src/__support/threads/callonce.h | 29 ++++++-
libc/src/__support/threads/linux/callonce.cpp | 18 +---
.../src/__support/OSUtil/linux/vdso_test.cpp | 82 +++++++------------
9 files changed, 129 insertions(+), 185 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/aarch64/vdso.h b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
index cf14ed724a186..68d2bdaac4fc7 100644
--- a/libc/src/__support/OSUtil/linux/aarch64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
@@ -10,23 +10,6 @@
#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
-// following the order in
-// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/kernel/vdso/vdso.lds.S
-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) {
diff --git a/libc/src/__support/OSUtil/linux/arm/vdso.h b/libc/src/__support/OSUtil/linux/arm/vdso.h
index 4cc5bbbb6777e..1cc41e47a2b7c 100644
--- a/libc/src/__support/OSUtil/linux/arm/vdso.h
+++ b/libc/src/__support/OSUtil/linux/arm/vdso.h
@@ -10,23 +10,6 @@
#include "src/__support/CPP/string_view.h"
namespace LIBC_NAMESPACE {
namespace vdso {
-// macro definitions
-// following the order in
-// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/vdso/vdso.lds.S
-#define LIBC_VDSO_HAS_CLOCK_GETTIME
-#define LIBC_VDSO_HAS_GETTIMEOFDAY
-#define LIBC_VDSO_HAS_CLOCK_GETRES
-#define LIBC_VDSO_HAS_CLOCK_GETTIME64
-
-// list of VDSO symbols
-enum class VDSOSym {
- ClockGetTime,
- GetTimeOfDay,
- ClockGetRes,
- ClockGetTime64,
- VDSOSymCount
-};
-
// translate VDSOSym to symbol names
LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
switch (sym) {
diff --git a/libc/src/__support/OSUtil/linux/riscv/vdso.h b/libc/src/__support/OSUtil/linux/riscv/vdso.h
index 313a94a8af00f..9a494437fd05f 100644
--- a/libc/src/__support/OSUtil/linux/riscv/vdso.h
+++ b/libc/src/__support/OSUtil/linux/riscv/vdso.h
@@ -10,29 +10,6 @@
#include "src/__support/CPP/string_view.h"
namespace LIBC_NAMESPACE {
namespace vdso {
-// macro definitions
-// following the order in
-// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/kernel/vdso/vdso.lds.S
-#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
-#define LIBC_VDSO_HAS_RISCV_HWPROBE
-
-// list of VDSO symbols
-enum class VDSOSym {
- RTSigReturn,
- GetTimeOfDay,
- ClockGetTime,
- ClockGetRes,
- GetCpu,
- FlushICache,
- RiscvHwProbe,
- VDSOSymCount
-};
-
// translate VDSOSym to symbol names
LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
switch (sym) {
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index d1ea951f22ae9..4e0467d6dade8 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -34,24 +34,10 @@ unsigned long getauxval(unsigned long id);
namespace vdso {
-namespace {
-
-// This class is an internal helper for symbol <-> index conversion and
-// improve the readability of the code.
-// We keep this class internal on purpose to avoid users from implicitly
-// converting between size_t and VDSOSym.
-class Symbol {
- VDSOSym sym;
-
-public:
- static constexpr size_t COUNT = static_cast<size_t>(VDSOSym::VDSOSymCount);
- constexpr Symbol(VDSOSym sym) : sym(sym) {}
- constexpr Symbol(size_t idx) : sym(static_cast<VDSOSym>(idx)) {}
- constexpr cpp::string_view name() const { return symbol_name(sym); }
- constexpr cpp::string_view version() const { return symbol_version(sym); }
- constexpr operator size_t() const { return static_cast<size_t>(sym); }
-};
+Symbol::VDSOArray Symbol::global_cache{};
+CallOnceFlag Symbol::once_flag = callonce_impl::NOT_CALLED;
+namespace {
// See https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
struct Verdaux {
ElfW(Word) vda_name; /* Version or dependency names */
@@ -101,10 +87,6 @@ cpp::string_view find_version(Verdef *verdef, ElfW(Half) * versym,
return "";
}
-using VDSOArray = cpp::array<void *, Symbol::COUNT>;
-
-VDSOArray symbol_table;
-
size_t shdr_get_symbol_count(ElfW(Shdr) * vdso_shdr, size_t e_shnum) {
// iterate all sections until we locate the dynamic symbol section
for (size_t i = 0; i < e_shnum; ++i) {
@@ -123,11 +105,14 @@ struct VDSOSymbolTable {
ElfW(Half) * versym;
Verdef *verdef;
- void populate_symbol_cache(size_t symbol_count, ElfW(Addr) vdso_addr) {
+ void populate_symbol_cache(Symbol::VDSOArray &symbol_table,
+ size_t symbol_count, ElfW(Addr) vdso_addr) {
for (size_t i = 0, e = symbol_table.size(); i < e; ++i) {
Symbol sym = i;
cpp::string_view name = sym.name();
cpp::string_view version = sym.version();
+ if (name.empty())
+ return;
for (size_t j = 0; j < symbol_count; ++j) {
if (name == strtab + symtab[j].st_name) {
// we find a symbol with desired name
@@ -200,10 +185,11 @@ struct PhdrInfo {
return VDSOSymbolTable{strtab, symtab, versym, verdef};
}
};
+} // namespace
-void initialize_vdso_global_cache() {
+void Symbol::initialize_vdso_global_cache() {
// first clear the symbol table
- for (auto &i : symbol_table)
+ for (auto &i : global_cache)
i = nullptr;
// get the address of the VDSO, protect errno since getauxval may change
@@ -249,20 +235,8 @@ void initialize_vdso_global_cache() {
return;
// finally, populate the global symbol table cache
- vdso_symbol_table->populate_symbol_cache(symbol_count, phdr_info->vdso_addr);
-}
-} // namespace
-
-void *get_symbol(VDSOSym sym) {
- // if sym is invalid, return nullptr
- Symbol symbol(sym);
- if (symbol >= symbol_table.size())
- return nullptr;
-
- static FutexWordType once_flag = 0;
- callonce(reinterpret_cast<CallOnceFlag *>(&once_flag),
- initialize_vdso_global_cache);
- return symbol_table[symbol];
+ vdso_symbol_table->populate_symbol_cache(global_cache, symbol_count,
+ phdr_info->vdso_addr);
}
} // namespace vdso
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/linux/vdso.h b/libc/src/__support/OSUtil/linux/vdso.h
index 31d3e413e242d..6e74d69b4d50c 100644
--- a/libc/src/__support/OSUtil/linux/vdso.h
+++ b/libc/src/__support/OSUtil/linux/vdso.h
@@ -7,8 +7,28 @@
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_VDSO_H
+#include "src/__support/CPP/array.h"
#include "src/__support/common.h"
+#include "src/__support/macros/attributes.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/threads/callonce.h"
+
+namespace LIBC_NAMESPACE {
+namespace vdso {
+enum class VDSOSym {
+ ClockGetTime,
+ ClockGetTime64,
+ GetTimeOfDay,
+ GetCpu,
+ Time,
+ ClockGetRes,
+ RTSigReturn,
+ FlushICache,
+ RiscvHwProbe,
+ VDSOSymCount
+};
+} // namespace vdso
+} // namespace LIBC_NAMESPACE
#if defined(LIBC_TARGET_ARCH_IS_X86)
#include "x86_64/vdso.h"
@@ -24,7 +44,44 @@
namespace LIBC_NAMESPACE {
namespace vdso {
-void *get_symbol(VDSOSym);
+class Symbol {
+ VDSOSym sym;
+
+public:
+ LIBC_INLINE_VAR static constexpr size_t COUNT =
+ static_cast<size_t>(VDSOSym::VDSOSymCount);
+ LIBC_INLINE constexpr explicit Symbol(VDSOSym sym) : sym(sym) {}
+ LIBC_INLINE constexpr Symbol(size_t idx) : sym(static_cast<VDSOSym>(idx)) {}
+ LIBC_INLINE constexpr cpp::string_view name() const {
+ return symbol_name(sym);
+ }
+ LIBC_INLINE constexpr cpp::string_view version() const {
+ return symbol_version(sym);
+ }
+ LIBC_INLINE constexpr operator size_t() const {
+ return static_cast<size_t>(sym);
+ }
+ LIBC_INLINE constexpr bool is_valid() const {
+ return *this < Symbol::global_cache.size();
+ }
+ using VDSOArray = cpp::array<void *, Symbol::COUNT>;
+
+private:
+ static CallOnceFlag once_flag;
+ static VDSOArray global_cache;
+ static void initialize_vdso_global_cache();
+ friend void *get_symbol(VDSOSym sym);
+
+public:
+ template <typename T> LIBC_INLINE T get() {
+ if (name().empty() || !is_valid())
+ return nullptr;
+
+ callonce(&once_flag, Symbol::initialize_vdso_global_cache);
+ return cpp::bit_cast<T>(global_cache[*this]);
+ }
+};
+
} // namespace vdso
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/linux/x86_64/vdso.h b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
index c5b5c45b5b01f..659d0b6e9a20d 100644
--- a/libc/src/__support/OSUtil/linux/x86_64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
@@ -10,25 +10,6 @@
#include "src/__support/CPP/string_view.h"
namespace LIBC_NAMESPACE {
namespace vdso {
-// macro definitions
-// following the order in
-// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/vdso/vdso.lds.S
-#define LIBC_VDSO_HAS_CLOCK_GETTIME
-#define LIBC_VDSO_HAS_GETTIMEOFDAY
-#define LIBC_VDSO_HAS_GETCPU
-#define LIBC_VDSO_HAS_TIME
-#define LIBC_VDSO_HAS_CLOCK_GETRES
-
-// list of VDSO symbols
-enum class VDSOSym {
- ClockGetTime,
- GetTimeOfDay,
- GetCpu,
- Time,
- ClockGetRes,
- VDSOSymCount
-};
-
// translate VDSOSym to symbol names
// On x86, there are symbols defined without the __vdso_ prefix, however,
// it is suggested that one should use the __vdso_ prefix.
diff --git a/libc/src/__support/threads/callonce.h b/libc/src/__support/threads/callonce.h
index b3d6813f7dda9..55199b6e30906 100644
--- a/libc/src/__support/threads/callonce.h
+++ b/libc/src/__support/threads/callonce.h
@@ -9,13 +9,38 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H
#define LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H
+#include "src/__support/macros/optimization.h"
+
+#ifdef __linux__
+#include "src/__support/threads/linux/futex_utils.h"
+#else
+#error "callonce is not supported on this platform"
+#endif
+
namespace LIBC_NAMESPACE {
-struct CallOnceFlag;
+#ifdef __linux__
+using CallOnceFlag = Futex;
+#endif
using CallOnceCallback = void(void);
+namespace callonce_impl {
+static constexpr FutexWordType NOT_CALLED = 0x0;
+static constexpr FutexWordType START = 0x11;
+static constexpr FutexWordType WAITING = 0x22;
+static constexpr FutexWordType FINISH = 0x33;
+int callonce_slowpath(CallOnceFlag *flag, CallOnceCallback *callback);
+} // namespace callonce_impl
-int callonce(CallOnceFlag *flag, CallOnceCallback *callback);
+LIBC_INLINE int callonce(CallOnceFlag *flag, CallOnceCallback *callback) {
+ using namespace callonce_impl;
+ // Avoid cmpxchg operation if the function has already been called.
+ // The destination operand of cmpxchg may receive a write cycle without
+ // regard to the result of the comparison
+ if (LIBC_LIKELY(flag->load(cpp::MemoryOrder::RELAXED) == FINISH))
+ return 0;
+ return callonce_slowpath(flag, callback);
+}
} // namespace LIBC_NAMESPACE
#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H
diff --git a/libc/src/__support/threads/linux/callonce.cpp b/libc/src/__support/threads/linux/callonce.cpp
index b48a514a44875..2bea2da2ae21d 100644
--- a/libc/src/__support/threads/linux/callonce.cpp
+++ b/libc/src/__support/threads/linux/callonce.cpp
@@ -7,27 +7,15 @@
//===----------------------------------------------------------------------===//
#include "src/__support/threads/callonce.h"
-#include "src/__support/macros/optimization.h"
#include "src/__support/threads/linux/futex_utils.h"
namespace LIBC_NAMESPACE {
-
-static constexpr FutexWordType NOT_CALLED = 0x0;
-static constexpr FutexWordType START = 0x11;
-static constexpr FutexWordType WAITING = 0x22;
-static constexpr FutexWordType FINISH = 0x33;
-
-int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
+namespace callonce_impl {
+int callonce_slowpath(CallOnceFlag *flag, CallOnceCallback *func) {
auto *futex_word = reinterpret_cast<Futex *>(flag);
FutexWordType not_called = NOT_CALLED;
- // Avoid cmpxchg operation if the function has already been called.
- // The destination operand of cmpxchg may receive a write cycle without
- // regard to the result of the comparison
- if (LIBC_LIKELY(futex_word->load(cpp::MemoryOrder::RELAXED) == FINISH))
- return 0;
-
// The call_once call can return only after the called function |func|
// returns. So, we use futexes to synchronize calls with the same flag value.
if (futex_word->compare_exchange_strong(not_called, START)) {
@@ -46,5 +34,5 @@ int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
return 0;
}
-
+} // namespace callonce_impl
} // namespace LIBC_NAMESPACE
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
index f023acff5642f..9787e8b456119 100644
--- a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -15,6 +15,7 @@
#include "hdr/types/time_t.h"
#include "src/__support/OSUtil/linux/vdso.h"
#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/macros/properties/architectures.h"
#include "src/signal/raise.h"
#include "src/signal/sigaction.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
@@ -24,11 +25,11 @@
#include <sys/syscall.h>
namespace LIBC_NAMESPACE {
-#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));
+ vdso::Symbol symbol{vdso::VDSOSym::GetTimeOfDay};
+ auto func = symbol.get<FuncTy>();
if (func == nullptr)
return;
timeval tv;
@@ -36,12 +37,11 @@ TEST(LlvmLibcOSUtilVDSOTest, GetTimeOfDay) {
// hopefully people are not building time machines using our libc.
EXPECT_GT(tv.tv_sec, static_cast<decltype(tv.tv_sec)>(0));
}
-#endif
-#ifdef LIBC_VDSO_HAS_TIME
TEST(LlvmLibcOSUtilVDSOTest, Time) {
using FuncTy = time_t (*)(time_t *);
- auto func = reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::Time));
+ vdso::Symbol symbol{vdso::VDSOSym::Time};
+ auto func = symbol.get<FuncTy>();
if (func == nullptr)
return;
time_t a, b;
@@ -49,15 +49,17 @@ TEST(LlvmLibcOSUtilVDSOTest, Time) {
EXPECT_GT(func(&b), static_cast<time_t>(0));
EXPECT_GE(b, a);
}
-#endif
-#ifdef LIBC_VDSO_HAS_CLOCK_GETTIME
TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime) {
using FuncTy = int (*)(clockid_t, timespec *);
- auto func =
- reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetTime));
+ vdso::Symbol symbol{vdso::VDSOSym::ClockGetTime};
+ auto func = symbol.get<FuncTy>();
+#ifdef LIBC_TARGET_ARCH_IS_X86
+ ASSERT_NE(func, static_cast<FuncTy>(nullptr));
+#else
if (func == nullptr)
return;
+#endif
timespec a, b;
EXPECT_EQ(func(CLOCK_MONOTONIC, &a), 0);
EXPECT_EQ(func(CLOCK_MONOTONIC, &b), 0);
@@ -67,13 +69,11 @@ TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime) {
EXPECT_LT(a.tv_sec, b.tv_sec);
}
}
-#endif
-#ifdef LIBC_VDSO_HAS_CLOCK_GETTIME64
TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime64) {
using FuncTy = int (*)(clockid_t, __kernel_timespec *);
- auto func =
- reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetTime64));
+ vdso::Symbol symbol{vdso::VDSOSym::ClockGetTime64};
+ auto func = symbol.get<FuncTy>();
if (func == nullptr)
return;
// See kernel API at
@@ -87,27 +87,24 @@ TEST(LlvmLibcOSUtilVDSOTest, ClockGetTime64) {
EXPECT_LT(a.tv_sec, b.tv_sec);
}
}
-#endif
-#ifdef LIBC_VDSO_HAS_CLOCK_GETRES
TEST(LlvmLibcOSUtilVDSOTest, ClockGetRes) {
using FuncTy = int (*)(clockid_t, timespec *);
- auto func =
- reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::ClockGetRes));
+ vdso::Symbol symbol{vdso::VDSOSym::ClockGetRes};
+ auto func = symbol.get<FuncTy>();
if (func == nullptr)
return;
timespec res{};
EXPECT_EQ(func(CLOCK_MONOTONIC, &res), 0);
EXPECT_TRUE(res.tv_sec > 0 || res.tv_nsec > 0);
}
-#endif
-#ifdef LIBC_VDSO_HAS_GETCPU
TEST(LlvmLibcOSUtilVDSOTest, GetCpu) {
// The kernel system call has a third argument, which should be passed as
// nullptr.
using FuncTy = int (*)(int *, int *, void *);
- auto func = reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::GetCpu));
+ vdso::Symbol symbol{vdso::VDSOSym::GetCpu};
+ auto func = symbol.get<FuncTy>();
if (func == nullptr)
return;
int cpu = -1, node = -1;
@@ -115,39 +112,23 @@ TEST(LlvmLibcOSUtilVDSOTest, GetCpu) {
EXPECT_GE(cpu, 0);
EXPECT_GE(node, 0);
}
-#endif
-
-// TODO: apply this change to __restore_rt in
-// libc/src/signal/linux/sigaction.cpp
-// Caution: user application typically should not play with the trampoline.
-// Let the libc handle it.
-[[gnu::noreturn]] static void __restore_rt() {
-#ifdef LIBC_VDSO_HAS_RT_SIGRETURN
- using FuncTy = void (*)();
- auto func =
- reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::RTSigReturn));
- if (func) {
- func();
- __builtin_trap();
- }
-#endif
- LIBC_NAMESPACE::syscall_impl<long>(SYS_rt_sigreturn);
- __builtin_trap();
-}
static bool flag = false;
-
static void sigprof_handler [[gnu::used]] (int) { flag = true; }
TEST(LlvmLibcOSUtilVDSOTest, RtSigReturn) {
using namespace testing::ErrnoSetterMatcher;
// must use struct since there is a function of the same name in the same
// scope.
- struct sigaction sa{};
- struct sigaction old_sa{};
+ struct sigaction sa {};
+ struct sigaction old_sa {};
sa.sa_handler = sigprof_handler;
sa.sa_flags = SA_RESTORER;
- sa.sa_restorer = __restore_rt;
+ vdso::Symbol symbol{vdso::VDSOSym::RTSigReturn};
+ auto func = symbol.get<decltype(sa.sa_restorer)>();
+ if (func == nullptr)
+ return;
+ sa.sa_restorer = func;
ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGPROF, &sa, &old_sa), Succeeds());
raise(SIGPROF);
ASSERT_TRUE(flag);
@@ -155,11 +136,10 @@ TEST(LlvmLibcOSUtilVDSOTest, RtSigReturn) {
ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGPROF, &old_sa, nullptr), Succeeds());
}
-#ifdef LIBC_VDSO_HAS_FLUSH_ICACHE
TEST(LlvmLibcOSUtilVDSOTest, FlushICache) {
using FuncTy = void (*)(void *, void *, unsigned long);
- auto func =
- reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::FlushICache));
+ vdso::Symbol symbol{vdso::VDSOSym::FlushICache};
+ auto func = symbol.get<FuncTy>();
if (func == nullptr)
return;
char buf[512];
@@ -169,11 +149,8 @@ TEST(LlvmLibcOSUtilVDSOTest, FlushICache) {
func(buf, buf + sizeof(buf), 0);
func(buf, buf + sizeof(buf), 1);
}
-#endif
// https://docs.kernel.org/6.5/riscv/hwprobe.html
-
-#ifdef LIBC_VDSO_HAS_RISCV_HWPROBE
TEST(LlvmLibcOSUtilVDSOTest, RiscvHwProbe) {
using namespace testing::ErrnoSetterMatcher;
struct riscv_hwprobe {
@@ -182,8 +159,8 @@ TEST(LlvmLibcOSUtilVDSOTest, RiscvHwProbe) {
};
using FuncTy =
long (*)(riscv_hwprobe *, size_t, size_t, struct cpu_set_t *, unsigned);
- auto func =
- reinterpret_cast<FuncTy>(vdso::get_symbol(vdso::VDSOSym::RiscvHwProbe));
+ vdso::Symbol symbol{vdso::VDSOSym::RiscvHwProbe};
+ auto func = symbol.get<FuncTy>();
if (func == nullptr)
return;
// If a key is unknown to the kernel, its key field will be cleared to -1, and
@@ -200,6 +177,5 @@ TEST(LlvmLibcOSUtilVDSOTest, RiscvHwProbe) {
EXPECT_EQ(probe.value, static_cast<decltype(probe.value)>(0));
}
}
-#endif
} // namespace LIBC_NAMESPACE
More information about the libc-commits
mailing list