libsanitizer: use calls forwarding mechanism in common and asan interceptors. 85/210785/14
authorAndrey Drobyshev <a.drobyshev@samsung.com>
Mon, 20 May 2019 17:48:56 +0000 (20:48 +0300)
committerDongkyun Son <dongkyun.s@samsung.com>
Sat, 27 Jul 2019 16:38:53 +0000 (16:38 +0000)
    * libsanitizer/asan/asan_allocator.cc: add (asan_pointer_is_mine)
    * libsanitizer/asan/asan_allocator.h: declare (asan_pointer_is_mine)
    * libsanitizer/asan/asan_interceptors.h: declare
    (InitializeMallocInterceptors), (InitializeNewDeleteInterceptors)
    * libsanitizer/asan/asan_new_delete.cc: intercept various new and
    delete operators. Implement (InitializeNewDeleteInterceptors)
    * libsanitizer/asan/asan_interceptors.cc: use MAYBE_FORWARD_TO_REAL
    in interceptors
    * libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:
    likewise
    * libsanitizer/asan/asan_malloc_linux.cc: likewise. Also implement
    (InitializeMallocInterceptors)
    * libsanitizer/asan/asan_mac.cc: add empty (InitializeMallocInterceptors)
    * libsanitizer/asan/asan_win.cc: likewise

Change-Id: I53d8b5d8476716282fd1438cdafd7fcf030291ab
Signed-off-by: Andrey Drobyshev <a.drobyshev@samsung.com>
libsanitizer/asan/asan_allocator.cc
libsanitizer/asan/asan_allocator.h
libsanitizer/asan/asan_interceptors.cc
libsanitizer/asan/asan_interceptors.h
libsanitizer/asan/asan_mac.cc
libsanitizer/asan/asan_malloc_linux.cc
libsanitizer/asan/asan_new_delete.cc
libsanitizer/asan/asan_win.cc
libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc

index 7bb766d..09783ec 100644 (file)
@@ -25,6 +25,7 @@
 #include "sanitizer_common/sanitizer_list.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
 #include "sanitizer_common/sanitizer_quarantine.h"
+#include "sanitizer_common/sanitizer_forward_calls.h"
 #include "lsan/lsan_common.h"
 
 namespace __asan {
@@ -847,6 +848,12 @@ void AsanSoftRssLimitExceededCallback(bool limit_exceeded) {
   instance.SetRssLimitExceeded(limit_exceeded);
 }
 
+#if SANITIZER_CALLS_FORWARDING
+bool asan_pointer_is_mine(const void *ptr) {
+  return instance.allocator.PointerIsMine(ptr);
+}
+#endif
+
 } // namespace __asan
 
 // --- Implementation of LSan-specific functions --- {{{1
index 70a3aa9..9bbca2d 100644 (file)
@@ -199,6 +199,12 @@ uptr asan_mz_size(const void *ptr);
 void asan_mz_force_lock();
 void asan_mz_force_unlock();
 
+#if SANITIZER_CALLS_FORWARDING
+bool asan_pointer_is_mine(const void *ptr);
+#else
+# define asan_pointer_is_mine(ptr) true
+#endif
+
 void PrintInternalAllocatorStats();
 void AsanSoftRssLimitExceededCallback(bool exceeded);
 
index 2e99a7f..1b8ab4a 100644 (file)
@@ -21,6 +21,7 @@
 #include "asan_suppressions.h"
 #include "lsan/lsan_common.h"
 #include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_forward_calls.h"
 
 #if SANITIZER_POSIX
 #include "sanitizer_common/sanitizer_posix.h"
@@ -237,6 +238,7 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
 INTERCEPTOR(int, pthread_create, void *thread,
     void *attr, void *(*start_routine)(void*), void *arg) {
   EnsureMainThreadIDIsCorrect();
+  MAYBE_FORWARD_TO_REAL(pthread_create, thread, attr, start_routine, arg);
   // Strict init-order checking is thread-hostile.
   if (flags()->strict_init_order)
     StopInitOrderChecking();
@@ -276,6 +278,7 @@ INTERCEPTOR(int, pthread_create, void *thread,
 }
 
 INTERCEPTOR(int, pthread_join, void *t, void **arg) {
+  MAYBE_FORWARD_TO_REAL(pthread_join, t, arg);
   return real_pthread_join(t, arg);
 }
 
@@ -286,6 +289,7 @@ DEFINE_REAL_PTHREAD_FUNCTIONS
 
 #if SANITIZER_ANDROID
 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
+  MAYBE_FORWARD_TO_REAL(bsd_signal, signum, handler);
   if (!IsHandledDeadlySignal(signum) ||
       common_flags()->allow_user_segv_handler) {
     return REAL(bsd_signal)(signum, handler);
@@ -295,6 +299,7 @@ INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
 #endif
 
 INTERCEPTOR(void*, signal, int signum, void *handler) {
+  MAYBE_FORWARD_TO_REAL(signal, signum, handler);
   if (!IsHandledDeadlySignal(signum) ||
       common_flags()->allow_user_segv_handler) {
     return REAL(signal)(signum, handler);
@@ -304,6 +309,7 @@ INTERCEPTOR(void*, signal, int signum, void *handler) {
 
 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
                             struct sigaction *oldact) {
+  MAYBE_FORWARD_TO_REAL(sigaction, signum, act, oldact);
   if (!IsHandledDeadlySignal(signum) ||
       common_flags()->allow_user_segv_handler) {
     return REAL(sigaction)(signum, act, oldact);
@@ -339,6 +345,7 @@ static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
 
 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
             struct ucontext_t *ucp) {
+  MAYBE_FORWARD_TO_REAL(swapcontext, oucp, ucp);
   static bool reported_warning = false;
   if (!reported_warning) {
     Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
@@ -361,12 +368,14 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
 #endif  // ASAN_INTERCEPT_SWAPCONTEXT
 
 INTERCEPTOR(void, longjmp, void *env, int val) {
+  MAYBE_FORWARD_TO_REAL(longjmp, env, val);
   __asan_handle_no_return();
   REAL(longjmp)(env, val);
 }
 
 #if ASAN_INTERCEPT__LONGJMP
 INTERCEPTOR(void, _longjmp, void *env, int val) {
+  MAYBE_FORWARD_TO_REAL(_longjmp, env, val);
   __asan_handle_no_return();
   REAL(_longjmp)(env, val);
 }
@@ -374,6 +383,7 @@ INTERCEPTOR(void, _longjmp, void *env, int val) {
 
 #if ASAN_INTERCEPT___LONGJMP_CHK
 INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
+  MAYBE_FORWARD_TO_REAL(__longjmp_chk, env, val);
   __asan_handle_no_return();
   REAL(__longjmp_chk)(env, val);
 }
@@ -381,6 +391,7 @@ INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
 
 #if ASAN_INTERCEPT_SIGLONGJMP
 INTERCEPTOR(void, siglongjmp, void *env, int val) {
+  MAYBE_FORWARD_TO_REAL(siglongjmp, env, val);
   __asan_handle_no_return();
   REAL(siglongjmp)(env, val);
 }
@@ -388,6 +399,7 @@ INTERCEPTOR(void, siglongjmp, void *env, int val) {
 
 #if ASAN_INTERCEPT__LIBC_SIGLONGJMP
 INTERCEPTOR(void, __libc_siglongjmp, void *env, int val) {
+  MAYBE_FORWARD_TO_REAL(__libc_siglongjmp, env, val);
   __asan_handle_no_return();
   REAL(__libc_siglongjmp)(env, val);
 }
@@ -395,6 +407,7 @@ INTERCEPTOR(void, __libc_siglongjmp, void *env, int val) {
 
 #if ASAN_INTERCEPT__LIBC_LONGJMP
 INTERCEPTOR(void, __libc_longjmp, void *env, int val) {
+  MAYBE_FORWARD_TO_REAL(__libc_longjmp, env, val);
   __asan_handle_no_return();
   REAL(__libc_longjmp)(env, val);
 }
@@ -402,6 +415,7 @@ INTERCEPTOR(void, __libc_longjmp, void *env, int val) {
 
 #if ASAN_INTERCEPT___CXA_THROW
 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
+  MAYBE_FORWARD_TO_REAL(__cxa_throw, a, b, c);
   CHECK(REAL(__cxa_throw));
   __asan_handle_no_return();
   REAL(__cxa_throw)(a, b, c);
@@ -465,12 +479,14 @@ void *__asan_memmove(void *to, const void *from, uptr size) {
 }
 
 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(memmove, to, from, size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, memmove);
   ASAN_MEMMOVE_IMPL(ctx, to, from, size);
 }
 
 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(memcpy, to, from, size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, memcpy);
 #if !SANITIZER_MAC
@@ -487,6 +503,7 @@ INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
 }
 
 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
+  MAYBE_FORWARD_TO_REAL(memset, block, c, size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, memset);
   ASAN_MEMSET_IMPL(ctx, block, c, size);
@@ -509,6 +526,7 @@ DEFINE_REAL(char*, index, const char *string, int c)
 // For both strcat() and strncat() we need to check the validity of |to|
 // argument irrespective of the |from| length.
 INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
+  MAYBE_FORWARD_TO_REAL(strcat, to, from);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strcat);  // NOLINT
   ENSURE_ASAN_INITED();
@@ -530,6 +548,7 @@ INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
 }
 
 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(strncat, to, from, size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strncat);
   ENSURE_ASAN_INITED();
@@ -549,6 +568,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
 }
 
 INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
+  MAYBE_FORWARD_TO_REAL(strcpy, to, from);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strcpy);  // NOLINT
 #if SANITIZER_MAC
@@ -570,6 +590,7 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
 }
 
 INTERCEPTOR(char*, strdup, const char *s) {
+  MAYBE_FORWARD_TO_REAL(strdup, s);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
@@ -586,6 +607,7 @@ INTERCEPTOR(char*, strdup, const char *s) {
 
 #if ASAN_INTERCEPT___STRDUP
 INTERCEPTOR(char*, __strdup, const char *s) {
+  MAYBE_FORWARD_TO_REAL(__strdup, s);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
@@ -602,6 +624,7 @@ INTERCEPTOR(char*, __strdup, const char *s) {
 #endif // ASAN_INTERCEPT___STRDUP
 
 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
+  MAYBE_FORWARD_TO_REAL(wcslen, s);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
   SIZE_T length = internal_wcslen(s);
@@ -613,6 +636,7 @@ INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
 }
 
 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(strncpy, to, from, size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
   ENSURE_ASAN_INITED();
@@ -628,6 +652,7 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
 #if ASAN_INTERCEPT__FORTIFY_SOURCE
 INTERCEPTOR(char*, __strcpy_chk, char *to, const char *from,
             uptr to_size) {  // NOLINT
+  MAYBE_FORWARD_TO_REAL(__strcpy_chk, to, from, to_size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, __strcpy_chk);  // NOLINT
 #if SANITIZER_MAC
@@ -650,6 +675,7 @@ INTERCEPTOR(char*, __strcpy_chk, char *to, const char *from,
 
 INTERCEPTOR(char*, __strncpy_chk, char *to, const char *from, uptr size,
             uptr to_size) {
+  MAYBE_FORWARD_TO_REAL(__strncpy_chk, to, from, size, to_size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, __strncpy_chk);
   ENSURE_ASAN_INITED();
@@ -663,6 +689,7 @@ INTERCEPTOR(char*, __strncpy_chk, char *to, const char *from, uptr size,
 }
 
 INTERCEPTOR(char*, __strcat_chk, char *to, const char *from, uptr to_size) {
+  MAYBE_FORWARD_TO_REAL(__strcat_chk, to, from, to_size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, __strcat_chk);  // NOLINT
   ENSURE_ASAN_INITED();
@@ -685,6 +712,7 @@ INTERCEPTOR(char*, __strcat_chk, char *to, const char *from, uptr to_size) {
 
 INTERCEPTOR(char*, __strncat_chk, char *to, const char *from, uptr size,
             uptr to_size) {
+  MAYBE_FORWARD_TO_REAL(__strncat_chk, to, from, size, to_size);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, __strncat_chk);
   ENSURE_ASAN_INITED();
@@ -706,6 +734,7 @@ INTERCEPTOR(char*, __strncat_chk, char *to, const char *from, uptr size,
 
 INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
             char **endptr, int base) {
+  MAYBE_FORWARD_TO_REAL(strtol, nptr, endptr, base);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strtol);
   ENSURE_ASAN_INITED();
@@ -719,6 +748,7 @@ INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
 }
 
 INTERCEPTOR(int, atoi, const char *nptr) {
+  MAYBE_FORWARD_TO_REAL(atoi, nptr);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, atoi);
 #if SANITIZER_MAC
@@ -740,6 +770,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
 }
 
 INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
+  MAYBE_FORWARD_TO_REAL(atol, nptr);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, atol);
 #if SANITIZER_MAC
@@ -759,6 +790,7 @@ INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
 INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
             char **endptr, int base) {
+  MAYBE_FORWARD_TO_REAL(strtoll, nptr, endptr, base);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
   ENSURE_ASAN_INITED();
@@ -772,6 +804,7 @@ INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
 }
 
 INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
+  MAYBE_FORWARD_TO_REAL(atoll, nptr);
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, atoll);
   ENSURE_ASAN_INITED();
@@ -798,6 +831,7 @@ INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
 #endif
   ENSURE_ASAN_INITED();
+  MAYBE_FORWARD_TO_REAL(__cxa_atexit, func, arg, dso_handle);
   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
   return res;
@@ -807,6 +841,7 @@ INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
 #if ASAN_INTERCEPT_FORK
 INTERCEPTOR(int, fork, void) {
   ENSURE_ASAN_INITED();
+  MAYBE_FORWARD_TO_REAL(fork,);
   if (common_flags()->coverage) CovBeforeFork();
   int pid = REAL(fork)();
   if (common_flags()->coverage) CovAfterFork(pid);
@@ -917,6 +952,11 @@ void InitializeAsanInterceptors() {
 
   InitializePlatformInterceptors();
 
+#if SANITIZER_CALLS_FORWARDING
+  InitializeMallocInterceptors();
+  InitializeNewDeleteInterceptors();
+#endif
+
   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
 }
 
index 1d9f30b..9458265 100644 (file)
@@ -126,6 +126,11 @@ namespace __asan {
 void InitializeAsanInterceptors();
 void InitializePlatformInterceptors();
 
+#if SANITIZER_CALLS_FORWARDING
+void InitializeMallocInterceptors();
+void InitializeNewDeleteInterceptors();
+#endif
+
 #define ENSURE_ASAN_INITED() do { \
   CHECK(!asan_init_is_running); \
   if (UNLIKELY(!asan_inited)) { \
index 4bf79be..b6b7bc7 100644 (file)
@@ -47,6 +47,10 @@ namespace __asan {
 void InitializePlatformInterceptors() {}
 void InitializePlatformExceptionHandlers() {}
 
+#if SANITIZER_CALLS_FORWARDING
+void InitializeMallocInterceptors() {}
+#endif
+
 bool PlatformHasDifferentMemcpyAndMemmove() {
   // On OS X 10.7 memcpy() and memmove() are both resolved
   // into memmove$VARIANT$sse42.
index 28b8b1f..babec77 100644 (file)
@@ -16,6 +16,7 @@
 #if SANITIZER_FREEBSD || SANITIZER_LINUX
 
 #include "sanitizer_common/sanitizer_tls_get_addr.h"
+#include "sanitizer_common/sanitizer_forward_calls.h"
 #include "asan_allocator.h"
 #include "asan_interceptors.h"
 #include "asan_internal.h"
@@ -45,6 +46,8 @@ INTERCEPTOR(void, free, void *ptr) {
   GET_STACK_TRACE_FREE;
   if (UNLIKELY(IsInDlsymAllocPool(ptr)))
     return;
+  if (UNLIKELY(!asan_pointer_is_mine(ptr)))
+    MAYBE_FORWARD_TO_REAL(free, ptr);
   asan_free(ptr, &stack, FROM_MALLOC);
 }
 
@@ -52,6 +55,8 @@ INTERCEPTOR(void, cfree, void *ptr) {
   GET_STACK_TRACE_FREE;
   if (UNLIKELY(IsInDlsymAllocPool(ptr)))
     return;
+  if (UNLIKELY(!asan_pointer_is_mine(ptr)))
+    MAYBE_FORWARD_TO_REAL(cfree, ptr);
   asan_free(ptr, &stack, FROM_MALLOC);
 }
 
@@ -60,6 +65,7 @@ INTERCEPTOR(void*, malloc, uptr size) {
     // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym.
     return AllocateFromLocalPool(size);
   ENSURE_ASAN_INITED();
+  MAYBE_FORWARD_TO_REAL(malloc, size);
   GET_STACK_TRACE_MALLOC;
   return asan_malloc(size, &stack);
 }
@@ -69,6 +75,7 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
     // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
     return AllocateFromLocalPool(nmemb * size);
   ENSURE_ASAN_INITED();
+  MAYBE_FORWARD_TO_REAL(calloc, nmemb, size);
   GET_STACK_TRACE_MALLOC;
   return asan_calloc(nmemb, size, &stack);
 }
@@ -91,21 +98,26 @@ INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
   if (UNLIKELY(asan_init_is_running))
     return AllocateFromLocalPool(size);
   ENSURE_ASAN_INITED();
+  if (UNLIKELY(!asan_pointer_is_mine(ptr)))
+    MAYBE_FORWARD_TO_REAL(realloc, ptr, size);
   GET_STACK_TRACE_MALLOC;
   return asan_realloc(ptr, size, &stack);
 }
 
 INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
+  MAYBE_FORWARD_TO_REAL(memalign, boundary, size);
   GET_STACK_TRACE_MALLOC;
   return asan_memalign(boundary, size, &stack, FROM_MALLOC);
 }
 
 INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {
+  MAYBE_FORWARD_TO_REAL(aligned_alloc, boundary, size);
   GET_STACK_TRACE_MALLOC;
   return asan_memalign(boundary, size, &stack, FROM_MALLOC);
 }
 
 INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__libc_memalign, boundary, size);
   GET_STACK_TRACE_MALLOC;
   void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC);
   DTLS_on_libc_memalign(res, size);
@@ -113,6 +125,7 @@ INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
 }
 
 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
+  MAYBE_FORWARD_TO_REAL(malloc_usable_size, ptr);
   GET_CURRENT_PC_BP_SP;
   (void)sp;
   return asan_malloc_usable_size(ptr, pc, bp);
@@ -127,35 +140,64 @@ struct fake_mallinfo {
 };
 
 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
+  MAYBE_FORWARD_TO_REAL(mallinfo,);
   struct fake_mallinfo res;
   REAL(memset)(&res, 0, sizeof(res));
   return res;
 }
 
 INTERCEPTOR(int, mallopt, int cmd, int value) {
+  MAYBE_FORWARD_TO_REAL(mallopt, cmd, value);
   return -1;
 }
 
 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
+  MAYBE_FORWARD_TO_REAL(posix_memalign, memptr, alignment, size);
   GET_STACK_TRACE_MALLOC;
   // Printf("posix_memalign: %zx %zu\n", alignment, size);
   return asan_posix_memalign(memptr, alignment, size, &stack);
 }
 
 INTERCEPTOR(void*, valloc, uptr size) {
+  MAYBE_FORWARD_TO_REAL(valloc, size);
   GET_STACK_TRACE_MALLOC;
   return asan_valloc(size, &stack);
 }
 
 INTERCEPTOR(void*, pvalloc, uptr size) {
+  MAYBE_FORWARD_TO_REAL(pvalloc, size);
   GET_STACK_TRACE_MALLOC;
   return asan_pvalloc(size, &stack);
 }
 
 INTERCEPTOR(void, malloc_stats, void) {
+  MAYBE_FORWARD_TO_REAL(malloc_stats,);
   __asan_print_accumulated_stats();
 }
 
+#if SANITIZER_CALLS_FORWARDING
+namespace __asan {
+// Explicitly intercept memory related functions at initialization stage
+void InitializeMallocInterceptors() {
+  ASAN_INTERCEPT_FUNC(free);
+  ASAN_INTERCEPT_FUNC(cfree);
+  ASAN_INTERCEPT_FUNC(malloc);
+  ASAN_INTERCEPT_FUNC(calloc);
+  ASAN_INTERCEPT_FUNC(realloc);
+  ASAN_INTERCEPT_FUNC(memalign);
+  ASAN_INTERCEPT_FUNC(aligned_alloc);
+  ASAN_INTERCEPT_FUNC(__libc_memalign);
+  ASAN_INTERCEPT_FUNC(malloc_usable_size);
+  ASAN_INTERCEPT_FUNC(mallinfo);
+  ASAN_INTERCEPT_FUNC(mallopt);
+  ASAN_INTERCEPT_FUNC(posix_memalign);
+  ASAN_INTERCEPT_FUNC(valloc);
+  ASAN_INTERCEPT_FUNC(pvalloc);
+  ASAN_INTERCEPT_FUNC(malloc_stats);
+}
+} // namespace __asan
+#endif // SANITIZER_CALLS_FORWARDING
+
 #if SANITIZER_ANDROID
 // Format of __libc_malloc_dispatch has changed in Android L.
 // While we are moving towards a solution that does not depend on bionic
index 20fa7ef..53b4a63 100644 (file)
 #include "asan_allocator.h"
 #include "asan_internal.h"
 #include "asan_stack.h"
+#include "asan_interceptors.h"
 
 #include "interception/interception.h"
+#include "sanitizer_common/sanitizer_forward_calls.h"
 
 #include <stddef.h>
 
@@ -72,6 +74,7 @@ struct nothrow_t {};
 #endif  // __FreeBSD_version
 #endif  // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32
 
+#if !SANITIZER_CALLS_FORWARDING
 CXX_OPERATOR_ATTRIBUTE
 void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); }
 CXX_OPERATOR_ATTRIBUTE
@@ -83,6 +86,55 @@ CXX_OPERATOR_ATTRIBUTE
 void *operator new[](size_t size, std::nothrow_t const&)
 { OPERATOR_NEW_BODY(FROM_NEW_BR); }
 
+#else // SANITIZER_CALLS_FORWARDING
+// size_t type is *implementation-defined*, intercept unsigned long/int versions
+// for x32/x64 as a workaround for now.
+// operator new(unsigned long)
+INTERCEPTOR(void *, _Znwm, size_t size) {
+  MAYBE_FORWARD_TO_REAL(_Znwm, size);
+  OPERATOR_NEW_BODY(FROM_NEW);
+}
+// operator new(unsigned int)
+INTERCEPTOR(void *, _Znwj, size_t size) {
+  MAYBE_FORWARD_TO_REAL(_Znwj, size);
+  OPERATOR_NEW_BODY(FROM_NEW);
+}
+// operator new[](unsigned long)
+INTERCEPTOR(void *, _Znam, size_t size) {
+  MAYBE_FORWARD_TO_REAL(_Znam, size);
+  OPERATOR_NEW_BODY(FROM_NEW_BR);
+}
+// operator new[](unsigned int)
+INTERCEPTOR(void *, _Znaj, size_t size) {
+  MAYBE_FORWARD_TO_REAL(_Znaj, size);
+  OPERATOR_NEW_BODY(FROM_NEW_BR);
+}
+// operator new(unsigned long, std::nothrow_t const&)
+INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size,
+            std::nothrow_t const& tag) {
+  MAYBE_FORWARD_TO_REAL(_ZnwmRKSt9nothrow_t, size, tag);
+  OPERATOR_NEW_BODY(FROM_NEW);
+}
+// operator new(unsigned int, std::nothrow_t const&)
+INTERCEPTOR(void *, _ZnwjRKSt9nothrow_t, size_t size,
+            std::nothrow_t const& tag) {
+  MAYBE_FORWARD_TO_REAL(_ZnwjRKSt9nothrow_t, size, tag);
+  OPERATOR_NEW_BODY(FROM_NEW);
+}
+// operator new[](unsigned long, std::nothrow_t const&)
+INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size,
+            std::nothrow_t const& tag) {
+  MAYBE_FORWARD_TO_REAL(_ZnamRKSt9nothrow_t, size, tag);
+  OPERATOR_NEW_BODY(FROM_NEW_BR);
+}
+// operator new[](unsigned int, std::nothrow_t const&)
+INTERCEPTOR(void *, _ZnajRKSt9nothrow_t, size_t size,
+            std::nothrow_t const& tag) {
+  MAYBE_FORWARD_TO_REAL(_ZnajRKSt9nothrow_t, size, tag);
+  OPERATOR_NEW_BODY(FROM_NEW_BR);
+}
+#endif
+
 #else  // SANITIZER_MAC
 INTERCEPTOR(void *, _Znwm, size_t size) {
   OPERATOR_NEW_BODY(FROM_NEW);
@@ -102,7 +154,12 @@ INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
   GET_STACK_TRACE_FREE;\
   asan_free(ptr, &stack, type);
 
+#define OPERATOR_SIZED_DELETE_BODY(type) \
+  GET_STACK_TRACE_FREE;\
+  asan_sized_free(ptr, size, &stack, type);
+
 #if !SANITIZER_MAC
+#if !SANITIZER_CALLS_FORWARDING
 CXX_OPERATOR_ATTRIBUTE
 void operator delete(void *ptr) NOEXCEPT {
   OPERATOR_DELETE_BODY(FROM_NEW);
@@ -121,15 +178,58 @@ void operator delete[](void *ptr, std::nothrow_t const&) {
 }
 CXX_OPERATOR_ATTRIBUTE
 void operator delete(void *ptr, size_t size) NOEXCEPT {
-  GET_STACK_TRACE_FREE;
-  asan_sized_free(ptr, size, &stack, FROM_NEW);
+  OPERATOR_SIZED_DELETE_BODY(FROM_NEW);
 }
 CXX_OPERATOR_ATTRIBUTE
 void operator delete[](void *ptr, size_t size) NOEXCEPT {
-  GET_STACK_TRACE_FREE;
-  asan_sized_free(ptr, size, &stack, FROM_NEW_BR);
+  OPERATOR_SIZED_DELETE_BODY(FROM_NEW_BR);
 }
 
+#else // SANITIZER_CALLS_FORWARDING
+// operator delete(void*)
+INTERCEPTOR(void, _ZdlPv, void *ptr) {
+  MAYBE_FORWARD_TO_REAL(_ZdlPv, ptr);
+  OPERATOR_DELETE_BODY(FROM_NEW);
+}
+// operator delete[](void*)
+INTERCEPTOR(void, _ZdaPv, void *ptr) {
+  MAYBE_FORWARD_TO_REAL(_ZdaPv, ptr);
+  OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
+// operator delete(void*, std::nothrow_t const&)
+INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr,
+            std::nothrow_t const& tag) {
+  MAYBE_FORWARD_TO_REAL(_ZdlPvRKSt9nothrow_t, ptr, tag);
+  OPERATOR_DELETE_BODY(FROM_NEW);
+}
+// operator delete[](void*, std::nothrow_t const&)
+INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr,
+            std::nothrow_t const& tag) {
+  MAYBE_FORWARD_TO_REAL(_ZdaPvRKSt9nothrow_t, ptr, tag);
+  OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
+// operator delete(void*, unsigned long)
+INTERCEPTOR(void, _ZdlPvm, void *ptr, size_t size) {
+  MAYBE_FORWARD_TO_REAL(_ZdlPvm, ptr, size);
+  OPERATOR_SIZED_DELETE_BODY(FROM_NEW);
+}
+// operator delete(void*, unsigned int)
+INTERCEPTOR(void, _ZdlPvj, void *ptr, size_t size) {
+  MAYBE_FORWARD_TO_REAL(_ZdlPvj, ptr, size);
+  OPERATOR_SIZED_DELETE_BODY(FROM_NEW);
+}
+// operator delete[](void*, unsigned long)
+INTERCEPTOR(void, _ZdaPvm, void *ptr, size_t size) {
+  MAYBE_FORWARD_TO_REAL(_ZdaPvm, ptr, size);
+  OPERATOR_SIZED_DELETE_BODY(FROM_NEW_BR);
+}
+// operator delete[](void*, unsigned int)
+INTERCEPTOR(void, _ZdaPvj, void *ptr, size_t size) {
+  MAYBE_FORWARD_TO_REAL(_ZdaPvj, ptr, size);
+  OPERATOR_SIZED_DELETE_BODY(FROM_NEW_BR);
+}
+#endif
+
 #else  // SANITIZER_MAC
 INTERCEPTOR(void, _ZdlPv, void *ptr) {
   OPERATOR_DELETE_BODY(FROM_NEW);
@@ -144,3 +244,49 @@ INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) {
   OPERATOR_DELETE_BODY(FROM_NEW_BR);
 }
 #endif
+
+namespace __asan {
+#if SANITIZER_CALLS_FORWARDING
+// Explicitly intercept various versions of operator new and operator delete
+// at initialization stage
+void InitializeNewDeleteInterceptors() {
+# if SANITIZER_WORDSIZE == 32
+  // operator new(unsigned int)
+  ASAN_INTERCEPT_FUNC(_Znwj);
+  // operator new[](unsigned int)
+  ASAN_INTERCEPT_FUNC(_Znaj);
+  // operator new(unsigned int, std::nothrow_t const&)
+  ASAN_INTERCEPT_FUNC(_ZnwjRKSt9nothrow_t);
+  // operator new[](unsigned int, std::nothrow_t const&)
+  ASAN_INTERCEPT_FUNC(_ZnajRKSt9nothrow_t);
+  // operator delete(void*, unsigned int)
+  ASAN_INTERCEPT_FUNC(_ZdlPvj);
+  // operator delete[](void*, unsigned int)
+  ASAN_INTERCEPT_FUNC(_ZdaPvj);
+# elif SANITIZER_WORDSIZE == 64
+  // operator new(unsigned long)
+  ASAN_INTERCEPT_FUNC(_Znwm);
+  // operator new[](unsigned long)
+  ASAN_INTERCEPT_FUNC(_Znam);
+  // operator new(unsigned long, std::nothrow_t const&)
+  ASAN_INTERCEPT_FUNC(_ZnwmRKSt9nothrow_t);
+  // operator new[](unsigned long, std::nothrow_t const&)
+  ASAN_INTERCEPT_FUNC(_ZnamRKSt9nothrow_t);
+  // operator delete(void*, unsigned long)
+  ASAN_INTERCEPT_FUNC(_ZdlPvm);
+  // operator delete[](void*, unsigned long)
+  ASAN_INTERCEPT_FUNC(_ZdaPvm);
+# endif
+  // operator delete(void*)
+  ASAN_INTERCEPT_FUNC(_ZdlPv);
+  // operator delete[](void*)
+  ASAN_INTERCEPT_FUNC(_ZdaPv);
+  // operator delete(void*, std::nothrow_t const&)
+  ASAN_INTERCEPT_FUNC(_ZdlPvRKSt9nothrow_t);
+  // operator delete[](void*, std::nothrow_t const&)
+  ASAN_INTERCEPT_FUNC(_ZdaPvRKSt9nothrow_t);
+}
+#else
+void InitializeNewDeleteInterceptors() {}
+#endif // SANITIZER_CALLS_FORWARDING
+} // namespace __asan
index efd82bf..8ac95db 100644 (file)
@@ -201,6 +201,10 @@ void AsanCheckDynamicRTPrereqs() {}
 
 void AsanCheckIncompatibleRT() {}
 
+#if SANITIZER_CALLS_FORWARDING
+void InitializeMallocInterceptors() {}
+#endif
+
 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   UNIMPLEMENTED();
 }
index 19879b6..e8cee58 100644 (file)
@@ -35,6 +35,7 @@
 #include "sanitizer_placement_new.h"
 #include "sanitizer_platform_interceptors.h"
 #include "sanitizer_tls_get_addr.h"
+#include "sanitizer_forward_calls.h"
 
 #include <stdarg.h>
 
@@ -219,6 +220,7 @@ INTERCEPTOR(SIZE_T, strlen, const char *s) {
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_strlen(s);
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strlen, s);
   COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
   SIZE_T result = REAL(strlen)(s);
   if (common_flags()->intercept_strlen)
@@ -233,6 +235,7 @@ INTERCEPTOR(SIZE_T, strlen, const char *s) {
 #if SANITIZER_INTERCEPT_STRNLEN
 INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strnlen, s, maxlen);
   COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
   SIZE_T length = REAL(strnlen)(s, maxlen);
   if (common_flags()->intercept_strlen)
@@ -247,6 +250,7 @@ INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
 #if SANITIZER_INTERCEPT_TEXTDOMAIN
 INTERCEPTOR(char*, textdomain, const char *domainname) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(textdomain, domainname);
   COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
   COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
   char *domain = REAL(textdomain)(domainname);
@@ -270,6 +274,7 @@ DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
 
 INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strcmp, s1, s2);
   COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
   unsigned char c1, c2;
   uptr i;
@@ -294,6 +299,7 @@ INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_strncmp(s1, s2, size);
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strncmp, s1, s2, size);
   COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
   unsigned char c1 = 0, c2 = 0;
   uptr i;
@@ -329,6 +335,7 @@ DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
 
 INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strcasecmp, s1, s2);
   COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
   unsigned char c1 = 0, c2 = 0;
   uptr i;
@@ -351,6 +358,7 @@ DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
 
 INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strncasecmp, s1, s2, n);
   COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
   unsigned char c1 = 0, c2 = 0;
   uptr i;
@@ -394,6 +402,7 @@ INTERCEPTOR(char*, strstr, const char *s1, const char *s2) {
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_strstr(s1, s2);
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strstr, s1, s2);
   COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2);
   char *r = REAL(strstr)(s1, s2);
   if (common_flags()->intercept_strstr)
@@ -415,6 +424,7 @@ DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
 
 INTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strcasestr, s1, s2);
   COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2);
   char *r = REAL(strcasestr)(s1, s2);
   if (common_flags()->intercept_strstr)
@@ -437,6 +447,7 @@ DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
 INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
             SIZE_T len2) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(memmem, s1, len1, s2, len2);
   COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
   void *r = REAL(memmem)(s1, len1, s2, len2);
   if (common_flags()->intercept_memmem) {
@@ -456,6 +467,7 @@ INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
 #if SANITIZER_INTERCEPT_STRCHR
 INTERCEPTOR(char*, strchr, const char *s, int c) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strchr, s, c);
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_strchr(s, c);
   COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
@@ -474,6 +486,7 @@ INTERCEPTOR(char*, strchr, const char *s, int c) {
 #if SANITIZER_INTERCEPT_STRCHRNUL
 INTERCEPTOR(char*, strchrnul, const char *s, int c) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strchrnul, s, c);
   COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
   char *result = REAL(strchrnul)(s, c);
   uptr len = result - s + 1;
@@ -489,6 +502,7 @@ INTERCEPTOR(char*, strchrnul, const char *s, int c) {
 #if SANITIZER_INTERCEPT_STRRCHR
 INTERCEPTOR(char*, strrchr, const char *s, int c) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strrchr, s, c);
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_strrchr(s, c);
   COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
@@ -505,6 +519,7 @@ INTERCEPTOR(char*, strrchr, const char *s, int c) {
 #if SANITIZER_INTERCEPT_STRSPN
 INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strspn, s1, s2);
   COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
   SIZE_T r = REAL(strspn)(s1, s2);
   if (common_flags()->intercept_strspn) {
@@ -516,6 +531,7 @@ INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
 
 INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strcspn, s1, s2);
   COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
   SIZE_T r = REAL(strcspn)(s1, s2);
   if (common_flags()->intercept_strspn) {
@@ -535,6 +551,7 @@ INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
 #if SANITIZER_INTERCEPT_STRPBRK
 INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strpbrk, s1, s2);
   COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
   char *r = REAL(strpbrk)(s1, s2);
   if (common_flags()->intercept_strpbrk) {
@@ -555,6 +572,7 @@ INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_memset(dst, v, size);
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(memset, dst, v, size);
   COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);
   if (common_flags()->intercept_intrin)
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
@@ -571,6 +589,7 @@ INTERCEPTOR(void*, memmove, void *dst, const void *src, uptr size) {
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_memmove(dst, src, size);
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(memmove, dst, src, size);
   COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);
   if (common_flags()->intercept_intrin) {
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
@@ -593,6 +612,7 @@ INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
     return internal_memmove(dst, src, size);
   }
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(memcpy, dst, src, size);
   COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);
   if (common_flags()->intercept_intrin) {
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
@@ -618,6 +638,7 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_memcmp(a1, a2, size);
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(memcmp, a1, a2, size);
   COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
   if (common_flags()->intercept_memcmp) {
     if (common_flags()->strict_memcmp) {
@@ -660,6 +681,7 @@ INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
   if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
     return internal_memchr(s, c, n);
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(memchr, s, c, n);
   COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
 #if SANITIZER_WINDOWS
   void *res;
@@ -684,6 +706,7 @@ INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
 #if SANITIZER_INTERCEPT_MEMRCHR
 INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(memrchr, s, c, n);
   COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
   return REAL(memrchr)(s, c, n);
@@ -697,6 +720,7 @@ INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
 #if SANITIZER_INTERCEPT_FREXP
 INTERCEPTOR(double, frexp, double x, int *exp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(frexp, x, exp);
   COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
   // Assuming frexp() always writes to |exp|.
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
@@ -712,6 +736,7 @@ INTERCEPTOR(double, frexp, double x, int *exp) {
 #if SANITIZER_INTERCEPT_FREXPF_FREXPL
 INTERCEPTOR(float, frexpf, float x, int *exp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(frexpf, x, exp);
   COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -723,6 +748,7 @@ INTERCEPTOR(float, frexpf, float x, int *exp) {
 
 INTERCEPTOR(long double, frexpl, long double x, int *exp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(frexpl, x, exp);
   COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -763,6 +789,7 @@ static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
 #if SANITIZER_INTERCEPT_READ
 INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(read, fd, ptr, count);
   COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -782,6 +809,7 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
 INTERCEPTOR(SSIZE_T, __read_chk, int fd, void *ptr, SIZE_T count,
             SIZE_T bufflen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__read_chk, fd, ptr, count, bufflen);
   COMMON_INTERCEPTOR_ENTER(ctx, __read_chk, fd, ptr, count, bufflen);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -800,6 +828,7 @@ INTERCEPTOR(SSIZE_T, __read_chk, int fd, void *ptr, SIZE_T count,
 #if SANITIZER_INTERCEPT_PREAD
 INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pread, fd, ptr, count, offset);
   COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -819,6 +848,7 @@ INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
 INTERCEPTOR(SSIZE_T, __pread_chk, int fd, void *ptr, SIZE_T count,
             OFF_T offset, SIZE_T buflen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__pread_chk, fd, ptr, count, offset, buflen);
   COMMON_INTERCEPTOR_ENTER(ctx, __pread_chk, fd, ptr, count, offset, buflen);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -837,6 +867,7 @@ INTERCEPTOR(SSIZE_T, __pread_chk, int fd, void *ptr, SIZE_T count,
 #if SANITIZER_INTERCEPT_PREAD64
 INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pread64, fd, ptr, count, offset);
   COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -856,6 +887,7 @@ INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
 INTERCEPTOR(SSIZE_T, __pread64_chk, int fd, void *ptr, SIZE_T count,
             OFF64_T offset, SIZE_T buflen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__pread64_chk, fd, ptr, count, offset, buflen);
   COMMON_INTERCEPTOR_ENTER(ctx, __pread64_chk, fd, ptr, count, offset,
                           buflen);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
@@ -876,6 +908,7 @@ INTERCEPTOR(SSIZE_T, __pread64_chk, int fd, void *ptr, SIZE_T count,
 INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
                         int iovcnt) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(readv, fd, iov, iovcnt);
   COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
@@ -892,6 +925,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
 INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
             OFF_T offset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(preadv, fd, iov, iovcnt, offset);
   COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
@@ -908,6 +942,7 @@ INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
 INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
             OFF64_T offset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(preadv64, fd, iov, iovcnt, offset);
   COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
@@ -923,6 +958,7 @@ INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
 #if SANITIZER_INTERCEPT_WRITE
 INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(write, fd, ptr, count);
   COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
@@ -939,6 +975,7 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
 #if SANITIZER_INTERCEPT_PWRITE
 INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pwrite, fd, ptr, count, offset);
   COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
@@ -955,6 +992,7 @@ INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
 INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
             OFF64_T offset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pwrite64, fd, ptr, count, offset);
   COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
@@ -971,6 +1009,7 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
 INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
                         int iovcnt) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(writev, fd, iov, iovcnt);
   COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
@@ -987,6 +1026,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
 INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
             OFF_T offset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pwritev, fd, iov, iovcnt, offset);
   COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
@@ -1003,6 +1043,7 @@ INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
 INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
             OFF64_T offset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pwritev64, fd, iov, iovcnt, offset);
   COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
@@ -1020,6 +1061,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2,
             unsigned long arg3,                        // NOLINT
             unsigned long arg4, unsigned long arg5) {  // NOLINT
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(prctl, option, arg2, arg3, arg4, arg5);
   COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
   static const int PR_SET_NAME = 15;
   int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
@@ -1039,6 +1081,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2,
 #if SANITIZER_INTERCEPT_TIME
 INTERCEPTOR(unsigned long, time, unsigned long *t) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(time, t);
   COMMON_INTERCEPTOR_ENTER(ctx, time, t);
   unsigned long local_t;
   unsigned long res = REAL(time)(&local_t);
@@ -1065,6 +1108,7 @@ static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
 }
 INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(localtime, timep);
   COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
   __sanitizer_tm *res = REAL(localtime)(timep);
   if (res) {
@@ -1075,6 +1119,7 @@ INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
 }
 INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(localtime_r, timep, result);
   COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
   __sanitizer_tm *res = REAL(localtime_r)(timep, result);
   if (res) {
@@ -1085,6 +1130,7 @@ INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
 }
 INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gmtime, timep);
   COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
   __sanitizer_tm *res = REAL(gmtime)(timep);
   if (res) {
@@ -1095,6 +1141,7 @@ INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
 }
 INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gmtime_r, timep, result);
   COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
   __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
   if (res) {
@@ -1105,6 +1152,7 @@ INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
 }
 INTERCEPTOR(char *, ctime, unsigned long *timep) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ctime, timep);
   COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1118,6 +1166,7 @@ INTERCEPTOR(char *, ctime, unsigned long *timep) {
 }
 INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ctime_r, timep, result);
   COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1131,6 +1180,7 @@ INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
 }
 INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(asctime, tm);
   COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1144,6 +1194,7 @@ INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
 }
 INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(asctime_r, tm, result);
   COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1157,6 +1208,7 @@ INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
 }
 INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(mktime, tm);
   COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
   COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
@@ -1186,6 +1238,7 @@ INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
 #if SANITIZER_INTERCEPT_STRPTIME
 INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strptime, s, format, tm);
   COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
   if (format)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
@@ -1228,6 +1281,7 @@ INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
 #define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
   {                                                                            \
     void *ctx;                                                                 \
+    MAYBE_FORWARD_TO_REAL(vname, __VA_ARGS__);                                 \
     COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
     va_list aq;                                                                \
     va_copy(aq, ap);                                                           \
@@ -1318,6 +1372,7 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
 
 #define VPRINTF_INTERCEPTOR_IMPL(vname, ...)                                   \
   {                                                                            \
+    MAYBE_FORWARD_TO_REAL(vname, __VA_ARGS__);                                 \
     VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__);                             \
     if (common_flags()->check_printf)                                          \
       printf_common(ctx, format, aq);                                          \
@@ -1331,6 +1386,7 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
 // https://github.com/google/sanitizers/issues/321.
 #define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...)                             \
   {                                                                            \
+    MAYBE_FORWARD_TO_REAL(vname, str, __VA_ARGS__);                            \
     VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__)                         \
     if (common_flags()->check_printf) {                                        \
       printf_common(ctx, format, aq);                                          \
@@ -1348,6 +1404,7 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
 // https://github.com/google/sanitizers/issues/321.
 #define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...)                      \
   {                                                                            \
+    MAYBE_FORWARD_TO_REAL(vname, str, size, __VA_ARGS__);                      \
     VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__)                   \
     if (common_flags()->check_printf) {                                        \
       printf_common(ctx, format, aq);                                          \
@@ -1365,6 +1422,7 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
 // https://github.com/google/sanitizers/issues/321.
 #define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...)                           \
   {                                                                            \
+    MAYBE_FORWARD_TO_REAL(vname, strp, __VA_ARGS__);                           \
     VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__)                        \
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *));                 \
     if (common_flags()->check_printf) {                                        \
@@ -1552,6 +1610,7 @@ INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
   va_start(ap, request);
   void *arg = va_arg(ap, void *);
   va_end(ap);
+  MAYBE_FORWARD_TO_REAL(ioctl, d, request, arg);
   COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
 
   CHECK(ioctl_initialized);
@@ -1643,6 +1702,7 @@ static void unpoison_group(void *ctx, __sanitizer_group *grp) {
 #if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
 INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getpwnam, name);
   COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
   __sanitizer_passwd *res = REAL(getpwnam)(name);
@@ -1651,6 +1711,7 @@ INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
 }
 INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getpwuid, uid);
   COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
   __sanitizer_passwd *res = REAL(getpwuid)(uid);
   if (res) unpoison_passwd(ctx, res);
@@ -1658,6 +1719,7 @@ INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
 }
 INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getgrnam, name);
   COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
   __sanitizer_group *res = REAL(getgrnam)(name);
@@ -1666,6 +1728,7 @@ INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
 }
 INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getgrgid, gid);
   COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
   __sanitizer_group *res = REAL(getgrgid)(gid);
   if (res) unpoison_group(ctx, res);
@@ -1684,6 +1747,7 @@ INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
 INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
             char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getpwnam_r, name, pwd, buf, buflen, result);
   COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -1700,6 +1764,7 @@ INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
 INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
             SIZE_T buflen, __sanitizer_passwd **result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getpwuid_r, uid, pwd, buf, buflen, result);
   COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1715,6 +1780,7 @@ INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
 INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
             char *buf, SIZE_T buflen, __sanitizer_group **result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getgrnam_r, name, grp, buf, buflen, result);
   COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -1731,6 +1797,7 @@ INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
 INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
             SIZE_T buflen, __sanitizer_group **result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getgrgid_r, gid, grp, buf, buflen, result);
   COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1755,6 +1822,7 @@ INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
 #if SANITIZER_INTERCEPT_GETPWENT
 INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getpwent, dummy);
   COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
   __sanitizer_passwd *res = REAL(getpwent)(dummy);
   if (res) unpoison_passwd(ctx, res);
@@ -1762,6 +1830,7 @@ INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
 }
 INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getgrent, dummy);
   COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
   __sanitizer_group *res = REAL(getgrent)(dummy);
   if (res) unpoison_group(ctx, res);;
@@ -1777,6 +1846,7 @@ INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
 #if SANITIZER_INTERCEPT_FGETPWENT
 INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fgetpwent, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
   __sanitizer_passwd *res = REAL(fgetpwent)(fp);
   if (res) unpoison_passwd(ctx, res);
@@ -1784,6 +1854,7 @@ INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
 }
 INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fgetgrent, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
   __sanitizer_group *res = REAL(fgetgrent)(fp);
   if (res) unpoison_group(ctx, res);
@@ -1800,6 +1871,7 @@ INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
 INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
             SIZE_T buflen, __sanitizer_passwd **pwbufp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getpwent_r, pwbuf, buf, buflen, pwbufp);
   COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1815,6 +1887,7 @@ INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
 INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
             SIZE_T buflen, __sanitizer_passwd **pwbufp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
   COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1830,6 +1903,7 @@ INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
 INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
             __sanitizer_group **pwbufp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getgrent_r, pwbuf, buf, buflen, pwbufp);
   COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1845,6 +1919,7 @@ INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
 INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
             SIZE_T buflen, __sanitizer_group **pwbufp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
   COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1872,21 +1947,25 @@ INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
 // them, and we don't want things like strlen() to trigger.
 INTERCEPTOR(void, setpwent, int dummy) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(setpwent, dummy);
   COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
   REAL(setpwent)(dummy);
 }
 INTERCEPTOR(void, endpwent, int dummy) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(endpwent, dummy);
   COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
   REAL(endpwent)(dummy);
 }
 INTERCEPTOR(void, setgrent, int dummy) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(setgrent, dummy);
   COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
   REAL(setgrent)(dummy);
 }
 INTERCEPTOR(void, endgrent, int dummy) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(endgrent, dummy);
   COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
   REAL(endgrent)(dummy);
 }
@@ -1902,6 +1981,7 @@ INTERCEPTOR(void, endgrent, int dummy) {
 #if SANITIZER_INTERCEPT_CLOCK_GETTIME
 INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(clock_getres, clk_id, tp);
   COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1914,6 +1994,7 @@ INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
 }
 INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(clock_gettime, clk_id, tp);
   COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1926,6 +2007,7 @@ INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
 }
 INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(clock_settime, clk_id, tp);
   COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
   return REAL(clock_settime)(clk_id, tp);
@@ -1941,6 +2023,7 @@ INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
 #if SANITIZER_INTERCEPT_GETITIMER
 INTERCEPTOR(int, getitimer, int which, void *curr_value) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getitimer, which, curr_value);
   COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -1953,6 +2036,7 @@ INTERCEPTOR(int, getitimer, int which, void *curr_value) {
 }
 INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(setitimer, which, new_value, old_value);
   COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
   if (new_value)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
@@ -2024,6 +2108,7 @@ INTERCEPTOR(int, glob, const char *pattern, int flags,
             int (*errfunc)(const char *epath, int eerrno),
             __sanitizer_glob_t *pglob) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(glob, pattern, flags, errfunc, pglob);
   COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
   COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
   __sanitizer_glob_t glob_copy;
@@ -2053,6 +2138,7 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags,
             int (*errfunc)(const char *epath, int eerrno),
             __sanitizer_glob_t *pglob) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(glob64, pattern, flags, errfunc, pglob);
   COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
   COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
   __sanitizer_glob_t glob_copy;
@@ -2090,6 +2176,7 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags,
 // details.
 INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(wait, status);
   COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2108,6 +2195,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
                         int options) {
 #endif
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(waitid, idtype, id, infop, options);
   COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2119,6 +2207,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
 }
 INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(waitpid, pid, status, options);
   COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2130,6 +2219,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
 }
 INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(wait3, status, options, rusage);
   COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2144,6 +2234,7 @@ INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
 #if SANITIZER_ANDROID
 INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__wait4, pid, status, options, rusage);
   COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2159,6 +2250,7 @@ INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
 #else
 INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(wait4, pid, status, options, rusage);
   COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2185,6 +2277,7 @@ INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
 #if SANITIZER_INTERCEPT_INET
 INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(inet_ntop, af, src, dst, size);
   COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
   uptr sz = __sanitizer_in_addr_sz(af);
   if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
@@ -2198,6 +2291,7 @@ INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
 }
 INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(inet_pton, af, src, dst);
   COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
   COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0);
   // FIXME: figure out read size based on the address family.
@@ -2221,6 +2315,7 @@ INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
 #if SANITIZER_INTERCEPT_INET
 INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(inet_aton, cp, dst);
   COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
   if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -2241,6 +2336,7 @@ INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
 #if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
 INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pthread_getschedparam, thread, policy, param);
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2263,6 +2359,7 @@ INTERCEPTOR(int, getaddrinfo, char *node, char *service,
             struct __sanitizer_addrinfo *hints,
             struct __sanitizer_addrinfo **out) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getaddrinfo, node, service, hints, out);
   COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
   if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
   if (service)
@@ -2297,6 +2394,8 @@ INTERCEPTOR(int, getaddrinfo, char *node, char *service,
 INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
             unsigned hostlen, char *serv, unsigned servlen, int flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getnameinfo, sockaddr, salen, host, hostlen,
+                        serv, servlen, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
                            serv, servlen, flags);
   // FIXME: consider adding READ_RANGE(sockaddr, salen)
@@ -2322,6 +2421,7 @@ INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
 #if SANITIZER_INTERCEPT_GETSOCKNAME
 INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getsockname, sock_fd, addr, addrlen);
   COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
   int addrlen_in = *addrlen;
@@ -2364,6 +2464,7 @@ static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
 #if SANITIZER_INTERCEPT_GETHOSTBYNAME
 INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gethostbyname, name);
   COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
   struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
   if (res) write_hostent(ctx, res);
@@ -2373,6 +2474,7 @@ INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
 INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
             int type) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gethostbyaddr, addr, len, type);
   COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
   struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
@@ -2382,6 +2484,7 @@ INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
 
 INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gethostent, fake);
   COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
   struct __sanitizer_hostent *res = REAL(gethostent)(fake);
   if (res) write_hostent(ctx, res);
@@ -2390,6 +2493,7 @@ INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
 
 INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gethostbyname2, name, af);
   COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
   struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
   if (res) write_hostent(ctx, res);
@@ -2409,6 +2513,8 @@ INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
             char *buf, SIZE_T buflen, __sanitizer_hostent **result,
             int *h_errnop) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gethostbyname_r, name, ret, buf, buflen, result,
+                        h_errnop);
   COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
                            h_errnop);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -2432,6 +2538,7 @@ INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
 INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
             SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gethostent_r, ret, buf, buflen, result, h_errnop);
   COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
                            h_errnop);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -2457,6 +2564,8 @@ INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
             struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
             __sanitizer_hostent **result, int *h_errnop) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gethostbyaddr_r, addr, len, type, ret, buf, buflen,
+                        result, h_errnop);
   COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
                            buflen, result, h_errnop);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
@@ -2484,6 +2593,8 @@ INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
             struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
             __sanitizer_hostent **result, int *h_errnop) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(gethostbyname2_r, name, af, ret, buf, buflen,
+                        result, h_errnop);
   COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
                            result, h_errnop);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -2509,6 +2620,7 @@ INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
 INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
             int *optlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getsockopt, sockfd, level, optname, optval, optlen);
   COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
                            optlen);
   if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
@@ -2528,6 +2640,7 @@ INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
 #if SANITIZER_INTERCEPT_ACCEPT
 INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(accept, fd, addr, addrlen);
   COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
   unsigned addrlen0 = 0;
   if (addrlen) {
@@ -2550,6 +2663,7 @@ INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
 #if SANITIZER_INTERCEPT_ACCEPT4
 INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(accept4, fd, addr, addrlen, f);
   COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
   unsigned addrlen0 = 0;
   if (addrlen) {
@@ -2575,6 +2689,7 @@ INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
 #if SANITIZER_INTERCEPT_MODF
 INTERCEPTOR(double, modf, double x, double *iptr) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(modf, x, iptr);
   COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2587,6 +2702,7 @@ INTERCEPTOR(double, modf, double x, double *iptr) {
 }
 INTERCEPTOR(float, modff, float x, float *iptr) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(modff, x, iptr);
   COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2599,6 +2715,7 @@ INTERCEPTOR(float, modff, float x, float *iptr) {
 }
 INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(modfl, x, iptr);
   COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2634,6 +2751,7 @@ static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
 INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
             int flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(recvmsg, fd, msg, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2707,6 +2825,7 @@ static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
 INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
             int flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sendmsg, fd, msg, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
   if (fd >= 0) {
     COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
@@ -2725,6 +2844,7 @@ INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
 #if SANITIZER_INTERCEPT_GETPEERNAME
 INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getpeername, sockfd, addr, addrlen);
   COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
   unsigned addr_sz;
   if (addrlen) addr_sz = *addrlen;
@@ -2744,6 +2864,7 @@ INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
 #if SANITIZER_INTERCEPT_SYSINFO
 INTERCEPTOR(int, sysinfo, void *info) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sysinfo, info);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
   // https://github.com/google/sanitizers/issues/321.
@@ -2761,6 +2882,7 @@ INTERCEPTOR(int, sysinfo, void *info) {
 #if SANITIZER_INTERCEPT_READDIR
 INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(opendir, path);
   COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   __sanitizer_dirent *res = REAL(opendir)(path);
@@ -2771,6 +2893,7 @@ INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
 
 INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(readdir, dirp);
   COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2783,6 +2906,7 @@ INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
 INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
             __sanitizer_dirent **result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(readdir_r, dirp, entry, result);
   COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2807,6 +2931,7 @@ INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
 #if SANITIZER_INTERCEPT_READDIR64
 INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(readdir64, dirp);
   COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2819,6 +2944,7 @@ INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
 INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
             __sanitizer_dirent64 **result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(readdir64_r, dirp, entry, result);
   COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2841,6 +2967,7 @@ INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
 #if SANITIZER_INTERCEPT_PTRACE
 INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ptrace, request, pid, addr, data);
   COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
   __sanitizer_iovec local_iovec;
 
@@ -2905,6 +3032,7 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
 #if SANITIZER_INTERCEPT_SETLOCALE
 INTERCEPTOR(char *, setlocale, int category, char *locale) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(setlocale, category, locale);
   COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
   if (locale)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
@@ -2921,6 +3049,7 @@ INTERCEPTOR(char *, setlocale, int category, char *locale) {
 #if SANITIZER_INTERCEPT_GETCWD
 INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getcwd, buf, size);
   COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2937,6 +3066,7 @@ INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
 #if SANITIZER_INTERCEPT_FORTIFY_SOURCE
 INTERCEPTOR(char *, __getcwd_chk, char *buf, SIZE_T size, SIZE_T buflen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__getcwd_chk, buf, size, buflen);
   COMMON_INTERCEPTOR_ENTER(ctx, __getcwd_chk, buf, size, buflen);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -2953,6 +3083,7 @@ INTERCEPTOR(char *, __getcwd_chk, char *buf, SIZE_T size, SIZE_T buflen) {
 #if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
 INTERCEPTOR(char *, get_current_dir_name, int fake) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(get_current_dir_name, fake);
   COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3002,6 +3133,7 @@ UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
 #if SANITIZER_INTERCEPT_STRTOIMAX
 INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strtoimax, nptr, endptr, base);
   COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3014,6 +3146,7 @@ INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
 
 INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strtoumax, nptr, endptr, base);
   COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3034,6 +3167,7 @@ INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
 #if SANITIZER_INTERCEPT_MBSTOWCS
 INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(mbstowcs, dest, src, len);
   COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3049,6 +3183,7 @@ INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
 INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
             void *ps) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(mbsrtowcs, dest, src, len, ps);
   COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
   if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
   if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
@@ -3076,6 +3211,7 @@ INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
 INTERCEPTOR(SIZE_T, __mbstowcs_chk, wchar_t *dest, const char *src,
             SIZE_T len, SIZE_T destlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__mbstowcs_chk, dest, src, len, destlen);
   COMMON_INTERCEPTOR_ENTER(ctx, __mbstowcs_chk, dest, src, len, destlen);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3091,6 +3227,7 @@ INTERCEPTOR(SIZE_T, __mbstowcs_chk, wchar_t *dest, const char *src,
 INTERCEPTOR(SIZE_T, __mbsrtowcs_chk, wchar_t *dest, const char **src,
             SIZE_T len, void *ps, SIZE_T destlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__mbsrtowcs_chk, dest, src, len, ps, destlen);
   COMMON_INTERCEPTOR_ENTER(ctx, __mbsrtowcs_chk, dest, src, len, ps, destlen);
   if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
   if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
@@ -3118,6 +3255,7 @@ INTERCEPTOR(SIZE_T, __mbsrtowcs_chk, wchar_t *dest, const char **src,
 INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
             SIZE_T len, void *ps) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(mbsnrtowcs, dest, src, nms, len, ps);
   COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
   if (src) {
     COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
@@ -3144,6 +3282,7 @@ INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
 INTERCEPTOR(SIZE_T, __mbsnrtowcs_chk, wchar_t *dest, const char **src,
             SIZE_T nms, SIZE_T len, void *ps, SIZE_T destlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__mbsnrtowcs_chk, dest, src, nms, len, ps, destlen);
   COMMON_INTERCEPTOR_ENTER(ctx, __mbsnrtowcs_chk, dest, src, nms, len, ps,
                            destlen);
   if (src) {
@@ -3170,6 +3309,7 @@ INTERCEPTOR(SIZE_T, __mbsnrtowcs_chk, wchar_t *dest, const char **src,
 #if SANITIZER_INTERCEPT_WCSTOMBS
 INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(wcstombs, dest, src, len);
   COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3185,6 +3325,7 @@ INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
 INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
             void *ps) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(wcsrtombs, dest, src, len, ps);
   COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
   if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
   if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
@@ -3210,6 +3351,7 @@ INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
 INTERCEPTOR(SIZE_T, __wcstombs_chk, char *dest, const wchar_t *src,
             SIZE_T len, SIZE_T destlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__wcstombs_chk, dest, src, len, destlen);
   COMMON_INTERCEPTOR_ENTER(ctx, __wcstombs_chk, dest, src, len, destlen);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3225,6 +3367,7 @@ INTERCEPTOR(SIZE_T, __wcstombs_chk, char *dest, const wchar_t *src,
 INTERCEPTOR(SIZE_T, __wcsrtombs_chk, char *dest, const wchar_t **src,
             SIZE_T len, void *ps, SIZE_T destlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__wcsrtombs_chk, dest, src, len, ps, destlen);
   COMMON_INTERCEPTOR_ENTER(ctx, __wcsrtombs_chk, dest, src, len, ps,
                            destlen);
   if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
@@ -3251,6 +3394,7 @@ INTERCEPTOR(SIZE_T, __wcsrtombs_chk, char *dest, const wchar_t **src,
 INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
             SIZE_T len, void *ps) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(wcsnrtombs, dest, src, nms, len, ps);
   COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
   if (src) {
     COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
@@ -3277,6 +3421,7 @@ INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
 INTERCEPTOR(SIZE_T, __wcsnrtombs_chk, char *dest, const wchar_t **src,
             SIZE_T nms, SIZE_T len, void *ps, SIZE_T destlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__wcsnrtombs_chk, dest, src, nms, len, ps, destlen);
   COMMON_INTERCEPTOR_ENTER(ctx, __wcsnrtombs_chk, dest, src, nms, len, ps,
                            destlen);
   if (src) {
@@ -3303,6 +3448,7 @@ INTERCEPTOR(SIZE_T, __wcsnrtombs_chk, char *dest, const wchar_t **src,
 #if SANITIZER_INTERCEPT_WCRTOMB
 INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(wcrtomb, dest, src, ps);
   COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps);
   if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -3325,6 +3471,7 @@ INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
 INTERCEPTOR(SIZE_T, __wcrtomb_chk, char *dest, wchar_t src, void *ps,
             SIZE_T destlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__wcrtomb_chk, dest, src, ps, destlen);
   COMMON_INTERCEPTOR_ENTER(ctx, __wcrtomb_chk, dest, src, ps, destlen);
   if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -3346,6 +3493,7 @@ INTERCEPTOR(SIZE_T, __wcrtomb_chk, char *dest, wchar_t src, void *ps,
 #if SANITIZER_INTERCEPT_TCGETATTR
 INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(tcgetattr, fd, termios_p);
   COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3414,6 +3562,7 @@ INTERCEPTOR(char *, __realpath_chk, const char *path, char *resolved_path,
 #if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
 INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(canonicalize_file_name, path);
   COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   char *res = REAL(canonicalize_file_name)(path);
@@ -3429,6 +3578,7 @@ INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
 #if SANITIZER_INTERCEPT_CONFSTR
 INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(confstr, name, buf, len);
   COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3447,6 +3597,7 @@ INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
 INTERCEPTOR(SIZE_T, __confstr_chk, int name, char *buf, SIZE_T len,
             SIZE_T bufflen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__confstr_chk, name, buf, len, bufflen);
   COMMON_INTERCEPTOR_ENTER(ctx, __confstr_chk, name, buf, len, bufflen);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3464,6 +3615,7 @@ INTERCEPTOR(SIZE_T, __confstr_chk, int name, char *buf, SIZE_T len,
 #if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
 INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sched_getaffinity, pid, cpusetsize, mask);
   COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3480,6 +3632,7 @@ INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
 #if SANITIZER_INTERCEPT_SCHED_GETPARAM
 INTERCEPTOR(int, sched_getparam, int pid, void *param) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sched_getparam, pid, param);
   COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param);
   int res = REAL(sched_getparam)(pid, param);
   if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz);
@@ -3493,6 +3646,7 @@ INTERCEPTOR(int, sched_getparam, int pid, void *param) {
 #if SANITIZER_INTERCEPT_STRERROR
 INTERCEPTOR(char *, strerror, int errnum) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strerror, errnum);
   COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
   char *res = REAL(strerror)(errnum);
   if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
@@ -3506,6 +3660,7 @@ INTERCEPTOR(char *, strerror, int errnum) {
 #if SANITIZER_INTERCEPT_STRERROR_R
 INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(strerror_r, errnum, buf, buflen);
   COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3537,6 +3692,7 @@ INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
 #if SANITIZER_INTERCEPT_XPG_STRERROR_R
 INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__xpg_strerror_r, errnum, buf, buflen);
   COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3579,6 +3735,7 @@ static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
 INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
             scandir_filter_f filter, scandir_compar_f compar) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(scandir, dirp, namelist, filter, compar);
   COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
   if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
   scandir_filter = filter;
@@ -3632,6 +3789,7 @@ static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
 INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
             scandir64_filter_f filter, scandir64_compar_f compar) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(scandir64, dirp, namelist, filter, compar);
   COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
   if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
   scandir64_filter = filter;
@@ -3662,6 +3820,7 @@ INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
 #if SANITIZER_INTERCEPT_GETGROUPS
 INTERCEPTOR(int, getgroups, int size, u32 *lst) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getgroups, size, lst);
   COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3678,6 +3837,7 @@ INTERCEPTOR(int, getgroups, int size, u32 *lst) {
 #if SANITIZER_INTERCEPT_FORTIFY_SOURCE
 INTERCEPTOR(int, __getgroups_chk, int size, u32 *lst, SIZE_T lstsize) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__getgroups_chk, size, lst, lstsize);
   COMMON_INTERCEPTOR_ENTER(ctx, __getgroups_chk, size, lst, lstsize);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3711,6 +3871,7 @@ static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
 INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
             int timeout) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(poll, fds, nfds, timeout);
   COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
   if (fds && nfds) read_pollfd(ctx, fds, nfds);
   int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
@@ -3726,6 +3887,7 @@ INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
 INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
             void *timeout_ts, __sanitizer_sigset_t *sigmask) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ppoll, fds, nfds, timeout_ts, sigmask);
   COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
   if (fds && nfds) read_pollfd(ctx, fds, nfds);
   if (timeout_ts)
@@ -3745,6 +3907,7 @@ INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
 INTERCEPTOR(int, __poll_chk, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
             int timeout, SIZE_T fdslen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__poll_chk, fds, nfds, timeout, fdslen);
   COMMON_INTERCEPTOR_ENTER(ctx, __poll_chk, fds, nfds, timeout, fdslen);
   if (fds && nfds) read_pollfd(ctx, fds, nfds);
   int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
@@ -3761,6 +3924,7 @@ INTERCEPTOR(int, __ppoll_chk, __sanitizer_pollfd *fds,
             __sanitizer_nfds_t nfds, void *timeout_ts,
             __sanitizer_sigset_t *sigmask, SIZE_T fdslen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__ppoll_chk, fds, nfds, timeout_ts, sigmask, fdslen);
   COMMON_INTERCEPTOR_ENTER(ctx, __ppoll_chk, fds, nfds, timeout_ts,
                            sigmask, fdslen);
   if (fds && nfds) read_pollfd(ctx, fds, nfds);
@@ -3780,6 +3944,7 @@ INTERCEPTOR(int, __ppoll_chk, __sanitizer_pollfd *fds,
 #if SANITIZER_INTERCEPT_WORDEXP
 INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(wordexp, s, p, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
   if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -3806,6 +3971,7 @@ INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
 #if SANITIZER_INTERCEPT_SIGWAIT
 INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sigwait, set, sig);
   COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
   // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -3823,6 +3989,7 @@ INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
 #if SANITIZER_INTERCEPT_SIGWAITINFO
 INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sigwaitinfo, set, info);
   COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
   // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -3841,6 +4008,7 @@ INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
 INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
             void *timeout) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sigtimedwait, set, info, timeout);
   COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
   if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
   // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
@@ -3859,6 +4027,7 @@ INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
 #if SANITIZER_INTERCEPT_SIGSETOPS
 INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sigemptyset, set);
   COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3870,6 +4039,7 @@ INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
 
 INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sigfillset, set);
   COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3888,6 +4058,7 @@ INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
 #if SANITIZER_INTERCEPT_SIGPENDING
 INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sigpending, set);
   COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3905,6 +4076,7 @@ INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
 INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
             __sanitizer_sigset_t *oldset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sigprocmask, how, set, oldset);
   COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
   // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -3923,6 +4095,7 @@ INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
 #if SANITIZER_INTERCEPT_BACKTRACE
 INTERCEPTOR(int, backtrace, void **buffer, int size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(backtrace, buffer, size);
   COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -3935,6 +4108,7 @@ INTERCEPTOR(int, backtrace, void **buffer, int size) {
 
 INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(backtrace_symbols, buffer, size);
   COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
   if (buffer && size)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
@@ -3959,6 +4133,7 @@ INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
 #if SANITIZER_INTERCEPT__EXIT
 INTERCEPTOR(void, _exit, int status) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(_exit, status);
   COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
   COMMON_INTERCEPTOR_USER_CALLBACK_START();
   int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
@@ -3974,6 +4149,7 @@ INTERCEPTOR(void, _exit, int status) {
 #if SANITIZER_INTERCEPT_PHTREAD_MUTEX
 INTERCEPTOR(int, pthread_mutex_lock, void *m) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pthread_mutex_lock, m);
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
   int res = REAL(pthread_mutex_lock)(m);
   if (res == errno_EOWNERDEAD)
@@ -3987,6 +4163,7 @@ INTERCEPTOR(int, pthread_mutex_lock, void *m) {
 
 INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pthread_mutex_unlock, m);
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
   COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
   int res = REAL(pthread_mutex_unlock)(m);
@@ -4024,6 +4201,7 @@ static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
 #if SANITIZER_INTERCEPT_GETMNTENT
 INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getmntent, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
   __sanitizer_mntent *res = REAL(getmntent)(fp);
   if (res) write_mntent(ctx, res);
@@ -4038,6 +4216,7 @@ INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
 INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
             __sanitizer_mntent *mntbuf, char *buf, int buflen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getmntent_r, fp, mntbuf, buf, buflen);
   COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
   __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
   if (res) write_mntent(ctx, res);
@@ -4051,6 +4230,7 @@ INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
 #if SANITIZER_INTERCEPT_STATFS
 INTERCEPTOR(int, statfs, char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(statfs, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4062,6 +4242,7 @@ INTERCEPTOR(int, statfs, char *path, void *buf) {
 }
 INTERCEPTOR(int, fstatfs, int fd, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fstatfs, fd, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4080,6 +4261,7 @@ INTERCEPTOR(int, fstatfs, int fd, void *buf) {
 #if SANITIZER_INTERCEPT_STATFS64
 INTERCEPTOR(int, statfs64, char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(statfs64, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4091,6 +4273,7 @@ INTERCEPTOR(int, statfs64, char *path, void *buf) {
 }
 INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fstatfs64, fd, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4109,6 +4292,7 @@ INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
 #if SANITIZER_INTERCEPT_STATVFS
 INTERCEPTOR(int, statvfs, char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(statvfs, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4120,6 +4304,7 @@ INTERCEPTOR(int, statvfs, char *path, void *buf) {
 }
 INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fstatvfs, fd, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4138,6 +4323,7 @@ INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
 #if SANITIZER_INTERCEPT_STATVFS64
 INTERCEPTOR(int, statvfs64, char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(statvfs64, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4149,6 +4335,7 @@ INTERCEPTOR(int, statvfs64, char *path, void *buf) {
 }
 INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fstatvfs64, fd, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4167,6 +4354,7 @@ INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
 #if SANITIZER_INTERCEPT_INITGROUPS
 INTERCEPTOR(int, initgroups, char *user, u32 group) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(initgroups, user, group);
   COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
   if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
   int res = REAL(initgroups)(user, group);
@@ -4180,6 +4368,7 @@ INTERCEPTOR(int, initgroups, char *user, u32 group) {
 #if SANITIZER_INTERCEPT_ETHER_NTOA_ATON
 INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ether_ntoa, addr);
   COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
   if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
   char *res = REAL(ether_ntoa)(addr);
@@ -4188,6 +4377,7 @@ INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
 }
 INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ether_aton, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
   if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
   __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
@@ -4204,6 +4394,7 @@ INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
 #if SANITIZER_INTERCEPT_ETHER_HOST
 INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ether_ntohost, hostname, addr);
   COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
   if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4216,6 +4407,7 @@ INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
 }
 INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ether_hostton, hostname, addr);
   COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
   if (hostname)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
@@ -4229,6 +4421,7 @@ INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
 INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
             char *hostname) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ether_line, line, addr, hostname);
   COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
   if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4253,6 +4446,7 @@ INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
 #if SANITIZER_INTERCEPT_ETHER_R
 INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ether_ntoa_r, addr, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
   if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4265,6 +4459,7 @@ INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
 INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
             __sanitizer_ether_addr *addr) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ether_aton_r, buf, addr);
   COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
   if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4284,6 +4479,7 @@ INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
 #if SANITIZER_INTERCEPT_SHMCTL
 INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(shmctl, shmid, cmd, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4309,6 +4505,7 @@ INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
 #if SANITIZER_INTERCEPT_RANDOM_R
 INTERCEPTOR(int, random_r, void *buf, u32 *result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(random_r, buf, result);
   COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4335,6 +4532,7 @@ INTERCEPTOR(int, random_r, void *buf, u32 *result) {
 #define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz)            \
   INTERCEPTOR(int, fn, void *attr, void *r) {                  \
     void *ctx;                                                 \
+    MAYBE_FORWARD_TO_REAL(fn, attr, r);                        \
     COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r);                \
     int res = REAL(fn)(attr, r);                               \
     if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \
@@ -4361,6 +4559,7 @@ INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
 INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
 INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pthread_attr_getstack, attr, addr, size);
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4409,6 +4608,7 @@ INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))
 INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
             void *cpuset) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pthread_attr_getaffinity_np, attr, cpusetsize, cpuset);
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
                            cpuset);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4517,6 +4717,7 @@ INTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android
 #if SANITIZER_INTERCEPT_TMPNAM
 INTERCEPTOR(char *, tmpnam, char *s) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(tmpnam, s);
   COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
   char *res = REAL(tmpnam)(s);
   if (res) {
@@ -4538,6 +4739,7 @@ INTERCEPTOR(char *, tmpnam, char *s) {
 #if SANITIZER_INTERCEPT_TMPNAM_R
 INTERCEPTOR(char *, tmpnam_r, char *s) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(tmpnam_r, s);
   COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4554,6 +4756,7 @@ INTERCEPTOR(char *, tmpnam_r, char *s) {
 #if SANITIZER_INTERCEPT_TTYNAME_R
 INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ttyname_r, fd, name, namesize);
   COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
   int res = REAL(ttyname_r)(fd, name, namesize);
   if (res == 0)
@@ -4569,6 +4772,7 @@ INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
 INTERCEPTOR(int, __ttyname_r_chk, int fd, char *name, SIZE_T namesize,
             SIZE_T namelen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__ttyname_r_chk, fd, name, namesize, namelen);
   COMMON_INTERCEPTOR_ENTER(ctx, __ttyname_r_chk, fd, name, namesize, namelen);
   int res = REAL(ttyname_r)(fd, name, namesize);
   if (res == 0)
@@ -4583,6 +4787,7 @@ INTERCEPTOR(int, __ttyname_r_chk, int fd, char *name, SIZE_T namesize,
 #if SANITIZER_INTERCEPT_TEMPNAM
 INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(tempnam, dir, pfx);
   COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
   if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
   if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
@@ -4598,6 +4803,7 @@ INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
 #if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP
 INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pthread_setname_np, thread, name);
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
   COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
@@ -4611,6 +4817,7 @@ INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
 #if SANITIZER_INTERCEPT_SINCOS
 INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sincos, x, sin, cos);
   COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4621,6 +4828,7 @@ INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
 }
 INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sincosf, x, sin, cos);
   COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4631,6 +4839,7 @@ INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
 }
 INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sincosl, x, sin, cos);
   COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4650,6 +4859,7 @@ INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
 #if SANITIZER_INTERCEPT_REMQUO
 INTERCEPTOR(double, remquo, double x, double y, int *quo) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(remquo, x, y, quo);
   COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4660,6 +4870,7 @@ INTERCEPTOR(double, remquo, double x, double y, int *quo) {
 }
 INTERCEPTOR(float, remquof, float x, float y, int *quo) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(remquof, x, y, quo);
   COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4670,6 +4881,7 @@ INTERCEPTOR(float, remquof, float x, float y, int *quo) {
 }
 INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(remquol, x, y, quo);
   COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4690,6 +4902,7 @@ INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
 extern int signgam;
 INTERCEPTOR(double, lgamma, double x) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(lgamma, x);
   COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
   double res = REAL(lgamma)(x);
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
@@ -4697,6 +4910,7 @@ INTERCEPTOR(double, lgamma, double x) {
 }
 INTERCEPTOR(float, lgammaf, float x) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(lgammaf, x);
   COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
   float res = REAL(lgammaf)(x);
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
@@ -4704,6 +4918,7 @@ INTERCEPTOR(float, lgammaf, float x) {
 }
 INTERCEPTOR(long double, lgammal, long double x) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(lgammal, x);
   COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
   long double res = REAL(lgammal)(x);
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
@@ -4720,6 +4935,7 @@ INTERCEPTOR(long double, lgammal, long double x) {
 #if SANITIZER_INTERCEPT_LGAMMA_R
 INTERCEPTOR(double, lgamma_r, double x, int *signp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(lgamma_r, x, signp);
   COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4730,6 +4946,7 @@ INTERCEPTOR(double, lgamma_r, double x, int *signp) {
 }
 INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(lgammaf_r, x, signp);
   COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4748,6 +4965,7 @@ INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
 #if SANITIZER_INTERCEPT_LGAMMAL_R
 INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(lgammal_r, x, signp);
   COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4764,6 +4982,7 @@ INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
 #if SANITIZER_INTERCEPT_DRAND48_R
 INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(drand48_r, buffer, result);
   COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4774,6 +4993,7 @@ INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
 }
 INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(lrand48_r, buffer, result);
   COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4792,6 +5012,7 @@ INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
 #if SANITIZER_INTERCEPT_RAND_R
 INTERCEPTOR(int, rand_r, unsigned *seedp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(rand_r, seedp);
   COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
   return REAL(rand_r)(seedp);
@@ -4804,6 +5025,7 @@ INTERCEPTOR(int, rand_r, unsigned *seedp) {
 #if SANITIZER_INTERCEPT_GETLINE
 INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getline, lineptr, n, stream);
   COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4823,6 +5045,7 @@ INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
 #define GETDELIM_INTERCEPTOR_IMPL(vname)                                       \
   {                                                                            \
     void *ctx;                                                                 \
+    MAYBE_FORWARD_TO_REAL(vname, lineptr, n, delim, stream);                   \
     COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream);           \
     SSIZE_T res = REAL(vname)(lineptr, n, delim, stream);                      \
     if (res > 0) {                                                             \
@@ -4855,6 +5078,7 @@ GETDELIM_INTERCEPTOR_IMPL(getdelim)
 INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
             char **outbuf, SIZE_T *outbytesleft) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(iconv, cd, inbuf, inbytesleft, outbuf, outbytesleft);
   COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf,
                            outbytesleft);
   if (inbytesleft)
@@ -4882,6 +5106,7 @@ INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
 #if SANITIZER_INTERCEPT_TIMES
 INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(times, tms);
   COMMON_INTERCEPTOR_ENTER(ctx, times, tms);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -4907,6 +5132,7 @@ INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
 // because sanitizers use initial-exec tls model).
 INTERCEPTOR(void *, __tls_get_addr, void *arg) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__tls_get_addr, arg);
   COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
   void *res = REAL(__tls_get_addr)(arg);
   uptr tls_begin, tls_end;
@@ -4938,6 +5164,7 @@ void *__tls_get_addr_opt(void *arg);
 #define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr_internal)
 INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__tls_get_addr_internal, arg);
   COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
   uptr res = REAL(__tls_get_addr_internal)(arg);
   uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
@@ -4986,6 +5213,7 @@ asm(
 #if SANITIZER_INTERCEPT_LISTXATTR
 INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(listxattr, path, list, size);
   COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -4999,6 +5227,7 @@ INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
 }
 INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(llistxattr, path, list, size);
   COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -5010,6 +5239,7 @@ INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
 }
 INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(flistxattr, fd, list, size);
   COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5030,6 +5260,7 @@ INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
 INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
             SIZE_T size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getxattr, path, name, value, size);
   COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
@@ -5043,6 +5274,7 @@ INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
 INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
             SIZE_T size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(lgetxattr, path, name, value, size);
   COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
@@ -5056,6 +5288,7 @@ INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
 INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
             SIZE_T size) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fgetxattr, fd, name, value, size);
   COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
   if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
   // FIXME: under ASan the call below may write to freed memory and corrupt
@@ -5076,6 +5309,7 @@ INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
 #if SANITIZER_INTERCEPT_GETRESID
 INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getresuid, ruid, euid, suid);
   COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5090,6 +5324,7 @@ INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
 }
 INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getresgid, rgid, egid, sgid);
   COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5115,6 +5350,7 @@ INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
 // intercept it to poison the memory again.
 INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getifaddrs, ifap);
   COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5151,6 +5387,7 @@ INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
 #if SANITIZER_INTERCEPT_IF_INDEXTONAME
 INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(if_indextoname, ifindex, ifname);
   COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5162,6 +5399,7 @@ INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
 }
 INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(if_nametoindex, ifname);
   COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
   if (ifname)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
@@ -5177,6 +5415,7 @@ INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
 #if SANITIZER_INTERCEPT_CAPGET
 INTERCEPTOR(int, capget, void *hdrp, void *datap) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(capget, hdrp, datap);
   COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
   if (hdrp)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
@@ -5193,6 +5432,7 @@ INTERCEPTOR(int, capget, void *hdrp, void *datap) {
 }
 INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(capset, hdrp, datap);
   COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
   if (hdrp)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
@@ -5213,40 +5453,52 @@ DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *, const void *, uptr)
 DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr)
 
 INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memmove, to, from, size);
   return WRAP(memmove)(to, from, size);
 }
 INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memmove4, to, from, size);
   return WRAP(memmove)(to, from, size);
 }
 INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memmove8, to, from, size);
   return WRAP(memmove)(to, from, size);
 }
 INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memcpy, to, from, size);
   return WRAP(memcpy)(to, from, size);
 }
 INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memcpy4, to, from, size);
   return WRAP(memcpy)(to, from, size);
 }
 INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memcpy8, to, from, size);
   return WRAP(memcpy)(to, from, size);
 }
 // Note the argument order.
 INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memset, block, size, c);
   return WRAP(memset)(block, c, size);
 }
 INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memset4, block, size, c);
   return WRAP(memset)(block, c, size);
 }
 INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memset8, block, size, c);
   return WRAP(memset)(block, c, size);
 }
 INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memclr, block, size);
   return WRAP(memset)(block, 0, size);
 }
 INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memclr4, block, size);
   return WRAP(memset)(block, 0, size);
 }
 INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__aeabi_memclr8, block, size);
   return WRAP(memset)(block, 0, size);
 }
 #define INIT_AEABI_MEM                         \
@@ -5270,6 +5522,7 @@ INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
 DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);
 
 INTERCEPTOR(void *, __bzero, void *block, uptr size) {
+  MAYBE_FORWARD_TO_REAL(__bzero, block, size);
   return WRAP(memset)(block, 0, size);
 }
 #define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
@@ -5280,6 +5533,7 @@ INTERCEPTOR(void *, __bzero, void *block, uptr size) {
 #if SANITIZER_INTERCEPT_FTIME
 INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ftime, tp);
   COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5298,6 +5552,7 @@ INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
 INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
             unsigned size, int op) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(xdrmem_create, xdrs, addr, size, op);
   COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5313,6 +5568,7 @@ INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
 
 INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(xdrstdio_create, xdrs, file, op);
   COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5327,6 +5583,7 @@ INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
 #define XDR_INTERCEPTOR(F, T)                             \
   INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) {      \
     void *ctx;                                            \
+    MAYBE_FORWARD_TO_REAL(F, xdrs, p);                    \
     COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p);            \
     if (p && xdrs->x_op == __sanitizer_XDR_ENCODE)        \
       COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));  \
@@ -5369,6 +5626,7 @@ XDR_INTERCEPTOR(xdr_double, double)
 INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
             unsigned maxsize) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(xdr_bytes, xdrs, p, sizep, maxsize);
   COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
   if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
     COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
@@ -5390,6 +5648,7 @@ INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
 INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
             unsigned maxsize) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(xdr_string, xdrs, p, maxsize);
   COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
   if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
     COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
@@ -5446,6 +5705,7 @@ INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
 INTERCEPTOR(void *, tsearch, void *key, void **rootp,
             int (*compar)(const void *, const void *)) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(tsearch, key, rootp, compar);
   COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5476,6 +5736,7 @@ void unpoison_file(__sanitizer_FILE *fp) {
 // These guys are called when a .c source is built with -O2.
 INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__uflow, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
   int res = REAL(__uflow)(fp);
   unpoison_file(fp);
@@ -5483,6 +5744,7 @@ INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
 }
 INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__underflow, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
   int res = REAL(__underflow)(fp);
   unpoison_file(fp);
@@ -5490,6 +5752,7 @@ INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
 }
 INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__overflow, fp, ch);
   COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
   int res = REAL(__overflow)(fp, ch);
   unpoison_file(fp);
@@ -5497,6 +5760,7 @@ INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
 }
 INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__wuflow, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
   int res = REAL(__wuflow)(fp);
   unpoison_file(fp);
@@ -5504,6 +5768,7 @@ INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
 }
 INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__wunderflow, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
   int res = REAL(__wunderflow)(fp);
   unpoison_file(fp);
@@ -5511,6 +5776,7 @@ INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
 }
 INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__woverflow, fp, ch);
   COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
   int res = REAL(__woverflow)(fp, ch);
   unpoison_file(fp);
@@ -5530,6 +5796,7 @@ INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
 #if SANITIZER_INTERCEPT_FOPEN
 INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fopen, path, mode);
   COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
@@ -5540,6 +5807,7 @@ INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
 }
 INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fdopen, fd, mode);
   COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
   __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
@@ -5549,6 +5817,7 @@ INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
 INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
             __sanitizer_FILE *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(freopen, path, mode, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
@@ -5569,6 +5838,7 @@ INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
 #if SANITIZER_INTERCEPT_FOPEN64
 INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fopen64, path, mode);
   COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
@@ -5580,6 +5850,7 @@ INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
 INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
             __sanitizer_FILE *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(freopen64, path, mode, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
   if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
@@ -5599,6 +5870,7 @@ INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
 #if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
 INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(open_memstream, ptr, sizeloc);
   COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5616,6 +5888,7 @@ INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
 INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
             SIZE_T *sizeloc) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(open_wmemstream, ptr, sizeloc);
   COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
   __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
   if (res) {
@@ -5630,6 +5903,7 @@ INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
 INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
             const char *mode) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fmemopen, buf, size, mode);
   COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
@@ -5658,6 +5932,7 @@ INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
             int align, void *(*alloc_fn)(uptr arg, uptr sz),
             void (*free_fn)(uptr arg, void *p)) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(_obstack_begin_1, obstack, sz, align, alloc_fn, free_fn);
   COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
                            free_fn);
   int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
@@ -5667,6 +5942,7 @@ INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
 INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
             int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(_obstack_begin, obstack, sz, align, alloc_fn, free_fn);
   COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
                            free_fn);
   int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
@@ -5675,6 +5951,7 @@ INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
 }
 INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(_obstack_newchunk, obstack, length);
   COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
   REAL(_obstack_newchunk)(obstack, length);
   if (obstack->chunk)
@@ -5692,6 +5969,7 @@ INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
 #if SANITIZER_INTERCEPT_FFLUSH
 INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fflush, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
   int res = REAL(fflush)(fp);
   // FIXME: handle fp == NULL
@@ -5709,6 +5987,7 @@ INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
 #if SANITIZER_INTERCEPT_FCLOSE
 INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fclose, fp);
   COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
   COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
   const FileMetadata *m = GetInterceptorMetadata(fp);
@@ -5727,6 +6006,7 @@ INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
 #if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
 INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(dlopen, filename, flag);
   COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
   if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
   COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag);
@@ -5737,6 +6017,7 @@ INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
 
 INTERCEPTOR(int, dlclose, void *handle) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(dlclose, handle);
   COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
   int res = REAL(dlclose)(handle);
   COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
@@ -5752,6 +6033,7 @@ INTERCEPTOR(int, dlclose, void *handle) {
 #if SANITIZER_INTERCEPT_GETPASS
 INTERCEPTOR(char *, getpass, const char *prompt) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(getpass, prompt);
   COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
   if (prompt)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1);
@@ -5769,6 +6051,7 @@ INTERCEPTOR(char *, getpass, const char *prompt) {
 INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
             void *old_value) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(timerfd_settime, fd, flags, new_value, old_value);
   COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value,
                            old_value);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz);
@@ -5780,6 +6063,7 @@ INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
 
 INTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(timerfd_gettime, fd, curr_value);
   COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value);
   int res = REAL(timerfd_gettime)(fd, curr_value);
   if (res != -1 && curr_value)
@@ -5805,21 +6089,25 @@ static void MlockIsUnsupported() {
 }
 
 INTERCEPTOR(int, mlock, const void *addr, uptr len) {
+  MAYBE_FORWARD_TO_REAL(mlock, addr, len);
   MlockIsUnsupported();
   return 0;
 }
 
 INTERCEPTOR(int, munlock, const void *addr, uptr len) {
+  MAYBE_FORWARD_TO_REAL(munlock, addr, len);
   MlockIsUnsupported();
   return 0;
 }
 
 INTERCEPTOR(int, mlockall, int flags) {
+  MAYBE_FORWARD_TO_REAL(mlockall, flags);
   MlockIsUnsupported();
   return 0;
 }
 
 INTERCEPTOR(int, munlockall, void) {
+  MAYBE_FORWARD_TO_REAL(munlockall,);
   MlockIsUnsupported();
   return 0;
 }
@@ -5875,6 +6163,7 @@ static int wrapped_close(void *cookie) {
 INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
             __sanitizer_cookie_io_functions_t io_funcs) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(fopencookie, cookie, mode, io_funcs);
   COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs);
   WrappedCookie *wrapped_cookie =
       (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie));
@@ -5906,6 +6195,7 @@ INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
 
 INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sem_destroy, s);
   COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
   int res = REAL(sem_destroy)(s);
   return res;
@@ -5913,6 +6203,7 @@ INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
 
 INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sem_wait, s);
   COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
   int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
   if (res == 0) {
@@ -5923,6 +6214,7 @@ INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
 
 INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sem_trywait, s);
   COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
   int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s);
   if (res == 0) {
@@ -5933,6 +6225,7 @@ INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
 
 INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sem_timedwait, s, abstime);
   COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
   COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
   int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime);
@@ -5944,6 +6237,7 @@ INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
 
 INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sem_post, s);
   COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
   COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
   int res = REAL(sem_post)(s);
@@ -5952,6 +6246,7 @@ INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
 
 INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sem_getvalue, s, sval);
   COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
   int res = REAL(sem_getvalue)(s, sval);
   if (res == 0) {
@@ -5975,6 +6270,7 @@ INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
 #if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
 INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pthread_setcancelstate, state, oldstate);
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
   int res = REAL(pthread_setcancelstate)(state, oldstate);
   if (res == 0)
@@ -5984,6 +6280,7 @@ INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
 
 INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(pthread_setcanceltype, type, oldtype);
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
   int res = REAL(pthread_setcanceltype)(type, oldtype);
   if (res == 0)
@@ -6000,6 +6297,7 @@ INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
 #if SANITIZER_INTERCEPT_MINCORE
 INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(mincore, addr, length, vec);
   COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
   int res = REAL(mincore)(addr, length, vec);
   if (res == 0) {
@@ -6019,6 +6317,8 @@ INTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov,
             uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
             uptr flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(process_vm_readv, pid, local_iov, liovcnt, remote_iov,
+                        riovcnt, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt,
                            remote_iov, riovcnt, flags);
   SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov,
@@ -6032,6 +6332,8 @@ INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
             uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
             uptr flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(process_vm_writev, pid, local_iov, liovcnt, remote_iov,
+                        riovcnt, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt,
                            remote_iov, riovcnt, flags);
   SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov,
@@ -6050,6 +6352,7 @@ INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
 #if SANITIZER_INTERCEPT_CTERMID
 INTERCEPTOR(char *, ctermid, char *s) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ctermid, s);
   COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
   char *res = REAL(ctermid)(s);
   if (res) {
@@ -6065,6 +6368,7 @@ INTERCEPTOR(char *, ctermid, char *s) {
 #if SANITIZER_INTERCEPT_CTERMID_R
 INTERCEPTOR(char *, ctermid_r, char *s) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(ctermid_r, s);
   COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
   char *res = REAL(ctermid_r)(s);
   if (res) {
@@ -6080,6 +6384,7 @@ INTERCEPTOR(char *, ctermid_r, char *s) {
 #if SANITIZER_INTERCEPT_RECV_RECVFROM
 INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(recv, fd, buf, len, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   SSIZE_T res = REAL(recv)(fd, buf, len, flags);
@@ -6093,6 +6398,7 @@ INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
 INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
             void *srcaddr, int *addrlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(recvfrom, fd, buf, len, flags, srcaddr, addrlen);
   COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
                            addrlen);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
@@ -6119,6 +6425,7 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
 INTERCEPTOR(SSIZE_T, __recv_chk, int fd, void *buf, SIZE_T len, SIZE_T buflen,
             int flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__recv_chk, fd, buf, len, buflen, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, __recv_chk, fd, buf, len, buflen, flags);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   SSIZE_T res = REAL(recv)(fd, buf, len, flags);
@@ -6132,6 +6439,8 @@ INTERCEPTOR(SSIZE_T, __recv_chk, int fd, void *buf, SIZE_T len, SIZE_T buflen,
 INTERCEPTOR(SSIZE_T, __recvfrom_chk, int fd, void *buf, SIZE_T len,
             SIZE_T buflen, int flags, void *srcaddr, int *addrlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__recvfrom_chk, fd, buf, len, buflen, flags, srcaddr,
+                        addrlen);
   COMMON_INTERCEPTOR_ENTER(ctx, __recvfrom_chk, fd, buf, len, buflen, flags,
                            srcaddr, addrlen);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
@@ -6157,6 +6466,7 @@ INTERCEPTOR(SSIZE_T, __recvfrom_chk, int fd, void *buf, SIZE_T len,
 #if SANITIZER_INTERCEPT_SEND_SENDTO
 INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(send, fd, buf, len, flags);
   COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
   if (fd >= 0) {
     COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
@@ -6171,6 +6481,7 @@ INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
 INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
             void *dstaddr, int addrlen) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(sendto, fd, buf, len, flags, dstaddr, addrlen);
   COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
   if (fd >= 0) {
     COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
@@ -6192,6 +6503,7 @@ INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
 #if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
 INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(eventfd_read, fd, value);
   COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
   COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
   int res = REAL(eventfd_read)(fd, value);
@@ -6203,6 +6515,7 @@ INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
 }
 INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(eventfd_write, fd, value);
   COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
   if (fd >= 0) {
     COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
@@ -6221,6 +6534,7 @@ INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
 #if SANITIZER_INTERCEPT_STAT
 INTERCEPTOR(int, stat, const char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(stat, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
   if (common_flags()->intercept_stat)
     COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
@@ -6237,6 +6551,7 @@ INTERCEPTOR(int, stat, const char *path, void *buf) {
 #if SANITIZER_INTERCEPT___XSTAT
 INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__xstat, version, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
   if (common_flags()->intercept_stat)
     COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
@@ -6253,6 +6568,7 @@ INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
 #if SANITIZER_INTERCEPT___XSTAT64
 INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__xstat64, version, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
   if (common_flags()->intercept_stat)
     COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
@@ -6269,6 +6585,7 @@ INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
 #if SANITIZER_INTERCEPT___LXSTAT
 INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__lxstat, version, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
   if (common_flags()->intercept_stat)
     COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
@@ -6285,6 +6602,7 @@ INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
 #if SANITIZER_INTERCEPT___LXSTAT64
 INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
   void *ctx;
+  MAYBE_FORWARD_TO_REAL(__lxstat64, version, path, buf);
   COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
   if (common_flags()->intercept_stat)
     COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
@@ -6302,16 +6620,19 @@ INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
 
 #if SANITIZER_INTERCEPT_MCHECK_MPROBE
 INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
+  MAYBE_FORWARD_TO_REAL(mcheck, abortfunc);
   return 0;
 }
 #define INIT_MCHECK COMMON_INTERCEPT_FUNCTION(mcheck)
 
 INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
+  MAYBE_FORWARD_TO_REAL(mcheck_pedantic, abortfunc);
   return 0;
 }
 #define INIT_MCHECK_PEDANTIC COMMON_INTERCEPT_FUNCTION(mcheck_pedantic)
 
 INTERCEPTOR(int, mprobe, void *ptr) {
+  MAYBE_FORWARD_TO_REAL(mprobe, ptr);
   return 0;
 }
 #define INIT_MPROBE COMMON_INTERCEPT_FUNCTION(mprobe)