Index: third_party/tcmalloc/chromium/src/base/elf_mem_image.cc |
diff --git a/third_party/tcmalloc/chromium/src/base/vdso_support.cc b/third_party/tcmalloc/chromium/src/base/elf_mem_image.cc |
similarity index 67% |
copy from third_party/tcmalloc/chromium/src/base/vdso_support.cc |
copy to third_party/tcmalloc/chromium/src/base/elf_mem_image.cc |
index 444be26aa56f0f683ff641f1cc8f8c239b0d20a0..2949343700d57761480da81cfaf92847062768bd 100644 |
--- a/third_party/tcmalloc/chromium/src/base/vdso_support.cc |
+++ b/third_party/tcmalloc/chromium/src/base/elf_mem_image.cc |
@@ -1,10 +1,10 @@ |
// Copyright (c) 2008, Google Inc. |
// All rights reserved. |
-// |
+// |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
// met: |
-// |
+// |
// * Redistributions of source code must retain the above copyright |
// notice, this list of conditions and the following disclaimer. |
// * Redistributions in binary form must reproduce the above |
@@ -14,7 +14,7 @@ |
// * Neither the name of Google Inc. nor the names of its |
// contributors may be used to endorse or promote products derived from |
// this software without specific prior written permission. |
-// |
+// |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
@@ -30,29 +30,15 @@ |
// --- |
// Author: Paul Pluzhnikov |
// |
-// Allow dynamic symbol lookup in the kernel VDSO page. |
+// Allow dynamic symbol lookup in an in-memory Elf image. |
// |
-// VDSOSupport -- a class representing kernel VDSO (if present). |
-// |
- |
-#include "base/vdso_support.h" |
-#ifdef HAVE_VDSO_SUPPORT // defined in vdso_support.h |
+#include "base/elf_mem_image.h" |
-#include <fcntl.h> |
-#include <stddef.h> // for std::ptrdiff_t |
+#ifdef HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h |
-#include "base/atomicops.h" // for MemoryBarrier |
+#include <stddef.h> // for size_t, ptrdiff_t |
#include "base/logging.h" |
-#include "base/linux_syscall_support.h" |
-#include "base/dynamic_annotations.h" |
-#include "base/basictypes.h" // for COMPILE_ASSERT |
- |
-using base::subtle::MemoryBarrier; |
- |
-#ifndef AT_SYSINFO_EHDR |
-#define AT_SYSINFO_EHDR 33 |
-#endif |
// From binutils/include/elf/common.h (this doesn't appear to be documented |
// anywhere else). |
@@ -121,18 +107,15 @@ const T* GetTableElement(const ElfW(Ehdr) *ehdr, |
} |
} // namespace |
-const void *const VDSOSupport::kInvalidBase = |
+const void *const ElfMemImage::kInvalidBase = |
reinterpret_cast<const void *>(~0L); |
-const void *VDSOSupport::vdso_base_ = kInvalidBase; |
-VDSOSupport::GetCpuFn VDSOSupport::getcpu_fn_ = &InitAndGetCPU; |
- |
-VDSOSupport::ElfMemImage::ElfMemImage(const void *base) { |
+ElfMemImage::ElfMemImage(const void *base) { |
CHECK(base != kInvalidBase); |
Init(base); |
} |
-int VDSOSupport::ElfMemImage::GetNumSymbols() const { |
+int ElfMemImage::GetNumSymbols() const { |
if (!hash_) { |
return 0; |
} |
@@ -140,17 +123,17 @@ int VDSOSupport::ElfMemImage::GetNumSymbols() const { |
return hash_[1]; |
} |
-const ElfW(Sym) *VDSOSupport::ElfMemImage::GetDynsym(int index) const { |
+const ElfW(Sym) *ElfMemImage::GetDynsym(int index) const { |
CHECK_LT(index, GetNumSymbols()); |
return dynsym_ + index; |
} |
-const ElfW(Versym) *VDSOSupport::ElfMemImage::GetVersym(int index) const { |
+const ElfW(Versym) *ElfMemImage::GetVersym(int index) const { |
CHECK_LT(index, GetNumSymbols()); |
return versym_ + index; |
} |
-const ElfW(Phdr) *VDSOSupport::ElfMemImage::GetPhdr(int index) const { |
+const ElfW(Phdr) *ElfMemImage::GetPhdr(int index) const { |
CHECK_LT(index, ehdr_->e_phnum); |
return GetTableElement<ElfW(Phdr)>(ehdr_, |
ehdr_->e_phoff, |
@@ -158,12 +141,12 @@ const ElfW(Phdr) *VDSOSupport::ElfMemImage::GetPhdr(int index) const { |
index); |
} |
-const char *VDSOSupport::ElfMemImage::GetDynstr(ElfW(Word) offset) const { |
+const char *ElfMemImage::GetDynstr(ElfW(Word) offset) const { |
CHECK_LT(offset, strsize_); |
return dynstr_ + offset; |
} |
-const void *VDSOSupport::ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const { |
+const void *ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const { |
if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) { |
// Symbol corresponds to "special" (e.g. SHN_ABS) section. |
return reinterpret_cast<const void *>(sym->st_value); |
@@ -172,7 +155,7 @@ const void *VDSOSupport::ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const { |
return GetTableElement<char>(ehdr_, 0, 1, sym->st_value) - link_base_; |
} |
-const ElfW(Verdef) *VDSOSupport::ElfMemImage::GetVerdef(int index) const { |
+const ElfW(Verdef) *ElfMemImage::GetVerdef(int index) const { |
CHECK_LE(index, verdefnum_); |
const ElfW(Verdef) *version_definition = verdef_; |
while (version_definition->vd_ndx < index && version_definition->vd_next) { |
@@ -185,17 +168,17 @@ const ElfW(Verdef) *VDSOSupport::ElfMemImage::GetVerdef(int index) const { |
return version_definition->vd_ndx == index ? version_definition : NULL; |
} |
-const ElfW(Verdaux) *VDSOSupport::ElfMemImage::GetVerdefAux( |
+const ElfW(Verdaux) *ElfMemImage::GetVerdefAux( |
const ElfW(Verdef) *verdef) const { |
return reinterpret_cast<const ElfW(Verdaux) *>(verdef+1); |
} |
-const char *VDSOSupport::ElfMemImage::GetVerstr(ElfW(Word) offset) const { |
+const char *ElfMemImage::GetVerstr(ElfW(Word) offset) const { |
CHECK_LT(offset, strsize_); |
return dynstr_ + offset; |
} |
-void VDSOSupport::ElfMemImage::Init(const void *base) { |
+void ElfMemImage::Init(const void *base) { |
ehdr_ = NULL; |
dynsym_ = NULL; |
dynstr_ = NULL; |
@@ -266,7 +249,7 @@ void VDSOSupport::ElfMemImage::Init(const void *base) { |
Init(0); |
return; |
} |
- std::ptrdiff_t relocation = |
+ ptrdiff_t relocation = |
base_as_char - reinterpret_cast<const char *>(link_base_); |
ElfW(Dyn) *dynamic_entry = |
reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr + |
@@ -329,81 +312,7 @@ void VDSOSupport::ElfMemImage::Init(const void *base) { |
} |
} |
-VDSOSupport::VDSOSupport() |
- // If vdso_base_ is still set to kInvalidBase, we got here |
- // before VDSOSupport::Init has been called. Call it now. |
- : image_(vdso_base_ == kInvalidBase ? Init() : vdso_base_) { |
-} |
- |
-// NOTE: we can't use GoogleOnceInit() below, because we can be |
-// called by tcmalloc, and none of the *once* stuff may be functional yet. |
-// |
-// In addition, we hope that the VDSOSupportHelper constructor |
-// causes this code to run before there are any threads, and before |
-// InitGoogle() has executed any chroot or setuid calls. |
-// |
-// Finally, even if there is a race here, it is harmless, because |
-// the operation should be idempotent. |
-const void *VDSOSupport::Init() { |
- if (vdso_base_ == 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_ = NULL; |
- getcpu_fn_ = &GetCPUViaSyscall; |
- return NULL; |
- } |
- int fd = open("/proc/self/auxv", O_RDONLY); |
- if (fd == -1) { |
- // Kernel too old to have a VDSO. |
- vdso_base_ = NULL; |
- getcpu_fn_ = &GetCPUViaSyscall; |
- return NULL; |
- } |
- ElfW(auxv_t) aux; |
- while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) { |
- if (aux.a_type == AT_SYSINFO_EHDR) { |
- COMPILE_ASSERT(sizeof(vdso_base_) == sizeof(aux.a_un.a_val), |
- unexpected_sizeof_pointer_NE_sizeof_a_val); |
- vdso_base_ = reinterpret_cast<void *>(aux.a_un.a_val); |
- break; |
- } |
- } |
- close(fd); |
- if (vdso_base_ == kInvalidBase) { |
- // Didn't find AT_SYSINFO_EHDR in auxv[]. |
- vdso_base_ = NULL; |
- } |
- } |
- GetCpuFn fn = &GetCPUViaSyscall; // default if VDSO not present. |
- if (vdso_base_) { |
- VDSOSupport vdso; |
- SymbolInfo info; |
- if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { |
- // Casting from an int to a pointer is not legal C++. To emphasize |
- // this, we use a C-style cast rather than a C++-style cast. |
- fn = (GetCpuFn)(info.address); |
- } |
- } |
- // Subtle: this code runs outside of any locks; prevent compiler |
- // from assigning to getcpu_fn_ more than once. |
- base::subtle::MemoryBarrier(); |
- getcpu_fn_ = fn; |
- return vdso_base_; |
-} |
- |
-const void *VDSOSupport::SetBase(const void *base) { |
- const void *old_base = vdso_base_; |
- vdso_base_ = base; |
- image_.Init(base); |
- // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO. |
- getcpu_fn_ = &InitAndGetCPU; |
- return old_base; |
-} |
- |
-bool VDSOSupport::LookupSymbol(const char *name, |
+bool ElfMemImage::LookupSymbol(const char *name, |
const char *version, |
int type, |
SymbolInfo *info) const { |
@@ -419,7 +328,7 @@ bool VDSOSupport::LookupSymbol(const char *name, |
return false; |
} |
-bool VDSOSupport::LookupSymbolByAddress(const void *address, |
+bool ElfMemImage::LookupSymbolByAddress(const void *address, |
SymbolInfo *info_out) const { |
for (SymbolIterator it = begin(); it != end(); ++it) { |
const char *const symbol_start = |
@@ -445,42 +354,42 @@ bool VDSOSupport::LookupSymbolByAddress(const void *address, |
return false; |
} |
-VDSOSupport::SymbolIterator::SymbolIterator(const void *const image, int index) |
+ElfMemImage::SymbolIterator::SymbolIterator(const void *const image, int index) |
: index_(index), image_(image) { |
} |
-const VDSOSupport::SymbolInfo *VDSOSupport::SymbolIterator::operator->() const { |
+const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->() const { |
return &info_; |
} |
-const VDSOSupport::SymbolInfo& VDSOSupport::SymbolIterator::operator*() const { |
+const ElfMemImage::SymbolInfo& ElfMemImage::SymbolIterator::operator*() const { |
return info_; |
} |
-bool VDSOSupport::SymbolIterator::operator==(const SymbolIterator &rhs) const { |
+bool ElfMemImage::SymbolIterator::operator==(const SymbolIterator &rhs) const { |
return this->image_ == rhs.image_ && this->index_ == rhs.index_; |
} |
-bool VDSOSupport::SymbolIterator::operator!=(const SymbolIterator &rhs) const { |
+bool ElfMemImage::SymbolIterator::operator!=(const SymbolIterator &rhs) const { |
return !(*this == rhs); |
} |
-VDSOSupport::SymbolIterator &VDSOSupport::SymbolIterator::operator++() { |
+ElfMemImage::SymbolIterator &ElfMemImage::SymbolIterator::operator++() { |
this->Update(1); |
return *this; |
} |
-VDSOSupport::SymbolIterator VDSOSupport::begin() const { |
- SymbolIterator it(&image_, 0); |
+ElfMemImage::SymbolIterator ElfMemImage::begin() const { |
+ SymbolIterator it(this, 0); |
it.Update(0); |
return it; |
} |
-VDSOSupport::SymbolIterator VDSOSupport::end() const { |
- return SymbolIterator(&image_, image_.GetNumSymbols()); |
+ElfMemImage::SymbolIterator ElfMemImage::end() const { |
+ return SymbolIterator(this, GetNumSymbols()); |
} |
-void VDSOSupport::SymbolIterator::Update(int increment) { |
+void ElfMemImage::SymbolIterator::Update(int increment) { |
const ElfMemImage *image = reinterpret_cast<const ElfMemImage *>(image_); |
CHECK(image->IsPresent() || increment == 0); |
if (!image->IsPresent()) { |
@@ -519,45 +428,6 @@ void VDSOSupport::SymbolIterator::Update(int increment) { |
info_.symbol = symbol; |
} |
-// NOLINT on 'long' because this routine mimics kernel api. |
-long VDSOSupport::GetCPUViaSyscall(unsigned *cpu, void *, void *) { // NOLINT |
-#if defined(__NR_getcpu) |
- return sys_getcpu(cpu, NULL, NULL); |
-#else |
- // x86_64 never implemented sys_getcpu(), except as a VDSO call. |
- errno = ENOSYS; |
- return -1; |
-#endif |
-} |
- |
-// Use fast __vdso_getcpu if available. |
-long VDSOSupport::InitAndGetCPU(unsigned *cpu, void *x, void *y) { // NOLINT |
- Init(); |
- CHECK_NE(getcpu_fn_, &InitAndGetCPU); // << "Init() did not set getcpu_fn_"; |
- return (*getcpu_fn_)(cpu, x, y); |
-} |
- |
-// This function must be very fast, and may be called from very |
-// low level (e.g. tcmalloc). Hence I avoid things like |
-// GoogleOnceInit() and ::operator new. |
-int GetCPU(void) { |
- unsigned cpu; |
- int ret_code = (*VDSOSupport::getcpu_fn_)(&cpu, NULL, NULL); |
- return ret_code == 0 ? cpu : ret_code; |
-} |
- |
-// We need to make sure VDSOSupport::Init() is called before |
-// the main() runs, since it might do something like setuid or |
-// chroot. If VDSOSupport |
-// is used in any global constructor, this will happen, since |
-// VDSOSupport's constructor calls Init. But if not, we need to |
-// ensure it here, with a global constructor of our own. This |
-// is an allowed exception to the normal rule against non-trivial |
-// global constructors. |
-static class VDSOInitHelper { |
- public: |
- VDSOInitHelper() { VDSOSupport::Init(); } |
-} vdso_init_helper; |
-} |
+} // namespace base |
-#endif // HAVE_VDSO_SUPPORT |
+#endif // HAVE_ELF_MEM_IMAGE |