Loading...
--- libmalloc/libmalloc-140.50.6/src/malloc.c
+++ libmalloc/libmalloc-116.50.8/src/malloc.c
@@ -102,18 +102,12 @@
static const char Malloc_Facility[] = "com.apple.Libsystem.malloc";
-// Used by memory resource exceptions and enabling/disabling malloc stack logging via malloc_memory_event_handler
-static boolean_t warn_mode_entered = false;
-static boolean_t warn_mode_disable_retries = false;
-static stack_logging_mode_type msl_type_enabled_at_runtime = stack_logging_mode_none;
-
/*
* Counters that coordinate zone destruction (in malloc_zone_unregister) with
* find_registered_zone (here abbreviated as FRZ).
*/
-static int32_t volatile counterAlice = 0, counterBob = 0;
-static int32_t volatile * volatile pFRZCounterLive = &counterAlice;
-static int32_t volatile * volatile pFRZCounterDrain = &counterBob;
+static int counterAlice = 0, counterBob = 0;
+static int *pFRZCounterLive = &counterAlice, *pFRZCounterDrain = &counterBob;
static inline malloc_zone_t *inline_malloc_default_zone(void) __attribute__((always_inline));
@@ -126,8 +120,12 @@
#define DEFAULT_PUREGEABLE_ZONE_STRING "DefaultPurgeableMallocZone"
boolean_t malloc_engaged_nano(void);
+#if CONFIG_NANOZONE
+boolean_t _malloc_engaged_nano;
+#endif
/********* Utilities ************/
+__attribute__((visibility("hidden"))) uint64_t malloc_entropy[2] = {0, 0};
static bool _malloc_entropy_initialized;
void __malloc_init(const char *apple[]);
@@ -166,13 +164,18 @@
void
__malloc_init(const char *apple[])
{
+ const char **p;
#if CONFIG_NANOZONE
- // TODO: envp should be passed down from Libsystem
- const char **envp = (const char **)*_NSGetEnviron();
- nano_init(envp, apple);
+ _malloc_engaged_nano = 0;
+ for (p = apple; p && *p; p++) {
+ if (0 == strncmp(*p, "MallocNanoZone=1", strlen("MallocNanoZone=1"))) {
+ // _malloc_printf(ASL_LEVEL_INFO, "MallocNanoZone=1\n");
+ _malloc_engaged_nano = 1;
+ break;
+ }
+ }
#endif
- const char **p;
for (p = apple; p && *p; p++) {
if (strstr(*p, "malloc_entropy") == *p) {
int count = __entropy_from_kernel(*p);
@@ -188,8 +191,6 @@
getentropy((void*)malloc_entropy, sizeof(malloc_entropy));
_malloc_entropy_initialized = true;
}
-
- mvm_aslr_init();
}
static malloc_zone_t* lite_zone = NULL;
@@ -330,7 +331,7 @@
{
zone = runtime_default_zone();
- return (void)zone->introspect->check(zone);
+ return zone->introspect->check(zone);
}
static void
@@ -482,11 +483,11 @@
}
}
- int32_t volatile *pFRZCounter = pFRZCounterLive; // Capture pointer to the counter of the moment
- OSAtomicIncrement32Barrier(pFRZCounter); // Advance this counter -- our thread is in FRZ
+ int *pFRZCounter = pFRZCounterLive; // Capture pointer to the counter of the moment
+ __sync_fetch_and_add(pFRZCounter, 1); // Advance this counter -- our thread is in FRZ
unsigned index;
- int32_t limit = *(int32_t volatile *)&malloc_num_zones;
+ int32_t limit = *(volatile int32_t *)&malloc_num_zones;
malloc_zone_t **zones = &malloc_zones[1];
// From this point on, FRZ is accessing the malloc_zones[] array without locking
@@ -508,18 +509,19 @@
zone = *zones;
size = zone->size(zone, ptr);
if (size) { // Claimed by this zone?
- goto out;
+ if (returned_size) {
+ *returned_size = size;
+ }
+ __sync_fetch_and_sub(pFRZCounter, 1); // our thread is leaving FRZ
+ return zone;
}
}
// Unclaimed by any zone.
- zone = NULL;
- size = 0;
-out:
if (returned_size) {
- *returned_size = size;
- }
- OSAtomicDecrement32Barrier(pFRZCounter); // our thread is leaving FRZ
- return zone;
+ *returned_size = 0;
+ }
+ __sync_fetch_and_sub(pFRZCounter, 1); // our thread is leaving FRZ
+ return NULL;
}
void
@@ -610,7 +612,7 @@
/* Update the malloc_zones pointer, which we leak if it was previously
* allocated, and the number of zones allocated */
- protect_size = (size_t)alloc_size;
+ protect_size = alloc_size;
malloc_zones = new_zones;
malloc_num_zones_allocated = (int32_t)(alloc_size / sizeof(malloc_zone_t *));
} else {
@@ -625,11 +627,11 @@
* in malloc_num_zones is visible then the pointer write before it must also be visible.
*
* While we could be slightly more efficent here with atomic ops the cleanest way to
- * ensure the proper store-release operation is performed is to use OSAtomic*Barrier
- * to update malloc_num_zones.
+ * ensure the proper store-release operation is performed is to use __sync... to update
+ * malloc_num_zones.
*/
malloc_zones[malloc_num_zones] = zone;
- OSAtomicIncrement32Barrier(&malloc_num_zones);
+ __sync_fetch_and_add(&malloc_num_zones, 1);
/* Finally, now that the zone is registered, disallow write access to the
* malloc_zones array */
@@ -698,13 +700,12 @@
malloc_printf("zone[0] is not the normal default zone so can't turn on lite mode.\n", mode);
ret = false;
} else {
- malloc_printf("recording malloc (and VM allocation) stacks using lite mode\n");
+ malloc_printf("recording malloc (but not VM allocation) stacks using lite mode\n");
if (lite_zone) {
enable_stack_logging_lite();
} else {
if (__prepare_to_log_stacks(true)) {
- __syscall_logger = __disk_stack_logging_log_stack;
stack_logging_mode = stack_logging_mode_lite;
stack_logging_enable_logging = 1;
__prepare_to_log_stacks_stage2();
@@ -846,7 +847,6 @@
__syscall_logger = __disk_stack_logging_log_stack;
break;
case stack_logging_mode_lite:
- __syscall_logger = __disk_stack_logging_log_stack;
create_and_insert_lite_zone_while_locked();
enable_stack_logging_lite();
break;
@@ -976,7 +976,7 @@
malloc_zone_t *tmp = create_purgeable_zone(0, inline_malloc_default_scalable_zone(), malloc_debug_flags);
malloc_zone_register(tmp);
malloc_set_zone_name(tmp, DEFAULT_PUREGEABLE_ZONE_STRING);
- if (!OSAtomicCompareAndSwapPtrBarrier(NULL, tmp, (void**)&dpz)) {
+ if (!__sync_bool_compare_and_swap(&dpz, NULL, tmp)) {
malloc_destroy_zone(tmp);
}
}
@@ -1079,7 +1079,7 @@
if (strcmp(flag, "lite") == 0) {
stack_logging_mode = stack_logging_mode_lite;
- _malloc_printf(ASL_LEVEL_INFO, "recording malloc and VM allocation stacks using lite mode\n");
+ _malloc_printf(ASL_LEVEL_INFO, "recording malloc (but not VM allocation) stacks using lite mode\n");
} else if (strcmp(flag,"malloc") == 0) {
stack_logging_mode = stack_logging_mode_malloc;
_malloc_printf(ASL_LEVEL_INFO, "recording malloc (but not VM allocation) stacks to disk using standard recorder\n");
@@ -1111,6 +1111,16 @@
if (getenv("MallocTracing")) {
malloc_tracing_enabled = true;
}
+#if CONFIG_NANOZONE
+ /* Explicit overrides from the environment */
+ if ((flag = getenv("MallocNanoZone"))) {
+ if (flag[0] == '1') {
+ _malloc_engaged_nano = 1;
+ } else if (flag[0] == '0') {
+ _malloc_engaged_nano = 0;
+ }
+ }
+#endif /* CONFIG_NANOZONE */
#if __LP64__
/* initialization above forces MALLOC_ABORT_ON_CORRUPTION of 64-bit processes */
@@ -1273,7 +1283,7 @@
if (b) {
_simple_sappend(b, "Stack for last operation where the malloc check succeeded: ");
while (index < num_frames)
- _simple_sprintf(b, "%p ", (void*)frames[index++]);
+ _simple_sprintf(b, "%p ", frames[index++]);
malloc_printf("%s\n(Use 'atos' for a symbolic stack)\n", _simple_string(b));
} else {
/*
@@ -1519,10 +1529,10 @@
// Exchange the roles of the FRZ counters. The counter that has captured the number of threads presently
// executing *inside* find_regiatered_zone is swapped with the counter drained to zero last time through.
// The former is then allowed to drain to zero while this thread yields.
- int32_t volatile *p = pFRZCounterLive;
+ int *p = pFRZCounterLive;
pFRZCounterLive = pFRZCounterDrain;
pFRZCounterDrain = p;
- OSMemoryBarrier(); // Full memory barrier
+ __sync_synchronize(); // Full memory barrier
while (0 != *pFRZCounterDrain) {
yield();
@@ -1931,65 +1941,6 @@
#endif
-static void
-handle_msl_memory_event(unsigned long event)
-{
- // don't mix and match enabling mechanisms
- if (warn_mode_entered) {
- return;
- }
-
- event &= NOTE_MEMORYSTATUS_MSL_STATUS;
-
- // sanity check
- if (event == 0) {
- return;
- }
-
- // first check if the disable bit is set
- if (event & MEMORYSTATUS_DISABLE_MSL) {
- turn_off_stack_logging();
- return;
- }
-
- boolean_t msl_malloc = (event & MEMORYSTATUS_ENABLE_MSL_MALLOC);
- boolean_t msl_vm = (event & MEMORYSTATUS_ENABLE_MSL_VM);
- boolean_t msl_lite = (event & MEMORYSTATUS_ENABLE_MSL_LITE);
-
- // The following always checks to make it's not possible to enable two different modes
- // For instance this would not be allowed:
- // Enable lite
- // Disable
- // Enable full
-
- // Currently there is no separation of malloc/vm in lite mode
- if (msl_lite) {
- if (msl_type_enabled_at_runtime == stack_logging_mode_none || msl_type_enabled_at_runtime == stack_logging_mode_lite) {
- msl_type_enabled_at_runtime = stack_logging_mode_lite;
- turn_on_stack_logging(stack_logging_mode_lite);
- }
- return;
- } else if (msl_malloc && msl_vm) {
- if (msl_type_enabled_at_runtime == stack_logging_mode_none || msl_type_enabled_at_runtime == stack_logging_mode_all) {
- msl_type_enabled_at_runtime = stack_logging_mode_all;
- turn_on_stack_logging(stack_logging_mode_all);
- }
- return;
- } else if (msl_malloc) {
- if (msl_type_enabled_at_runtime == stack_logging_mode_none || msl_type_enabled_at_runtime == stack_logging_mode_malloc) {
- msl_type_enabled_at_runtime = stack_logging_mode_malloc;
- turn_on_stack_logging(stack_logging_mode_malloc);
- }
- return;
- } else if (msl_vm) {
- if (msl_type_enabled_at_runtime == stack_logging_mode_none || msl_type_enabled_at_runtime == stack_logging_mode_vm) {
- msl_type_enabled_at_runtime = stack_logging_mode_vm;
- turn_on_stack_logging(stack_logging_mode_vm);
- }
- return;
- }
-}
-
// Note that malloc_memory_event_handler is not thread-safe, and we are relying on the callers of this for synchronization
void
malloc_memory_event_handler(unsigned long event)
@@ -1997,15 +1948,11 @@
if (event & NOTE_MEMORYSTATUS_PRESSURE_WARN) {
malloc_zone_pressure_relief(0, 0);
}
-
- // First check for enable/disable MSL - only recognize if all other bits are 0
- // Don't attempt this if we've either entered or exited MRE mode
- if ((event & NOTE_MEMORYSTATUS_MSL_STATUS) != 0 && (event & ~NOTE_MEMORYSTATUS_MSL_STATUS) == 0 && !warn_mode_entered && !warn_mode_disable_retries) {
- handle_msl_memory_event(event);
- return;
- }
#if ENABLE_MEMORY_RESOURCE_EXCEPTION_HANDLING
+ static boolean_t warn_mode_entered = false;
+ static boolean_t warn_mode_disable_retries = false;
+
// If we have reached EXC_RESOURCE, we no longer need stack log data.
// If we are under system-wide memory pressure, we should jettison stack log data.
if ((event & (NOTE_MEMORYSTATUS_PROC_LIMIT_CRITICAL | NOTE_MEMORYSTATUS_PRESSURE_CRITICAL)) &&