[compiler-rt] d2ac277 - [compiler-rt] Introduce the notion of an interceptor trampoline

Marco Elver via llvm-commits llvm-commits at lists.llvm.org
Thu May 25 03:01:42 PDT 2023


Author: Marco Elver
Date: 2023-05-25T12:01:09+02:00
New Revision: d2ac2776021def69e9d0e64c9a958e0c361a919a

URL: https://github.com/llvm/llvm-project/commit/d2ac2776021def69e9d0e64c9a958e0c361a919a
DIFF: https://github.com/llvm/llvm-project/commit/d2ac2776021def69e9d0e64c9a958e0c361a919a.diff

LOG: [compiler-rt] Introduce the notion of an interceptor trampoline

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

Added: 
    

Modified: 
    compiler-rt/lib/interception/interception.h
    compiler-rt/lib/interception/interception_linux.cpp
    compiler-rt/lib/interception/interception_linux.h

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/interception/interception.h b/compiler-rt/lib/interception/interception.h
index 4663fa48cdb39..1b069bd42621d 100644
--- a/compiler-rt/lib/interception/interception.h
+++ b/compiler-rt/lib/interception/interception.h
@@ -118,11 +118,13 @@ 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__);
@@ -130,6 +132,7 @@ const interpose_substitution substitution_##func_name[] \
     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
@@ -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__) \
@@ -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 
diff erent 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, ...)

diff  --git a/compiler-rt/lib/interception/interception_linux.cpp b/compiler-rt/lib/interception/interception_linux.cpp
index 5111a87f0a6c9..ef8136eb4fc70 100644
--- a/compiler-rt/lib/interception/interception_linux.cpp
+++ b/compiler-rt/lib/interception/interception_linux.cpp
@@ -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"))
@@ -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.
@@ -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
 

diff  --git a/compiler-rt/lib/interception/interception_linux.h b/compiler-rt/lib/interception/interception_linux.h
index a08f8cb98c409..77c94d66fc35c 100644
--- a/compiler-rt/lib/interception/interception_linux.h
+++ b/compiler-rt/lib/interception/interception_linux.h
@@ -23,9 +23,9 @@
 
 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) \
@@ -33,7 +33,7 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
       #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
@@ -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)


        


More information about the llvm-commits mailing list