Skip to content

Commit

Permalink
[compiler-rt] Introduce the notion of an interceptor trampoline
Browse files Browse the repository at this point in the history
To make the interceptor implementation more flexible, allowing for 2
levels of indirection instead of just 1 in the current scheme (where the
intercepted function aliases the interceptor implementation), introduce
the notion of an interceptor "trampoline".

A trampoline may be a real function (and not just an alias, where
aliases of aliases do not work), which will simply forward to the
interceptor implementation; the intercepted function will then alias the
trampoline:

	func -[alias]-> trampoline -[call]-> interceptor

Make the necessary changes to prepare for introducing real trampolines.

This change does not yet introduce any real trampolines, and so
trampoline == interceptor, and we currently still just have:

	func -[alias]-> interceptor

NFC.

Reviewed By: dvyukov, vitalybuka, MaskRay

Differential Revision: https://reviews.llvm.org/D151316
  • Loading branch information
melver committed May 25, 2023
1 parent f3c3f63 commit d2ac277
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 16 deletions.
14 changes: 10 additions & 4 deletions compiler-rt/lib/interception/interception.h
Expand Up @@ -118,18 +118,21 @@ const interpose_substitution substitution_##func_name[] \
}

# define WRAP(x) wrap_##x
# define TRAMPOLINE(x) WRAP(x)
# define INTERCEPTOR_ATTRIBUTE
# define DECLARE_WRAPPER(ret_type, func, ...)

#elif SANITIZER_WINDOWS
# define WRAP(x) __asan_wrap_##x
# define TRAMPOLINE(x) WRAP(x)
# define INTERCEPTOR_ATTRIBUTE __declspec(dllexport)
# 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__);
#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
# define WRAP(x) __interceptor_ ## x
# define TRAMPOLINE(x) WRAP(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
Expand All @@ -139,6 +142,7 @@ const interpose_substitution substitution_##func_name[] \
__attribute__((alias("__interceptor_" #func), visibility("default")));
#elif !SANITIZER_FUCHSIA
# define WRAP(x) __interceptor_ ## x
# define TRAMPOLINE(x) WRAP(x)
# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
# define DECLARE_WRAPPER(ret_type, func, ...) \
extern "C" ret_type func(__VA_ARGS__) \
Expand Down Expand Up @@ -172,14 +176,16 @@ const interpose_substitution substitution_##func_name[] \
#endif // SANITIZER_APPLE

#if !SANITIZER_FUCHSIA
# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
DECLARE_REAL(ret_type, func, __VA_ARGS__) \
extern "C" ret_type TRAMPOLINE(func)(__VA_ARGS__); \
extern "C" ret_type WRAP(func)(__VA_ARGS__);
// Declare an interceptor and its wrapper defined in a different translation
// unit (ex. asm).
# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \
extern "C" ret_type WRAP(func)(__VA_ARGS__); \
extern "C" ret_type func(__VA_ARGS__);
# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \
extern "C" ret_type TRAMPOLINE(func)(__VA_ARGS__); \
extern "C" ret_type WRAP(func)(__VA_ARGS__); \
extern "C" ret_type func(__VA_ARGS__);
#else
# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...)
# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...)
Expand Down
16 changes: 8 additions & 8 deletions compiler-rt/lib/interception/interception_linux.cpp
Expand Up @@ -33,7 +33,7 @@ static int StrCmp(const char *s1, const char *s2) {
}
#endif

static void *GetFuncAddr(const char *name, uptr wrapper_addr) {
static void *GetFuncAddr(const char *name, uptr trampoline) {
#if SANITIZER_NETBSD
// FIXME: Find a better way to handle renames
if (StrCmp(name, "sigaction"))
Expand All @@ -50,17 +50,17 @@ static void *GetFuncAddr(const char *name, uptr wrapper_addr) {

// In case `name' is not loaded, dlsym ends up finding the actual wrapper.
// We don't want to intercept the wrapper and have it point to itself.
if ((uptr)addr == wrapper_addr)
if ((uptr)addr == trampoline)
addr = nullptr;
}
return addr;
}

bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
uptr wrapper) {
void *addr = GetFuncAddr(name, wrapper);
uptr trampoline) {
void *addr = GetFuncAddr(name, trampoline);
*ptr_to_real = (uptr)addr;
return addr && (func == wrapper);
return addr && (func == trampoline);
}

// dlvsym is a GNU extension supported by some other platforms.
Expand All @@ -70,12 +70,12 @@ static void *GetFuncAddr(const char *name, const char *ver) {
}

bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
uptr func, uptr wrapper) {
uptr func, uptr trampoline) {
void *addr = GetFuncAddr(name, ver);
*ptr_to_real = (uptr)addr;
return addr && (func == wrapper);
return addr && (func == trampoline);
}
#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
# endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD

} // namespace __interception

Expand Down
8 changes: 4 additions & 4 deletions compiler-rt/lib/interception/interception_linux.h
Expand Up @@ -23,17 +23,17 @@

namespace __interception {
bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
uptr wrapper);
uptr trampoline);
bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
uptr func, uptr wrapper);
uptr func, uptr trampoline);
} // namespace __interception

#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
::__interception::InterceptFunction( \
#func, \
(::__interception::uptr *) & REAL(func), \
(::__interception::uptr) & (func), \
(::__interception::uptr) & WRAP(func))
(::__interception::uptr) & TRAMPOLINE(func))

// dlvsym is a GNU extension supported by some other platforms.
#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
Expand All @@ -42,7 +42,7 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
#func, symver, \
(::__interception::uptr *) & REAL(func), \
(::__interception::uptr) & (func), \
(::__interception::uptr) & WRAP(func))
(::__interception::uptr) & TRAMPOLINE(func))
#else
#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
Expand Down

0 comments on commit d2ac277

Please sign in to comment.