123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef replace_malloc_bridge_h
- #define replace_malloc_bridge_h
- /*
- * The replace-malloc bridge allows bidirectional method calls between
- * a program and the replace-malloc library that has been loaded for it.
- * In Firefox, this is used to allow method calls between code in libxul
- * and code in the replace-malloc library, without libxul needing to link
- * against that library or vice-versa.
- *
- * Subsystems can add methods for their own need. Replace-malloc libraries
- * can decide to implement those methods or not.
- *
- * Replace-malloc libraries can provide such a bridge by implementing
- * a ReplaceMallocBridge-derived class, and a replace_get_bridge function
- * returning an instance of that class. The default methods in
- * ReplaceMallocBridge are expected to return values that callers would
- * understand as "the bridge doesn't implement this method", so that a
- * replace-malloc library doesn't have to implement all methods.
- *
- * The ReplaceMallocBridge class contains definitions for methods for
- * all replace-malloc libraries. Each library picks the methods it wants
- * to reply to in its ReplaceMallocBridge-derived class instance.
- * All methods of ReplaceMallocBridge must be virtual. Similarly,
- * anything passed as an argument to those methods must be plain data, or
- * an instance of a class with only virtual methods.
- *
- * Binary compatibility is expected to be maintained, such that a newer
- * Firefox can be used with an old replace-malloc library, or an old
- * Firefox can be used with a newer replace-malloc library. As such, only
- * new virtual methods should be added to ReplaceMallocBridge, and
- * each change should have a corresponding bump of the mVersion value.
- * At the same time, each virtual method should have a corresponding
- * wrapper calling the virtual method on the instance from
- * ReplaceMallocBridge::Get(), giving it the version the virtual method
- * was added.
- *
- * Parts that are not relevant to the replace-malloc library end of the
- * bridge are hidden when REPLACE_MALLOC_IMPL is not defined, which is
- * the case when including replace_malloc.h.
- */
- struct ReplaceMallocBridge;
- #include "mozilla/Types.h"
- MOZ_BEGIN_EXTERN_C
- #ifndef REPLACE_MALLOC_IMPL
- /* Returns the replace-malloc bridge if there is one to be returned. */
- MFBT_API ReplaceMallocBridge* get_bridge();
- #endif
- /* Table of malloc functions.
- * e.g. void* (*malloc)(size_t), etc.
- */
- #define MALLOC_DECL(name, return_type, ...) \
- typedef return_type(name ## _impl_t)(__VA_ARGS__);
- #include "malloc_decls.h"
- #define MALLOC_DECL(name, return_type, ...) \
- name ## _impl_t * name;
- typedef struct {
- #include "malloc_decls.h"
- } malloc_table_t;
- /* Table of malloc hook functions.
- * Those functions are called with the arguments and results of malloc
- * functions after they are called.
- * e.g. void* (*malloc_hook)(void*, size_t), etc.
- * They can either return the result they're given, or alter it before
- * returning it.
- * The hooks corresponding to functions, like free(void*), that return no
- * value, don't take an extra argument.
- * The table must at least contain a pointer for malloc_hook and free_hook
- * functions. They will be used as fallback if no pointer is given for
- * other allocation functions, like calloc_hook.
- */
- #define MALLOC_DECL(name, return_type, ...) \
- return_type (*name ## _hook)(return_type, __VA_ARGS__);
- #define MALLOC_DECL_VOID(name, ...) \
- void (*name ## _hook)(__VA_ARGS__);
- typedef struct {
- #include "malloc_decls.h"
- /* Like free_hook, but called before realloc_hook. free_hook is called
- * instead of not given. */
- void (*realloc_hook_before)(void* aPtr);
- } malloc_hook_table_t;
- MOZ_END_EXTERN_C
- #ifdef __cplusplus
- namespace mozilla {
- namespace dmd {
- struct DMDFuncs;
- } // namespace dmd
- /* Callbacks to register debug file handles for Poison IO interpose.
- * See Mozilla(|Un)RegisterDebugHandle in xpcom/build/PoisonIOInterposer.h */
- struct DebugFdRegistry
- {
- virtual void RegisterHandle(intptr_t aFd);
- virtual void UnRegisterHandle(intptr_t aFd);
- };
- } // namespace mozilla
- struct ReplaceMallocBridge
- {
- ReplaceMallocBridge() : mVersion(3) {}
- /* This method was added in version 1 of the bridge. */
- virtual mozilla::dmd::DMDFuncs* GetDMDFuncs() { return nullptr; }
- /* Send a DebugFdRegistry instance to the replace-malloc library so that
- * it can register/unregister file descriptors whenever needed. The
- * instance is valid until the process dies.
- * This method was added in version 2 of the bridge. */
- virtual void InitDebugFd(mozilla::DebugFdRegistry&) {}
- /* Register a list of malloc functions and hook functions to the
- * replace-malloc library so that it can choose to dispatch to them
- * when needed. The details of what is dispatched when is left to the
- * replace-malloc library.
- * Passing a nullptr for either table will unregister a previously
- * registered table under the same name.
- * Returns nullptr if registration failed.
- * If registration succeeded, a table of "pure" malloc functions is
- * returned. Those "pure" malloc functions won't call hooks.
- * /!\ Do not rely on registration/unregistration to be instantaneous.
- * Functions from a previously registered table may still be called for
- * a brief time after RegisterHook returns.
- * This method was added in version 3 of the bridge. */
- virtual const malloc_table_t*
- RegisterHook(const char* aName, const malloc_table_t* aTable,
- const malloc_hook_table_t* aHookTable) { return nullptr; }
- #ifndef REPLACE_MALLOC_IMPL
- /* Returns the replace-malloc bridge if its version is at least the
- * requested one. */
- static ReplaceMallocBridge* Get(int aMinimumVersion) {
- static ReplaceMallocBridge* sSingleton = get_bridge();
- return (sSingleton && sSingleton->mVersion >= aMinimumVersion)
- ? sSingleton : nullptr;
- }
- #endif
- protected:
- const int mVersion;
- };
- #ifndef REPLACE_MALLOC_IMPL
- /* Class containing wrappers for calls to ReplaceMallocBridge methods.
- * Those wrappers need to be static methods in a class because compilers
- * complain about unused static global functions, and linkers complain
- * about multiple definitions of non-static global functions.
- * Using a separate class from ReplaceMallocBridge allows the function
- * names to be identical. */
- struct ReplaceMalloc
- {
- /* Don't call this method from performance critical code. Use
- * mozilla::dmd::DMDFuncs::Get() instead, it has less overhead. */
- static mozilla::dmd::DMDFuncs* GetDMDFuncs()
- {
- auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 1);
- return singleton ? singleton->GetDMDFuncs() : nullptr;
- }
- static void InitDebugFd(mozilla::DebugFdRegistry& aRegistry)
- {
- auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 2);
- if (singleton) {
- singleton->InitDebugFd(aRegistry);
- }
- }
- static const malloc_table_t*
- RegisterHook(const char* aName, const malloc_table_t* aTable,
- const malloc_hook_table_t* aHookTable)
- {
- auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 3);
- return singleton ? singleton->RegisterHook(aName, aTable, aHookTable)
- : nullptr;
- }
- };
- #endif
- #endif /* __cplusplus */
- #endif /* replace_malloc_bridge_h */
|