> For the complete documentation index, see [llms.txt](https://docs.hex-rays.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hex-rays.com/ida-9.5/core/disassembler/concepts/extracting-cache-images.md).

# Extracting cache images

Apple ships system code in caches, not as files: a [dyld shared cache](/ida-9.5/core/disassembler/concepts/dsc-workflow.md) holds thousands of dylibs ([DriverKit](/ida-9.5/core/disassembler/concepts/driverkit.md#the-driverkit-shared-cache) has one of its own), a [kernelcache](/ida-9.5/core/disassembler/concepts/kc-workflow.md) 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`](https://github.com/HexRaysSA/IDAPython/tree/9.5/examples/disassembler/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](/ida-9.5/core/disassembler/concepts/environment-variables.md#idausr) (`$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](/ida-9.5/core/disassembler/concepts/dsc-workflow.md#the-dsc-index) or the [KC Index](/ida-9.5/core/disassembler/concepts/kc-workflow.md#the-kc-index) and pick **Extract Mach-O image to file...** from the context menu.

<figure><img src="https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-1d659888ef67319c2adb67116d235d61db120850%2Fextract_macho_menu.png?alt=media" alt="The extract action in the DSC Index context menu"><figcaption><p>The action, on a selection of three images</p></figcaption></figure>

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

<figure><img src="https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-33fd853d759cc7bf137261bd993722da77ceb0b8%2Fextract_macho_output_dir.png?alt=media" alt="The output directory prompt"><figcaption><p>Extracting several at once: one prompt for the directory they all go under</p></figcaption></figure>

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:

```
usr
`-- lib
    |-- libmorphun.dylib
    `-- system
        |-- libmacho.dylib
        `-- libxpc.dylib
```

A bundle id is not a path and is unique in its collection, so KEXTs go side by side:

```
|-- com.apple.driver.AppleARMPMU
|-- com.apple.driver.AppleMobileFileIntegrity
`-- com.apple.iokit.IOHIDFamily
```

In the disassembly, <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>M</kbd> 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](/ida-9.5/core/disassembler/concepts/dsc-workflow.md) — Apple's userland cache.
* [Apple Kernelcache](/ida-9.5/core/disassembler/concepts/kc-workflow.md) — the XNU kernel and its KEXTs.
* [Apple DriverKit](/ida-9.5/core/disassembler/concepts/driverkit.md) — user-space drivers and their shared cache.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.hex-rays.com/ida-9.5/core/disassembler/concepts/extracting-cache-images.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
