master
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_
26typedef void* PVOID;
27typedef int BOOL;
28typedef union _RTL_RUN_ONCE {
29 PVOID ptr;
30} INIT_ONCE, *PINIT_ONCE;
31
32extern "C" {
33__declspec(dllimport) int WINAPI InitOnceExecuteOnce(
34 PINIT_ONCE, BOOL(WINAPI*)(PINIT_ONCE, PVOID, PVOID*), void*, void*);
35}
36# endif
37
38namespace __sanitizer {
39template <class Ty>
40BOOL 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
46template <class Ty, typename Arg>
47BOOL 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
54template <class Ty>
55Ty& 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
62template <class Ty, typename Arg>
63Ty& 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