Bug 1941128 - Turn off network.dns.native_https_query on Mac again
[gecko.git] / memory / build / replace_malloc_bridge.h
blob0e1a9e9f75534910a3519d5f02fb04abbd8958eb
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef replace_malloc_bridge_h
8 #define replace_malloc_bridge_h
10 // The replace-malloc bridge allows bidirectional method calls between
11 // a program and the replace-malloc library that has been loaded for it.
12 // In Firefox, this is used to allow method calls between code in libxul
13 // and code in the replace-malloc library, without libxul needing to link
14 // against that library or vice-versa.
16 // Subsystems can add methods for their own need. Replace-malloc libraries
17 // can decide to implement those methods or not.
19 // Replace-malloc libraries can provide such a bridge by implementing
20 // a ReplaceMallocBridge-derived class, and a get_bridge function
21 // returning an instance of that class. The default methods in
22 // ReplaceMallocBridge are expected to return values that callers would
23 // understand as "the bridge doesn't implement this method", so that a
24 // replace-malloc library doesn't have to implement all methods.
26 // The ReplaceMallocBridge class contains definitions for methods for
27 // all replace-malloc libraries. Each library picks the methods it wants
28 // to reply to in its ReplaceMallocBridge-derived class instance.
29 // All methods of ReplaceMallocBridge must be virtual. Similarly,
30 // anything passed as an argument to those methods must be plain data, or
31 // an instance of a class with only virtual methods.
33 // Binary compatibility is expected to be maintained, such that a newer
34 // Firefox can be used with an old replace-malloc library, or an old
35 // Firefox can be used with a newer replace-malloc library. As such, only
36 // new virtual methods should be added to ReplaceMallocBridge, and
37 // each change should have a corresponding bump of the mVersion value.
38 // At the same time, each virtual method should have a corresponding
39 // wrapper calling the virtual method on the instance from
40 // ReplaceMallocBridge::Get(), giving it the version the virtual method
41 // was added.
43 // Parts that are not relevant to the replace-malloc library end of the
44 // bridge are hidden when REPLACE_MALLOC_IMPL is not defined, which is
45 // the case when including replace_malloc.h.
47 struct ReplaceMallocBridge;
49 #include "mozilla/Types.h"
51 #ifdef _WIN32
52 typedef void* platform_handle_t;
53 #else
54 typedef int platform_handle_t;
55 #endif
57 MOZ_BEGIN_EXTERN_C
59 #ifndef REPLACE_MALLOC_IMPL
60 // Returns the replace-malloc bridge if there is one to be returned.
61 MFBT_API ReplaceMallocBridge* get_bridge();
62 #endif
64 // Table of malloc functions.
65 // e.g. void* (*malloc)(size_t), etc.
67 #define MALLOC_DECL(name, return_type, ...) \
68 typedef return_type(name##_impl_t)(__VA_ARGS__);
70 #include "malloc_decls.h"
72 #define MALLOC_DECL(name, return_type, ...) name##_impl_t* name;
74 typedef struct {
75 #include "malloc_decls.h"
76 } malloc_table_t;
78 MOZ_END_EXTERN_C
80 #ifdef __cplusplus
82 // Table of malloc hook functions.
83 // Those functions are called with the arguments and results of malloc
84 // functions after they are called.
85 // e.g. void* (*malloc_hook)(void*, size_t), etc.
86 // They can either return the result they're given, or alter it before
87 // returning it.
88 // The hooks corresponding to functions, like free(void*), that return no
89 // value, don't take an extra argument.
90 // The table must at least contain a pointer for malloc_hook and free_hook
91 // functions. They will be used as fallback if no pointer is given for
92 // other allocation functions, like calloc_hook.
93 namespace mozilla {
94 namespace detail {
95 template <typename R, typename... Args>
96 struct AllocHookType {
97 using Type = R (*)(R, Args...);
100 template <typename... Args>
101 struct AllocHookType<void, Args...> {
102 using Type = void (*)(Args...);
105 } // namespace detail
106 } // namespace mozilla
108 # define MALLOC_DECL(name, return_type, ...) \
109 typename mozilla::detail::AllocHookType<return_type, ##__VA_ARGS__>::Type \
110 name##_hook;
112 typedef struct {
113 # include "malloc_decls.h"
114 // Like free_hook, but called before realloc_hook. free_hook is called
115 // instead of not given.
116 void (*realloc_hook_before)(void* aPtr);
117 } malloc_hook_table_t;
119 namespace mozilla {
120 namespace dmd {
121 struct DMDFuncs;
122 } // namespace dmd
124 namespace phc {
126 class AddrInfo;
128 } // namespace phc
130 // Callbacks to register debug file handles for Poison IO interpose.
131 // See Mozilla(|Un)RegisterDebugHandle in xpcom/build/PoisonIOInterposer.h
132 struct DebugFdRegistry {
133 virtual void RegisterHandle(platform_handle_t aFd);
135 virtual void UnRegisterHandle(platform_handle_t aFd);
137 } // namespace mozilla
139 struct ReplaceMallocBridge {
140 ReplaceMallocBridge() : mVersion(6) {}
142 // This method was added in version 1 of the bridge.
143 virtual mozilla::dmd::DMDFuncs* GetDMDFuncs() { return nullptr; }
145 // Send a DebugFdRegistry instance to the replace-malloc library so that
146 // it can register/unregister file descriptors whenever needed. The
147 // instance is valid until the process dies.
148 // This method was added in version 2 of the bridge.
149 virtual void InitDebugFd(mozilla::DebugFdRegistry&) {}
151 // Register a list of malloc functions and hook functions to the
152 // replace-malloc library so that it can choose to dispatch to them
153 // when needed. The details of what is dispatched when is left to the
154 // replace-malloc library.
155 // Passing a nullptr for either table will unregister a previously
156 // registered table under the same name.
157 // Returns nullptr if registration failed.
158 // If registration succeeded, a table of "pure" malloc functions is
159 // returned. Those "pure" malloc functions won't call hooks.
160 // /!\ Do not rely on registration/unregistration to be instantaneous.
161 // Functions from a previously registered table may still be called for
162 // a brief time after RegisterHook returns.
163 // This method was added in version 3 of the bridge.
164 virtual const malloc_table_t* RegisterHook(
165 const char* aName, const malloc_table_t* aTable,
166 const malloc_hook_table_t* aHookTable) {
167 return nullptr;
170 # ifndef REPLACE_MALLOC_IMPL
171 // Returns the replace-malloc bridge if its version is at least the
172 // requested one.
173 static ReplaceMallocBridge* Get(int aMinimumVersion) {
174 static ReplaceMallocBridge* sSingleton = get_bridge();
175 return (sSingleton && sSingleton->mVersion >= aMinimumVersion) ? sSingleton
176 : nullptr;
178 # endif
180 protected:
181 const int mVersion;
184 # ifndef REPLACE_MALLOC_IMPL
185 // Class containing wrappers for calls to ReplaceMallocBridge methods.
186 // Those wrappers need to be static methods in a class because compilers
187 // complain about unused static global functions, and linkers complain
188 // about multiple definitions of non-static global functions.
189 // Using a separate class from ReplaceMallocBridge allows the function
190 // names to be identical.
191 struct ReplaceMalloc {
192 // Don't call this method from performance critical code. Use
193 // mozilla::dmd::DMDFuncs::Get() instead, it has less overhead.
194 static mozilla::dmd::DMDFuncs* GetDMDFuncs() {
195 auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 1);
196 return singleton ? singleton->GetDMDFuncs() : nullptr;
199 static void InitDebugFd(mozilla::DebugFdRegistry& aRegistry) {
200 auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 2);
201 if (singleton) {
202 singleton->InitDebugFd(aRegistry);
206 static const malloc_table_t* RegisterHook(
207 const char* aName, const malloc_table_t* aTable,
208 const malloc_hook_table_t* aHookTable) {
209 auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 3);
210 return singleton ? singleton->RegisterHook(aName, aTable, aHookTable)
211 : nullptr;
214 # endif
216 #endif // __cplusplus
218 #endif // replace_malloc_bridge_h