How LibraryPrepare in ipatool Selects Platform-Specific Unicorn Library Builds

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 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. This file defines the Prepare() function that queries the Go runtime's standard environment variables to determine where the code is executing.

// 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 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 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 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 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)
Windows ARM64 unicorn-windows-arm64.dll ZIP (archive_zip.go)
Linux AMD64 unicorn-linux-amd64.so Tar-Zstd (archive_tar_zstd.go)
macOS ARM64 unicorn-darwin-arm64.dylib Tar-Zstd (archive_tar_zstd.go)

The 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, while Unix-like systems use internal/sap/unicorn/archive_tar_zstd.go.

Once extracted, the loading phase begins:

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:

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:

Summary

  • libraryprepare detects the host platform using runtime.GOOS and runtime.GOARCH in 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 (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 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 and 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →