Home | History | Annotate | Download | only in esan
      1 //===-- esan_interceptors.cpp ---------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of EfficiencySanitizer, a family of performance tuners.
     11 //
     12 // Interception routines for the esan run-time.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "esan.h"
     16 #include "esan_shadow.h"
     17 #include "interception/interception.h"
     18 #include "sanitizer_common/sanitizer_common.h"
     19 #include "sanitizer_common/sanitizer_libc.h"
     20 #include "sanitizer_common/sanitizer_linux.h"
     21 #include "sanitizer_common/sanitizer_stacktrace.h"
     22 
     23 using namespace __esan; // NOLINT
     24 
     25 #define CUR_PC() (StackTrace::GetCurrentPc())
     26 
     27 //===----------------------------------------------------------------------===//
     28 // Interception via sanitizer common interceptors
     29 //===----------------------------------------------------------------------===//
     30 
     31 // Get the per-platform defines for what is possible to intercept
     32 #include "sanitizer_common/sanitizer_platform_interceptors.h"
     33 
     34 // TODO(bruening): tsan disables several interceptors (getpwent, etc.) claiming
     35 // that interception is a perf hit: should we do the same?
     36 
     37 // We have no need to intercept:
     38 #undef SANITIZER_INTERCEPT_TLS_GET_ADDR
     39 
     40 // TODO(bruening): the common realpath interceptor assumes malloc is
     41 // intercepted!  We should try to parametrize that, though we'll
     42 // intercept malloc soon ourselves and can then remove this undef.
     43 #undef SANITIZER_INTERCEPT_REALPATH
     44 
     45 // We provide our own version:
     46 #undef SANITIZER_INTERCEPT_SIGPROCMASK
     47 
     48 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!EsanIsInitialized)
     49 
     50 #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
     51 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
     52   INTERCEPT_FUNCTION_VER(name, ver)
     53 
     54 // We must initialize during early interceptors, to support tcmalloc.
     55 // This means that for some apps we fully initialize prior to
     56 // __esan_init() being called.
     57 // We currently do not use ctx.
     58 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
     59   do {                                                                         \
     60     if (UNLIKELY(COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)) {                 \
     61       if (!UNLIKELY(EsanDuringInit))                                           \
     62         initializeLibrary(__esan_which_tool);                                  \
     63       return REAL(func)(__VA_ARGS__);                                          \
     64     }                                                                          \
     65     ctx = nullptr;                                                             \
     66     (void)ctx;                                                                 \
     67   } while (false)
     68 
     69 #define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...)                      \
     70   COMMON_INTERCEPTOR_ENTER(ctx, func, __VA_ARGS__)
     71 
     72 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                         \
     73   processRangeAccess(CUR_PC(), (uptr)ptr, size, true)
     74 
     75 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)                          \
     76   processRangeAccess(CUR_PC(), (uptr)ptr, size, false)
     77 
     78 // This is only called if the app explicitly calls exit(), not on
     79 // a normal exit.
     80 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) finalizeLibrary()
     81 
     82 #define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path)                          \
     83   do {                                                                         \
     84     (void)(ctx);                                                               \
     85     (void)(file);                                                              \
     86     (void)(path);                                                              \
     87   } while (false)
     88 #define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file)                               \
     89   do {                                                                         \
     90     (void)(ctx);                                                               \
     91     (void)(file);                                                              \
     92   } while (false)
     93 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)                    \
     94   do {                                                                         \
     95     (void)(filename);                                                          \
     96     (void)(handle);                                                            \
     97   } while (false)
     98 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()                                  \
     99   do {                                                                         \
    100   } while (false)
    101 #define COMMON_INTERCEPTOR_ACQUIRE(ctx, u)                                     \
    102   do {                                                                         \
    103     (void)(ctx);                                                               \
    104     (void)(u);                                                                 \
    105   } while (false)
    106 #define COMMON_INTERCEPTOR_RELEASE(ctx, u)                                     \
    107   do {                                                                         \
    108     (void)(ctx);                                                               \
    109     (void)(u);                                                                 \
    110   } while (false)
    111 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path)                              \
    112   do {                                                                         \
    113     (void)(ctx);                                                               \
    114     (void)(path);                                                              \
    115   } while (false)
    116 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd)                                 \
    117   do {                                                                         \
    118     (void)(ctx);                                                               \
    119     (void)(fd);                                                                \
    120   } while (false)
    121 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd)                                 \
    122   do {                                                                         \
    123     (void)(ctx);                                                               \
    124     (void)(fd);                                                                \
    125   } while (false)
    126 #define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd)                                  \
    127   do {                                                                         \
    128     (void)(ctx);                                                               \
    129     (void)(fd);                                                                \
    130   } while (false)
    131 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd)                    \
    132   do {                                                                         \
    133     (void)(ctx);                                                               \
    134     (void)(fd);                                                                \
    135     (void)(newfd);                                                             \
    136   } while (false)
    137 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name)                          \
    138   do {                                                                         \
    139     (void)(ctx);                                                               \
    140     (void)(name);                                                              \
    141   } while (false)
    142 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name)                 \
    143   do {                                                                         \
    144     (void)(ctx);                                                               \
    145     (void)(thread);                                                            \
    146     (void)(name);                                                              \
    147   } while (false)
    148 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
    149 #define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m)                                  \
    150   do {                                                                         \
    151     (void)(ctx);                                                               \
    152     (void)(m);                                                                 \
    153   } while (false)
    154 #define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m)                                \
    155   do {                                                                         \
    156     (void)(ctx);                                                               \
    157     (void)(m);                                                                 \
    158   } while (false)
    159 #define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m)                                \
    160   do {                                                                         \
    161     (void)(ctx);                                                               \
    162     (void)(m);                                                                 \
    163   } while (false)
    164 #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg)                            \
    165   do {                                                                         \
    166     (void)(ctx);                                                               \
    167     (void)(msg);                                                               \
    168   } while (false)
    169 #define COMMON_INTERCEPTOR_USER_CALLBACK_START()                               \
    170   do {                                                                         \
    171   } while (false)
    172 #define COMMON_INTERCEPTOR_USER_CALLBACK_END()                                 \
    173   do {                                                                         \
    174   } while (false)
    175 
    176 #include "sanitizer_common/sanitizer_common_interceptors.inc"
    177 
    178 //===----------------------------------------------------------------------===//
    179 // Syscall interception
    180 //===----------------------------------------------------------------------===//
    181 
    182 // We want the caller's PC b/c unlike the other function interceptors these
    183 // are separate pre and post functions called around the app's syscall().
    184 
    185 #define COMMON_SYSCALL_PRE_READ_RANGE(ptr, size)                               \
    186   processRangeAccess(GET_CALLER_PC(), (uptr)ptr, size, false)
    187 
    188 #define COMMON_SYSCALL_PRE_WRITE_RANGE(ptr, size)                              \
    189   do {                                                                         \
    190     (void)(ptr);                                                               \
    191     (void)(size);                                                              \
    192   } while (false)
    193 
    194 #define COMMON_SYSCALL_POST_READ_RANGE(ptr, size)                              \
    195   do {                                                                         \
    196     (void)(ptr);                                                               \
    197     (void)(size);                                                              \
    198   } while (false)
    199 
    200 // The actual amount written is in post, not pre.
    201 #define COMMON_SYSCALL_POST_WRITE_RANGE(ptr, size)                             \
    202   processRangeAccess(GET_CALLER_PC(), (uptr)ptr, size, true)
    203 
    204 #define COMMON_SYSCALL_ACQUIRE(addr)                                           \
    205   do {                                                                         \
    206     (void)(addr);                                                              \
    207   } while (false)
    208 #define COMMON_SYSCALL_RELEASE(addr)                                           \
    209   do {                                                                         \
    210     (void)(addr);                                                              \
    211   } while (false)
    212 #define COMMON_SYSCALL_FD_CLOSE(fd)                                            \
    213   do {                                                                         \
    214     (void)(fd);                                                                \
    215   } while (false)
    216 #define COMMON_SYSCALL_FD_ACQUIRE(fd)                                          \
    217   do {                                                                         \
    218     (void)(fd);                                                                \
    219   } while (false)
    220 #define COMMON_SYSCALL_FD_RELEASE(fd)                                          \
    221   do {                                                                         \
    222     (void)(fd);                                                                \
    223   } while (false)
    224 #define COMMON_SYSCALL_PRE_FORK()                                              \
    225   do {                                                                         \
    226   } while (false)
    227 #define COMMON_SYSCALL_POST_FORK(res)                                          \
    228   do {                                                                         \
    229     (void)(res);                                                               \
    230   } while (false)
    231 
    232 #include "sanitizer_common/sanitizer_common_syscalls.inc"
    233 
    234 //===----------------------------------------------------------------------===//
    235 // Custom interceptors
    236 //===----------------------------------------------------------------------===//
    237 
    238 // TODO(bruening): move more of these to the common interception pool as they
    239 // are shared with tsan and asan.
    240 // While our other files match LLVM style, here we match sanitizer style as we
    241 // expect to move these to the common pool.
    242 
    243 INTERCEPTOR(char *, strcpy, char *dst, const char *src) { // NOLINT
    244   void *ctx;
    245   COMMON_INTERCEPTOR_ENTER(ctx, strcpy, dst, src);
    246   uptr srclen = internal_strlen(src);
    247   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, srclen + 1);
    248   COMMON_INTERCEPTOR_READ_RANGE(ctx, src, srclen + 1);
    249   return REAL(strcpy)(dst, src); // NOLINT
    250 }
    251 
    252 INTERCEPTOR(char *, strncpy, char *dst, char *src, uptr n) {
    253   void *ctx;
    254   COMMON_INTERCEPTOR_ENTER(ctx, strncpy, dst, src, n);
    255   uptr srclen = internal_strnlen(src, n);
    256   uptr copied_size = srclen + 1 > n ? n : srclen + 1;
    257   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, copied_size);
    258   COMMON_INTERCEPTOR_READ_RANGE(ctx, src, copied_size);
    259   return REAL(strncpy)(dst, src, n);
    260 }
    261 
    262 INTERCEPTOR(int, open, const char *name, int flags, int mode) {
    263   void *ctx;
    264   COMMON_INTERCEPTOR_ENTER(ctx, open, name, flags, mode);
    265   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
    266   return REAL(open)(name, flags, mode);
    267 }
    268 
    269 #if SANITIZER_LINUX
    270 INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
    271   void *ctx;
    272   COMMON_INTERCEPTOR_ENTER(ctx, open64, name, flags, mode);
    273   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
    274   return REAL(open64)(name, flags, mode);
    275 }
    276 #define ESAN_MAYBE_INTERCEPT_OPEN64 INTERCEPT_FUNCTION(open64)
    277 #else
    278 #define ESAN_MAYBE_INTERCEPT_OPEN64
    279 #endif
    280 
    281 INTERCEPTOR(int, creat, const char *name, int mode) {
    282   void *ctx;
    283   COMMON_INTERCEPTOR_ENTER(ctx, creat, name, mode);
    284   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
    285   return REAL(creat)(name, mode);
    286 }
    287 
    288 #if SANITIZER_LINUX
    289 INTERCEPTOR(int, creat64, const char *name, int mode) {
    290   void *ctx;
    291   COMMON_INTERCEPTOR_ENTER(ctx, creat64, name, mode);
    292   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
    293   return REAL(creat64)(name, mode);
    294 }
    295 #define ESAN_MAYBE_INTERCEPT_CREAT64 INTERCEPT_FUNCTION(creat64)
    296 #else
    297 #define ESAN_MAYBE_INTERCEPT_CREAT64
    298 #endif
    299 
    300 INTERCEPTOR(int, unlink, char *path) {
    301   void *ctx;
    302   COMMON_INTERCEPTOR_ENTER(ctx, unlink, path);
    303   COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
    304   return REAL(unlink)(path);
    305 }
    306 
    307 INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
    308   void *ctx;
    309   COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, f);
    310   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size * nmemb);
    311   return REAL(fread)(ptr, size, nmemb, f);
    312 }
    313 
    314 INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
    315   void *ctx;
    316   COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, f);
    317   COMMON_INTERCEPTOR_READ_RANGE(ctx, p, size * nmemb);
    318   return REAL(fwrite)(p, size, nmemb, f);
    319 }
    320 
    321 INTERCEPTOR(int, puts, const char *s) {
    322   void *ctx;
    323   COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
    324   COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s));
    325   return REAL(puts)(s);
    326 }
    327 
    328 INTERCEPTOR(int, rmdir, char *path) {
    329   void *ctx;
    330   COMMON_INTERCEPTOR_ENTER(ctx, rmdir, path);
    331   COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
    332   return REAL(rmdir)(path);
    333 }
    334 
    335 //===----------------------------------------------------------------------===//
    336 // Shadow-related interceptors
    337 //===----------------------------------------------------------------------===//
    338 
    339 // These are candidates for sharing with all sanitizers if shadow memory
    340 // support is also standardized.
    341 
    342 INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags,
    343                  int fd, OFF_T off) {
    344   if (UNLIKELY(REAL(mmap) == nullptr)) {
    345     // With esan init during interceptor init and a static libc preventing
    346     // our early-calloc from triggering, we can end up here before our
    347     // REAL pointer is set up.
    348     return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
    349   }
    350   void *ctx;
    351   COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
    352   if (!fixMmapAddr(&addr, sz, flags))
    353     return (void *)-1;
    354   void *result = REAL(mmap)(addr, sz, prot, flags, fd, off);
    355   return (void *)checkMmapResult((uptr)result, sz);
    356 }
    357 
    358 #if SANITIZER_LINUX
    359 INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags,
    360                  int fd, OFF64_T off) {
    361   void *ctx;
    362   COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);
    363   if (!fixMmapAddr(&addr, sz, flags))
    364     return (void *)-1;
    365   void *result = REAL(mmap64)(addr, sz, prot, flags, fd, off);
    366   return (void *)checkMmapResult((uptr)result, sz);
    367 }
    368 #define ESAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64)
    369 #else
    370 #define ESAN_MAYBE_INTERCEPT_MMAP64
    371 #endif
    372 
    373 //===----------------------------------------------------------------------===//
    374 // Signal-related interceptors
    375 //===----------------------------------------------------------------------===//
    376 
    377 #if SANITIZER_LINUX
    378 typedef void (*signal_handler_t)(int);
    379 INTERCEPTOR(signal_handler_t, signal, int signum, signal_handler_t handler) {
    380   void *ctx;
    381   COMMON_INTERCEPTOR_ENTER(ctx, signal, signum, handler);
    382   signal_handler_t result;
    383   if (!processSignal(signum, handler, &result))
    384     return result;
    385   else
    386     return REAL(signal)(signum, handler);
    387 }
    388 #define ESAN_MAYBE_INTERCEPT_SIGNAL INTERCEPT_FUNCTION(signal)
    389 #else
    390 #error Platform not supported
    391 #define ESAN_MAYBE_INTERCEPT_SIGNAL
    392 #endif
    393 
    394 #if SANITIZER_LINUX
    395 DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
    396              struct sigaction *oldact)
    397 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
    398             struct sigaction *oldact) {
    399   void *ctx;
    400   COMMON_INTERCEPTOR_ENTER(ctx, sigaction, signum, act, oldact);
    401   if (!processSigaction(signum, act, oldact))
    402     return 0;
    403   else
    404     return REAL(sigaction)(signum, act, oldact);
    405 }
    406 
    407 // This is required to properly use internal_sigaction.
    408 namespace __sanitizer {
    409 int real_sigaction(int signum, const void *act, void *oldact) {
    410   if (REAL(sigaction) == nullptr) {
    411     // With an instrumented allocator, this is called during interceptor init
    412     // and we need a raw syscall solution.
    413     return internal_sigaction_syscall(signum, act, oldact);
    414   }
    415   return REAL(sigaction)(signum, (const struct sigaction *)act,
    416                          (struct sigaction *)oldact);
    417 }
    418 } // namespace __sanitizer
    419 
    420 #define ESAN_MAYBE_INTERCEPT_SIGACTION INTERCEPT_FUNCTION(sigaction)
    421 #else
    422 #error Platform not supported
    423 #define ESAN_MAYBE_INTERCEPT_SIGACTION
    424 #endif
    425 
    426 #if SANITIZER_LINUX
    427 INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
    428             __sanitizer_sigset_t *oldset) {
    429   void *ctx;
    430   COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
    431   int res = 0;
    432   if (processSigprocmask(how, set, oldset))
    433     res = REAL(sigprocmask)(how, set, oldset);
    434   if (!res && oldset)
    435     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
    436   return res;
    437 }
    438 #define ESAN_MAYBE_INTERCEPT_SIGPROCMASK INTERCEPT_FUNCTION(sigprocmask)
    439 #else
    440 #define ESAN_MAYBE_INTERCEPT_SIGPROCMASK
    441 #endif
    442 
    443 #if !SANITIZER_WINDOWS
    444 INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set,
    445             __sanitizer_sigset_t *oldset) {
    446   void *ctx;
    447   COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset);
    448   int res = 0;
    449   if (processSigprocmask(how, set, oldset))
    450     res = REAL(sigprocmask)(how, set, oldset);
    451   if (!res && oldset)
    452     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
    453   return res;
    454 }
    455 #define ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK INTERCEPT_FUNCTION(pthread_sigmask)
    456 #else
    457 #define ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK
    458 #endif
    459 
    460 //===----------------------------------------------------------------------===//
    461 // Malloc interceptors
    462 //===----------------------------------------------------------------------===//
    463 
    464 static char early_alloc_buf[128];
    465 static bool used_early_alloc_buf;
    466 
    467 static void *handleEarlyAlloc(uptr size) {
    468   // If esan is initialized during an interceptor (which happens with some
    469   // tcmalloc implementations that call pthread_mutex_lock), the call from
    470   // dlsym to calloc will deadlock.  There is only one such calloc (dlsym
    471   // allocates a single pthread key), so we work around it by using a
    472   // static buffer for the calloc request.  The loader currently needs
    473   // 32 bytes but we size at 128 to allow for future changes.
    474   // This solution will also allow us to deliberately intercept malloc & family
    475   // in the future (to perform tool actions on each allocation, without
    476   // replacing the allocator), as it also solves the problem of intercepting
    477   // calloc when it will itself be called before its REAL pointer is
    478   // initialized.
    479   CHECK(!used_early_alloc_buf && size < sizeof(early_alloc_buf));
    480   // We do not handle multiple threads here.  This only happens at process init
    481   // time, and while it's possible for a shared library to create early threads
    482   // that race here, we consider that to be a corner case extreme enough that
    483   // it's not worth the effort to handle.
    484   used_early_alloc_buf = true;
    485   return (void *)early_alloc_buf;
    486 }
    487 
    488 INTERCEPTOR(void*, calloc, uptr size, uptr n) {
    489   if (EsanDuringInit && REAL(calloc) == nullptr)
    490     return handleEarlyAlloc(size * n);
    491   void *ctx;
    492   COMMON_INTERCEPTOR_ENTER(ctx, calloc, size, n);
    493   void *res = REAL(calloc)(size, n);
    494   // The memory is zeroed and thus is all written.
    495   COMMON_INTERCEPTOR_WRITE_RANGE(nullptr, (uptr)res, size * n);
    496   return res;
    497 }
    498 
    499 INTERCEPTOR(void, free, void *p) {
    500   void *ctx;
    501   COMMON_INTERCEPTOR_ENTER(ctx, free, p);
    502   if (p == (void *)early_alloc_buf) {
    503     // We expect just a singleton use but we clear this for cleanliness.
    504     used_early_alloc_buf = false;
    505     return;
    506   }
    507   REAL(free)(p);
    508 }
    509 
    510 namespace __esan {
    511 
    512 void initializeInterceptors() {
    513   InitializeCommonInterceptors();
    514 
    515   INTERCEPT_FUNCTION(strcpy); // NOLINT
    516   INTERCEPT_FUNCTION(strncpy);
    517 
    518   INTERCEPT_FUNCTION(open);
    519   ESAN_MAYBE_INTERCEPT_OPEN64;
    520   INTERCEPT_FUNCTION(creat);
    521   ESAN_MAYBE_INTERCEPT_CREAT64;
    522   INTERCEPT_FUNCTION(unlink);
    523   INTERCEPT_FUNCTION(fread);
    524   INTERCEPT_FUNCTION(fwrite);
    525   INTERCEPT_FUNCTION(puts);
    526   INTERCEPT_FUNCTION(rmdir);
    527 
    528   INTERCEPT_FUNCTION(mmap);
    529   ESAN_MAYBE_INTERCEPT_MMAP64;
    530 
    531   ESAN_MAYBE_INTERCEPT_SIGNAL;
    532   ESAN_MAYBE_INTERCEPT_SIGACTION;
    533   ESAN_MAYBE_INTERCEPT_SIGPROCMASK;
    534   ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK;
    535 
    536   INTERCEPT_FUNCTION(calloc);
    537   INTERCEPT_FUNCTION(free);
    538 
    539   // TODO(bruening): intercept routines that other sanitizers intercept that
    540   // are not in the common pool or here yet, ideally by adding to the common
    541   // pool.  Examples include wcslen and bcopy.
    542 
    543   // TODO(bruening): there are many more libc routines that read or write data
    544   // structures that no sanitizer is intercepting: sigaction, strtol, etc.
    545 }
    546 
    547 } // namespace __esan
    548