S Lab

[Sibin Mohan]

Systems Security Research Group at GWU and University of Illinois


Team Members:

Collaborators:


Ichnaea

Precise, lossless, low-overhead tracing of individual memory objects in C/C++ programs.

Ichnaea is a lightweight, interrupt-driven tracer built on Intel/ARM Memory Protection Keys (MPK). Point it at the objects you care about and it records who accessed each one, when, how, and from where — while staying effectively dormant until one of those objects is actually touched. Named after the Greek goddess of tracing and tracking, Ichnaea is designed to make object-level tracing practical on real, multithreaded software.

To appear at OSDI ‘26.

Why Ichnaea

Existing dynamic tracers force an uncomfortable choice. Instruction-level tools like Intel Pin or Valgrind watch every load and store and slow programs down by 10–100× — too slow for long-running test suites, benchmarks, or fuzzing. Backing-memory tricks (debug registers, mprotect) are cheaper but lossy: they miss accesses under multithreading, false sharing, and system calls.

Ichnaea is the first object tracer to use MPK for per-thread access control. Because permission changes are a single CPU-register write (~50 ns) rather than a global page-table update, Ichnaea eliminates the dominant sources of trace loss and runs far cheaper:

Features

How It Works

  1. Register the objects you want to watch with a single API call. Ichnaea tags their backing pages with an MPK and revokes access.
  2. Fault & handle. Any access raises a SIGSEGV; a custom signal handler unlocks the page for the current thread, emulates the faulting instruction, and logs the access with full context.
  3. Post-process. On exit, buffered events are serialized to JSON for offline analysis — debugging, forensics, access-pattern recovery, or compartmentalization studies.

Quick Start

Annotate the objects you want to trace (the header uses a weak reference, so the call is a harmless no-op when the library isn’t loaded):

#include <ichnaea.h>

double object_of_interest;

int main(void) {
    if (ichnaea_register_object) {
        ichnaea_register_object(
            &object_of_interest,
            sizeof(object_of_interest),
            "Object of Interest",
            "double");
    }
    // ... your program ...
}

Build as usual, then run under the tracer:

# Build (no build-system changes required)
make

# Run your program with Ichnaea preloaded
LD_PRELOAD=./libichnaea.so ./your_program

Traces are written on exit; a companion decode_logs.py script turns the binary snapshots into readable JSON.

Ichnaea vs. Intel Pin

  Intel Pin Ichnaea
Runtime cost High Very low
Startup cost High Low
Traces kernel writes No Yes
Fuzzing support No Yes
Lossy No No
Manual write-site discovery No No

Repository

Source and updates: github.com/IchnaeaTracer/Ichnaea (updates coming soon).

Citation

TBD

Funding

This material is based upon work supported by,