2012-02-09 03:52:01 +08:00
|
|
|
//===-- interception.h ------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is a part of AddressSanitizer, an address sanity checker.
|
|
|
|
//
|
|
|
|
// Machinery for providing replacements/wrappers for system functions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef INTERCEPTION_H
|
|
|
|
#define INTERCEPTION_H
|
|
|
|
|
2014-02-24 16:37:41 +08:00
|
|
|
#if !defined(__linux__) && !defined(__FreeBSD__) && \
|
|
|
|
!defined(__APPLE__) && !defined(_WIN32)
|
2012-02-09 03:52:01 +08:00
|
|
|
# error "Interception doesn't work on this operating system."
|
|
|
|
#endif
|
|
|
|
|
2013-01-30 22:27:41 +08:00
|
|
|
#include "sanitizer_common/sanitizer_internal_defs.h"
|
2012-12-13 14:31:40 +08:00
|
|
|
|
|
|
|
// These typedefs should be used only in the interceptor definitions to replace
|
|
|
|
// the standard system types (e.g. SSIZE_T instead of ssize_t)
|
2013-02-27 19:22:40 +08:00
|
|
|
typedef __sanitizer::uptr SIZE_T;
|
|
|
|
typedef __sanitizer::sptr SSIZE_T;
|
|
|
|
typedef __sanitizer::sptr PTRDIFF_T;
|
|
|
|
typedef __sanitizer::s64 INTMAX_T;
|
|
|
|
typedef __sanitizer::OFF_T OFF_T;
|
|
|
|
typedef __sanitizer::OFF64_T OFF64_T;
|
2012-12-13 14:31:40 +08:00
|
|
|
|
2012-02-09 03:52:01 +08:00
|
|
|
// How to add an interceptor:
|
|
|
|
// Suppose you need to wrap/replace system function (generally, from libc):
|
|
|
|
// int foo(const char *bar, double baz);
|
|
|
|
// You'll need to:
|
|
|
|
// 1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in
|
2013-05-20 21:32:35 +08:00
|
|
|
// your source file. See the notes below for cases when
|
|
|
|
// INTERCEPTOR_WITH_SUFFIX(...) should be used instead.
|
2012-02-09 03:52:01 +08:00
|
|
|
// 2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo".
|
|
|
|
// INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was
|
|
|
|
// intercepted successfully.
|
|
|
|
// You can access original function by calling REAL(foo)(bar, baz).
|
|
|
|
// By default, REAL(foo) will be visible only inside your interceptor, and if
|
|
|
|
// you want to use it in other parts of RTL, you'll need to:
|
2012-06-28 16:27:24 +08:00
|
|
|
// 3a) add DECLARE_REAL(int, foo, const char*, double) to a
|
2012-02-09 03:52:01 +08:00
|
|
|
// header file.
|
|
|
|
// However, if the call "INTERCEPT_FUNCTION(foo)" and definition for
|
|
|
|
// INTERCEPTOR(..., foo, ...) are in different files, you'll instead need to:
|
2012-06-28 16:27:24 +08:00
|
|
|
// 3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double)
|
2012-02-09 03:52:01 +08:00
|
|
|
// to a header file.
|
|
|
|
|
2013-02-21 22:41:16 +08:00
|
|
|
// Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or
|
2012-06-28 16:27:24 +08:00
|
|
|
// DECLARE_REAL(...) are located inside namespaces.
|
2013-02-21 22:41:16 +08:00
|
|
|
// 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to
|
2012-02-09 03:52:01 +08:00
|
|
|
// effectively redirect calls from "foo" to "zoo". In this case
|
|
|
|
// you aren't required to implement
|
2012-06-28 16:27:24 +08:00
|
|
|
// INTERCEPTOR(int, foo, const char *bar, double baz) {...}
|
2012-02-09 03:52:01 +08:00
|
|
|
// but instead you'll have to add
|
2013-02-21 22:41:16 +08:00
|
|
|
// DECLARE_REAL(int, foo, const char *bar, double baz) in your
|
2012-02-09 03:52:01 +08:00
|
|
|
// source file (to define a pointer to overriden function).
|
2013-05-20 21:32:35 +08:00
|
|
|
// 3. Some Mac functions have symbol variants discriminated by
|
|
|
|
// additional suffixes, e.g. _$UNIX2003 (see
|
|
|
|
// https://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/index.html
|
|
|
|
// for more details). To intercept such functions you need to use the
|
|
|
|
// INTERCEPTOR_WITH_SUFFIX(...) macro.
|
2012-02-09 03:52:01 +08:00
|
|
|
|
|
|
|
// How it works:
|
2012-05-24 21:54:31 +08:00
|
|
|
// To replace system functions on Linux we just need to declare functions
|
2012-02-09 03:52:01 +08:00
|
|
|
// with same names in our library and then obtain the real function pointers
|
2012-05-24 21:54:31 +08:00
|
|
|
// using dlsym().
|
|
|
|
// There is one complication. A user may also intercept some of the functions
|
2012-05-28 15:47:35 +08:00
|
|
|
// we intercept. To resolve this we declare our interceptors with __interceptor_
|
|
|
|
// prefix, and then make actual interceptors weak aliases to __interceptor_
|
2012-05-24 21:54:31 +08:00
|
|
|
// functions.
|
2013-02-21 22:41:16 +08:00
|
|
|
//
|
2012-05-24 21:54:31 +08:00
|
|
|
// This is not so on Mac OS, where the two-level namespace makes
|
2012-02-09 03:52:01 +08:00
|
|
|
// our replacement functions invisible to other libraries. This may be overcomed
|
|
|
|
// using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
|
2013-02-05 23:57:12 +08:00
|
|
|
// libraries in Chromium were noticed when doing so.
|
|
|
|
// Instead we create a dylib containing a __DATA,__interpose section that
|
|
|
|
// associates library functions with their wrappers. When this dylib is
|
|
|
|
// preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all
|
|
|
|
// the calls to interposed functions done through stubs to the wrapper
|
|
|
|
// functions.
|
2013-02-21 22:41:16 +08:00
|
|
|
// As it's decided at compile time which functions are to be intercepted on Mac,
|
|
|
|
// INTERCEPT_FUNCTION() is effectively a no-op on this system.
|
2012-02-09 03:52:01 +08:00
|
|
|
|
|
|
|
#if defined(__APPLE__)
|
2013-05-20 21:32:35 +08:00
|
|
|
#include <sys/cdefs.h> // For __DARWIN_ALIAS_C().
|
2013-02-21 22:41:16 +08:00
|
|
|
|
|
|
|
// Just a pair of pointers.
|
|
|
|
struct interpose_substitution {
|
|
|
|
const uptr replacement;
|
|
|
|
const uptr original;
|
|
|
|
};
|
|
|
|
|
|
|
|
// For a function foo() create a global pair of pointers { wrap_foo, foo } in
|
|
|
|
// the __DATA,__interpose section.
|
|
|
|
// As a result all the calls to foo() will be routed to wrap_foo() at runtime.
|
|
|
|
#define INTERPOSER(func_name) __attribute__((used)) \
|
|
|
|
const interpose_substitution substitution_##func_name[] \
|
|
|
|
__attribute__((section("__DATA, __interpose"))) = { \
|
|
|
|
{ reinterpret_cast<const uptr>(WRAP(func_name)), \
|
|
|
|
reinterpret_cast<const uptr>(func_name) } \
|
|
|
|
}
|
|
|
|
|
|
|
|
// For a function foo() and a wrapper function bar() create a global pair
|
|
|
|
// of pointers { bar, foo } in the __DATA,__interpose section.
|
|
|
|
// As a result all the calls to foo() will be routed to bar() at runtime.
|
|
|
|
#define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \
|
|
|
|
const interpose_substitution substitution_##func_name[] \
|
|
|
|
__attribute__((section("__DATA, __interpose"))) = { \
|
|
|
|
{ reinterpret_cast<const uptr>(wrapper_name), \
|
|
|
|
reinterpret_cast<const uptr>(func_name) } \
|
|
|
|
}
|
|
|
|
|
2012-02-09 03:52:01 +08:00
|
|
|
# define WRAP(x) wrap_##x
|
|
|
|
# define WRAPPER_NAME(x) "wrap_"#x
|
|
|
|
# define INTERCEPTOR_ATTRIBUTE
|
2012-09-11 23:02:20 +08:00
|
|
|
# define DECLARE_WRAPPER(ret_type, func, ...)
|
2013-02-21 22:41:16 +08:00
|
|
|
|
2012-02-09 03:52:01 +08:00
|
|
|
#elif defined(_WIN32)
|
2014-08-22 20:38:07 +08:00
|
|
|
# define WRAP(x) __asan_wrap_##x
|
|
|
|
# define WRAPPER_NAME(x) "__asan_wrap_"#x
|
|
|
|
# define INTERCEPTOR_ATTRIBUTE __declspec(dllexport)
|
2013-09-10 22:42:15 +08:00
|
|
|
# define DECLARE_WRAPPER(ret_type, func, ...) \
|
|
|
|
extern "C" ret_type func(__VA_ARGS__);
|
|
|
|
# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
|
|
|
|
extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
|
2014-07-10 17:16:58 +08:00
|
|
|
#elif defined(__FreeBSD__)
|
|
|
|
# define WRAP(x) __interceptor_ ## x
|
|
|
|
# define WRAPPER_NAME(x) "__interceptor_" #x
|
|
|
|
# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
|
|
|
|
// FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher
|
|
|
|
// priority than weak ones so weak aliases won't work for indirect calls
|
|
|
|
// in position-independent (-fPIC / -fPIE) mode.
|
|
|
|
# define DECLARE_WRAPPER(ret_type, func, ...) \
|
|
|
|
extern "C" ret_type func(__VA_ARGS__) \
|
|
|
|
__attribute__((alias("__interceptor_" #func), visibility("default")));
|
2012-02-09 03:52:01 +08:00
|
|
|
#else
|
2012-05-28 15:47:35 +08:00
|
|
|
# define WRAP(x) __interceptor_ ## x
|
|
|
|
# define WRAPPER_NAME(x) "__interceptor_" #x
|
2012-02-09 03:52:01 +08:00
|
|
|
# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
|
2012-09-11 23:02:20 +08:00
|
|
|
# define DECLARE_WRAPPER(ret_type, func, ...) \
|
|
|
|
extern "C" ret_type func(__VA_ARGS__) \
|
2012-06-28 16:07:19 +08:00
|
|
|
__attribute__((weak, alias("__interceptor_" #func), visibility("default")));
|
2012-02-09 03:52:01 +08:00
|
|
|
#endif
|
|
|
|
|
2013-02-05 23:57:12 +08:00
|
|
|
#if !defined(__APPLE__)
|
2012-08-17 17:00:08 +08:00
|
|
|
# define PTR_TO_REAL(x) real_##x
|
|
|
|
# define REAL(x) __interception::PTR_TO_REAL(x)
|
|
|
|
# define FUNC_TYPE(x) x##_f
|
|
|
|
|
|
|
|
# define DECLARE_REAL(ret_type, func, ...) \
|
|
|
|
typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
|
|
|
|
namespace __interception { \
|
|
|
|
extern FUNC_TYPE(func) PTR_TO_REAL(func); \
|
|
|
|
}
|
[compiler-rt] Fix warnings in interception code
Summary:
This patch is re-introducing the code to fix the
dynamic hooking on windows and to fix a compiler
warning on Apple.
Related patches:
* https://reviews.llvm.org/D22641
* https://reviews.llvm.org/D22610
* https://reviews.llvm.org/rL276311
* https://reviews.llvm.org/rL276490
Both architecture are using different techniques to
hook on library functions (memchr, strcpy,...).
On Apple, the function is not dynamically hooked and
the symbol always points to a valid function
(i.e. can't be null). The REAL macro returns the
symbol.
On windows, the function is dynamically patch and the
REAL(...) function may or may not be null. It depend
on whether or not the function was hooked correctly.
Also, on windows memcpy and memmove are the same.
```
#if !defined(__APPLE__)
[...]
# define REAL(x) __interception::PTR_TO_REAL(x)
# define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
[...]
#else // __APPLE__
[...]
# define REAL(x) x
# define ASSIGN_REAL(x, y)
[...]
#endif // __APPLE__
Reviewers: rnk
Subscribers: kcc, hans, kubabrecka, llvm-commits, bruno, chrisha
Differential Revision: https://reviews.llvm.org/D22758
llvm-svn: 276885
2016-07-28 00:16:54 +08:00
|
|
|
# define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
|
2013-02-05 23:57:12 +08:00
|
|
|
#else // __APPLE__
|
2012-08-17 17:00:08 +08:00
|
|
|
# define REAL(x) x
|
|
|
|
# define DECLARE_REAL(ret_type, func, ...) \
|
|
|
|
extern "C" ret_type func(__VA_ARGS__);
|
[compiler-rt] Fix warnings in interception code
Summary:
This patch is re-introducing the code to fix the
dynamic hooking on windows and to fix a compiler
warning on Apple.
Related patches:
* https://reviews.llvm.org/D22641
* https://reviews.llvm.org/D22610
* https://reviews.llvm.org/rL276311
* https://reviews.llvm.org/rL276490
Both architecture are using different techniques to
hook on library functions (memchr, strcpy,...).
On Apple, the function is not dynamically hooked and
the symbol always points to a valid function
(i.e. can't be null). The REAL macro returns the
symbol.
On windows, the function is dynamically patch and the
REAL(...) function may or may not be null. It depend
on whether or not the function was hooked correctly.
Also, on windows memcpy and memmove are the same.
```
#if !defined(__APPLE__)
[...]
# define REAL(x) __interception::PTR_TO_REAL(x)
# define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
[...]
#else // __APPLE__
[...]
# define REAL(x) x
# define ASSIGN_REAL(x, y)
[...]
#endif // __APPLE__
Reviewers: rnk
Subscribers: kcc, hans, kubabrecka, llvm-commits, bruno, chrisha
Differential Revision: https://reviews.llvm.org/D22758
llvm-svn: 276885
2016-07-28 00:16:54 +08:00
|
|
|
# define ASSIGN_REAL(x, y)
|
2013-02-05 23:57:12 +08:00
|
|
|
#endif // __APPLE__
|
2012-02-09 03:52:01 +08:00
|
|
|
|
2012-06-25 14:53:10 +08:00
|
|
|
#define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
|
2012-09-12 17:42:23 +08:00
|
|
|
DECLARE_REAL(ret_type, func, __VA_ARGS__) \
|
2012-02-09 03:52:01 +08:00
|
|
|
extern "C" ret_type WRAP(func)(__VA_ARGS__);
|
|
|
|
|
2012-09-11 23:02:20 +08:00
|
|
|
// Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR
|
|
|
|
// macros does its job. In exceptional cases you may need to call REAL(foo)
|
|
|
|
// without defining INTERCEPTOR(..., foo, ...). For example, if you override
|
|
|
|
// foo with an interceptor for other function.
|
2013-02-05 23:57:12 +08:00
|
|
|
#if !defined(__APPLE__)
|
2012-09-11 23:02:20 +08:00
|
|
|
# define DEFINE_REAL(ret_type, func, ...) \
|
|
|
|
typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
|
2012-08-17 17:00:08 +08:00
|
|
|
namespace __interception { \
|
|
|
|
FUNC_TYPE(func) PTR_TO_REAL(func); \
|
|
|
|
}
|
|
|
|
#else
|
2012-09-11 23:02:20 +08:00
|
|
|
# define DEFINE_REAL(ret_type, func, ...)
|
2012-08-17 17:00:08 +08:00
|
|
|
#endif
|
2012-02-24 23:28:43 +08:00
|
|
|
|
2013-02-21 22:41:16 +08:00
|
|
|
#if !defined(__APPLE__)
|
2012-09-11 23:02:20 +08:00
|
|
|
#define INTERCEPTOR(ret_type, func, ...) \
|
|
|
|
DEFINE_REAL(ret_type, func, __VA_ARGS__) \
|
|
|
|
DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
|
2012-02-09 03:52:01 +08:00
|
|
|
extern "C" \
|
|
|
|
INTERCEPTOR_ATTRIBUTE \
|
2012-09-11 23:02:20 +08:00
|
|
|
ret_type WRAP(func)(__VA_ARGS__)
|
2013-05-20 21:32:35 +08:00
|
|
|
|
|
|
|
// We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now.
|
|
|
|
#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
|
|
|
|
INTERCEPTOR(ret_type, func, __VA_ARGS__)
|
|
|
|
|
2013-02-21 22:41:16 +08:00
|
|
|
#else // __APPLE__
|
2013-05-20 21:32:35 +08:00
|
|
|
|
|
|
|
#define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \
|
|
|
|
extern "C" ret_type func(__VA_ARGS__) suffix; \
|
2013-02-21 22:41:16 +08:00
|
|
|
extern "C" ret_type WRAP(func)(__VA_ARGS__); \
|
|
|
|
INTERPOSER(func); \
|
|
|
|
extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
|
|
|
|
|
2013-05-20 21:32:35 +08:00
|
|
|
#define INTERCEPTOR(ret_type, func, ...) \
|
|
|
|
INTERCEPTOR_ZZZ(/*no symbol variants*/, ret_type, func, __VA_ARGS__)
|
|
|
|
|
|
|
|
#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
|
|
|
|
INTERCEPTOR_ZZZ(__DARWIN_ALIAS_C(func), ret_type, func, __VA_ARGS__)
|
|
|
|
|
2013-02-21 22:41:16 +08:00
|
|
|
// Override |overridee| with |overrider|.
|
|
|
|
#define OVERRIDE_FUNCTION(overridee, overrider) \
|
|
|
|
INTERPOSER_2(overridee, WRAP(overrider))
|
|
|
|
#endif
|
2012-02-24 23:28:43 +08:00
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
# define INTERCEPTOR_WINAPI(ret_type, func, ...) \
|
2012-09-11 23:02:20 +08:00
|
|
|
typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \
|
|
|
|
namespace __interception { \
|
|
|
|
FUNC_TYPE(func) PTR_TO_REAL(func); \
|
|
|
|
} \
|
|
|
|
extern "C" \
|
|
|
|
INTERCEPTOR_ATTRIBUTE \
|
|
|
|
ret_type __stdcall WRAP(func)(__VA_ARGS__)
|
2012-02-24 23:28:43 +08:00
|
|
|
#endif
|
2012-02-09 03:52:01 +08:00
|
|
|
|
2012-08-02 19:19:13 +08:00
|
|
|
// ISO C++ forbids casting between pointer-to-function and pointer-to-object,
|
|
|
|
// so we use casting via an integral type __interception::uptr,
|
|
|
|
// assuming that system is POSIX-compliant. Using other hacks seem
|
|
|
|
// challenging, as we don't even pass function type to
|
|
|
|
// INTERCEPT_FUNCTION macro, only its name.
|
|
|
|
namespace __interception {
|
2012-09-24 19:43:40 +08:00
|
|
|
#if defined(_WIN64)
|
|
|
|
typedef unsigned long long uptr; // NOLINT
|
|
|
|
#else
|
2012-08-02 19:19:13 +08:00
|
|
|
typedef unsigned long uptr; // NOLINT
|
2012-09-24 19:43:40 +08:00
|
|
|
#endif // _WIN64
|
2012-08-02 19:19:13 +08:00
|
|
|
} // namespace __interception
|
|
|
|
|
2012-02-09 03:52:01 +08:00
|
|
|
#define INCLUDED_FROM_INTERCEPTION_LIB
|
|
|
|
|
2014-02-24 16:37:41 +08:00
|
|
|
#if defined(__linux__) || defined(__FreeBSD__)
|
2012-02-09 03:52:01 +08:00
|
|
|
# include "interception_linux.h"
|
2014-02-24 16:37:41 +08:00
|
|
|
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
|
2013-10-16 16:20:31 +08:00
|
|
|
# define INTERCEPT_FUNCTION_VER(func, symver) \
|
2014-02-24 16:37:41 +08:00
|
|
|
INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
|
2012-02-09 03:52:01 +08:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
# include "interception_mac.h"
|
|
|
|
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
|
2013-10-16 16:20:31 +08:00
|
|
|
# define INTERCEPT_FUNCTION_VER(func, symver) \
|
|
|
|
INTERCEPT_FUNCTION_VER_MAC(func, symver)
|
2012-02-09 03:52:01 +08:00
|
|
|
#else // defined(_WIN32)
|
2012-02-22 21:59:49 +08:00
|
|
|
# include "interception_win.h"
|
|
|
|
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_WIN(func)
|
2013-10-16 16:20:31 +08:00
|
|
|
# define INTERCEPT_FUNCTION_VER(func, symver) \
|
|
|
|
INTERCEPT_FUNCTION_VER_WIN(func, symver)
|
2012-02-09 03:52:01 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#undef INCLUDED_FROM_INTERCEPTION_LIB
|
|
|
|
|
|
|
|
#endif // INTERCEPTION_H
|