|
||||
File indexing completed on 2025-01-18 09:27:16
0001 // 0002 // Copyright 2017 The Abseil Authors. 0003 // 0004 // Licensed under the Apache License, Version 2.0 (the "License"); 0005 // you may not use this file except in compliance with the License. 0006 // You may obtain a copy of the License at 0007 // 0008 // https://www.apache.org/licenses/LICENSE-2.0 0009 // 0010 // Unless required by applicable law or agreed to in writing, software 0011 // distributed under the License is distributed on an "AS IS" BASIS, 0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0013 // See the License for the specific language governing permissions and 0014 // limitations under the License. 0015 // 0016 0017 // Allow dynamic symbol lookup in the kernel VDSO page. 0018 // 0019 // VDSO stands for "Virtual Dynamic Shared Object" -- a page of 0020 // executable code, which looks like a shared library, but doesn't 0021 // necessarily exist anywhere on disk, and which gets mmap()ed into 0022 // every process by kernels which support VDSO, such as 2.6.x for 32-bit 0023 // executables, and 2.6.24 and above for 64-bit executables. 0024 // 0025 // More details could be found here: 0026 // http://www.trilithium.com/johan/2005/08/linux-gate/ 0027 // 0028 // VDSOSupport -- a class representing kernel VDSO (if present). 0029 // 0030 // Example usage: 0031 // VDSOSupport vdso; 0032 // VDSOSupport::SymbolInfo info; 0033 // typedef (*FN)(unsigned *, void *, void *); 0034 // FN fn = nullptr; 0035 // if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { 0036 // fn = reinterpret_cast<FN>(info.address); 0037 // } 0038 0039 #ifndef ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_ 0040 #define ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_ 0041 0042 #include <atomic> 0043 0044 #include "absl/base/attributes.h" 0045 #include "absl/debugging/internal/elf_mem_image.h" 0046 0047 #ifdef ABSL_HAVE_ELF_MEM_IMAGE 0048 0049 #ifdef ABSL_HAVE_VDSO_SUPPORT 0050 #error ABSL_HAVE_VDSO_SUPPORT cannot be directly set 0051 #else 0052 #define ABSL_HAVE_VDSO_SUPPORT 1 0053 #endif 0054 0055 namespace absl { 0056 ABSL_NAMESPACE_BEGIN 0057 namespace debugging_internal { 0058 0059 // NOTE: this class may be used from within tcmalloc, and can not 0060 // use any memory allocation routines. 0061 class VDSOSupport { 0062 public: 0063 VDSOSupport(); 0064 0065 typedef ElfMemImage::SymbolInfo SymbolInfo; 0066 typedef ElfMemImage::SymbolIterator SymbolIterator; 0067 0068 // On PowerPC64 VDSO symbols can either be of type STT_FUNC or STT_NOTYPE 0069 // depending on how the kernel is built. The kernel is normally built with 0070 // STT_NOTYPE type VDSO symbols. Let's make things simpler first by using a 0071 // compile-time constant. 0072 #ifdef __powerpc64__ 0073 enum { kVDSOSymbolType = STT_NOTYPE }; 0074 #else 0075 enum { kVDSOSymbolType = STT_FUNC }; 0076 #endif 0077 0078 // Answers whether we have a vdso at all. 0079 bool IsPresent() const { return image_.IsPresent(); } 0080 0081 // Allow to iterate over all VDSO symbols. 0082 SymbolIterator begin() const { return image_.begin(); } 0083 SymbolIterator end() const { return image_.end(); } 0084 0085 // Look up versioned dynamic symbol in the kernel VDSO. 0086 // Returns false if VDSO is not present, or doesn't contain given 0087 // symbol/version/type combination. 0088 // If info_out != nullptr, additional details are filled in. 0089 bool LookupSymbol(const char *name, const char *version, 0090 int symbol_type, SymbolInfo *info_out) const; 0091 0092 // Find info about symbol (if any) which overlaps given address. 0093 // Returns true if symbol was found; false if VDSO isn't present 0094 // or doesn't have a symbol overlapping given address. 0095 // If info_out != nullptr, additional details are filled in. 0096 bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const; 0097 0098 // Used only for testing. Replace real VDSO base with a mock. 0099 // Returns previous value of vdso_base_. After you are done testing, 0100 // you are expected to call SetBase() with previous value, in order to 0101 // reset state to the way it was. 0102 const void *SetBase(const void *s); 0103 0104 // Computes vdso_base_ and returns it. Should be called as early as 0105 // possible; before any thread creation, chroot or setuid. 0106 static const void *Init(); 0107 0108 private: 0109 // image_ represents VDSO ELF image in memory. 0110 // image_.ehdr_ == nullptr implies there is no VDSO. 0111 ElfMemImage image_; 0112 0113 // Cached value of auxv AT_SYSINFO_EHDR, computed once. 0114 // This is a tri-state: 0115 // kInvalidBase => value hasn't been determined yet. 0116 // 0 => there is no VDSO. 0117 // else => vma of VDSO Elf{32,64}_Ehdr. 0118 // 0119 // When testing with mock VDSO, low bit is set. 0120 // The low bit is always available because vdso_base_ is 0121 // page-aligned. 0122 static std::atomic<const void *> vdso_base_; 0123 0124 // NOLINT on 'long' because these routines mimic kernel api. 0125 // The 'cache' parameter may be used by some versions of the kernel, 0126 // and should be nullptr or point to a static buffer containing at 0127 // least two 'long's. 0128 static long InitAndGetCPU(unsigned *cpu, void *cache, // NOLINT 'long'. 0129 void *unused); 0130 static long GetCPUViaSyscall(unsigned *cpu, void *cache, // NOLINT 'long'. 0131 void *unused); 0132 typedef long (*GetCpuFn)(unsigned *cpu, void *cache, // NOLINT 'long'. 0133 void *unused); 0134 0135 // This function pointer may point to InitAndGetCPU, 0136 // GetCPUViaSyscall, or __vdso_getcpu at different stages of initialization. 0137 ABSL_CONST_INIT static std::atomic<GetCpuFn> getcpu_fn_; 0138 0139 friend int GetCPU(void); // Needs access to getcpu_fn_. 0140 0141 VDSOSupport(const VDSOSupport&) = delete; 0142 VDSOSupport& operator=(const VDSOSupport&) = delete; 0143 }; 0144 0145 // Same as sched_getcpu() on later glibc versions. 0146 // Return current CPU, using (fast) __vdso_getcpu@LINUX_2.6 if present, 0147 // otherwise use syscall(SYS_getcpu,...). 0148 // May return -1 with errno == ENOSYS if the kernel doesn't 0149 // support SYS_getcpu. 0150 int GetCPU(); 0151 0152 } // namespace debugging_internal 0153 ABSL_NAMESPACE_END 0154 } // namespace absl 0155 0156 #endif // ABSL_HAVE_ELF_MEM_IMAGE 0157 0158 #endif // ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |