vdso_support.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright (c) 2008, Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above
  11. // copyright notice, this list of conditions and the following disclaimer
  12. // in the documentation and/or other materials provided with the
  13. // distribution.
  14. // * Neither the name of Google Inc. nor the names of its
  15. // contributors may be used to endorse or promote products derived from
  16. // this software without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. // ---
  30. // Author: Paul Pluzhnikov
  31. //
  32. // Allow dynamic symbol lookup in the kernel VDSO page.
  33. //
  34. // VDSOSupport -- a class representing kernel VDSO (if present).
  35. //
  36. #include "vdso_support.h"
  37. #ifdef HAVE_VDSO_SUPPORT // defined in vdso_support.h
  38. #include <fcntl.h>
  39. #include <stddef.h> // for ptrdiff_t
  40. #include "linux_syscall_support.h"
  41. #include "logging.h"
  42. #ifndef AT_SYSINFO_EHDR
  43. #define AT_SYSINFO_EHDR 33
  44. #endif
  45. namespace base {
  46. const void *VDSOSupport::vdso_base_ = NULL;
  47. VDSOSupport::VDSOSupport()
  48. // If vdso_base_ is still set to NULL, we got here
  49. // before VDSOSupport::Init has been called. Call it now.
  50. : image_(Init()) {
  51. }
  52. // NOTE: we can't use GoogleOnceInit() below, because we can be
  53. // called by tcmalloc, and none of the *once* stuff may be functional yet.
  54. //
  55. // In addition, we hope that the VDSOSupportHelper constructor
  56. // causes this code to run before there are any threads, and before
  57. // InitGoogle() has executed any chroot or setuid calls.
  58. //
  59. // Finally, even if there is a race here, it is harmless, because
  60. // the operation should be idempotent.
  61. const void *VDSOSupport::Init() {
  62. if (vdso_base_ == NULL) {
  63. // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
  64. // on stack, and so glibc works as if VDSO was not present.
  65. // But going directly to kernel via /proc/self/auxv below bypasses
  66. // Valgrind zapping. So we check for Valgrind separately.
  67. if (RunningOnValgrind()) {
  68. vdso_base_ = ElfMemImage::kInvalidBase;
  69. return vdso_base_;
  70. }
  71. int fd = open("/proc/self/auxv", O_RDONLY);
  72. if (fd == -1) {
  73. // Kernel too old to have a VDSO.
  74. vdso_base_ = ElfMemImage::kInvalidBase;
  75. return vdso_base_;
  76. }
  77. ElfW(auxv_t) aux;
  78. while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) {
  79. if (aux.a_type == AT_SYSINFO_EHDR) {
  80. COMPILE_ASSERT(sizeof(vdso_base_) == sizeof(aux.a_un.a_val),
  81. unexpected_sizeof_pointer_NE_sizeof_a_val);
  82. vdso_base_ = reinterpret_cast<void *>(aux.a_un.a_val);
  83. break;
  84. }
  85. }
  86. close(fd);
  87. if (vdso_base_ == NULL) {
  88. // Didn't find AT_SYSINFO_EHDR in auxv[].
  89. vdso_base_ = ElfMemImage::kInvalidBase;
  90. }
  91. }
  92. return vdso_base_;
  93. }
  94. const void *VDSOSupport::SetBase(const void *base) {
  95. CHECK(base != NULL);
  96. const void *old_base = vdso_base_;
  97. vdso_base_ = base;
  98. image_.Init(base);
  99. return old_base;
  100. }
  101. bool VDSOSupport::LookupSymbol(const char *name,
  102. const char *version,
  103. int type,
  104. SymbolInfo *info) const {
  105. return image_.LookupSymbol(name, version, type, info);
  106. }
  107. bool VDSOSupport::LookupSymbolByAddress(const void *address,
  108. SymbolInfo *info_out) const {
  109. return image_.LookupSymbolByAddress(address, info_out);
  110. }
  111. // We need to make sure VDSOSupport::Init() is called before
  112. // the main() runs, since it might do something like setuid or
  113. // chroot. If VDSOSupport
  114. // is used in any global constructor, this will happen, since
  115. // VDSOSupport's constructor calls Init. But if not, we need to
  116. // ensure it here, with a global constructor of our own. This
  117. // is an allowed exception to the normal rule against non-trivial
  118. // global constructors.
  119. static class VDSOInitHelper {
  120. public:
  121. VDSOInitHelper() { VDSOSupport::Init(); }
  122. } vdso_init_helper;
  123. }
  124. #endif // HAVE_VDSO_SUPPORT