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 a GumStalkerCallout that runs your own C function with access to the live register state. For hot paths, emitting instrumentation inline is much cheaper than a callout — see gum_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);
  }
}

Ancestors

Constructors

gum_stalker_new

Creates a new Stalker.

Functions

gum_stalker_backpatch_get_from

Gets the address of the block a backpatch originates from.

gum_stalker_backpatch_get_to

Gets the address of the block a backpatch points to.

gum_stalker_is_supported

Checks whether Stalker is available on the current architecture and OS.

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_get_trust_threshold

Gets the trust threshold; see gum_stalker_set_trust_threshold().

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_is_following_me

Checks whether the calling thread is currently being traced.

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_remove_call_probe

Removes the call probe identified by id.

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_run_on_thread_sync

Synchronously runs func on the specified thread.

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 GObject (43)

Please see GObject for a full list of methods.

Methods inherited from GumUnwindPcTranslator (2)
gum_unwind_pc_translator_install_resume_context
No description available.

gum_unwind_pc_translator_translate
No description available.

Properties

Gum.Stalker:adjacent-blocks
No description available.

Gum.Stalker:ic-entries
No description available.

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.

Class structure

struct GumStalkerClass {
  GObjectClass parent_class;
  
}

No description available.

Class members
parent_class: GObjectClass

No description available.