Library / SDK
frida/frida-gum avatar
frida/frida-gum

Frida Gum: the C layer that does the hooking, tracing, and code generation

Cross-platform instrumentation and introspection library written in C

1,040 stars398 forksCNOASSERTION

At a glance

What is it?
Gum is the cross-platform instrumentation and introspection library written in C that sits underneath Frida, providing inline hooking, stealthy code tracing, memory access monitoring, symbol and module introspection, and per-architecture code writers and relocators. It is not usually used directly, since most people meet it through Frida's JavaScript bindings.
Who is it for?
Gum fits a developer embedding Frida into their own tooling, where they need the native layer rather than the JavaScript runtime, or a developer who needs code generation and relocation for several architectures from one C API. It is the wrong entry point for most people, because the library exists to be consumed by frida-core through GumJS.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • frida/frida-gum1,040 ★ · +7
Star history
Repository2026-10-192026-11-07
frida/frida-gum1k1k

7 Stars in the last 19 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

A library layer most people never call directly

Gum is a cross-platform instrumentation and introspection library written in C, and the first thing to understand is where it sits. This library is consumed by frida-core through its JavaScript bindings, GumJS. In other words, Gum is the engine and frida-core is the vehicle most people drive.

That framing matters for anyone evaluating it. If you have used Frida, you have used Gum, through the JavaScript API, without ever seeing a C symbol. The case for going deeper is that the JavaScript layer is a convenience, and a convenience layer cannot always express what you need. Gum exposes the same capabilities as a C API with no runtime in the middle, which is what you want when you are embedding instrumentation into a product, a debugger, a fuzzing harness, or a reverse engineering tool of your own.

The capability list is organised into layers, and the organisation is informative. The instrumentation core has inline hooking through Interceptor, stealthy code tracing through Stalker, and memory monitoring through MemoryAccessMonitor. Cross-platform introspection covers running threads and other process state, loaded modules with their imports, exports, and symbols, memory scanning, DebugSymbol lookups, Backtracer implementations, and kernel state, which is iOS only for now.

Then there are the two layers that make the first two possible. Code generation provides X86Writer, ArmWriter, ThumbWriter, Arm64Writer, and MipsWriter, and code relocation provides the matching X86Relocator, ArmRelocator, ThumbRelocator, Arm64Relocator, and MipsRelocator. Hooking without those two is not possible, and the fact that both sets exist per architecture tells you how much of the library is architecture-aware rather than abstracted away.

The last group are helper libraries for developers needing highly granular control: Heap for allocation tracking and leak checking, and Profiling with a worst-case inspector callback.

The build is a Makefile that hands the work to Meson

The build instructions describe a configure script with options, and the repository contains a `configure` script, a `configure.bat` for Windows users, a `Makefile`, and a `make.bat`. But the Makefile at the root is not a conventional makefile, and reading it is the fastest way to understand the real build.

Here is the whole thing:

makefile
PYTHON ?= $(shell which python3 >/dev/null && echo python3 || echo python)

all $(MAKECMDGOALS):
	@$(PYTHON) \
		-c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_make import main; main()" \
		"$(shell pwd)" \
		./build \
		$(MAKECMDGOALS)

Every make target is intercepted and passed to a Python script, `releng/meson_make`, along with the source directory, the build directory, and the original goal. So `make` is a thin front end for Meson, and the actual configuration lives in `meson.build` and `meson.options`, with `subprojects/` holding the vendored dependencies. The `PYTHON ?=` line with the shell fallback finds python3 or falls back to python, which is a small detail that tells you the build assumes a Python on the machine.

There is a `git-submodules` target that runs `git submodule update --init --recursive --depth 1` when `releng/meson/meson.py` is missing, and it is included as a makefile dependency, so the submodules are fetched automatically on the first build. The tree has a `.gitmodules` file to match.

The configure script approach is still documented, and it takes the flags you would expect for a project with optional components:

bash
./configure --enable-gumpp --enable-gumjs --enable-tests
make

`configure --help` lists the rest of the switches. So there are two supported front ends to the same build, and the tree also carries a `BSDmakefile` alongside the GNU one, plus a `releng/` directory, a `vapi/` directory of Vala API definitions, an `ext/` directory for extensions, and `tools/`.

The test suite is addressable by path

Tests are built with `make test` and run with `./build/tests/gum-tests`, and the detail that makes this suite usable at scale is that you can target a specific test or group.

You specify a test path with `-p`, and the paths follow the pattern `/<Area>/<Module>/<test_name>`, where the area and module come from TESTENTRY macros in the fixture files, with the example given as `TESTENTRY_WITH_FIXTURE("Core/Interceptor", ...)`. The two invocations look like this:

bash
./build/tests/gum-tests
./build/tests/gum-tests -p /Core/Interceptor/attach_one

Naming tests this way matters more than it first appears. A library that hooks functions into other people's processes has a test surface where one failure can mean an architecture-specific problem, a kernel version problem, or a genuine logic bug, and a flat list of test names makes that distinction painful. Grouping by area and module means you can run the whole interceptor suite after a change to the interceptor, and that the failure list tells you where to look.

The build has to be configured with tests enabled for this to work, which is what the `--enable-tests` flag in the configure invocation is for.

The other structural detail in the tree is `bindings/`, which holds the GumJS bindings that frida-core consumes. The `gum/` directory is the C library proper, and the headers for each capability are in there, named after the component, such as `guminterceptor.h`, `gumstalker.h`, `gummemoryaccessmonitor.h`, `gumprocess.h`, `gummemory.h`, `gumsymbolutil.h`, `gumbacktracer.h`, and `gumkernel.h`.

The Darwin mapper solves an iOS specific problem

One entry in the capability list is easy to overlook and it is the clearest signal of what platform constraints this library lives under: an out-of-process dynamic linker for iOS and macOS, Gum.Darwin.Mapper.

The reason it exists is the platform's security model. On Darwin, the dynamic linker decides which images a process may load, and a process that has been instrumented or that wants to load an image outside the normal rules runs into that check. The mapper is the mechanism that performs the linking step in a separate process, so the load happens outside the target's own address space and without the target's own linker making the decision. The header lives in a Darwin-specific backend directory, at `gum/backend-darwin/include/gum/gumdarwinmapper.h`, which confirms it is platform code rather than something with a general implementation behind an interface.

This is the kind of feature that tells you the project is a product rather than a research artifact. An instrumentation library that only worked when it could inject into the target's own process would be useless on a locked-down mobile platform, and the out-of-process path is what keeps it working there.

The kernel state entry has a similar character. Kernel state is iOS only for now, which is an honest limitation stated inline rather than a gap left for the reader to discover. The MacOS part of the mapper, by contrast, is listed alongside iOS, so the same mechanism covers both.

For anyone reading the capability list as a feature matrix, the Darwin mapper and the iOS-only kernel state are the two entries to look up in the documentation, because they are the ones where a platform caveat is attached.

What the release history and the licence say about the project

The release history shows an active project with a fast patch cadence. The three most recent tags are 17.23.1 on 2026-10-08, 17.23.2 on 2026-10-09, and 17.23.3 on 2026-10-09, and the last push to the repository was on 2026-10-19. Three patch releases in two days, then continued work, is the signature of a project that ships fixes as they land.

The default branch is `main`, and the repository description records the language as C with the topics `frida` and `instrumentation`.

The licence is the interesting part. It is recorded as Other, a custom licence GitHub cannot classify, with the terms in a `COPYING` file at the root of the tree. That file has to be read directly rather than inferred from a standard identifier, and the classification tells you the terms are not one of the common OSI licences. Any organisation with a policy that requires a recognised licence identifier will need to review that file before adopting the library, and it is worth doing that review before writing code against it rather than after.

The tree also contains a `CLAUDE.md` at the root, which is instructions for coding agents working in the repository, alongside a `.cirrus.yml` for the Cirrus CI configuration used on some platforms and a `.github/` directory. The presence of `vapi/` is another signal of the project's scope: Vala API definitions mean the library is consumable from Vala as well as from C, and from the JavaScript bindings.

Binaries are also published. A devkit for statically linking into your own projects is downloadable from the Frida releases page, which is the practical route for anyone who needs Gum without building it.

Where Gum is the wrong tool

The boundaries here are clearer than they are for most libraries, because the position in the stack is defined.

First, if all you want is to instrument a program, Gum is the wrong level. The supported path is frida-core with the JavaScript bindings, and writing a small script through GumJS is faster and more maintainable than embedding the C library in your own tool. Choosing Gum means taking on the integration work that frida-core already does, including the runtime, the scripting engine, and the plumbing for getting your code into the target process.

Second, the architecture support is finite and specific. There are writers and relocators for x86, Arm, Thumb, Arm64, and Mips, and that list is what determines where the library can hook code at all. A platform outside that set is not a configuration problem, it is an absent implementation.

Third, the out-of-process mapper is Darwin only, and the kernel state is iOS only for now. The library is not uniformly capable across platforms, and the capability list is where you find that out.

Fourth, this is a low-level library with a low-level failure mode. Inline hooking replaces code at a function entry, and Stalker traces execution by translating blocks on the fly. Both break down in the presence of hardened runtimes, aggressive anti-instrumentation, or unusual kernel configurations. The library gives you the primitives, not a guarantee that a given target will let you use them.

Fifth, the build is unusual. Two front ends, a configure script and a Makefile, both delegating to Meson, with a Python script in the middle and submodules to fetch, and a make.bat and BSDmakefile for the other platforms. A team whose build infrastructure assumes a plain autoconf project will spend time on this, and the supported paths are the two described.

Editorial conclusion

Gum fits a developer embedding Frida into their own tooling, where they need the native layer rather than the JavaScript runtime, or a developer who needs code generation and relocation for several architectures from one C API. It is the wrong entry point for most people, because the library exists to be consumed by frida-core through GumJS. Check three things before you build against it: that you actually want the C API rather than the JavaScript bindings, that your target architectures are covered by the writers and relocators you need, since the list covers x86, Arm, Thumb, Arm64, and Mips, and that you accept a build driven by a Python wrapper around Meson rather than a conventional configure script, because the Makefile in the tree is a shim that delegates to a Python script.

Frequently asked questions

What is Frida Gum and how does it relate to Frida?

Gum is a cross-platform instrumentation and introspection library written in C, and it is consumed by frida-core through its JavaScript bindings, GumJS. Most people meet it through the Frida JavaScript API rather than the C API directly.

How do I build Frida Gum?

Run `./configure --enable-gumpp --enable-gumjs --enable-tests` and then `make`, with `configure.bat` available for Windows users. The Makefile at the root is a thin front end that passes the goal to a Python script, `releng/meson_make`, which drives the real Meson build, and it fetches the submodules automatically on the first run.

How do I run a single test in the Gum test suite?

Build with `make test` and run `./build/tests/gum-tests`. You can target a specific test or group with `-p`, and test paths follow the pattern `/<Area>/<Module>/<test_name>`, for example `./build/tests/gum-tests -p /Core/Interceptor/attach_one`.

What architectures does Frida Gum support?

The code generation writers and code relocation relocators cover x86, Arm, Thumb, Arm64, and Mips, with X86Writer, ArmWriter, ThumbWriter, Arm64Writer, and MipsWriter and the matching relocators. There is also an out-of-process dynamic linker for iOS and macOS, and kernel state support that is iOS only for now.

Official sources

  1. frida/frida-gum on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/frida-frida-gum.svg)](https://hysenlabs.com/projects/frida-frida-gum)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/frida-frida-gum.svg)](https://hysenlabs.com/projects/frida-frida-gum)

Was this useful?