# How LibraryPrepare in ipatool Selects Platform-Specific Unicorn Library Builds

> ipatool's library_prepare selects platform-specific Unicorn builds by detecting OS and architecture. Discover how it downloads and loads the correct native binary.

- Repository: [Majd/ipatool](https://github.com/majd/ipatool)
- Tags: internals
- Published: 2026-09-06

---

**`libraryprepare` in `ipatool` detects the host OS and architecture using `runtime.GOOS` and `runtime.GOARCH`, then dispatches to a platform-specific preparer that downloads, extracts, and loads the matching Unicorn native binary.**

The `ipatool` repository embeds the [Unicorn](https://www.unicorn-engine.org/) CPU emulator to enable remote code execution during IPA analysis. Because Unicorn ships distinct native libraries for each operating system and CPU architecture, the tool needs a robust selection mechanism. The `libraryprepare` functionality—implemented across the `internal/sap/unicorn` package—automates this platform detection and binary preparation pipeline.

## Platform Detection in Library.go

The entry point for library preparation resides in [`internal/sap/unicorn/library.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library.go). This file defines the `Prepare()` function that queries the Go runtime's standard environment variables to determine where the code is executing.

```go
// Simplified conceptual flow from library.go
func Prepare() (Loader, error) {
    os := runtime.GOOS
    arch := runtime.GOARCH
    
    // Dispatch to platform-specific preparer
    return prepareForPlatform(os, arch)
}

```

The `runtime.GOOS` and `runtime.GOARCH` constants provide reliable, build-time-invariant values that eliminate guesswork. Based on these values, the generic `Prepare` implementation delegates to specialized preparers using Go's build constraints and explicit platform checks.

## Platform-Specific Preparer Dispatch

The `ipatool` repository organizes preparers into separate files that handle distinct platform combinations. Each preparer hard-codes the expected artifact name and extraction logic for its target environment.

### Windows AMD64 Preparer

The file [`internal/sap/unicorn/library_prepare_windows_amd64.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library_prepare_windows_amd64.go) handles 64-bit Intel and AMD Windows systems. It constructs the artifact filename `unicorn-windows-amd64.dll` and coordinates download through the artifact package.

### Windows ARM64 Preparer

For ARM64 Windows devices—including modern Surface tablets and Windows Dev Kits—[`internal/sap/unicorn/library_prepare_windows_arm64.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library_prepare_windows_arm64.go) defines the corresponding logic. It targets `unicorn-windows-arm64.dll` and uses the same download pipeline with architecture-specific validation.

### Windows Fallback Preparer

The file [`internal/sap/unicorn/library_prepare_windows_other.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library_prepare_windows_other.go) provides a graceful degradation path for unsupported Windows architectures. Rather than failing silently, this preparer returns a descriptive error indicating that no prebuilt Unicorn binary exists for the detected platform.

### Unix-Like Platform Preparer

Non-Windows systems—encompassing macOS, Linux, and BSD variants—route through [`internal/sap/unicorn/library_prepare_windows.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library_prepare_windows.go) or equivalent Unix-specific implementations. These preparers construct `.so` or `.dylib` filenames following the pattern `unicorn-{os}-{arch}.{ext}` and use tar-zstd archives rather than ZIP files.

## Artifact Naming and Download Pipeline

Each platform-specific preparer builds the expected artifact filename using a consistent template:

| Platform | Artifact Filename Pattern | Archive Format |
|----------|---------------------------|----------------|
| Windows AMD64 | `unicorn-windows-amd64.dll` | ZIP ([`archive_zip.go`](https://github.com/majd/ipatool/blob/main/archive_zip.go)) |
| Windows ARM64 | `unicorn-windows-arm64.dll` | ZIP ([`archive_zip.go`](https://github.com/majd/ipatool/blob/main/archive_zip.go)) |
| Linux AMD64 | `unicorn-linux-amd64.so` | Tar-Zstd ([`archive_tar_zstd.go`](https://github.com/majd/ipatool/blob/main/archive_tar_zstd.go)) |
| macOS ARM64 | `unicorn-darwin-arm64.dylib` | Tar-Zstd ([`archive_tar_zstd.go`](https://github.com/majd/ipatool/blob/main/archive_tar_zstd.go)) |

The [`internal/sap/unicorn/artifact.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/artifact.go) file centralizes the download and verification logic. It fetches releases from the official Unicorn distribution channel, validates checksums, and stages files for extraction.

## Extraction and Native Library Loading

After download, platform-specific extractors handle the archive format differences. Windows systems use [`internal/sap/unicorn/archive_zip.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/archive_zip.go), while Unix-like systems use [`internal/sap/unicorn/archive_tar_zstd.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/archive_tar_zstd.go).

Once extracted, the loading phase begins:

- **[`runtime_library_windows_arm64.go`](https://github.com/majd/ipatool/blob/main/runtime_library_windows_arm64.go)**: Implements `syscall.LoadLibrary` for ARM64 Windows
- **[`runtime_library_default.go`](https://github.com/majd/ipatool/blob/main/runtime_library_default.go)**: Wraps `plugin.Open` for Unix-like platforms with `cgo` support
- Additional runtime variants exist for other architecture combinations

These runtime loaders return a unified `Loader` interface that the rest of `ipatool` consumes without platform awareness.

## Practical Usage Example

The following code demonstrates how client code interacts with the `libraryprepare` system without concerning itself with platform details:

```go
package main

import (
    "log"
    "github.com/majd/ipatool/internal/sap/unicorn"
)

func main() {
    // Prepare automatically selects the correct Unicorn binary
    loader, err := unicorn.Prepare()
    if err != nil {
        log.Fatalf("failed to prepare unicorn library: %v", err)
    }

    // Create a new emulation engine through the loaded library
    engine, err := loader.NewEngine()
    if err != nil {
        log.Fatalf("failed to create unicorn engine: %v", err)
    }

    // Engine is ready for CPU emulation tasks
    defer engine.Close()
    
    // Configure emulation parameters...
}

```

The `Prepare()` call encapsulates all platform detection, download, extraction, and loading operations. This abstraction allows `ipatool` to support new platforms by adding preparer files without modifying caller code.

## Key Source Files

Understanding the `libraryprepare` architecture requires familiarity with these components:

- **[`internal/sap/unicorn/library.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library.go)** — Core `Prepare()` entry point with platform dispatch
- **[`internal/sap/unicorn/library_prepare_windows_amd64.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library_prepare_windows_amd64.go)** — Windows x64 specific preparation
- **[`internal/sap/unicorn/library_prepare_windows_arm64.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library_prepare_windows_arm64.go)** — Windows ARM64 specific preparation
- **[`internal/sap/unicorn/library_prepare_windows_other.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/library_prepare_windows_other.go)** — Windows fallback for unsupported architectures
- **[`internal/sap/unicorn/runtime_library_windows_arm64.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/runtime_library_windows_arm64.go)** — Native library loading for Windows ARM64
- **[`internal/sap/unicorn/runtime_library_default.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/runtime_library_default.go)** — Default loader for Unix-like systems
- **[`internal/sap/unicorn/artifact.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/artifact.go)** — Download and verification coordinator
- **[`internal/sap/unicorn/archive_zip.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/archive_zip.go)** — Windows ZIP extraction
- **[`internal/sap/unicorn/archive_tar_zstd.go`](https://github.com/majd/ipatool/blob/main/internal/sap/unicorn/archive_tar_zstd.go)** — Unix tar-zstd extraction

## Summary

- **`libraryprepare` detects the host platform** using `runtime.GOOS` and `runtime.GOARCH` in [`library.go`](https://github.com/majd/ipatool/blob/main/library.go)
- **Platform-specific preparers dispatch** to dedicated files for Windows AMD64, Windows ARM64, Windows fallback, and Unix-like systems
- **Artifact names follow predictable patterns** (`unicorn-{os}-{arch}.{ext}`) hard-coded in each preparer
- **Download and extraction differ by platform**—ZIP for Windows, tar-zstd for Unix
- **Runtime loaders abstract native library access** through `syscall.LoadLibrary` on Windows and `plugin.Open` on Unix
- **The `Prepare()` interface hides all complexity** from calling code, enabling portable Unicorn integration

## Frequently Asked Questions

### How does `libraryprepare` handle unsupported platforms?

When `runtime.GOARCH` or `runtime.GOOS` indicates a platform without a prebuilt Unicorn binary—such as Windows on 32-bit x86 or niche BSD variants—the fallback preparer in [`library_prepare_windows_other.go`](https://github.com/majd/ipatool/blob/main/library_prepare_windows_other.go) (or equivalent) returns a descriptive error. This prevents runtime crashes and provides clear guidance about platform limitations.

### Can I override which Unicorn binary `libraryprepare` selects?

The current implementation in `majd/ipatool` does not expose configuration hooks for manual binary selection. The `Prepare()` function relies exclusively on runtime detection. Advanced users could modify the source in [`library.go`](https://github.com/majd/ipatool/blob/main/library.go) to accept environment variable overrides, though this would require maintaining a fork.

### Why does Windows use ZIP while Unix uses tar-zstd archives?

The archive format divergence reflects upstream Unicorn release packaging conventions. The `ipatool` project mirrors the official Unicorn distribution formats to avoid recompression. The [`archive_zip.go`](https://github.com/majd/ipatool/blob/main/archive_zip.go) and [`archive_tar_zstd.go`](https://github.com/majd/ipatool/blob/main/archive_tar_zstd.go) files provide thin wrappers around Go's standard `archive/zip` and third-party zstd libraries to handle these formats transparently.

### What happens if the downloaded Unicorn binary fails checksum verification?

The [`artifact.go`](https://github.com/majd/ipatool/blob/main/artifact.go) implementation performs cryptographic verification of downloaded releases against published checksums. If verification fails—whether due to network corruption, tampering, or version mismatch—the `Prepare()` call returns an error before any extraction or loading occurs. This ensures only authentic, intact binaries reach the execution stage.