Geek Culture
Published in

Geek Culture

How iOS 15 makes your app launch faster

Read the full version of this post on the Emerge Tools Blog

The most intriguing feature from WWDC21 was buried deep in the Xcode 13 release notes:

All programs and dylibs built with a deployment target of macOS 12 or iOS 15 or later now use the chained fixups format. This uses different load commands and LINKEDIT data, and won’t run or load on older OS versions.

There isn’t any documentation or sessions to learn more about this change, but we can reverse engineer it to see what Apple is doing differently on the new OSes and if it will help your apps. First, a bit of background on the program that controls app startup.

Meet dyld

The dynamic linker (dyld) is the entry point of every app. It’s responsible for getting your code ready to run, so it would make sense that any improvement to dyld would result in improved app launch time. Before calling main, running static initializers, or setting up the Objective-C runtime, dyld performs fixups. These consist of rebase and bind operations which modify pointers in the app binary to contain addresses that will be valid at runtime. To see what these look like, you can use the dyldinfo command line tool.

% xcrun dyldinfo -rebase -bind
rebase information (from compressed dyld info):
segment section address type
__DATA __got 0x10748C0C8 pointer
bind information:
segment section address type addend dylib symbol
__DATA __const 0x107595A70 pointer 0 libswiftCore _$sSHMp

This means address 0x10748C0C8 is located in __DATA/__got and needs to be shifted by a constant value (known as the slide). While address 0x107595A70 is in __DATA/__const and should point to the protocol descriptor for Hashable[1] found in libswiftCore.dylib

dyld uses the LC_DYLD_INFO load command anddyld_info_command struct to determine the location and size of rebases, binds and exported symbols[2] in a binary. Emerge (disclaimer: I’m the founder 😬), parses this data to let you visualize their contribution to binary size as well as suggest linker flags to make them smaller:

A new format

When I first uploaded an app built for iOS 15 to Emerge there was no visualization of dyld fixups. This was because the LC_DYLD_INFO_ONLY load command was missing, it had been replaced by LC_DYLD_CHAINED_FIXUPS and LC_DYLD_EXPORTS_TRIE.

% otool -l | grep LC_DYLD
% otool -l | grep LC_DYLD

The export data is exactly the same as before, a trie where each node represents part of a symbol name.

Portion of the exports trie for Wikipedia

The only change in iOS 15 is the data is now referenced by a linkedit_data_command which contains the offset of the first node. To validate this, I wrote a short Swift app to parse the iOS 15 binary and print each symbol:


The real change is in LC_DYLD_CHAINED_FIXUPS. Before iOS 15, rebases, binds and lazy binds were each stored in a separate table. Now they have been combined into chains, with pointers to the starts of the chains contained in this new load command…

Read the full version of this post on the Emerge Tools Blog




A new tech publication by Start it up (

Recommended from Medium

UIScrollView dynamic content size through storyboard in iOS

iOS 14 UISplitViewController: 5 Issues That You May Run Into

My experience using SwiftUI as the main framework to build iOS apps in my company

SwiftUI Previews —Is there an easy way to visualize all different UI variations?

Get the most out of Sign in with Apple

Adding Text Fileld in UIAlertController like a promt box in iOS

Finding information about a crash iOS

Comparing Images iOS

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Noah Martin

Noah Martin

Co-founder of Emerge Tools, previously software engineer at Airbnb.

More from Medium

Swift Coding Standards And Best Practices

Goodbye Moya & Alamofire. Simplify Your Dependencies

WebEngage in iOS