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