# Goblin for Rust binary parsing, ELF, PE, and Mach-O

> Goblin is a Rust crate for parsing ELF, Mach-O, PE, TE, and Unix archive formats with zero-copy structures and configurable runtime needs. It suits binary-analysis tools and constrained `no_std` software, but its feature matrix and format-specific dependencies require careful selection.

**m4b/goblin** — An impish, cross-platform binary parsing crate, written in Rust

- Repository: https://github.com/m4b/goblin
- Stars: 1,565 · Forks: 208
- Language: Rust
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/m4b-goblin

## Goblin's scope across executable and archive formats

Goblin addresses a specific Rust integration problem: applications often need to inspect binary metadata without implementing separate readers for ELF, Mach-O, PE, TE, and Unix archives. The crate presents common format records as `#[repr(C)]` structures and supports both 32-bit and 64-bit variants where applicable. Its default feature set covers `elf32`, `elf64`, `mach32`, `mach64`, `pe32`, `pe64`, `te`, `archive`, `endian_fd`, and `std`.

The intended audience includes reverse-engineering tools, static binary analysis systems, compiler-adjacent software, linkers, kernels, and other programs that need to parse binary structures. Goblin does not present itself as a complete disassembly engine or a replacement for every executable-analysis package. It is the parsing and loading layer. The README points to projects such as `panopticon`, `falcon`, `cargo-sym`, and `bingrep` as clients or related examples of this parsing role.

There is a meaningful boundary around that role. The README does not document instruction decoding, symbolic execution, runtime instrumentation, or automatic identification of every executable format. Consumers still need their own analysis layers when those capabilities are required. Goblin is most useful when the application already knows what it wants from a file header, program structure, section, symbol, or archive entry.

## Zero-copy records and four configuration modes

The core design is based on zero-copy, endian-aware parsing. Core mode exposes small `#[repr(C)]` structures and does not require the Rust standard library. This mode is intended for environments that need little compile-time footprint, direct access to binary-layout definitions, or support for both 32-bit and 64-bit variants of a type. The repository includes `examples/automagic.rs` as the documented example for defining behavior once across type variants.

`std` adds reading and writing implementations through `Pread` and `Pwrite`. It also introduces file-reading facilities, convenience allocations, and extra methods. That mode is the normal starting point for a hosted application that can allocate memory and read binaries from disk. Enabling `std` also enables `alloc` in the manifest.

`endian_fd` addresses binary analysis that must read data whose endianness differs from the host. The feature is based on reading the endianness recorded in the binary. It requires `alloc`, as declared in `Cargo.toml`. The Mach-O, PE, and TE features also depend on `endian_fd` and `alloc`, while archive parsing requires `alloc`. Those dependencies are not cosmetic. They define the actual minimum environment for each parser and mean that choosing `pe64` is not equivalent to selecting a completely standalone header-only definition.

Feature selection is the main engineering decision in this crate. Shipping every default parser may be convenient, while a constrained build can compile a smaller subset. The README calls the configuration heavily configurable, but that flexibility also transfers complexity to the application maintainer.

## Installing Goblin 0.10 for a Rust project

The package manifest specifies Goblin 0.10.6, Rust edition 2024, and a minimum `rustc` version of 1.85.0. The README tells users to add `goblin = "0.10"` to `Cargo.toml`. With the default features, Cargo resolves the `std`, executable-format, archive, and endian-aware parser configuration listed by the project.

Add the dependency to an existing crate:

```toml
[dependencies]
goblin = "0.10"
```

After adding it, run Cargo's normal dependency resolution and build flow. The repository's `Makefile` documents this build command:

```bash
cargo build
```

The command should complete with the crate available to the Rust package. Its exact compiler output is not documented, so the result to look for is a successful Cargo build rather than a specific message.

The repository also provides a concrete reader example. After dependencies resolve, run the documented command with the target file as its argument:

```bash
cargo run --example=rdr -- /bin/ls
```

This launches `examples/rdr.rs` and passes `/bin/ls` to it. The repository documents no expected terminal transcript for that example, so it should not be used as a visual output fixture. The real first-use check is whether Cargo builds `rdr` and the example accepts the supplied file path.

## Reading examples without inventing a Goblin API

The repository contains several examples, but the cleaned README does not expose their source. Their names still indicate distinct integration tasks: `ar.rs` concerns archive handling, `lipo.rs` concerns Mach-O operations, `rewrite_pe.rs` concerns PE writing, `scroll.rs` covers the scroll-related interface, and files such as `dotnet_pe_analysis.rs` and `dyldinfo.rs` target more specialized analysis paths. These names describe repository intent, not guaranteed APIs, so copying an imagined function call into an application would go beyond what can be confirmed.

The one executable invocation that is documented is the `rdr` example in the `Makefile`. That makes it the safest initial path for checking the crate in a local checkout. For a downstream crate, the next reference should be the API documentation at `https://docs.rs/goblin/`, linked directly from the README.

The application must also decide what happens after format detection. Parsing records is separate from interpreting their contents. The README cites `bin2json` as a possible kind of client, where selected binary structures could be represented as JSON, but it does not claim that Goblin performs JSON serialization. Any such transformation belongs in the integrating project.

## Where Goblin is the wrong parsing choice

The clearest wrong-tool case is a program that does not need several formats and values dependency simplicity above format breadth. Even a minimal selected feature can acquire transitive requirements: `mach64`, for example, enables `alloc`, `endian_fd`, and `archive`, while `pe64` enables `alloc` and `endian_fd`. The default build enables all documented parsers. An application supporting one format may therefore carry parser code and dependencies it will never invoke.

Goblin is also a poor fit for consumers that need a high-level vulnerability scanner, disassembler, debugger, or runtime instrumentation engine. Nothing in the README assigns those functions to the crate. Its raw structures and parsers can feed such tools, but the higher-level behavior must come from elsewhere.

Malformed or hostile input requires application-level validation regardless of the crate. The README reports extensive fuzzing, including a quoted statement about 100 million runs, but that statement does not establish that every parser accepts arbitrary truncated files or that higher layers can safely trust all returned offsets. Bounds checking, error handling, and semantic validation remain consumer responsibilities. The project’s fuzzing claim is historical and should not be treated as a substitute for tests against the exact inputs and formats an application accepts.

## Goblin versus custom header and writing logic

A real alternative for a project that only emits a known binary format is to define its own layout structures and use the `Pwrite` implementations described in the README. The repository suggests this route for compiler and code-generation systems such as `faerie`. Instead of loading and analyzing foreign binaries, such software constructs output and needs serialization behavior.

The distinction is direction. Goblin provides parsers for recognized input structures across several executable and archive families, including endian-aware reading for foreign data. Custom `#[repr(C)]` definitions and `Pwrite` logic focus on producing bytes according to a layout the application already understands. The first approach reduces the need to implement readers for many existing formats. The second gives tighter control when generation is the primary task, but leaves the application responsible for format definitions and consistency.

The repository also mentions tools built on Goblin, but those are integrations rather than feature-complete replacements. `cargo-sym` and `bingrep` illustrate symbol or search-oriented clients, while `dryad` illustrates a linker-like use case. Their existence indicates that Goblin can serve as a base layer; it does not show that Goblin itself performs their end-user jobs.

## Maintenance, licensing, and dependency review

The repository is not archived, and its last push was on 2026-08-30. That is recent enough to avoid describing it as abandoned, but the absence of GitHub releases is important for upgrade planning. The documented source of release history is `CHANGELOG.md`, while the crate dependency declared by the README is the `0.10` line and the manifest currently contains version `0.10.6`. A production project should therefore distinguish the Cargo requirement from the exact checked-in package version.

Goblin is licensed under the MIT License, as stated in both `Cargo.toml` and the `LICENSE` entry. The manifest also depends on `plain`, `scroll`, and optionally `log`; `scroll` defaults are disabled, and `alloc` activates `scroll/derive` and `log`. Upgrade review must include those dependency relationships because disabling default features in Goblin does not mean the build graph is empty.

Backend ownership is divided among named maintainers for PE, ELF, and Mach-O. The repository states that m4b currently has merge rights for all pull requests, while format-specific maintainers are first-contact reviewers. This division is relevant when filing format problems, although the README does not promise any response time or support window.

## Conclusion

Adopt Goblin when a Rust project needs one configurable library for common executable and archive formats, especially when `no_std` or foreign-endian parsing matters. Do not choose it merely to inspect one narrow format or if the full feature matrix adds unnecessary surface. Before integration, verify Rust 1.85.0 support, select only the format and allocation features required by the target, and inspect the generated Cargo feature graph for the build configuration in `Cargo.toml`.

## FAQ

### What Rust version does Goblin 0.10 require?

Goblin requires `rustc` 1.85.0 and uses Rust edition 2024. `Cargo.toml` records 1.85.0 as `rust-version`.

### Which binary formats can Goblin parse?

Goblin has features for 32-bit and 64-bit ELF, 32-bit and 64-bit Mach-O, 32-bit and 64-bit PE, TE, and Unix-style archives. Archive support is also pulled in by the Mach-O features.

### Can Goblin run in a `no_std` environment?

Yes, the core mode uses small `#[repr(C)]` structures and is intended for `no_std` environments. Allocations, file-style helpers, and endian-aware file-descriptor access are enabled through separate features.

## Sources

- [Issues](https://github.com/m4b/goblin/issues)
- [License: MIT](https://github.com/m4b/goblin/blob/master/LICENSE)
- [m4b/goblin on GitHub](https://github.com/m4b/goblin)
- [README](https://github.com/m4b/goblin/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/m4b-goblin
