Extracting cache images
Apple ships system code in caches, not as files: a dyld shared cache holds thousands of dylibs, a kernelcache the XNU kernel and hundreds of KEXTs. The builder takes each image apart — segments spread across the container, every __LINKEDIT merged into one blob, one string pool shared by all — so an image inside a cache is not a file you can hand to another tool.
IDA ships an IDAPython example that puts one back together: extract_macho_image.py, under python/examples/disassembler/.
What it rebuilds
It reads the image's own load commands, lays its segments out contiguously, and rebuilds a private __LINKEDIT from that image's symbols, function starts, data-in-code table and export trie. The private string pool is typically two to three orders of magnitude smaller than the shared one.
Every byte comes from the database, through ida_dscu/ida_kcu and ida_bytes: you write out the image as IDA currently sees it, pointer chains resolved and your patches included.
One code path serves both containers. Only three things differ — where the header is, which spans hold the content, how the shared __LINKEDIT is mapped — and each container has a backend class for them.
What you get
A file that opens on its own, with code, data and symbols at the addresses the cache gives them. An address noted while reading the cache, or read off a crash report, still means the same thing in the extracted file.
It will not run. Keeping those addresses is the point, so the extractor retains the container's layout rather than rewriting it into something a loader would accept, and regenerates no rebase or bind information. The result is made to be analysed.
Using it
Drop the file in the plugins subdirectory of your user directory ($IDAUSR). There is nothing to run: it loads itself for any database opened from a shared cache or a kernelcache, and stays out of the way otherwise.
Select images in the DSC Index or the KC Index and pick Extract Mach-O image to file... from the context menu.

One image asks where to save it; several ask once for a directory. Anything that would be overwritten is reported first.

Under that directory, a cache image keeps the tree of its install name, so two images with the same file name do not land on each other:
A bundle id is not a path and is unique in its collection, so KEXTs go side by side:
In the disassembly, Ctrl+Alt+Shift+M extracts the image under the cursor.
Why an example
For most people it is the whole answer: install, extract, carry on. But needs differ, and the biggest difference is the one above — the file does not run, because the layout is retained on purpose. Wanting a loader-acceptable file means different trade-offs, and the right ones depend on the job. Smaller variations come up too: output naming, a load command to keep or drop, which symbols reach the private __LINKEDIT.
So it ships as Python source rather than as a feature, meant to be read and edited. extract(name, path) is the whole job, the container-specific parts are two backend classes, and the rest is plain Mach-O assembly.
See also
Dyld Shared Cache — Apple's userland cache.
Apple Kernelcache — the XNU kernel and its KEXTs.
Last updated
Was this helpful?
