[libc-commits] [libc] [libc] implement vdso (PR #91572)

Nick Desaulniers via libc-commits libc-commits at lists.llvm.org
Tue May 21 14:47:20 PDT 2024


================
@@ -0,0 +1,205 @@
+//===------------- 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 <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 {
+
+// 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 {
+
+namespace {
+// 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;
+} // namespace
+
+void *get_symbol(VDSOSym sym) {
+  // if sym is invalid, return nullptr
+  const size_t index = static_cast<size_t>(sym);
----------------
nickdesaulniers wrote:

```suggestion
  const auto index = static_cast<size_t>(sym);
```

https://github.com/llvm/llvm-project/pull/91572


More information about the libc-commits mailing list