dyld crash before main() on macOS Tahoe 26 due to shared cache mapping failure

I am developing a large iOS application with an extensive UI test suite (hundreds of UI test scenarios).

After upgrading our CI runners to macOS Tahoe 26, we started observing an intermittent issue where an iOS Simulator may operate normally for many successful application launches before unexpectedly entering a persistent degraded state. Once this occurs, every subsequent application launch crashes inside dyld before reaching our application’s main(). The degraded state persists until the simulator device is reset

This causes UI tests to hang and eventually timeout.

Business impact

  • CI/CD jobs frequently timeout (90+ minutes per failed run)
  • Significant loss of CI capacity
  • Difficult to maintain reliable quality gates

At our scale, this has become a serious issue affecting release confidence and overall engineering productivity.


Technical details

Crash report

Demo project

  • dyld_crash_demo — a minimal reproducible project demonstrating the relevant dyld execution path.

The project intentionally returns errors from system functions along the shared cache initialization path to demonstrate that dyld continues execution until DyldSharedCache::getUUID(), where it subsequently crashes. Simply open the project and run it in iOS Simulator 26.2.

Environment

ComponentVersion
macOSTahoe 26.x
Xcode26.2, 26.5
iOS Simulator26.2, 26.5, 26.6
ArchitectureApple Silicon
dyld1378
dyld_sim1335

What we have ruled out

  • multiple Xcode versions
  • multiple macOS 26.x releases
  • multiple iOS Simulator runtimes
  • multiple simulator devices
  • UI tests with parallel execution disabled
  • deleting the simulator dyld shared cache
  • recreating simulator devices
  • application-specific issues (the crash happens before main())

The issue is still reproducible.


Investigation

The earliest observable failure sequence is consistently:

  1. shared_region_check_np()"Cannot allocate memory" (ENOMEM)
  2. Shared cache mmap(0x180000000, ...)EACCES
  3. The shared cache region remains unmapped
  4. DyldSharedCache::getUUID() reads 0x180000058
  5. EXC_BAD_ACCESS (Translation fault)

The crash occurs before any application code executes. The first faulting instruction belongs to DyldSharedCache::getUUID(), while the shared-cache region is still unmapped.

Published dyld source analysis

Relevant execution path:

loadDyldCache()
    ↓
mapSplitCachePrivate()
    ↓
preflightCacheFile()

Based on the published sources of dyld-1378, this appears to be the execution path leading to the observed failure. After the loadDyldCache() function failed to load the cache, dyld continued execution anyway and moved on to calling the DyldSharedCache::getUUID() function, where it subsequently failed.


Additional observations

Once the simulator enters the degraded state:

  • simctl spawn succeeds.
  • simctl launch crashes inside dyld before reaching main().

During our experiments, both processes were created by the same launchd_sim instance

Before dyld::_dyld_start, both processes expose the same virtual address layout, including an unmapped shared-cache region (0x180000000–0x300000000).


Current workaround

As a temporary mitigation, we launch the application with

DYLD_SHARED_REGION=avoid

In our environment, this completely avoids the launch failures.

However, this mode appears to be undocumented and intended primarily for debugging.

We are concerned that it may change or stop working in future macOS or Xcode releases, so we are reluctant to depend on it in our production CI infrastructure.


Questions

1. dyld

Is it expected for dyld to continue dereferencing the shared-cache header after both the shared-region initialization and the shared-cache mapping have already failed?

Execution appears to continue into:

loadInfo.loadAddress->getUUID(cacheUuid)

which results in an access to an unmapped address.

The attached demo project reproduces this behavior by simulating failures from the shared-cache initialization path.

Is there an expected fallback behavior for this situation or is continuing into DyldSharedCache::getUUID() the intended behavior ?

2. Simulator state

Why does a simulator that initially launches applications successfully eventually enter a state where every subsequent launch fails while the shared cache can no longer be mapper?

The earliest related system log we have found is:

vm_shared_region_start_address() returned 0x1

Is this a known CoreSimulator or macOS Tahoe issue?

If so, is there a supported workaround or recommended long-term solution besides DYLD_SHARED_REGION=avoid?

Any guidance would be greatly appreciated.

dyld crash before main() on macOS Tahoe 26 due to shared cache mapping failure
 
 
Q