| OLD | NEW |
| 1 // Copyright (c) 2008, Google Inc. | 1 // Copyright (c) 2008, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 // Allow dynamic symbol lookup in the kernel VDSO page. | 33 // Allow dynamic symbol lookup in the kernel VDSO page. |
| 34 // | 34 // |
| 35 // VDSOSupport -- a class representing kernel VDSO (if present). | 35 // VDSOSupport -- a class representing kernel VDSO (if present). |
| 36 // | 36 // |
| 37 | 37 |
| 38 #include "base/vdso_support.h" | 38 #include "base/vdso_support.h" |
| 39 | 39 |
| 40 #ifdef HAVE_VDSO_SUPPORT // defined in vdso_support.h | 40 #ifdef HAVE_VDSO_SUPPORT // defined in vdso_support.h |
| 41 | 41 |
| 42 #include <fcntl.h> | 42 #include <fcntl.h> |
| 43 #include <stddef.h> // for std::ptrdiff_t |
| 43 | 44 |
| 44 #include "base/atomicops.h" // for MemoryBarrier | 45 #include "base/atomicops.h" // for MemoryBarrier |
| 45 #include "base/logging.h" | 46 #include "base/logging.h" |
| 46 #include "base/linux_syscall_support.h" | 47 #include "base/linux_syscall_support.h" |
| 47 #include "base/dynamic_annotations.h" | 48 #include "base/dynamic_annotations.h" |
| 48 #include "base/basictypes.h" // for COMPILE_ASSERT | 49 #include "base/basictypes.h" // for COMPILE_ASSERT |
| 49 | 50 |
| 50 using base::subtle::MemoryBarrier; | 51 using base::subtle::MemoryBarrier; |
| 51 | 52 |
| 52 #ifndef AT_SYSINFO_EHDR | 53 #ifndef AT_SYSINFO_EHDR |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 dynstr_ = NULL; | 201 dynstr_ = NULL; |
| 201 versym_ = NULL; | 202 versym_ = NULL; |
| 202 verdef_ = NULL; | 203 verdef_ = NULL; |
| 203 hash_ = NULL; | 204 hash_ = NULL; |
| 204 strsize_ = 0; | 205 strsize_ = 0; |
| 205 verdefnum_ = 0; | 206 verdefnum_ = 0; |
| 206 link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this. | 207 link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this. |
| 207 if (!base) { | 208 if (!base) { |
| 208 return; | 209 return; |
| 209 } | 210 } |
| 211 const intptr_t base_as_uintptr_t = reinterpret_cast<uintptr_t>(base); |
| 212 // Fake VDSO has low bit set. |
| 213 const bool fake_vdso = ((base_as_uintptr_t & 1) != 0); |
| 214 base = reinterpret_cast<const void *>(base_as_uintptr_t & ~1); |
| 210 const char *const base_as_char = reinterpret_cast<const char *>(base); | 215 const char *const base_as_char = reinterpret_cast<const char *>(base); |
| 211 if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 || | 216 if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 || |
| 212 base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) { | 217 base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) { |
| 213 RAW_DCHECK(false, "no ELF magic"); // at %p", base); | 218 RAW_DCHECK(false, "no ELF magic"); // at %p", base); |
| 214 return; | 219 return; |
| 215 } | 220 } |
| 216 int elf_class = base_as_char[EI_CLASS]; | 221 int elf_class = base_as_char[EI_CLASS]; |
| 217 if (elf_class != CurrentElfClass::kElfClass) { | 222 if (elf_class != CurrentElfClass::kElfClass) { |
| 218 DCHECK_EQ(elf_class, CurrentElfClass::kElfClass); | 223 DCHECK_EQ(elf_class, CurrentElfClass::kElfClass); |
| 219 return; | 224 return; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO"); | 264 RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO"); |
| 260 // Mark this image as not present. Can not recur infinitely. | 265 // Mark this image as not present. Can not recur infinitely. |
| 261 Init(0); | 266 Init(0); |
| 262 return; | 267 return; |
| 263 } | 268 } |
| 264 std::ptrdiff_t relocation = | 269 std::ptrdiff_t relocation = |
| 265 base_as_char - reinterpret_cast<const char *>(link_base_); | 270 base_as_char - reinterpret_cast<const char *>(link_base_); |
| 266 ElfW(Dyn) *dynamic_entry = | 271 ElfW(Dyn) *dynamic_entry = |
| 267 reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr + | 272 reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr + |
| 268 relocation); | 273 relocation); |
| 269 bool fake_vdso = false; // Assume we are dealing with the real VDSO. | |
| 270 for (ElfW(Dyn) *de = dynamic_entry; de->d_tag != DT_NULL; ++de) { | |
| 271 ElfW(Sxword) tag = de->d_tag; | |
| 272 if (tag == DT_PLTGOT || tag == DT_RELA || tag == DT_JMPREL || | |
| 273 tag == DT_NEEDED || tag == DT_RPATH || tag == DT_VERNEED || | |
| 274 tag == DT_INIT || tag == DT_FINI) { | |
| 275 /* Real vdso can not reasonably have any of the above entries. */ | |
| 276 fake_vdso = true; | |
| 277 break; | |
| 278 } | |
| 279 } | |
| 280 for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) { | 274 for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) { |
| 281 ElfW(Xword) value = dynamic_entry->d_un.d_val; | 275 ElfW(Xword) value = dynamic_entry->d_un.d_val; |
| 282 if (fake_vdso) { | 276 if (fake_vdso) { |
| 283 // A complication: in the real VDSO, dynamic entries are not relocated | 277 // A complication: in the real VDSO, dynamic entries are not relocated |
| 284 // (it wasn't loaded by a dynamic loader). But when testing with a | 278 // (it wasn't loaded by a dynamic loader). But when testing with a |
| 285 // "fake" dlopen()ed vdso library, the loader relocates some (but | 279 // "fake" dlopen()ed vdso library, the loader relocates some (but |
| 286 // not all!) of them before we get here. | 280 // not all!) of them before we get here. |
| 287 if (dynamic_entry->d_tag == DT_VERDEF) { | 281 if (dynamic_entry->d_tag == DT_VERDEF) { |
| 288 // The only dynamic entry (of the ones we care about) libc-2.3.6 | 282 // The only dynamic entry (of the ones we care about) libc-2.3.6 |
| 289 // loader doesn't relocate. | 283 // loader doesn't relocate. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 VDSOSupport vdso; | 382 VDSOSupport vdso; |
| 389 SymbolInfo info; | 383 SymbolInfo info; |
| 390 if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { | 384 if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { |
| 391 // Casting from an int to a pointer is not legal C++. To emphasize | 385 // Casting from an int to a pointer is not legal C++. To emphasize |
| 392 // this, we use a C-style cast rather than a C++-style cast. | 386 // this, we use a C-style cast rather than a C++-style cast. |
| 393 fn = (GetCpuFn)(info.address); | 387 fn = (GetCpuFn)(info.address); |
| 394 } | 388 } |
| 395 } | 389 } |
| 396 // Subtle: this code runs outside of any locks; prevent compiler | 390 // Subtle: this code runs outside of any locks; prevent compiler |
| 397 // from assigning to getcpu_fn_ more than once. | 391 // from assigning to getcpu_fn_ more than once. |
| 398 MemoryBarrier(); | 392 base::subtle::MemoryBarrier(); |
| 399 getcpu_fn_ = fn; | 393 getcpu_fn_ = fn; |
| 400 return vdso_base_; | 394 return vdso_base_; |
| 401 } | 395 } |
| 402 | 396 |
| 403 const void *VDSOSupport::SetBase(const void *base) { | 397 const void *VDSOSupport::SetBase(const void *base) { |
| 404 const void *old_base = vdso_base_; | 398 const void *old_base = vdso_base_; |
| 405 vdso_base_ = base; | 399 vdso_base_ = base; |
| 406 image_.Init(base); | 400 image_.Init(base); |
| 407 // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO. | 401 // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO. |
| 408 getcpu_fn_ = &InitAndGetCPU; | 402 getcpu_fn_ = &InitAndGetCPU; |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 // ensure it here, with a global constructor of our own. This | 554 // ensure it here, with a global constructor of our own. This |
| 561 // is an allowed exception to the normal rule against non-trivial | 555 // is an allowed exception to the normal rule against non-trivial |
| 562 // global constructors. | 556 // global constructors. |
| 563 static class VDSOInitHelper { | 557 static class VDSOInitHelper { |
| 564 public: | 558 public: |
| 565 VDSOInitHelper() { VDSOSupport::Init(); } | 559 VDSOInitHelper() { VDSOSupport::Init(); } |
| 566 } vdso_init_helper; | 560 } vdso_init_helper; |
| 567 } | 561 } |
| 568 | 562 |
| 569 #endif // HAVE_VDSO_SUPPORT | 563 #endif // HAVE_VDSO_SUPPORT |
| OLD | NEW |