aboutsummaryrefslogtreecommitdiffhomepage
path: root/absl/debugging/internal/vdso_support.cc
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2017-10-24 10:37:49 -0700
committerGravatar Jon Cohen <cohenjon@google.com>2017-10-24 14:52:11 -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 5026e1c..815e702 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