interception_linux.cpp revision 360784
1//===-- interception_linux.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// This file is a part of AddressSanitizer, an address sanity checker. 10// 11// Linux-specific interception methods. 12//===----------------------------------------------------------------------===// 13 14#include "interception.h" 15 16#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ 17 SANITIZER_OPENBSD || SANITIZER_SOLARIS 18 19#include <dlfcn.h> // for dlsym() and dlvsym() 20 21namespace __interception { 22 23#if SANITIZER_NETBSD 24static int StrCmp(const char *s1, const char *s2) { 25 while (true) { 26 if (*s1 != *s2) 27 return false; 28 if (*s1 == 0) 29 return true; 30 s1++; 31 s2++; 32 } 33} 34#endif 35 36static void *GetFuncAddr(const char *name, uptr wrapper_addr) { 37#if SANITIZER_NETBSD 38 // FIXME: Find a better way to handle renames 39 if (StrCmp(name, "sigaction")) 40 name = "__sigaction14"; 41#endif 42 void *addr = dlsym(RTLD_NEXT, name); 43 if (!addr) { 44 // If the lookup using RTLD_NEXT failed, the sanitizer runtime library is 45 // later in the library search order than the DSO that we are trying to 46 // intercept, which means that we cannot intercept this function. We still 47 // want the address of the real definition, though, so look it up using 48 // RTLD_DEFAULT. 49 addr = dlsym(RTLD_DEFAULT, name); 50 51 // In case `name' is not loaded, dlsym ends up finding the actual wrapper. 52 // We don't want to intercept the wrapper and have it point to itself. 53 if ((uptr)addr == wrapper_addr) 54 addr = nullptr; 55 } 56 return addr; 57} 58 59bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, 60 uptr wrapper) { 61 void *addr = GetFuncAddr(name, wrapper); 62 *ptr_to_real = (uptr)addr; 63 return addr && (func == wrapper); 64} 65 66// Android and Solaris do not have dlvsym 67#if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD 68static void *GetFuncAddr(const char *name, const char *ver) { 69 return dlvsym(RTLD_NEXT, name, ver); 70} 71 72bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, 73 uptr func, uptr wrapper) { 74 void *addr = GetFuncAddr(name, ver); 75 *ptr_to_real = (uptr)addr; 76 return addr && (func == wrapper); 77} 78#endif // !SANITIZER_ANDROID 79 80} // namespace __interception 81 82#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || 83 // SANITIZER_OPENBSD || SANITIZER_SOLARIS 84