1 //===-- sanitizer_win_immortalize.h ---------------------------------------===// 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 shared between AddressSanitizer, and interception. 10 // 11 // Windows-specific thread-safe and pre-CRT global initialization safe 12 // infrastructure to create an object whose destructor is never called. 13 //===----------------------------------------------------------------------===// 14 #if SANITIZER_WINDOWS 15 # pragma once 16 // Requires including sanitizer_placement_new.h (which is not allowed to be 17 // included in headers). 18 19 # include "sanitizer_win_defs.h" 20 // These types are required to satisfy XFG which requires that the names of the 21 // types for indirect calls to be correct as well as the name of the original 22 // type for any typedefs. 23 24 // TODO: There must be a better way to do this 25 # ifndef _WINDOWS_ 26 typedef void* PVOID; 27 typedef int BOOL; 28 typedef union _RTL_RUN_ONCE { 29 PVOID ptr; 30 } INIT_ONCE, *PINIT_ONCE; 31 32 extern "C" { 33 __declspec(dllimport) int WINAPI InitOnceExecuteOnce( 34 PINIT_ONCE, BOOL(WINAPI*)(PINIT_ONCE, PVOID, PVOID*), void*, void*); 35 } 36 # endif 37 38 namespace __sanitizer { 39 template <class Ty> 40 BOOL WINAPI immortalize_impl(PINIT_ONCE, PVOID storage_ptr, PVOID*) noexcept { 41 // Ty must provide a placement new operator 42 new (storage_ptr) Ty(); 43 return 1; 44 } 45 46 template <class Ty, typename Arg> 47 BOOL WINAPI immortalize_impl(PINIT_ONCE, PVOID storage_ptr, 48 PVOID* param) noexcept { 49 // Ty must provide a placement new operator 50 new (storage_ptr) Ty(*((Arg*)param)); 51 return 1; 52 } 53 54 template <class Ty> 55 Ty& immortalize() { // return a reference to an object that will live forever 56 static INIT_ONCE flag; 57 alignas(Ty) static unsigned char storage[sizeof(Ty)]; 58 InitOnceExecuteOnce(&flag, immortalize_impl<Ty>, &storage, nullptr); 59 return reinterpret_cast<Ty&>(storage); 60 } 61 62 template <class Ty, typename Arg> 63 Ty& immortalize( 64 Arg arg) { // return a reference to an object that will live forever 65 static INIT_ONCE flag; 66 alignas(Ty) static unsigned char storage[sizeof(Ty)]; 67 InitOnceExecuteOnce(&flag, immortalize_impl<Ty, Arg>, &storage, &arg); 68 return reinterpret_cast<Ty&>(storage); 69 } 70 } // namespace __sanitizer 71 #endif // SANITIZER_WINDOWS 72