diff options
Diffstat (limited to 'lib/interception/interception_linux.cc')
| -rw-r--r-- | lib/interception/interception_linux.cc | 60 | 
1 files changed, 44 insertions, 16 deletions
diff --git a/lib/interception/interception_linux.cc b/lib/interception/interception_linux.cc index 26bfcd8f6794d..4b27102a159c8 100644 --- a/lib/interception/interception_linux.cc +++ b/lib/interception/interception_linux.cc @@ -1,9 +1,8 @@  //===-- interception_linux.cc -----------------------------------*- C++ -*-===//  // -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception  //  //===----------------------------------------------------------------------===//  // @@ -19,33 +18,62 @@  #include <dlfcn.h>   // for dlsym() and dlvsym() +namespace __interception { +  #if SANITIZER_NETBSD -#include "sanitizer_common/sanitizer_libc.h" +static int StrCmp(const char *s1, const char *s2) { +  while (true) { +    if (*s1 != *s2) +      return false; +    if (*s1 == 0) +      return true; +    s1++; +    s2++; +  } +}  #endif -namespace __interception { -bool GetRealFunctionAddress(const char *func_name, uptr *func_addr, -    uptr real, uptr wrapper) { +static void *GetFuncAddr(const char *name, uptr wrapper_addr) {  #if SANITIZER_NETBSD -  // XXX: Find a better way to handle renames -  if (internal_strcmp(func_name, "sigaction") == 0) func_name = "__sigaction14"; +  // FIXME: Find a better way to handle renames +  if (StrCmp(name, "sigaction")) +    name = "__sigaction14";  #endif -  *func_addr = (uptr)dlsym(RTLD_NEXT, func_name); -  if (!*func_addr) { +  void *addr = dlsym(RTLD_NEXT, name); +  if (!addr) {      // If the lookup using RTLD_NEXT failed, the sanitizer runtime library is      // later in the library search order than the DSO that we are trying to      // intercept, which means that we cannot intercept this function. We still      // want the address of the real definition, though, so look it up using      // RTLD_DEFAULT. -    *func_addr = (uptr)dlsym(RTLD_DEFAULT, func_name); +    addr = dlsym(RTLD_DEFAULT, name); + +    // In case `name' is not loaded, dlsym ends up finding the actual wrapper. +    // We don't want to intercept the wrapper and have it point to itself. +    if ((uptr)addr == wrapper_addr) +      addr = nullptr;    } -  return real == wrapper; +  return addr; +} + +bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, +                       uptr wrapper) { +  void *addr = GetFuncAddr(name, wrapper); +  *ptr_to_real = (uptr)addr; +  return addr && (func == wrapper);  }  // Android and Solaris do not have dlvsym  #if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD -void *GetFuncAddrVer(const char *func_name, const char *ver) { -  return dlvsym(RTLD_NEXT, func_name, ver); +static void *GetFuncAddr(const char *name, const char *ver) { +  return dlvsym(RTLD_NEXT, name, ver); +} + +bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, +                       uptr func, uptr wrapper) { +  void *addr = GetFuncAddr(name, ver); +  *ptr_to_real = (uptr)addr; +  return addr && (func == wrapper);  }  #endif  // !SANITIZER_ANDROID  | 
