interception.h revision 5d71de26cedae3dafc17449fe0182045c0bd20e8
1a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org//===-- interception.h ------------------------------------------*- C++ -*-===// 2ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 3ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// The LLVM Compiler Infrastructure 4ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 5ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// This file is distributed under the University of Illinois Open Source 6ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// License. See LICENSE.TXT for details. 7ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 8ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org//===----------------------------------------------------------------------===// 9ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 10ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// This file is a part of AddressSanitizer, an address sanity checker. 11ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 12ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// Machinery for providing replacements/wrappers for system functions. 13ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org//===----------------------------------------------------------------------===// 14ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 15ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#ifndef INTERCEPTION_H 16ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define INTERCEPTION_H 17ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 18ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#if !defined(__linux__) && !defined(__FreeBSD__) && \ 19ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org !defined(__APPLE__) && !defined(_WIN32) 20ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# error "Interception doesn't work on this operating system." 21ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#endif 22ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 23ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#include "sanitizer_common/sanitizer_internal_defs.h" 24ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 25ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// These typedefs should be used only in the interceptor definitions to replace 26ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// the standard system types (e.g. SSIZE_T instead of ssize_t) 27ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgtypedef __sanitizer::uptr SIZE_T; 28ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgtypedef __sanitizer::sptr SSIZE_T; 29ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgtypedef __sanitizer::sptr PTRDIFF_T; 30ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgtypedef __sanitizer::s64 INTMAX_T; 31ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgtypedef __sanitizer::OFF_T OFF_T; 32ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgtypedef __sanitizer::OFF64_T OFF64_T; 33ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 34ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// How to add an interceptor: 35ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// Suppose you need to wrap/replace system function (generally, from libc): 36ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// int foo(const char *bar, double baz); 37ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// You'll need to: 38ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in 39ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// your source file. See the notes below for cases when 40ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// INTERCEPTOR_WITH_SUFFIX(...) should be used instead. 41ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo". 42ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was 43ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// intercepted successfully. 44ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// You can access original function by calling REAL(foo)(bar, baz). 45ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// By default, REAL(foo) will be visible only inside your interceptor, and if 46ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// you want to use it in other parts of RTL, you'll need to: 47ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 3a) add DECLARE_REAL(int, foo, const char*, double) to a 48ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// header file. 49ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// However, if the call "INTERCEPT_FUNCTION(foo)" and definition for 50ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// INTERCEPTOR(..., foo, ...) are in different files, you'll instead need to: 51ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double) 52ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// to a header file. 53ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 54ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or 55ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// DECLARE_REAL(...) are located inside namespaces. 56ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to 57ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// effectively redirect calls from "foo" to "zoo". In this case 58ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// you aren't required to implement 59ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// INTERCEPTOR(int, foo, const char *bar, double baz) {...} 60ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// but instead you'll have to add 61ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// DECLARE_REAL(int, foo, const char *bar, double baz) in your 62ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// source file (to define a pointer to overriden function). 63ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 3. Some Mac functions have symbol variants discriminated by 64ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// additional suffixes, e.g. _$UNIX2003 (see 65ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// https://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/index.html 66ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// for more details). To intercept such functions you need to use the 67ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// INTERCEPTOR_WITH_SUFFIX(...) macro. 68ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 69ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// How it works: 70ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// To replace system functions on Linux we just need to declare functions 71ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// with same names in our library and then obtain the real function pointers 72ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// using dlsym(). 73ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// There is one complication. A user may also intercept some of the functions 74ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// we intercept. To resolve this we declare our interceptors with __interceptor_ 75a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// prefix, and then make actual interceptors weak aliases to __interceptor_ 76ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// functions. 77ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// 78ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// This is not so on Mac OS, where the two-level namespace makes 79ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// our replacement functions invisible to other libraries. This may be overcomed 80ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared 81ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// libraries in Chromium were noticed when doing so. 82ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// Instead we create a dylib containing a __DATA,__interpose section that 83ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// associates library functions with their wrappers. When this dylib is 84ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all 85ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// the calls to interposed functions done through stubs to the wrapper 86ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// functions. 87ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// As it's decided at compile time which functions are to be intercepted on Mac, 88ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// INTERCEPT_FUNCTION() is effectively a no-op on this system. 89ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 90ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#if defined(__APPLE__) 91ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#include <sys/cdefs.h> // For __DARWIN_ALIAS_C(). 92ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 93ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// Just a pair of pointers. 94ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgstruct interpose_substitution { 95ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org const uptr replacement; 967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org const uptr original; 977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}; 98ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 99ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// For a function foo() create a global pair of pointers { wrap_foo, foo } in 100ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// the __DATA,__interpose section. 101ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// As a result all the calls to foo() will be routed to wrap_foo() at runtime. 1027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#define INTERPOSER(func_name) __attribute__((used)) \ 103ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgconst interpose_substitution substitution_##func_name[] \ 104ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __attribute__((section("__DATA, __interpose"))) = { \ 105ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org { reinterpret_cast<const uptr>(WRAP(func_name)), \ 106ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org reinterpret_cast<const uptr>(func_name) } \ 107ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org} 108ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 109ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// For a function foo() and a wrapper function bar() create a global pair 110ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// of pointers { bar, foo } in the __DATA,__interpose section. 111ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// As a result all the calls to foo() will be routed to bar() at runtime. 112ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \ 113ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgconst interpose_substitution substitution_##func_name[] \ 114ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __attribute__((section("__DATA, __interpose"))) = { \ 115ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org { reinterpret_cast<const uptr>(wrapper_name), \ 116ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org reinterpret_cast<const uptr>(func_name) } \ 117ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org} 118ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 119ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define WRAP(x) wrap_##x 120ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define WRAPPER_NAME(x) "wrap_"#x 121ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPTOR_ATTRIBUTE 122ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define DECLARE_WRAPPER(ret_type, func, ...) 123ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 124ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#elif defined(_WIN32) 125ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# if defined(_DLL) // DLL CRT 126ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define WRAP(x) x 127ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define WRAPPER_NAME(x) #x 128ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPTOR_ATTRIBUTE 129ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# else // Static CRT 130ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define WRAP(x) __asan_wrap_##x 131ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define WRAPPER_NAME(x) "__asan_wrap_"#x 132ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPTOR_ATTRIBUTE __declspec(dllexport) 133ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# endif 134ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define DECLARE_WRAPPER(ret_type, func, ...) \ 135ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org extern "C" ret_type func(__VA_ARGS__); 136ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \ 137ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__); 138ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#elif defined(__FreeBSD__) 139a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define WRAP(x) __interceptor_ ## x 140a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define WRAPPER_NAME(x) "__interceptor_" #x 141a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) 142a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher 143a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// priority than weak ones so weak aliases won't work for indirect calls 144a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// in position-independent (-fPIC / -fPIE) mode. 145a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define DECLARE_WRAPPER(ret_type, func, ...) \ 146a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org extern "C" ret_type func(__VA_ARGS__) \ 147a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org __attribute__((alias("__interceptor_" #func), visibility("default"))); 148a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org#else 149a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define WRAP(x) __interceptor_ ## x 150a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define WRAPPER_NAME(x) "__interceptor_" #x 151a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) 152a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define DECLARE_WRAPPER(ret_type, func, ...) \ 153a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org extern "C" ret_type func(__VA_ARGS__) \ 154a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org __attribute__((weak, alias("__interceptor_" #func), visibility("default"))); 155a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org#endif 156a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org 157a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org#if !defined(__APPLE__) 158a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define PTR_TO_REAL(x) real_##x 159a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define REAL(x) __interception::PTR_TO_REAL(x) 160a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define FUNC_TYPE(x) x##_f 161a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org 162a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define DECLARE_REAL(ret_type, func, ...) \ 163a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \ 164a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org namespace __interception { \ 165a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org extern FUNC_TYPE(func) PTR_TO_REAL(func); \ 166a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org } 167a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org#else // __APPLE__ 168a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define REAL(x) x 169a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define DECLARE_REAL(ret_type, func, ...) \ 170a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org extern "C" ret_type func(__VA_ARGS__); 171a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org#endif // __APPLE__ 172a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org 173a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org#define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \ 174a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org DECLARE_REAL(ret_type, func, __VA_ARGS__) \ 175a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org extern "C" ret_type WRAP(func)(__VA_ARGS__); 176a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org 177a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR 178a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// macros does its job. In exceptional cases you may need to call REAL(foo) 179a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// without defining INTERCEPTOR(..., foo, ...). For example, if you override 180a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// foo with an interceptor for other function. 181a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org#if !defined(__APPLE__) 182a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org# define DEFINE_REAL(ret_type, func, ...) \ 183a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \ 184a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org namespace __interception { \ 185a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org FUNC_TYPE(func) PTR_TO_REAL(func); \ 186ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org } 187ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#else 188ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define DEFINE_REAL(ret_type, func, ...) 189ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#endif 190ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 191ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#if !defined(__APPLE__) 192ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define INTERCEPTOR(ret_type, func, ...) \ 193ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org DEFINE_REAL(ret_type, func, __VA_ARGS__) \ 194ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \ 195ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org extern "C" \ 196ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERCEPTOR_ATTRIBUTE \ 197ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ret_type WRAP(func)(__VA_ARGS__) 198ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 199ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now. 200ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \ 201ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERCEPTOR(ret_type, func, __VA_ARGS__) 202ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 203ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#else // __APPLE__ 204ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 205ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \ 206ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org extern "C" ret_type func(__VA_ARGS__) suffix; \ 207ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org extern "C" ret_type WRAP(func)(__VA_ARGS__); \ 208ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERPOSER(func); \ 209ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__) 210ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 211ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define INTERCEPTOR(ret_type, func, ...) \ 212ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERCEPTOR_ZZZ(/*no symbol variants*/, ret_type, func, __VA_ARGS__) 213ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 214ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \ 215ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERCEPTOR_ZZZ(__DARWIN_ALIAS_C(func), ret_type, func, __VA_ARGS__) 216ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 217ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// Override |overridee| with |overrider|. 218ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define OVERRIDE_FUNCTION(overridee, overrider) \ 219ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERPOSER_2(overridee, WRAP(overrider)) 220ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#endif 221ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 222ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#if defined(_WIN32) 223ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPTOR_WINAPI(ret_type, func, ...) \ 224ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \ 225ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org namespace __interception { \ 226a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org FUNC_TYPE(func) PTR_TO_REAL(func); \ 227ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org } \ 228ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org DECLARE_WRAPPER_WINAPI(ret_type, func, __VA_ARGS__) \ 229ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org extern "C" \ 230ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERCEPTOR_ATTRIBUTE \ 231ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ret_type __stdcall WRAP(func)(__VA_ARGS__) 232ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#endif 233ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 234ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// ISO C++ forbids casting between pointer-to-function and pointer-to-object, 235ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// so we use casting via an integral type __interception::uptr, 236ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// assuming that system is POSIX-compliant. Using other hacks seem 237ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// challenging, as we don't even pass function type to 238ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// INTERCEPT_FUNCTION macro, only its name. 239ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgnamespace __interception { 240ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#if defined(_WIN64) 241ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgtypedef unsigned long long uptr; // NOLINT 242ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#else 243ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgtypedef unsigned long uptr; // NOLINT 244ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#endif // _WIN64 245ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org} // namespace __interception 2467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 247ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#define INCLUDED_FROM_INTERCEPTION_LIB 248ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 249ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#if defined(__linux__) || defined(__FreeBSD__) 250ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# include "interception_linux.h" 251ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) 252ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPT_FUNCTION_VER(func, symver) \ 253ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) 254ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#elif defined(__APPLE__) 255ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# include "interception_mac.h" 256ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func) 257ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPT_FUNCTION_VER(func, symver) \ 258ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERCEPT_FUNCTION_VER_MAC(func, symver) 259ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#else // defined(_WIN32) 260ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# include "interception_win.h" 261ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_WIN(func) 262ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org# define INTERCEPT_FUNCTION_VER(func, symver) \ 263ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org INTERCEPT_FUNCTION_VER_WIN(func, symver) 264ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#endif 265ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 266ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#undef INCLUDED_FROM_INTERCEPTION_LIB 267ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 268ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#endif // INTERCEPTION_H 269ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org