Skip to content

Commit

Permalink
Review changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name authored and oleavr committed Jan 17, 2024
1 parent 160953f commit 016ac0b
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 59 deletions.
118 changes: 86 additions & 32 deletions bindings/gumjs/gumquickprocess.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ struct _GumQuickFindRangeByAddressContext
struct _GumQuickRunOnThreadContext
{
GumQuickCore * core;
GumQuickScope scope;
JSValue user_func;
gboolean sync;
};

static void gumjs_free_main_module_value (GumQuickProcess * self);
Expand Down Expand Up @@ -122,6 +120,9 @@ static gboolean gum_quick_exception_handler_on_exception (
GumExceptionDetails * details, GumQuickExceptionHandler * handler);
static void gum_js_process_run_cb (const GumCpuContext * cpu_context,
gpointer user_data);
static void gum_quick_flush_stalker (GumQuickProcess * self,
GumQuickScope * scope);
static gboolean gum_quick_flush_stalker_callback (GumQuickProcess * self);

static const JSCFunctionListEntry gumjs_process_entries[] =
{
Expand Down Expand Up @@ -159,6 +160,7 @@ _gum_quick_process_init (GumQuickProcess * self,
self->module = module;
self->core = core;
self->main_module_value = JS_UNINITIALIZED;
self->stalker = NULL;

_gum_quick_core_store_module_data (core, "process", self);

Expand Down Expand Up @@ -186,6 +188,8 @@ _gum_quick_process_flush (GumQuickProcess * self)
void
_gum_quick_process_dispose (GumQuickProcess * self)
{
g_assert (self->flush_timer == NULL);

g_clear_pointer (&self->exception_handler, gum_quick_exception_handler_free);
gumjs_free_main_module_value (self);
}
Expand Down Expand Up @@ -638,58 +642,108 @@ gum_quick_exception_handler_on_exception (GumExceptionDetails * details,

GUMJS_DEFINE_FUNCTION (gumjs_process_run_on_thread)
{
GumQuickProcess * self = gumjs_get_parent_module (core);
GumQuickScope scope = GUM_QUICK_SCOPE_INIT (core);
GumThreadId thread_id;
JSValue user_func;
GumQuickRunOnThreadContext sync_ctx;
GumStalker * stalker;
gboolean success;
GumQuickRunOnThreadContext context;
gboolean run;

if (!_gum_quick_args_parse (args, "ZF", &thread_id, &user_func))
return JS_EXCEPTION;

if (thread_id == 0)
return JS_UNDEFINED;

_gum_quick_scope_suspend (&scope);

sync_ctx.core = core;
sync_ctx.scope = scope;
sync_ctx.user_func = JS_DupValue (core->ctx, user_func);
sync_ctx.sync = FALSE;
context.core = core;
context.user_func = JS_DupValue (core->ctx, user_func);

stalker = gum_stalker_new ();
if (self->stalker == NULL)
self->stalker = gum_stalker_new ();

run = gum_stalker_run_on_thread (self->stalker, thread_id,
gum_js_process_run_cb, &context);

success = gum_stalker_run_on_thread (stalker, thread_id,
gum_js_process_run_cb, &sync_ctx);
_gum_quick_scope_resume (&scope);
gum_quick_flush_stalker (self, &scope);

while (gum_stalker_garbage_collect (stalker))
g_usleep (10000);
if (!run)
goto error;

g_object_unref (stalker);
return JS_UNDEFINED;

if (success)
{
return JS_UNDEFINED;
}
else
{
_gum_quick_throw_literal (ctx, "Failed to run on thread");
return JS_EXCEPTION;
}
error:
_gum_quick_throw_literal (ctx, "failed to run on thread");
return JS_EXCEPTION;
}

static void
gum_js_process_run_cb (const GumCpuContext * cpu_context,
gpointer user_data)
{
GumQuickRunOnThreadContext * sync_ctx =
(GumQuickRunOnThreadContext *) user_data;
GumQuickRunOnThreadContext * context = user_data;
GumQuickCore * core = context->core;
JSValue user_func = context->user_func;
GumQuickScope scope;

_gum_quick_scope_call (&sync_ctx->scope, sync_ctx->user_func, JS_UNDEFINED, 0,
_gum_quick_scope_enter (&scope, core);

_gum_quick_scope_call (&scope, user_func, JS_UNDEFINED, 0,
NULL);

if (!sync_ctx->sync)
JS_FreeValue (sync_ctx->core->ctx, sync_ctx->user_func);
JS_FreeValue (core->ctx, user_func);

_gum_quick_scope_leave (&scope);
}

static void
gum_quick_flush_stalker (GumQuickProcess * self,
GumQuickScope * scope)
{
GumQuickCore * core = self->core;
GSource * source;

if (!gum_stalker_garbage_collect (self->stalker))
goto error;

if (self->flush_timer != NULL)
goto error;

source = g_timeout_source_new (10);
g_source_set_callback (source,
(GSourceFunc) gum_quick_flush_stalker_callback, self, NULL);
self->flush_timer = source;

_gum_quick_core_pin (core);
_gum_quick_scope_suspend (scope);

g_source_attach (source,
gum_script_scheduler_get_js_context (core->scheduler));
g_source_unref (source);

_gum_quick_scope_resume (scope);
return;

error:
g_object_unref (self->stalker);
self->stalker = NULL;
}

static gboolean
gum_quick_flush_stalker_callback (GumQuickProcess * self)
{
gboolean pending_garbage;

pending_garbage = gum_stalker_garbage_collect (self->stalker);
if (!pending_garbage)
{
GumQuickCore * core = self->core;
GumQuickScope scope;

_gum_quick_scope_enter (&scope, core);
_gum_quick_core_unpin (core);
self->flush_timer = NULL;
_gum_quick_scope_leave (&scope);
}

return pending_garbage;
}
3 changes: 3 additions & 0 deletions bindings/gumjs/gumquickprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ struct _GumQuickProcess

JSValue main_module_value;
GumQuickExceptionHandler * exception_handler;

GumStalker * stalker;
GSource * flush_timer;
};

G_GNUC_INTERNAL void _gum_quick_process_init (GumQuickProcess * self,
Expand Down
109 changes: 82 additions & 27 deletions bindings/gumjs/gumv8process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,7 @@ struct GumV8FindModuleByNameContext
struct GumV8RunOnThreadContext
{
GumV8Core * core;
Isolate * isolate;
Local<Context> context;
Local<Function> user_func;
MaybeLocal<Value> ret;
};

GUMJS_DECLARE_GETTER (gumjs_process_get_main_module)
Expand Down Expand Up @@ -103,6 +100,9 @@ static gboolean gum_v8_exception_handler_on_exception (
GumExceptionDetails * details, GumV8ExceptionHandler * handler);
static void gum_js_process_run_cb (const GumCpuContext * cpu_context,
gpointer user_data);
static void gum_v8_flush_stalker (GumV8Process * self);
static gboolean gum_v8_flush_stalker_callback (GumV8Process * self);


const gchar * gum_v8_script_exception_type_to_string (GumExceptionType type);

Expand Down Expand Up @@ -142,6 +142,8 @@ _gum_v8_process_init (GumV8Process * self,
self->module = module;
self->core = core;

self->stalker = NULL;

auto process_module = External::New (isolate, self);

auto process = _gum_v8_create_module ("Process", scope, isolate);
Expand Down Expand Up @@ -180,6 +182,8 @@ _gum_v8_process_flush (GumV8Process * self)
void
_gum_v8_process_dispose (GumV8Process * self)
{
g_assert (self->flush_timer == NULL);

g_clear_pointer (&self->exception_handler, gum_v8_exception_handler_free);

delete self->main_module_value;
Expand Down Expand Up @@ -530,51 +534,102 @@ GUMJS_DEFINE_FUNCTION (gumjs_process_run_on_thread)
{
GumThreadId thread_id;
Local<Function> user_func;
GumV8RunOnThreadContext sync_ctx;
GumStalker * stalker;
gboolean success;
GumV8RunOnThreadContext context;
gboolean run;

auto isolate = core->isolate;
auto context = isolate->GetCurrentContext ();

if (!_gum_v8_args_parse (args, "ZF", &thread_id, &user_func))
return;

if (thread_id == 0)
return;

stalker = gum_stalker_new ();
if (module->stalker == NULL)
module->stalker = gum_stalker_new ();

{
ScriptUnlocker unlocker (core);
sync_ctx.core = core;
sync_ctx.isolate = isolate;
sync_ctx.context = context;
sync_ctx.user_func = Local<Function>::New (isolate, user_func);
context.core = core;
context.user_func = Local<Function>::New (isolate, user_func);

success = gum_stalker_run_on_thread (stalker, thread_id,
gum_js_process_run_cb, &sync_ctx);
run = gum_stalker_run_on_thread (module->stalker, thread_id,
gum_js_process_run_cb, &context);
}

while (gum_stalker_garbage_collect (stalker))
g_usleep (10000);
gum_v8_flush_stalker (module);

g_object_unref (stalker);
if (!run)
goto error;

if (!success)
_gum_v8_throw_ascii_literal (isolate, "Failed to run on thread");
return;

error:
_gum_v8_throw_ascii_literal (isolate, "failed to run on thread");
}

static void
gum_js_process_run_cb (const GumCpuContext * cpu_context,
gpointer user_data)
{
GumV8RunOnThreadContext * sync_ctx = (GumV8RunOnThreadContext *) user_data;
GumV8RunOnThreadContext * context = (GumV8RunOnThreadContext *) user_data;
auto core = context->core;
auto isolate = core->isolate;
auto ctx = isolate->GetCurrentContext ();

ScriptScope scope (sync_ctx->core->script);
auto isolate = sync_ctx->isolate;
auto context = sync_ctx->context;
ScriptScope scope (core->script);
auto recv = Undefined (isolate);

sync_ctx->ret = sync_ctx->user_func->Call (context, recv, 0, nullptr);
auto result = context->user_func->Call (ctx, recv, 0, nullptr);
(void) result;
}

static void
gum_v8_flush_stalker (GumV8Process * self)
{
GumV8Core * core = self->core;

if (!gum_stalker_garbage_collect (self->stalker))
goto error;

if (self->flush_timer != NULL)
goto error;

{
auto source = g_timeout_source_new (10);
g_source_set_callback (source,
(GSourceFunc) gum_v8_flush_stalker_callback, self, NULL);
self->flush_timer = source;

_gum_v8_core_pin (core);

{
ScriptUnlocker unlocker (core);

g_source_attach (source,
gum_script_scheduler_get_js_context (core->scheduler));
g_source_unref (source);
}
}

return;

error:
g_object_unref (self->stalker);
self->stalker = NULL;
}

static gboolean
gum_v8_flush_stalker_callback (GumV8Process * self)
{
gboolean pending_garbage;

pending_garbage = gum_stalker_garbage_collect (self->stalker);
if (!pending_garbage)
{
GumV8Core * core = self->core;

ScriptScope scope (core->script);
_gum_v8_core_unpin (core);
self->flush_timer = NULL;
}

return pending_garbage;
}
3 changes: 3 additions & 0 deletions bindings/gumjs/gumv8process.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ struct GumV8Process

v8::Global<v8::Object> * main_module_value;
GumV8ExceptionHandler * exception_handler;

GumStalker * stalker;
GSource * flush_timer;
};

G_GNUC_INTERNAL void _gum_v8_process_init (GumV8Process * self,
Expand Down

0 comments on commit 016ac0b

Please sign in to comment.