xref: /llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_win_immortalize.h (revision 53a81d4d26f0409de8a0655d7af90f2bea222a12)
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