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