Class
GumStalker
Description [src]
final class Gum.Stalker : GObject.Object
implements Gum.UnwindPcTranslator {
/* No available fields */
}
Traces execution by dynamically recompiling code as a thread runs.
Stalker follows a thread one basic block at a time, JIT-compiling a shadow copy of each block just before it executes. That shadow copy can be observed and rewritten on the way through, which makes it possible to:
- Receive a stream of events — every call, return, block and instruction —
through a
GumEventSink. - Inspect and rewrite the instructions of each block through a
GumStalkerTransformer, for instance to insert aGumStalkerCalloutthat runs your own C function with access to the live register state. For hot paths, emitting instrumentation inline is much cheaper than a callout — seegum_stalker_iterator_put_callout().
Compiled blocks are cached per thread; the trust threshold
(gum_stalker_set_trust_threshold()) governs how aggressively that
cache is reused in the presence of self-modifying code. Ranges of memory can
be left to run uninstrumented with gum_stalker_exclude(), which is
also much faster for code you have no interest in.
Tracing begins with gum_stalker_follow_me() for the calling thread, or
gum_stalker_follow() for another thread, and ends at the matching unfollow.
Tracing the current thread
static void on_exec (GumStalkerIterator * iterator,
GumStalkerOutput * output, gpointer user_data);
void
trace (void)
{
g_autoptr(GumStalker) stalker = gum_stalker_new ();
GumStalkerTransformer * transformer =
gum_stalker_transformer_make_from_callback (on_exec, NULL, NULL);
gum_stalker_follow_me (stalker, transformer, NULL);
// ... code to trace runs here ...
gum_stalker_unfollow_me (stalker);
g_object_unref (transformer);
}
static void
on_exec (GumStalkerIterator * iterator,
GumStalkerOutput * output,
gpointer user_data)
{
const cs_insn * insn;
while (gum_stalker_iterator_next (iterator, &insn))
{
// Inspect insn here, then emit it into the recompiled block.
gum_stalker_iterator_keep (iterator);
}
}
Instance methods
gum_stalker_activate
Resumes tracing on the calling thread after a
gum_stalker_deactivate(), following it even through excluded ranges
until execution reaches target, at which point normal behavior resumes.
target must be the start of a basic block. This is primarily useful for
fuzzing; see gum_stalker_prefetch() for the bigger picture.
gum_stalker_add_call_probe
Registers callback to be invoked whenever a followed thread calls
target_address, giving it access to the call’s arguments through the supplied GumCallDetails. Cheaper than a transformer when all you
need is to observe calls to a specific function.
gum_stalker_deactivate
Pauses tracing on the calling thread while leaving it followed, so it runs
natively until gum_stalker_activate() is called. Has no effect if the
thread is not being traced.
gum_stalker_exclude
Marks range as off-limits: while a followed thread executes inside it, it
runs natively instead of being traced, resuming tracing once it returns.
Besides skipping code you have no interest in — which is also much faster —
this is essential for ranges that must not be instrumented, such as the
runtime backing Stalker itself.
gum_stalker_flush
Flushes the event sinks of all current sessions, ensuring any events still buffered are delivered.
gum_stalker_follow
Starts tracing the thread identified by thread_id. When thread_id is the
calling thread this behaves like gum_stalker_follow_me(); otherwise
the target thread is briefly suspended so it can be made to start executing
instrumented code. Stop with gum_stalker_unfollow().
gum_stalker_follow_me
Starts tracing the calling thread, continuing from the caller’s return
address. Each subsequently executed block is passed through transformer and
any generated events are delivered to sink. Stop with
gum_stalker_unfollow_me().
gum_stalker_garbage_collect
Reclaims resources left behind by threads that have unfollowed or exited but
could not be cleaned up synchronously, e.g. because they might still have
been executing instrumented code. Call this periodically until it returns
FALSE to drain such garbage.
gum_stalker_invalidate
Drops the cached instrumented block covering address on every followed
thread, so it is recompiled the next time it runs. Use this when the
underlying code, or the way you want it instrumented, has changed.
gum_stalker_invalidate_for_thread
Like gum_stalker_invalidate(), but limited to the thread identified by
thread_id.
gum_stalker_prefetch
This API is intended for use during fuzzing scenarios such as AFL forkserver. It allows for the child to feed back the addresses of instrumented blocks to the parent so that the next time a child is forked from the parent, it will already inherit the instrumented block rather than having to re-instrument every basic block again from scratch.
gum_stalker_prefetch_backpatch
Applies a backpatch previously reported through a
GumStalkerObserver. The companion to gum_stalker_prefetch()
for fork-server fuzzing: it lets the parent reproduce the inter-block
backpatches discovered by a child so forked children inherit them too.
gum_stalker_recompile
Forces the cached block at address to be recompiled, e.g. after something
the transformer depends on has changed.
gum_stalker_run_on_thread
Arranges for func to run on the thread identified by thread_id, with that
thread’s register state, by briefly hijacking it through Stalker. Returns once func has been scheduled; it may not have run yet. Use
gum_stalker_run_on_thread_sync() to wait for completion.
gum_stalker_set_observer
Sets a GumStalkerObserver that receives fine-grained notifications
about Stalker’s internals, such as backpatches and engine statistics. Mainly
of interest for diagnostics and performance work.
gum_stalker_set_trust_threshold
Controls how Stalker copes with self-modifying code. Each recompiled block is cached alongside a snapshot of the original bytes; when the block is reached again Stalker compares the current code against that snapshot and recompiles only if it actually changed. The trust threshold is how many times a block must be found unchanged before Stalker stops doing that comparison and trusts the cached copy outright.
gum_stalker_stop
Unfollows every thread still being traced and removes all call probes, then reclaims the associated resources.
gum_stalker_unfollow
Stops tracing the thread identified by thread_id. The thread resumes running
its original, uninstrumented code.
gum_stalker_unfollow_me
Stops tracing the calling thread, which must currently be followed by
gum_stalker_follow_me().
Methods inherited from GumUnwindPcTranslator (2)
gum_unwind_pc_translator_install_resume_context
gum_unwind_pc_translator_translate
Signals
Signals inherited from GObject (1)
GObject::notify
The notify signal is emitted on an object when one of its properties has its value set through g_object_set_property(), g_object_set(), et al.