TinyInst dynamic instrumentation for targeted module coverage
A lightweight dynamic instrumentation library
At a glance
- What is it?
- TinyInst rewrites selected process modules while leaving the rest to run natively. It fits controlled, well-behaved targets that need targeted binary rewriting without the broader mechanism of DynamoRIO or Intel PIN.
- Who is it for?
- Adopt TinyInst when a target lets you isolate well-behaved modules and needs selective binary rewriting or edge coverage. Do not choose it for self-modifying code, targets that directly inspect return addresses, or programs that genuinely require DEP to remain disabled.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 53 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why TinyInst limits instrumentation to selected modules
TinyInst addresses a specific problem: a process may spend most of its execution time in code that does not need observation, while one or a few modules contain the behavior being studied. Instead of translating every module, TinyInst instruments selected modules and leaves the rest of the process to run natively. The intended users are engineers embedding dynamic instrumentation in another C++ program, such as a coverage collector or a tool that needs control at selected target methods.
The project takes a narrower position than DynamoRIO and Intel PIN. The README says TinyInst is not designed for all targets and assumes that instrumented modules are well behaved. Compatibility is therefore a design boundary rather than a claim of universal support. An instrumented module must not use self-modifying code, and its program must not directly access the return address stored on the stack. Depending on the settings, the module must also avoid storing data at addresses below the current stack pointer.
Selective instrumentation may help when an uninstrumented module causes problems under a broader instrumentation framework. If that module does not need observation and the selected module satisfies TinyInst's assumptions, leaving it native can make the target viable. The practical benefit is scope control. The caller chooses which modules pay rewriting and runtime instrumentation costs instead of applying one policy to the entire process.
How TinyInst runs, attaches, and rewrites code
TinyInst is primarily a library embedded in another program. A client is written as a subclass of the `TinyInst` class and can override the API methods it needs. The documented lifecycle begins with `init(int argc, char **argv)`, which initializes TinyInst from command-line options. Clients can also define their own options.
After initialization, a client can call either `Run`, which launches a target command, or `Attach`, which connects to an already running process by process ID. Both calls accept a timeout in milliseconds. If the client has not specified a target method, TinyInst returns when the target exits, crashes, or reaches the timeout. If a target method is defined, TinyInst returns when that method is entered and when it returns. The caller can then perform additional work and either continue or terminate the live process through `Continue` or `Kill`.
TinyInst is described as a full binary rewriting solution. That distinction allows arbitrary behavior to be changed in the target module, including extraction of edge coverage rather than only basic-block information. It also identifies basic blocks without depending on software such as IDA Pro. Repository entries such as `coverage.cpp`, `litecov.cpp`, `hook.cpp`, and `tinyinst.cpp` separate coverage, hooking, and core instrumentation concerns, although the README does not document a complete internal execution diagram.
Building the Windows, macOS, and Linux configurations
The README documents CMake builds for Windows, macOS, and Linux. On Windows, it tells the user to set up the build environment by running `vcvars64.bat` or `vcvars32.bat` in a terminal. The documented Windows configuration uses the Visual Studio 2019 generator and the x64 architecture:
mkdir build
cd build
cmake -G "Visual Studio 16 2019" -A x64 ..
cmake --build . --config ReleaseCMake generates the Visual Studio solution and the last command builds its `Release` configuration. The README says that a 64-bit build can run against 32-bit targets on Windows and Linux. It also says users can open the generated `.sln` file in Visual Studio when a 32-bit build fails because the environment or libraries are missing.
For macOS, the README selects Xcode:
mkdir build
cd build
cmake -G Xcode ..
cmake --build . --config ReleaseFor Linux, it leaves generator selection to CMake:
mkdir build
cd build
cmake ..
cmake --build . --config ReleaseThese instructions build TinyInst from source. The README does not document installation through a system package manager, installation into a shared system library directory, or a platform-neutral executable name.
Cross-compiling TinyInst for Android ARM64
The README documents Android support for ARM64 through the Android NDK toolchain. It presents placeholder paths for the NDK and its CMake toolchain file, plus placeholders for the desired Android platform. Users must replace those placeholders with values appropriate to their own NDK installation and intended build. The documented commands are:
mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=<path/to/android/ndk>build/cmake/android.toolchain.cmake -DANDROID_NDK=<path/to/android/ndk> -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=<platform> ..
cmake --build . --config ReleaseThe toolchain file tells CMake to use Android's cross-compilation setup, `ANDROID_ABI` selects `arm64-v8a`, and `ANDROID_PLATFORM` selects the requested platform. The repository also contains an `Android/` directory, and the README directs readers there for platform-specific notes and limitations.
The supported-platform list covers Windows x86 and x64, macOS x64 and ARM64, Linux x64 and ARM64, and Android ARM64. Platform support does not remove the target requirements. Self-modifying code, prohibited stack behavior, and the DEP/NX requirement still apply to an instrumented Android target.
Using litecov and the TinyInst client API
TinyInst includes an example coverage binary. The README gives its general invocation as options, `--`, and the target command line. Its Windows example begins with `litecov.exe -instrument_module`, but the example stops before the selected module and target command. The README therefore does not provide a complete runnable coverage command. Users must check the platform-specific README files for additional options and limitations.
For a client, the documented lifecycle begins with `void init(int argc, char **argv);`. The README then documents `Run` for launching a target and `Attach` for connecting to an existing process, with a timeout expressed in milliseconds. `Kill` and `Continue` are the documented controls for a process that remains alive after either operation returns. A client that defines a target method receives control on entry and return, rather than waiting for every intervening native instruction.
A sensible first integration begins with one known module and one target method whose entry and return are useful to the client. The README does not document a complete constructor signature or a complete subclass, so it does not provide enough code to reproduce a client from scratch.
Stack assumptions, DEP/NX, and incompatible targets
TinyInst's target assumptions define several concrete failure modes. An instrumented module must not contain self-modifying code, and the program must never directly access a return address stored on the stack. Depending on configuration, TinyInst also requires that no data be written before the current stack pointer, meaning addresses lower than those referenced by `ESP` or `RSP`. The `-stack_offset` flag can relax that boundary to allow writes no lower than `ESP` or `RSP` minus an arbitrary offset, but the flag does not document support for unrestricted access below that point.
DEP/NX must be enabled for the target process. If necessary, `-force_dep` can force it on. The README warns that a target that genuinely needs DEP disabled may behave incorrectly when the flag changes that condition. This boundary matters for software with unusual runtime code generation, nonstandard stack layouts, or executable-data requirements that conflict with TinyInst's model.
Malware is an explicit warning rather than a supported use case. The README says users will probably not succeed against it because instrumented modules are assumed to be well behaved. TinyInst is therefore not a general sandboxing tool. It is more appropriate for controlled software whose code and stack behavior can be checked against the project's restrictions before deployment.
TinyInst's performance trade-offs and maintenance boundary
The README reports early measurements from an image-decoding scenario on a well-behaved 64-bit target. It states that default TinyInst settings produced overhead of around 15% without a client and about 20% with the example coverage client. It also says those figures exclude the timeout introduced while the selected modules are initially instrumented. These numbers belong to that specific scenario. The README does not establish comparable results for servers, startup-heavy applications, or targets outside the stated assumptions.
The design may perform well when execution spends substantial time in modules that remain native, because those modules avoid TinyInst's instrumentation work. Conversely, spending too long inside selected modules narrows the advantage. Initial instrumentation time and the behavior of a particular coverage client also need consideration beyond steady execution overhead.
TinyInst uses the `Apache-2.0` license and includes the Apache License 2.0 notice in its README. The repository is not archived, and the last push was on 2026-08-31. It has no GitHub releases, so there is no release version or published release cadence to rely on. Upgrade planning must therefore account for source compatibility and review of changes on `master`.
Where DynamoRIO, PIN, Mesos, and TrapFuzz differ
DynamoRIO and Intel PIN are broader instrumentation frameworks. The README explicitly says TinyInst is not a replacement for them. Their wider mechanisms may be appropriate when nearly all code must be observed or when a target violates TinyInst's well-behaved-module assumptions. TinyInst instead limits rewriting to selected modules and allows unrelated code to remain native, which can avoid failures caused by modules that do not need instrumentation.
Mesos and TrapFuzz represent a different design comparison. TinyInst describes itself as a full binary rewriting solution, allowing arbitrary behavior in the target module to be changed. That supports edge coverage rather than only basic-block coverage. TinyInst also identifies basic blocks without depending on IDA Pro or comparable external software. A workflow already designed around Mesos or TrapFuzz may still fit an existing experiment better, but TinyInst presents direct rewriting with fewer external-analysis dependencies for its stated coverage use case.
The trade-off is not simply smaller versus larger overhead. Instrumentation scope, target assumptions, startup cost, and the desired coverage detail all affect the choice. TinyInst is most defensible when selected modules contain the behavior under examination and the remaining modules can safely stay native.
Editorial conclusion
Adopt TinyInst when a target lets you isolate well-behaved modules and needs selective binary rewriting or edge coverage. Do not choose it for self-modifying code, targets that directly inspect return addresses, or programs that genuinely require DEP to remain disabled. Before integration, verify the target against TinyInst's code, stack, and DEP assumptions, then confirm that the initial instrumentation timeout is acceptable for the workload.
Frequently asked questions
Which operating systems does TinyInst support?
TinyInst documents support for Windows x86 and x64, macOS x64 and ARM64, Linux x64 and ARM64, and Android ARM64. The README directs users to each platform directory for additional notes and limitations.
Does TinyInst support malware and self-modifying code?
TinyInst assumes instrumented modules do not use self-modifying code. The README specifically says users will probably not succeed against malware because it does not fit TinyInst's well-behaved-target requirements.
How do I build and run TinyInst coverage?
The README documents CMake builds and a coverage invocation using `<options> -- <target command line>`. Its `litecov.exe` example stops after `litecov.exe -instrument_module`, so no complete target command is shown.
What is the difference between TinyInst and DynamoRIO or Intel PIN?
TinyInst instruments selected modules and leaves the rest of the process running natively. The README positions it as a lighter alternative for well-behaved targets, not as a replacement for broader instrumentation frameworks.
Does TinyInst require DEP or NX?
Yes. The README says TinyInst requires DEP/NX for the target process. Its `-force_dep` flag can enable the requirement, but forcing it on may cause a program that genuinely needs DEP disabled to misbehave.
Official sources
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.
[](https://hysenlabs.com/projects/googleprojectzero-tinyinst)Was this useful?