Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3686)

Unified Diff: base/allocator/allocator_interception_mac.mm

Issue 2712363002: Use mach_override to intercept all newly registered malloc zones.
Patch Set: compile error. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/allocator/allocator_interception_mac.h ('k') | base/allocator/allocator_interception_mac_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/allocator/allocator_interception_mac.mm
diff --git a/base/allocator/allocator_interception_mac.mm b/base/allocator/allocator_interception_mac.mm
index 687100e1b81d7d62cca0e8fa45371e050f8fb38c..6b01b9112fed739a5ea3c23b1477ca45894443cf 100644
--- a/base/allocator/allocator_interception_mac.mm
+++ b/base/allocator/allocator_interception_mac.mm
@@ -37,6 +37,7 @@
#include "base/scoped_clear_errno.h"
#include "build/build_config.h"
#include "third_party/apple_apsl/CFBase.h"
+#include "third_party/mach_override/mach_override.h"
namespace base {
namespace allocator {
@@ -302,6 +303,50 @@ void ReplaceZoneFunctions(ChromeMallocZone* zone,
}
}
+typedef void (*MallocZoneRegisterType)(malloc_zone_t* zone);
+MallocZoneRegisterType g_original_malloc_zone_register = nullptr;
+MallocZoneFunctions g_malloc_zone_functions;
+bool g_update_malloc_zone_during_interception = true;
+
+void ChromeMallocZoneRegister(malloc_zone_t* new_zone) {
+ DCHECK(g_original_malloc_zone_register);
+ if (!g_update_malloc_zone_during_interception) {
+ g_original_malloc_zone_register(new_zone);
+ return;
+ }
+
+ ChromeMallocZone* zone = reinterpret_cast<ChromeMallocZone*>(new_zone);
+
+ if (!StoreMallocZone(zone))
+ return;
+
+ ReplaceZoneFunctions(zone, &g_malloc_zone_functions);
+ g_original_malloc_zone_register(new_zone);
+}
+
+typedef struct _malloc_zone_t* (*MallocCreateZoneType)(vm_size_t start_size,
+ unsigned flags);
+MallocCreateZoneType g_original_malloc_create_zone = nullptr;
+
+struct _malloc_zone_t* ChromeMallocCreateZone(vm_size_t start_size,
+ unsigned flags) {
+ DCHECK(g_original_malloc_create_zone);
+
+ struct _malloc_zone_t* new_zone =
+ g_original_malloc_create_zone(start_size, flags);
+ if (!g_update_malloc_zone_during_interception) {
+ return new_zone;
+ }
+
+ ChromeMallocZone* zone = reinterpret_cast<ChromeMallocZone*>(new_zone);
+
+ if (!StoreMallocZone(zone))
+ return new_zone;
+
+ ReplaceZoneFunctions(zone, &g_malloc_zone_functions);
+ return new_zone;
+}
+
void UninterceptMallocZoneForTesting(struct _malloc_zone_t* zone) {
ChromeMallocZone* chrome_zone = reinterpret_cast<ChromeMallocZone*>(zone);
if (!IsMallocZoneAlreadyStored(chrome_zone))
@@ -513,6 +558,43 @@ void InterceptAllocationsMac() {
reinterpret_cast<IMP>(oom_killer_allocWithZone));
}
+void InterceptNewlyRegisteredMallocZones(const MallocZoneFunctions* functions) {
+ g_update_malloc_zone_during_interception = true;
+
+ // In a typical Chrome build, InterceptNewlyRegisteredMallocZones should only
+ // be called once. In a testing environment, it might be called more often.
+ if (g_original_malloc_zone_register)
+ return;
+
+ memcpy(&g_malloc_zone_functions, functions, sizeof(MallocZoneFunctions));
+ mach_error_t err = mach_override_ptr(
+ reinterpret_cast<void*>(malloc_zone_register),
+ reinterpret_cast<void*>(ChromeMallocZoneRegister),
+ reinterpret_cast<void**>(&g_original_malloc_zone_register));
+ if (err != err_none) {
+ DLOG(WARNING) << "mach_override malloc_zone_register: " << err;
+ }
+
+ // On macOS 10.9, the implementation of malloc_create_zone calls
+ // malloc_zone_register_while_locked, a private symbol in libmalloc, so we
+ // also need to interpose it. Starting from macOS 10.10.0, libmalloc was open
+ // sourced, and the implementation of malloc_create_zone calls
+ // malloc_zone_register.
+ if (base::mac::IsOS10_9()) {
+ err = mach_override_ptr(
+ reinterpret_cast<void*>(malloc_create_zone),
+ reinterpret_cast<void*>(ChromeMallocCreateZone),
+ reinterpret_cast<void**>(&g_original_malloc_create_zone));
+ if (err != err_none) {
+ DLOG(WARNING) << "mach_override malloc_create_zone: " << err;
+ }
+ }
+}
+
+void StopMallocZoneRegistrationInterceptionForTesting() {
+ g_update_malloc_zone_during_interception = false;
+}
+
void UninterceptMallocZonesForTesting() {
UninterceptMallocZoneForTesting(malloc_default_zone());
vm_address_t* zones;
@@ -525,6 +607,7 @@ void UninterceptMallocZonesForTesting() {
}
ClearAllMallocZonesForTesting();
+ StopMallocZoneRegistrationInterceptionForTesting();
}
} // namespace allocator
« no previous file with comments | « base/allocator/allocator_interception_mac.h ('k') | base/allocator/allocator_interception_mac_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698