Path: blob/main/contrib/llvm-project/compiler-rt/lib/interception/interception_linux.cpp
35262 views
//===-- interception_linux.cpp ----------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of AddressSanitizer, an address sanity checker.9//10// Linux-specific interception methods.11//===----------------------------------------------------------------------===//1213#include "interception.h"1415#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \16SANITIZER_SOLARIS1718#include <dlfcn.h> // for dlsym() and dlvsym()1920namespace __interception {2122#if SANITIZER_NETBSD23static int StrCmp(const char *s1, const char *s2) {24while (true) {25if (*s1 != *s2)26return false;27if (*s1 == 0)28return true;29s1++;30s2++;31}32}33#endif3435static void *GetFuncAddr(const char *name, uptr trampoline) {36#if SANITIZER_NETBSD37// FIXME: Find a better way to handle renames38if (StrCmp(name, "sigaction"))39name = "__sigaction14";40#endif41void *addr = dlsym(RTLD_NEXT, name);42if (!addr) {43// If the lookup using RTLD_NEXT failed, the sanitizer runtime library is44// later in the library search order than the DSO that we are trying to45// intercept, which means that we cannot intercept this function. We still46// want the address of the real definition, though, so look it up using47// RTLD_DEFAULT.48addr = dlsym(RTLD_DEFAULT, name);4950// In case `name' is not loaded, dlsym ends up finding the actual wrapper.51// We don't want to intercept the wrapper and have it point to itself.52if ((uptr)addr == trampoline)53addr = nullptr;54}55return addr;56}5758bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,59uptr trampoline) {60void *addr = GetFuncAddr(name, trampoline);61*ptr_to_real = (uptr)addr;62return addr && (func == trampoline);63}6465// dlvsym is a GNU extension supported by some other platforms.66#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD67static void *GetFuncAddr(const char *name, const char *ver) {68return dlvsym(RTLD_NEXT, name, ver);69}7071bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,72uptr func, uptr trampoline) {73void *addr = GetFuncAddr(name, ver);74*ptr_to_real = (uptr)addr;75return addr && (func == trampoline);76}77# endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD7879} // namespace __interception8081#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||82// SANITIZER_SOLARIS838485