tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

InterposerHelper.h (2416B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef InterposerHelper_h
      6 #define InterposerHelper_h
      7 
      8 #include <type_traits>
      9 
     10 #ifdef MOZ_LINKER
     11 #  include "Linker.h"
     12 #else
     13 #  include <dlfcn.h>
     14 #endif
     15 
     16 #include "mozilla/Assertions.h"
     17 
     18 template <typename T>
     19 static inline T dlsym_wrapper(void* aHandle, const char* aName) {
     20 #ifdef MOZ_LINKER
     21  return reinterpret_cast<T>(__wrap_dlsym(aHandle, aName));
     22 #else
     23  return reinterpret_cast<T>(dlsym(aHandle, aName));
     24 #endif  // MOZ_LINKER
     25 }
     26 
     27 static inline void* dlopen_wrapper(const char* aPath, int flags) {
     28 #ifdef MOZ_LINKER
     29  return __wrap_dlopen(aPath, flags);
     30 #else
     31  return dlopen(aPath, flags);
     32 #endif  // MOZ_LINKER
     33 }
     34 
     35 template <typename T>
     36 static T get_real_symbol(const char* aName, T aReplacementSymbol) {
     37  // T can only be a function pointer
     38  static_assert(std::is_function<typename std::remove_pointer<T>::type>::value);
     39 
     40  // Find the corresponding function in the linked libraries
     41  T real_symbol = dlsym_wrapper<T>(RTLD_NEXT, aName);
     42 
     43 #if defined(ANDROID)
     44  if ((real_symbol == nullptr) || (real_symbol == aReplacementSymbol)) {
     45    // On old versions of Android the application runtime links in libc before
     46    // we get a chance to link libmozglue, so its symbols don't appear when
     47    // resolving them with RTLD_NEXT. This behavior differs between the
     48    // different versions of Android so we'll just look for them directly into
     49    // libc.so. Note that this won't work if we're trying to interpose
     50    // functions that are in other libraries, but hopefully we'll never have
     51    // to do that.
     52    void* handle = dlopen_wrapper("libc.so", RTLD_LAZY);
     53 
     54    if (handle) {
     55      real_symbol = dlsym_wrapper<T>(handle, aName);
     56    }
     57  }
     58 #endif
     59 
     60  if (real_symbol == nullptr) {
     61    MOZ_CRASH_UNSAFE_PRINTF(
     62        "%s() interposition failed but the interposer function is "
     63        "still being called, this won't work!",
     64        aName);
     65  }
     66 
     67  if (real_symbol == aReplacementSymbol) {
     68    MOZ_CRASH_UNSAFE_PRINTF(
     69        "We could not obtain the real %s(). Calling the symbol we "
     70        "got would make us enter an infinite loop so stop here instead.",
     71        aName);
     72  }
     73 
     74  return real_symbol;
     75 }
     76 
     77 #define GET_REAL_SYMBOL(name) get_real_symbol(#name, name)
     78 
     79 #endif  // InterposerHelper_h