about summary refs log tree commit diff
path: root/absl/debugging/internal/vdso_support.cc
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2017-10-24T17·37-0700
committerJon Cohen <cohenjon@google.com>2017-10-24T18·52-0400
commitdedb4eec6cf0addc26cc27b67c270aa5a478fcc5 (patch)
tree18e2a5e11cdf70b2c11b35cb7533c57ba628c015 /absl/debugging/internal/vdso_support.cc
parent5fcbe86e7ba65b6457d98764aa511c4f05c9435b (diff)
Changes imported from Abseil "staging" branch:
  - fbff677ef850865ea67ed6771a8ed348be181e8e Modify sysinfo.cc to support GetTID on Akaros. by Abseil Team <absl-team@google.com>
  - f1c2929e08a3d4181e08cb5014c4a569306fd922 Two functions that did not refer to their arguments unles... by Abseil Team <absl-team@google.com>
  - ee43cc3bfdb4d84d40eee31fb25ecdc1aa060f47 Support Akaros (https://akaros.org) in the ABSL spinlock_... by Abseil Team <absl-team@google.com>
  - 6869c8c5253126459d6c7f0aa708d8612c8e5963 Make sure vdso_base_ is constant-intialized. by Abseil Team <absl-team@google.com>
  - d54e0366efc8d44cd5da5fd157734da966dc45e8 Add missing include for assert used by ABSL_ASSERT. by Derek Mauro <dmauro@google.com>
  - a5139775f3917bb5201e7fc838135766daa05b8d When building against GLIBC-2.16 or newer, use getauxval(... by Abseil Team <absl-team@google.com>

GitOrigin-RevId: fbff677ef850865ea67ed6771a8ed348be181e8e
Change-Id: Ie3549f6ef054783dd104304d2faf8d9800c16b83
Diffstat (limited to 'absl/debugging/internal/vdso_support.cc')
-rw-r--r--absl/debugging/internal/vdso_support.cc73
1 files changed, 44 insertions, 29 deletions
diff --git a/absl/debugging/internal/vdso_support.cc b/absl/debugging/internal/vdso_support.cc
index 5026e1c1a9..815e702f56 100644
--- a/absl/debugging/internal/vdso_support.cc
+++ b/absl/debugging/internal/vdso_support.cc
@@ -20,10 +20,15 @@
 
 #ifdef ABSL_HAVE_VDSO_SUPPORT     // defined in vdso_support.h
 
+#include <errno.h>
 #include <fcntl.h>
 #include <sys/syscall.h>
 #include <unistd.h>
 
+#if __GLIBC_PREREQ(2, 16)  // GLIBC-2.16 implements getauxval.
+#include <sys/auxv.h>
+#endif
+
 #include "absl/base/dynamic_annotations.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/port.h"
@@ -35,8 +40,10 @@
 namespace absl {
 namespace debug_internal {
 
+ABSL_CONST_INIT
 std::atomic<const void *> VDSOSupport::vdso_base_(
     debug_internal::ElfMemImage::kInvalidBase);
+
 std::atomic<VDSOSupport::GetCpuFn> VDSOSupport::getcpu_fn_(&InitAndGetCPU);
 VDSOSupport::VDSOSupport()
     // If vdso_base_ is still set to kInvalidBase, we got here
@@ -56,37 +63,44 @@ VDSOSupport::VDSOSupport()
 // Finally, even if there is a race here, it is harmless, because
 // the operation should be idempotent.
 const void *VDSOSupport::Init() {
-  if (vdso_base_.load(std::memory_order_relaxed) ==
-      debug_internal::ElfMemImage::kInvalidBase) {
-    {
-      // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
-      // on stack, and so glibc works as if VDSO was not present.
-      // But going directly to kernel via /proc/self/auxv below bypasses
-      // Valgrind zapping. So we check for Valgrind separately.
-      if (RunningOnValgrind()) {
-        vdso_base_.store(nullptr, std::memory_order_relaxed);
-        getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);
-        return nullptr;
-      }
-      int fd = open("/proc/self/auxv", O_RDONLY);
-      if (fd == -1) {
-        // Kernel too old to have a VDSO.
-        vdso_base_.store(nullptr, std::memory_order_relaxed);
-        getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);
-        return nullptr;
-      }
-      ElfW(auxv_t) aux;
-      while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) {
-        if (aux.a_type == AT_SYSINFO_EHDR) {
-          vdso_base_.store(reinterpret_cast<void *>(aux.a_un.a_val),
-                           std::memory_order_relaxed);
-          break;
-        }
+  const auto kInvalidBase = debug_internal::ElfMemImage::kInvalidBase;
+#if __GLIBC_PREREQ(2, 16)
+  if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
+    errno = 0;
+    const void *const sysinfo_ehdr =
+        reinterpret_cast<const void *>(getauxval(AT_SYSINFO_EHDR));
+    if (errno == 0) {
+      vdso_base_.store(sysinfo_ehdr, std::memory_order_relaxed);
+    }
+  }
+#endif  // __GLIBC_PREREQ(2, 16)
+  if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
+    // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
+    // on stack, and so glibc works as if VDSO was not present.
+    // But going directly to kernel via /proc/self/auxv below bypasses
+    // Valgrind zapping. So we check for Valgrind separately.
+    if (RunningOnValgrind()) {
+      vdso_base_.store(nullptr, std::memory_order_relaxed);
+      getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);
+      return nullptr;
+    }
+    int fd = open("/proc/self/auxv", O_RDONLY);
+    if (fd == -1) {
+      // Kernel too old to have a VDSO.
+      vdso_base_.store(nullptr, std::memory_order_relaxed);
+      getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);
+      return nullptr;
+    }
+    ElfW(auxv_t) aux;
+    while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) {
+      if (aux.a_type == AT_SYSINFO_EHDR) {
+        vdso_base_.store(reinterpret_cast<void *>(aux.a_un.a_val),
+                         std::memory_order_relaxed);
+        break;
       }
-      close(fd);
     }
-    if (vdso_base_.load(std::memory_order_relaxed) ==
-        debug_internal::ElfMemImage::kInvalidBase) {
+    close(fd);
+    if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
       // Didn't find AT_SYSINFO_EHDR in auxv[].
       vdso_base_.store(nullptr, std::memory_order_relaxed);
     }
@@ -135,6 +149,7 @@ long VDSOSupport::GetCPUViaSyscall(unsigned *cpu,  // NOLINT(runtime/int)
   return syscall(SYS_getcpu, cpu, nullptr, nullptr);
 #else
   // x86_64 never implemented sys_getcpu(), except as a VDSO call.
+  static_cast<void>(cpu);  // Avoid an unused argument compiler warning.
   errno = ENOSYS;
   return -1;
 #endif