brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · c93a411 Raw
157 lines · cpp
1//===-- sanitizer_win_interception.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-exception6//7//===----------------------------------------------------------------------===//8//9// Windows-specific export surface to provide interception for parts of the10// runtime that are always statically linked, both for overriding user-defined11// functions as well as registering weak functions that the ASAN runtime should12// use over defaults.13//14//===----------------------------------------------------------------------===//15 16#include "sanitizer_platform.h"17#if SANITIZER_WINDOWS18#  include <stddef.h>19 20#  include "interception/interception.h"21#  include "sanitizer_addrhashmap.h"22#  include "sanitizer_common.h"23#  include "sanitizer_internal_defs.h"24#  include "sanitizer_placement_new.h"25#  include "sanitizer_win_immortalize.h"26#  include "sanitizer_win_interception.h"27 28using namespace __sanitizer;29 30extern "C" void *__ImageBase;31 32namespace __sanitizer {33 34static uptr GetSanitizerDllExport(const char *export_name) {35  const uptr function_address =36      __interception::InternalGetProcAddress(&__ImageBase, export_name);37  if (function_address == 0) {38    Report("ERROR: Failed to find sanitizer DLL export '%s'\n", export_name);39    CHECK("Failed to find sanitizer DLL export" && 0);40  }41  return function_address;42}43 44struct WeakCallbackList {45  explicit constexpr WeakCallbackList(RegisterWeakFunctionCallback cb)46      : callback(cb), next(nullptr) {}47 48  static void *operator new(size_t size) { return InternalAlloc(size); }49 50  static void operator delete(void *p) { InternalFree(p); }51 52  RegisterWeakFunctionCallback callback;53  WeakCallbackList *next;54};55using WeakCallbackMap = AddrHashMap<WeakCallbackList *, 11>;56 57static WeakCallbackMap *GetWeakCallbackMap() {58  return &immortalize<WeakCallbackMap>();59}60 61void AddRegisterWeakFunctionCallback(uptr export_address,62                                     RegisterWeakFunctionCallback cb) {63  WeakCallbackMap::Handle h_find_or_create(GetWeakCallbackMap(), export_address,64                                           false, true);65  CHECK(h_find_or_create.exists());66  if (h_find_or_create.created()) {67    *h_find_or_create = new WeakCallbackList(cb);68  } else {69    (*h_find_or_create)->next = new WeakCallbackList(cb);70  }71}72 73static void RunWeakFunctionCallbacks(uptr export_address) {74  WeakCallbackMap::Handle h_find(GetWeakCallbackMap(), export_address, false,75                                 false);76  if (!h_find.exists()) {77    return;78  }79 80  WeakCallbackList *list = *h_find;81  do {82    list->callback();83  } while ((list = list->next));84}85 86}  // namespace __sanitizer87 88extern "C" __declspec(dllexport) bool __cdecl __sanitizer_override_function(89    const char *export_name, const uptr user_function,90    uptr *const old_user_function) {91  CHECK(export_name);92  CHECK(user_function);93 94  const uptr sanitizer_function = GetSanitizerDllExport(export_name);95 96  const bool function_overridden = __interception::OverrideFunction(97      user_function, sanitizer_function, old_user_function);98  if (!function_overridden) {99    Report(100        "ERROR: Failed to override local function at '%p' with sanitizer "101        "function '%s'\n",102        user_function, export_name);103    CHECK("Failed to replace local function with sanitizer version." && 0);104  }105 106  return function_overridden;107}108 109extern "C"110    __declspec(dllexport) bool __cdecl __sanitizer_override_function_by_addr(111        const uptr source_function, const uptr target_function,112        uptr *const old_target_function) {113  CHECK(source_function);114  CHECK(target_function);115 116  const bool function_overridden = __interception::OverrideFunction(117      target_function, source_function, old_target_function);118  if (!function_overridden) {119    Report(120        "ERROR: Failed to override function at '%p' with function at "121        "'%p'\n",122        target_function, source_function);123    CHECK("Failed to apply function override." && 0);124  }125 126  return function_overridden;127}128 129extern "C"130    __declspec(dllexport) bool __cdecl __sanitizer_register_weak_function(131        const char *export_name, const uptr user_function,132        uptr *const old_user_function) {133  CHECK(export_name);134  CHECK(user_function);135 136  const uptr sanitizer_function = GetSanitizerDllExport(export_name);137 138  const bool function_overridden = __interception::OverrideFunction(139      sanitizer_function, user_function, old_user_function);140  if (!function_overridden) {141    Report(142        "ERROR: Failed to register local function at '%p' to be used in "143        "place of sanitizer function '%s'\n.",144        user_function, export_name);145    CHECK("Failed to register weak function." && 0);146  }147 148  // Note that thread-safety of RunWeakFunctionCallbacks in InitializeFlags149  // depends on __sanitizer_register_weak_functions being called during the150  // loader lock.151  RunWeakFunctionCallbacks(sanitizer_function);152 153  return function_overridden;154}155 156#endif  // SANITIZER_WINDOWS157