From dedb4eec6cf0addc26cc27b67c270aa5a478fcc5 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 24 Oct 2017 10:37:49 -0700 Subject: Changes imported from Abseil "staging" branch: - fbff677ef850865ea67ed6771a8ed348be181e8e Modify sysinfo.cc to support GetTID on Akaros. by Abseil Team - f1c2929e08a3d4181e08cb5014c4a569306fd922 Two functions that did not refer to their arguments unles... by Abseil Team - ee43cc3bfdb4d84d40eee31fb25ecdc1aa060f47 Support Akaros (https://akaros.org) in the ABSL spinlock_... by Abseil Team - 6869c8c5253126459d6c7f0aa708d8612c8e5963 Make sure vdso_base_ is constant-intialized. by Abseil Team - d54e0366efc8d44cd5da5fd157734da966dc45e8 Add missing include for assert used by ABSL_ASSERT. by Derek Mauro - a5139775f3917bb5201e7fc838135766daa05b8d When building against GLIBC-2.16 or newer, use getauxval(... by Abseil Team GitOrigin-RevId: fbff677ef850865ea67ed6771a8ed348be181e8e Change-Id: Ie3549f6ef054783dd104304d2faf8d9800c16b83 --- absl/debugging/internal/vdso_support.cc | 73 ++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 29 deletions(-) (limited to 'absl/debugging/internal/vdso_support.cc') diff --git a/absl/debugging/internal/vdso_support.cc b/absl/debugging/internal/vdso_support.cc index 5026e1c1..815e702f 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 #include #include #include +#if __GLIBC_PREREQ(2, 16) // GLIBC-2.16 implements getauxval. +#include +#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 VDSOSupport::vdso_base_( debug_internal::ElfMemImage::kInvalidBase); + std::atomic 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(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(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(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(cpu); // Avoid an unused argument compiler warning. errno = ENOSYS; return -1; #endif -- cgit v1.2.3