19 #include "absl/debugging/internal/vdso_support.h"
21 #ifdef ABSL_HAVE_VDSO_SUPPORT // defined in vdso_support.h
23 #if !defined(__has_include)
24 #define __has_include(header) 0
29 #if __has_include(<syscall.h>)
31 #elif __has_include(<sys/syscall.h>)
32 #include <sys/syscall.h>
36 #if !defined(__UCLIBC__) && defined(__GLIBC__) && \
37 (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16))
38 #define ABSL_HAVE_GETAUXVAL
41 #ifdef ABSL_HAVE_GETAUXVAL
45 #include "absl/base/dynamic_annotations.h"
46 #include "absl/base/internal/raw_logging.h"
47 #include "absl/base/port.h"
49 #ifndef AT_SYSINFO_EHDR
50 #define AT_SYSINFO_EHDR 33 // for crosstoolv10
53 #if defined(__NetBSD__)
54 using Elf32_auxv_t = Aux32Info;
55 using Elf64_auxv_t = Aux64Info;
57 #if defined(__FreeBSD__)
58 #if defined(__ELF_WORD_SIZE) && __ELF_WORD_SIZE == 64
59 using Elf64_auxv_t = Elf64_Auxinfo;
61 using Elf32_auxv_t = Elf32_Auxinfo;
66 namespace debugging_internal {
69 std::atomic<const void *> VDSOSupport::vdso_base_(
70 debugging_internal::ElfMemImage::kInvalidBase);
72 ABSL_CONST_INIT std::atomic<VDSOSupport::GetCpuFn> VDSOSupport::getcpu_fn_(
75 VDSOSupport::VDSOSupport()
78 : image_(vdso_base_.
load(
std::memory_order_relaxed) ==
79 debugging_internal::ElfMemImage::kInvalidBase
81 : vdso_base_.
load(
std::memory_order_relaxed)) {}
93 const auto kInvalidBase = debugging_internal::ElfMemImage::kInvalidBase;
94 #ifdef ABSL_HAVE_GETAUXVAL
95 if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
97 const void *
const sysinfo_ehdr =
98 reinterpret_cast<const void *
>(getauxval(AT_SYSINFO_EHDR));
100 vdso_base_.store(sysinfo_ehdr, std::memory_order_relaxed);
103 #endif // ABSL_HAVE_GETAUXVAL
104 if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
105 int fd =
open(
"/proc/self/auxv", O_RDONLY);
108 vdso_base_.store(
nullptr, std::memory_order_relaxed);
109 getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);
113 while (
read(fd, &aux,
sizeof(aux)) ==
sizeof(aux)) {
114 if (aux.a_type == AT_SYSINFO_EHDR) {
115 #if defined(__NetBSD__)
116 vdso_base_.store(
reinterpret_cast<void *
>(aux.a_v),
117 std::memory_order_relaxed);
119 vdso_base_.store(
reinterpret_cast<void *
>(aux.a_un.a_val),
120 std::memory_order_relaxed);
126 if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
128 vdso_base_.store(
nullptr, std::memory_order_relaxed);
131 GetCpuFn
fn = &GetCPUViaSyscall;
132 if (vdso_base_.load(std::memory_order_relaxed)) {
135 if (vdso.LookupSymbol(
"__vdso_getcpu",
"LINUX_2.6",
STT_FUNC, &info)) {
136 fn =
reinterpret_cast<GetCpuFn
>(
const_cast<void *
>(info.address));
141 getcpu_fn_.store(
fn, std::memory_order_relaxed);
142 return vdso_base_.load(std::memory_order_relaxed);
145 const void *VDSOSupport::SetBase(
const void *
base) {
148 const void *old_base = vdso_base_.load(std::memory_order_relaxed);
149 vdso_base_.store(
base, std::memory_order_relaxed);
152 getcpu_fn_.store(&InitAndGetCPU, std::memory_order_relaxed);
156 bool VDSOSupport::LookupSymbol(
const char *
name,
159 SymbolInfo *info)
const {
163 bool VDSOSupport::LookupSymbolByAddress(
const void *address,
164 SymbolInfo *info_out)
const {
165 return image_.LookupSymbolByAddress(address, info_out);
169 long VDSOSupport::GetCPUViaSyscall(
unsigned *cpu,
172 return syscall(SYS_getcpu, cpu,
nullptr,
nullptr);
175 static_cast<void>(cpu);
182 long VDSOSupport::InitAndGetCPU(
unsigned *cpu,
185 GetCpuFn
fn = getcpu_fn_.load(std::memory_order_relaxed);
187 return (*
fn)(cpu,
x,
y);
196 int ret_code = (*VDSOSupport::getcpu_fn_)(&cpu,
nullptr,
nullptr);
197 return ret_code == 0 ? cpu : ret_code;
204 #endif // ABSL_HAVE_VDSO_SUPPORT