1 //===-- sanitizer_wrappers.cpp ----------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Redirect some functions to sanitizer interceptors. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include <dlfcn.h> 14 #include <errno.h> 15 #include <fcntl.h> 16 #include <stdarg.h> 17 #include <stdio.h> 18 #include <unistd.h> 19 20 #include <tuple> 21 22 namespace __sanitizer { 23 unsigned long internal_open(const char *filename, int flags); 24 unsigned long internal_open(const char *filename, int flags, unsigned mode); 25 unsigned long internal_close(int fd); 26 unsigned long internal_stat(const char *path, void *buf); 27 unsigned long internal_lstat(const char *path, void *buf); 28 unsigned long internal_fstat(int fd, void *buf); 29 size_t internal_strlen(const char *s); 30 unsigned long internal_mmap(void *addr, unsigned long length, int prot, 31 int flags, int fd, unsigned long long offset); 32 void *internal_memcpy(void *dest, const void *src, unsigned long n); 33 // Used to propagate errno. 34 bool internal_iserror(unsigned long retval, int *rverrno = 0); 35 } // namespace __sanitizer 36 37 namespace { 38 39 template <typename T> 40 struct GetTypes; 41 42 template <typename R, typename... Args> 43 struct GetTypes<R(Args...)> { 44 using Result = R; 45 template <size_t i> 46 struct Arg { 47 using Type = typename std::tuple_element<i, std::tuple<Args...>>::type; 48 }; 49 }; 50 51 #define LLVM_SYMBOLIZER_GET_FUNC(Function) \ 52 ((__interceptor_##Function) \ 53 ? (__interceptor_##Function) \ 54 : reinterpret_cast<decltype(&Function)>(dlsym(RTLD_NEXT, #Function))) 55 56 #define LLVM_SYMBOLIZER_INTERCEPTOR1(Function, ...) \ 57 GetTypes<__VA_ARGS__>::Result __interceptor_##Function( \ 58 GetTypes<__VA_ARGS__>::Arg<0>::Type) __attribute__((weak)); \ 59 GetTypes<__VA_ARGS__>::Result Function( \ 60 GetTypes<__VA_ARGS__>::Arg<0>::Type arg0) { \ 61 return LLVM_SYMBOLIZER_GET_FUNC(Function)(arg0); \ 62 } 63 64 #define LLVM_SYMBOLIZER_INTERCEPTOR2(Function, ...) \ 65 GetTypes<__VA_ARGS__>::Result __interceptor_##Function( \ 66 GetTypes<__VA_ARGS__>::Arg<0>::Type, \ 67 GetTypes<__VA_ARGS__>::Arg<1>::Type) __attribute__((weak)); \ 68 GetTypes<__VA_ARGS__>::Result Function( \ 69 GetTypes<__VA_ARGS__>::Arg<0>::Type arg0, \ 70 GetTypes<__VA_ARGS__>::Arg<1>::Type arg1) { \ 71 return LLVM_SYMBOLIZER_GET_FUNC(Function)(arg0, arg1); \ 72 } 73 74 #define LLVM_SYMBOLIZER_INTERCEPTOR3(Function, ...) \ 75 GetTypes<__VA_ARGS__>::Result __interceptor_##Function( \ 76 GetTypes<__VA_ARGS__>::Arg<0>::Type, \ 77 GetTypes<__VA_ARGS__>::Arg<1>::Type, \ 78 GetTypes<__VA_ARGS__>::Arg<2>::Type) __attribute__((weak)); \ 79 GetTypes<__VA_ARGS__>::Result Function( \ 80 GetTypes<__VA_ARGS__>::Arg<0>::Type arg0, \ 81 GetTypes<__VA_ARGS__>::Arg<1>::Type arg1, \ 82 GetTypes<__VA_ARGS__>::Arg<2>::Type arg2) { \ 83 return LLVM_SYMBOLIZER_GET_FUNC(Function)(arg0, arg1, arg2); \ 84 } 85 86 #define LLVM_SYMBOLIZER_INTERCEPTOR4(Function, ...) \ 87 GetTypes<__VA_ARGS__>::Result __interceptor_##Function( \ 88 GetTypes<__VA_ARGS__>::Arg<0>::Type, \ 89 GetTypes<__VA_ARGS__>::Arg<1>::Type, \ 90 GetTypes<__VA_ARGS__>::Arg<2>::Type, \ 91 GetTypes<__VA_ARGS__>::Arg<3>::Type) __attribute__((weak)); \ 92 GetTypes<__VA_ARGS__>::Result Function( \ 93 GetTypes<__VA_ARGS__>::Arg<0>::Type arg0, \ 94 GetTypes<__VA_ARGS__>::Arg<1>::Type arg1, \ 95 GetTypes<__VA_ARGS__>::Arg<2>::Type arg2, \ 96 GetTypes<__VA_ARGS__>::Arg<3>::Type arg3) { \ 97 return LLVM_SYMBOLIZER_GET_FUNC(Function)(arg0, arg1, arg2, arg3); \ 98 } 99 100 } // namespace 101 102 // C-style interface around internal sanitizer libc functions. 103 extern "C" { 104 105 #define RETURN_OR_SET_ERRNO(T, res) \ 106 int rverrno; \ 107 if (__sanitizer::internal_iserror(res, &rverrno)) { \ 108 errno = rverrno; \ 109 return (T)-1; \ 110 } \ 111 return (T)res; 112 113 int open(const char *filename, int flags, ...) { 114 unsigned long res; 115 if (flags | O_CREAT) { 116 va_list va; 117 va_start(va, flags); 118 unsigned mode = va_arg(va, unsigned); 119 va_end(va); 120 res = __sanitizer::internal_open(filename, flags, mode); 121 } else { 122 res = __sanitizer::internal_open(filename, flags); 123 } 124 RETURN_OR_SET_ERRNO(int, res); 125 } 126 127 int close(int fd) { 128 unsigned long res = __sanitizer::internal_close(fd); 129 RETURN_OR_SET_ERRNO(int, res); 130 } 131 132 #define STAT(func, arg, buf) \ 133 unsigned long res = __sanitizer::internal_##func(arg, buf); \ 134 RETURN_OR_SET_ERRNO(int, res); 135 136 int stat(const char *path, struct stat *buf) { STAT(stat, path, buf); } 137 138 int lstat(const char *path, struct stat *buf) { STAT(lstat, path, buf); } 139 140 int fstat(int fd, struct stat *buf) { STAT(fstat, fd, buf); } 141 142 // Redirect versioned stat functions to the __sanitizer::internal() as well. 143 int __xstat(int version, const char *path, struct stat *buf) { 144 STAT(stat, path, buf); 145 } 146 147 int __lxstat(int version, const char *path, struct stat *buf) { 148 STAT(lstat, path, buf); 149 } 150 151 int __fxstat(int version, int fd, struct stat *buf) { STAT(fstat, fd, buf); } 152 153 size_t strlen(const char *s) { return __sanitizer::internal_strlen(s); } 154 155 void *mmap(void *addr, size_t length, int prot, int flags, int fd, 156 off_t offset) { 157 unsigned long res = __sanitizer::internal_mmap( 158 addr, (unsigned long)length, prot, flags, fd, (unsigned long long)offset); 159 RETURN_OR_SET_ERRNO(void *, res); 160 } 161 162 LLVM_SYMBOLIZER_INTERCEPTOR3(read, ssize_t(int, void *, size_t)) 163 LLVM_SYMBOLIZER_INTERCEPTOR4(pread, ssize_t(int, void *, size_t, off_t)) 164 LLVM_SYMBOLIZER_INTERCEPTOR4(pread64, ssize_t(int, void *, size_t, off64_t)) 165 LLVM_SYMBOLIZER_INTERCEPTOR2(realpath, char *(const char *, char *)) 166 167 LLVM_SYMBOLIZER_INTERCEPTOR1(pthread_cond_broadcast, int(pthread_cond_t *)) 168 LLVM_SYMBOLIZER_INTERCEPTOR2(pthread_cond_wait, 169 int(pthread_cond_t *, pthread_mutex_t *)) 170 LLVM_SYMBOLIZER_INTERCEPTOR1(pthread_mutex_lock, int(pthread_mutex_t *)) 171 LLVM_SYMBOLIZER_INTERCEPTOR1(pthread_mutex_unlock, int(pthread_mutex_t *)) 172 LLVM_SYMBOLIZER_INTERCEPTOR1(pthread_mutex_destroy, int(pthread_mutex_t *)) 173 LLVM_SYMBOLIZER_INTERCEPTOR2(pthread_mutex_init, 174 int(pthread_mutex_t *, 175 const pthread_mutexattr_t *)) 176 LLVM_SYMBOLIZER_INTERCEPTOR1(pthread_mutexattr_destroy, 177 int(pthread_mutexattr_t *)) 178 LLVM_SYMBOLIZER_INTERCEPTOR1(pthread_mutexattr_init, int(pthread_mutexattr_t *)) 179 LLVM_SYMBOLIZER_INTERCEPTOR2(pthread_mutexattr_settype, 180 int(pthread_mutexattr_t *, int)) 181 LLVM_SYMBOLIZER_INTERCEPTOR1(pthread_getspecific, void *(pthread_key_t)) 182 LLVM_SYMBOLIZER_INTERCEPTOR2(pthread_key_create, 183 int(pthread_key_t *, void (*)(void *))) 184 LLVM_SYMBOLIZER_INTERCEPTOR2(pthread_once, 185 int(pthread_once_t *, void (*)(void))) 186 LLVM_SYMBOLIZER_INTERCEPTOR2(pthread_setspecific, 187 int(pthread_key_t, const void *)) 188 LLVM_SYMBOLIZER_INTERCEPTOR3(pthread_sigmask, 189 int(int, const sigset_t *, sigset_t *)) 190 191 } // extern "C" 192