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