xref: /openbsd-src/gnu/llvm/compiler-rt/lib/interception/interception.h (revision 68dd5bb1859285b71cb62a10bf107b8ad54064d9)
13cab2bb3Spatrick //===-- interception.h ------------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker.
103cab2bb3Spatrick //
113cab2bb3Spatrick // Machinery for providing replacements/wrappers for system functions.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick 
143cab2bb3Spatrick #ifndef INTERCEPTION_H
153cab2bb3Spatrick #define INTERCEPTION_H
163cab2bb3Spatrick 
173cab2bb3Spatrick #include "sanitizer_common/sanitizer_internal_defs.h"
183cab2bb3Spatrick 
19*68dd5bb1Srobert #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE &&      \
20d89ec533Spatrick     !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \
215e1c9963Sgnezdo     !SANITIZER_OPENBSD && !SANITIZER_SOLARIS
223cab2bb3Spatrick #  error "Interception doesn't work on this operating system."
233cab2bb3Spatrick #endif
243cab2bb3Spatrick 
253cab2bb3Spatrick // These typedefs should be used only in the interceptor definitions to replace
263cab2bb3Spatrick // the standard system types (e.g. SSIZE_T instead of ssize_t)
273cab2bb3Spatrick typedef __sanitizer::uptr    SIZE_T;
283cab2bb3Spatrick typedef __sanitizer::sptr    SSIZE_T;
293cab2bb3Spatrick typedef __sanitizer::sptr    PTRDIFF_T;
303cab2bb3Spatrick typedef __sanitizer::s64     INTMAX_T;
313cab2bb3Spatrick typedef __sanitizer::u64     UINTMAX_T;
323cab2bb3Spatrick typedef __sanitizer::OFF_T   OFF_T;
333cab2bb3Spatrick typedef __sanitizer::OFF64_T OFF64_T;
343cab2bb3Spatrick 
353cab2bb3Spatrick // How to add an interceptor:
363cab2bb3Spatrick // Suppose you need to wrap/replace system function (generally, from libc):
373cab2bb3Spatrick //      int foo(const char *bar, double baz);
383cab2bb3Spatrick // You'll need to:
393cab2bb3Spatrick //      1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in
403cab2bb3Spatrick //         your source file. See the notes below for cases when
413cab2bb3Spatrick //         INTERCEPTOR_WITH_SUFFIX(...) should be used instead.
423cab2bb3Spatrick //      2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo".
433cab2bb3Spatrick //         INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was
443cab2bb3Spatrick //         intercepted successfully.
453cab2bb3Spatrick // You can access original function by calling REAL(foo)(bar, baz).
463cab2bb3Spatrick // By default, REAL(foo) will be visible only inside your interceptor, and if
473cab2bb3Spatrick // you want to use it in other parts of RTL, you'll need to:
483cab2bb3Spatrick //      3a) add DECLARE_REAL(int, foo, const char*, double) to a
493cab2bb3Spatrick //          header file.
503cab2bb3Spatrick // However, if the call "INTERCEPT_FUNCTION(foo)" and definition for
513cab2bb3Spatrick // INTERCEPTOR(..., foo, ...) are in different files, you'll instead need to:
523cab2bb3Spatrick //      3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double)
533cab2bb3Spatrick //          to a header file.
543cab2bb3Spatrick 
553cab2bb3Spatrick // Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or
563cab2bb3Spatrick //           DECLARE_REAL(...) are located inside namespaces.
573cab2bb3Spatrick //        2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to
583cab2bb3Spatrick //           effectively redirect calls from "foo" to "zoo". In this case
593cab2bb3Spatrick //           you aren't required to implement
603cab2bb3Spatrick //           INTERCEPTOR(int, foo, const char *bar, double baz) {...}
613cab2bb3Spatrick //           but instead you'll have to add
623cab2bb3Spatrick //           DECLARE_REAL(int, foo, const char *bar, double baz) in your
633cab2bb3Spatrick //           source file (to define a pointer to overriden function).
643cab2bb3Spatrick //        3. Some Mac functions have symbol variants discriminated by
653cab2bb3Spatrick //           additional suffixes, e.g. _$UNIX2003 (see
663cab2bb3Spatrick //           https://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/index.html
673cab2bb3Spatrick //           for more details). To intercept such functions you need to use the
683cab2bb3Spatrick //           INTERCEPTOR_WITH_SUFFIX(...) macro.
693cab2bb3Spatrick 
703cab2bb3Spatrick // How it works:
713cab2bb3Spatrick // To replace system functions on Linux we just need to declare functions
723cab2bb3Spatrick // with same names in our library and then obtain the real function pointers
733cab2bb3Spatrick // using dlsym().
743cab2bb3Spatrick // There is one complication. A user may also intercept some of the functions
753cab2bb3Spatrick // we intercept. To resolve this we declare our interceptors with __interceptor_
763cab2bb3Spatrick // prefix, and then make actual interceptors weak aliases to __interceptor_
773cab2bb3Spatrick // functions.
783cab2bb3Spatrick //
793cab2bb3Spatrick // This is not so on Mac OS, where the two-level namespace makes
803cab2bb3Spatrick // our replacement functions invisible to other libraries. This may be overcomed
813cab2bb3Spatrick // using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
823cab2bb3Spatrick // libraries in Chromium were noticed when doing so.
833cab2bb3Spatrick // Instead we create a dylib containing a __DATA,__interpose section that
843cab2bb3Spatrick // associates library functions with their wrappers. When this dylib is
853cab2bb3Spatrick // preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all
863cab2bb3Spatrick // the calls to interposed functions done through stubs to the wrapper
873cab2bb3Spatrick // functions.
883cab2bb3Spatrick // As it's decided at compile time which functions are to be intercepted on Mac,
893cab2bb3Spatrick // INTERCEPT_FUNCTION() is effectively a no-op on this system.
903cab2bb3Spatrick 
91*68dd5bb1Srobert #if SANITIZER_APPLE
923cab2bb3Spatrick #include <sys/cdefs.h>  // For __DARWIN_ALIAS_C().
933cab2bb3Spatrick 
943cab2bb3Spatrick // Just a pair of pointers.
953cab2bb3Spatrick struct interpose_substitution {
963cab2bb3Spatrick   const __sanitizer::uptr replacement;
973cab2bb3Spatrick   const __sanitizer::uptr original;
983cab2bb3Spatrick };
993cab2bb3Spatrick 
1003cab2bb3Spatrick // For a function foo() create a global pair of pointers { wrap_foo, foo } in
1013cab2bb3Spatrick // the __DATA,__interpose section.
1023cab2bb3Spatrick // As a result all the calls to foo() will be routed to wrap_foo() at runtime.
1033cab2bb3Spatrick #define INTERPOSER(func_name) __attribute__((used)) \
1043cab2bb3Spatrick const interpose_substitution substitution_##func_name[] \
1053cab2bb3Spatrick     __attribute__((section("__DATA, __interpose"))) = { \
1063cab2bb3Spatrick     { reinterpret_cast<const uptr>(WRAP(func_name)), \
1073cab2bb3Spatrick       reinterpret_cast<const uptr>(func_name) } \
1083cab2bb3Spatrick }
1093cab2bb3Spatrick 
1103cab2bb3Spatrick // For a function foo() and a wrapper function bar() create a global pair
1113cab2bb3Spatrick // of pointers { bar, foo } in the __DATA,__interpose section.
1123cab2bb3Spatrick // As a result all the calls to foo() will be routed to bar() at runtime.
1133cab2bb3Spatrick #define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \
1143cab2bb3Spatrick const interpose_substitution substitution_##func_name[] \
1153cab2bb3Spatrick     __attribute__((section("__DATA, __interpose"))) = { \
1163cab2bb3Spatrick     { reinterpret_cast<const uptr>(wrapper_name), \
1173cab2bb3Spatrick       reinterpret_cast<const uptr>(func_name) } \
1183cab2bb3Spatrick }
1193cab2bb3Spatrick 
1203cab2bb3Spatrick # define WRAP(x) wrap_##x
1213cab2bb3Spatrick # define WRAPPER_NAME(x) "wrap_"#x
1223cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE
1233cab2bb3Spatrick # define DECLARE_WRAPPER(ret_type, func, ...)
1243cab2bb3Spatrick 
1253cab2bb3Spatrick #elif SANITIZER_WINDOWS
1263cab2bb3Spatrick # define WRAP(x) __asan_wrap_##x
1273cab2bb3Spatrick # define WRAPPER_NAME(x) "__asan_wrap_"#x
1283cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE __declspec(dllexport)
1293cab2bb3Spatrick # define DECLARE_WRAPPER(ret_type, func, ...) \
1303cab2bb3Spatrick     extern "C" ret_type func(__VA_ARGS__);
1313cab2bb3Spatrick # define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
1323cab2bb3Spatrick     extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
1333cab2bb3Spatrick #elif SANITIZER_FREEBSD || SANITIZER_NETBSD
1343cab2bb3Spatrick # define WRAP(x) __interceptor_ ## x
1353cab2bb3Spatrick # define WRAPPER_NAME(x) "__interceptor_" #x
1363cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
1373cab2bb3Spatrick // FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher
1383cab2bb3Spatrick // priority than weak ones so weak aliases won't work for indirect calls
1393cab2bb3Spatrick // in position-independent (-fPIC / -fPIE) mode.
1403cab2bb3Spatrick # define DECLARE_WRAPPER(ret_type, func, ...) \
1413cab2bb3Spatrick      extern "C" ret_type func(__VA_ARGS__) \
1423cab2bb3Spatrick      __attribute__((alias("__interceptor_" #func), visibility("default")));
1433cab2bb3Spatrick #elif !SANITIZER_FUCHSIA
1443cab2bb3Spatrick # define WRAP(x) __interceptor_ ## x
1453cab2bb3Spatrick # define WRAPPER_NAME(x) "__interceptor_" #x
1463cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
1473cab2bb3Spatrick # define DECLARE_WRAPPER(ret_type, func, ...) \
1483cab2bb3Spatrick     extern "C" ret_type func(__VA_ARGS__) \
1493cab2bb3Spatrick     __attribute__((weak, alias("__interceptor_" #func), visibility("default")));
1503cab2bb3Spatrick #endif
1513cab2bb3Spatrick 
1523cab2bb3Spatrick #if SANITIZER_FUCHSIA
1533cab2bb3Spatrick // There is no general interception at all on Fuchsia.
1543cab2bb3Spatrick // Sanitizer runtimes just define functions directly to preempt them,
1553cab2bb3Spatrick // and have bespoke ways to access the underlying libc functions.
1563cab2bb3Spatrick # include <zircon/sanitizer.h>
1573cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
1583cab2bb3Spatrick # define REAL(x) __unsanitized_##x
1593cab2bb3Spatrick # define DECLARE_REAL(ret_type, func, ...)
160*68dd5bb1Srobert #elif !SANITIZER_APPLE
1613cab2bb3Spatrick # define PTR_TO_REAL(x) real_##x
1623cab2bb3Spatrick # define REAL(x) __interception::PTR_TO_REAL(x)
1633cab2bb3Spatrick # define FUNC_TYPE(x) x##_type
1643cab2bb3Spatrick 
1653cab2bb3Spatrick # define DECLARE_REAL(ret_type, func, ...) \
1663cab2bb3Spatrick     typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
1673cab2bb3Spatrick     namespace __interception { \
1683cab2bb3Spatrick       extern FUNC_TYPE(func) PTR_TO_REAL(func); \
1693cab2bb3Spatrick     }
1703cab2bb3Spatrick # define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
171*68dd5bb1Srobert #else  // SANITIZER_APPLE
1723cab2bb3Spatrick # define REAL(x) x
1733cab2bb3Spatrick # define DECLARE_REAL(ret_type, func, ...) \
1743cab2bb3Spatrick     extern "C" ret_type func(__VA_ARGS__);
1753cab2bb3Spatrick # define ASSIGN_REAL(x, y)
176*68dd5bb1Srobert #endif  // SANITIZER_APPLE
1773cab2bb3Spatrick 
178d89ec533Spatrick #if !SANITIZER_FUCHSIA
1793cab2bb3Spatrick #  define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
1803cab2bb3Spatrick     DECLARE_REAL(ret_type, func, __VA_ARGS__)               \
1813cab2bb3Spatrick     extern "C" ret_type WRAP(func)(__VA_ARGS__);
1823cab2bb3Spatrick // Declare an interceptor and its wrapper defined in a different translation
1833cab2bb3Spatrick // unit (ex. asm).
1843cab2bb3Spatrick # define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...)    \
1853cab2bb3Spatrick   extern "C" ret_type WRAP(func)(__VA_ARGS__); \
1863cab2bb3Spatrick   extern "C" ret_type func(__VA_ARGS__);
1873cab2bb3Spatrick #else
1883cab2bb3Spatrick # define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...)
1893cab2bb3Spatrick # define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...)
1903cab2bb3Spatrick #endif
1913cab2bb3Spatrick 
1923cab2bb3Spatrick // Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR
1933cab2bb3Spatrick // macros does its job. In exceptional cases you may need to call REAL(foo)
1943cab2bb3Spatrick // without defining INTERCEPTOR(..., foo, ...). For example, if you override
1953cab2bb3Spatrick // foo with an interceptor for other function.
196*68dd5bb1Srobert #if !SANITIZER_APPLE && !SANITIZER_FUCHSIA
1973cab2bb3Spatrick #  define DEFINE_REAL(ret_type, func, ...)            \
1983cab2bb3Spatrick     typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
1993cab2bb3Spatrick     namespace __interception {                        \
2003cab2bb3Spatrick     FUNC_TYPE(func) PTR_TO_REAL(func);                \
2013cab2bb3Spatrick     }
2023cab2bb3Spatrick #else
2033cab2bb3Spatrick # define DEFINE_REAL(ret_type, func, ...)
2043cab2bb3Spatrick #endif
2053cab2bb3Spatrick 
2063cab2bb3Spatrick #if SANITIZER_FUCHSIA
2073cab2bb3Spatrick 
2083cab2bb3Spatrick // We need to define the __interceptor_func name just to get
2093cab2bb3Spatrick // sanitizer_common/scripts/gen_dynamic_list.py to export func.
2103cab2bb3Spatrick // But we don't need to export __interceptor_func to get that.
2113cab2bb3Spatrick #define INTERCEPTOR(ret_type, func, ...)                                \
2123cab2bb3Spatrick   extern "C"[[ gnu::alias(#func), gnu::visibility("hidden") ]] ret_type \
2133cab2bb3Spatrick       __interceptor_##func(__VA_ARGS__);                                \
2143cab2bb3Spatrick   extern "C" INTERCEPTOR_ATTRIBUTE ret_type func(__VA_ARGS__)
2153cab2bb3Spatrick 
216*68dd5bb1Srobert #elif !SANITIZER_APPLE
2173cab2bb3Spatrick 
2183cab2bb3Spatrick #define INTERCEPTOR(ret_type, func, ...) \
2193cab2bb3Spatrick   DEFINE_REAL(ret_type, func, __VA_ARGS__) \
2203cab2bb3Spatrick   DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
2213cab2bb3Spatrick   extern "C" \
2223cab2bb3Spatrick   INTERCEPTOR_ATTRIBUTE \
2233cab2bb3Spatrick   ret_type WRAP(func)(__VA_ARGS__)
2243cab2bb3Spatrick 
2253cab2bb3Spatrick // We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now.
2263cab2bb3Spatrick #define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
2273cab2bb3Spatrick   INTERCEPTOR(ret_type, func, __VA_ARGS__)
2283cab2bb3Spatrick 
229*68dd5bb1Srobert #else  // SANITIZER_APPLE
2303cab2bb3Spatrick 
2313cab2bb3Spatrick #define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \
2323cab2bb3Spatrick   extern "C" ret_type func(__VA_ARGS__) suffix; \
2333cab2bb3Spatrick   extern "C" ret_type WRAP(func)(__VA_ARGS__); \
2343cab2bb3Spatrick   INTERPOSER(func); \
2353cab2bb3Spatrick   extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
2363cab2bb3Spatrick 
2373cab2bb3Spatrick #define INTERCEPTOR(ret_type, func, ...) \
2383cab2bb3Spatrick   INTERCEPTOR_ZZZ(/*no symbol variants*/, ret_type, func, __VA_ARGS__)
2393cab2bb3Spatrick 
2403cab2bb3Spatrick #define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
2413cab2bb3Spatrick   INTERCEPTOR_ZZZ(__DARWIN_ALIAS_C(func), ret_type, func, __VA_ARGS__)
2423cab2bb3Spatrick 
2433cab2bb3Spatrick // Override |overridee| with |overrider|.
2443cab2bb3Spatrick #define OVERRIDE_FUNCTION(overridee, overrider) \
2453cab2bb3Spatrick   INTERPOSER_2(overridee, WRAP(overrider))
2463cab2bb3Spatrick #endif
2473cab2bb3Spatrick 
2483cab2bb3Spatrick #if SANITIZER_WINDOWS
2493cab2bb3Spatrick # define INTERCEPTOR_WINAPI(ret_type, func, ...) \
2503cab2bb3Spatrick     typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \
2513cab2bb3Spatrick     namespace __interception { \
2523cab2bb3Spatrick       FUNC_TYPE(func) PTR_TO_REAL(func); \
2533cab2bb3Spatrick     } \
2543cab2bb3Spatrick     extern "C" \
2553cab2bb3Spatrick     INTERCEPTOR_ATTRIBUTE \
2563cab2bb3Spatrick     ret_type __stdcall WRAP(func)(__VA_ARGS__)
2573cab2bb3Spatrick #endif
2583cab2bb3Spatrick 
2593cab2bb3Spatrick // ISO C++ forbids casting between pointer-to-function and pointer-to-object,
2603cab2bb3Spatrick // so we use casting via an integral type __interception::uptr,
2613cab2bb3Spatrick // assuming that system is POSIX-compliant. Using other hacks seem
2623cab2bb3Spatrick // challenging, as we don't even pass function type to
2633cab2bb3Spatrick // INTERCEPT_FUNCTION macro, only its name.
2643cab2bb3Spatrick namespace __interception {
2653cab2bb3Spatrick #if defined(_WIN64)
2663cab2bb3Spatrick typedef unsigned long long uptr;
2673cab2bb3Spatrick #else
2683cab2bb3Spatrick typedef unsigned long uptr;
2693cab2bb3Spatrick #endif  // _WIN64
2703cab2bb3Spatrick }  // namespace __interception
2713cab2bb3Spatrick 
2723cab2bb3Spatrick #define INCLUDED_FROM_INTERCEPTION_LIB
2733cab2bb3Spatrick 
2743cab2bb3Spatrick #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
2755e1c9963Sgnezdo     SANITIZER_OPENBSD || SANITIZER_SOLARIS
2763cab2bb3Spatrick 
2773cab2bb3Spatrick # include "interception_linux.h"
2783cab2bb3Spatrick # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
2793cab2bb3Spatrick # define INTERCEPT_FUNCTION_VER(func, symver) \
2803cab2bb3Spatrick     INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
281*68dd5bb1Srobert #elif SANITIZER_APPLE
2823cab2bb3Spatrick # include "interception_mac.h"
2833cab2bb3Spatrick # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
2843cab2bb3Spatrick # define INTERCEPT_FUNCTION_VER(func, symver) \
2853cab2bb3Spatrick     INTERCEPT_FUNCTION_VER_MAC(func, symver)
2863cab2bb3Spatrick #elif SANITIZER_WINDOWS
2873cab2bb3Spatrick # include "interception_win.h"
2883cab2bb3Spatrick # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_WIN(func)
2893cab2bb3Spatrick # define INTERCEPT_FUNCTION_VER(func, symver) \
2903cab2bb3Spatrick     INTERCEPT_FUNCTION_VER_WIN(func, symver)
2913cab2bb3Spatrick #endif
2923cab2bb3Spatrick 
2933cab2bb3Spatrick #undef INCLUDED_FROM_INTERCEPTION_LIB
2943cab2bb3Spatrick 
2953cab2bb3Spatrick #endif  // INTERCEPTION_H
296