diff --git a/bindings/gumjs/gumquickprocess.c b/bindings/gumjs/gumquickprocess.c index 2fbc9cbb0..37f26954d 100644 --- a/bindings/gumjs/gumquickprocess.c +++ b/bindings/gumjs/gumquickprocess.c @@ -110,6 +110,8 @@ static void gum_quick_exception_handler_free ( static gboolean gum_quick_exception_handler_on_exception ( GumExceptionDetails * details, GumQuickExceptionHandler * handler); +static void gumjs_free_main_module (GumQuickProcess * self); + static const JSCFunctionListEntry gumjs_process_entries[] = { JS_PROP_STRING_DEF ("arch", GUM_SCRIPT_ARCH, JS_PROP_C_W_E), @@ -144,6 +146,7 @@ _gum_quick_process_init (GumQuickProcess * self, self->module = module; self->core = core; + self->main_module = JS_UNINITIALIZED; _gum_quick_core_store_module_data (core, "process", self); @@ -164,17 +167,27 @@ _gum_quick_process_init (GumQuickProcess * self, void _gum_quick_process_flush (GumQuickProcess * self) { - g_clear_pointer (&self->main_module, gum_module_details_free); + gumjs_free_main_module (self); g_clear_pointer (&self->exception_handler, gum_quick_exception_handler_free); } void _gum_quick_process_dispose (GumQuickProcess * self) { - g_clear_pointer (&self->main_module, gum_module_details_free); + gumjs_free_main_module (self); g_clear_pointer (&self->exception_handler, gum_quick_exception_handler_free); } +static void +gumjs_free_main_module (GumQuickProcess * self) +{ + if (JS_IsUninitialized (self->main_module)) + return; + + JS_FreeValue (self->core->ctx, self->main_module); + self->main_module = JS_UNINITIALIZED; +} + void _gum_quick_process_finalize (GumQuickProcess * self) { @@ -192,10 +205,13 @@ GUMJS_DEFINE_GETTER (gumjs_process_get_main_module) self = gumjs_get_parent_module (core); - if (self->main_module == NULL) - self->main_module = gum_process_get_main_module (); + if (JS_IsUninitialized (self->main_module)) + { + const GumModuleDetails * main_details = gum_process_get_main_module (); + self->main_module = _gum_quick_module_new (ctx, main_details, self->module); + } - return _gum_quick_module_new (ctx, self->main_module, self->module); + return JS_DupValue (ctx, self->main_module); } GUMJS_DEFINE_FUNCTION (gumjs_process_get_current_dir) diff --git a/bindings/gumjs/gumquickprocess.h b/bindings/gumjs/gumquickprocess.h index dddd1d2f1..df9df344c 100644 --- a/bindings/gumjs/gumquickprocess.h +++ b/bindings/gumjs/gumquickprocess.h @@ -23,7 +23,7 @@ struct _GumQuickProcess GumQuickCore * core; GumQuickExceptionHandler * exception_handler; - GumModuleDetails * main_module; + JSValue main_module; }; G_GNUC_INTERNAL void _gum_quick_process_init (GumQuickProcess * self, diff --git a/bindings/gumjs/gumv8process.cpp b/bindings/gumjs/gumv8process.cpp index efe171f85..c15ee4d55 100644 --- a/bindings/gumjs/gumv8process.cpp +++ b/bindings/gumjs/gumv8process.cpp @@ -160,14 +160,12 @@ _gum_v8_process_realize (GumV8Process * self) void _gum_v8_process_flush (GumV8Process * self) { - g_clear_pointer (&self->main_module, gum_module_details_free); g_clear_pointer (&self->exception_handler, gum_v8_exception_handler_free); } void _gum_v8_process_dispose (GumV8Process * self) { - g_clear_pointer (&self->main_module, gum_module_details_free); g_clear_pointer (&self->exception_handler, gum_v8_exception_handler_free); } @@ -179,11 +177,11 @@ _gum_v8_process_finalize (GumV8Process * self) GUMJS_DEFINE_GETTER (gumjs_process_get_main_module) { auto self = module; + const GumModuleDetails * main_module; - if (self->main_module == NULL) - self->main_module = gum_process_get_main_module (); + main_module = gum_process_get_main_module (); - info.GetReturnValue ().Set (_gum_v8_module_value_new (self->main_module, + info.GetReturnValue ().Set (_gum_v8_module_value_new (main_module, self->module)); } diff --git a/bindings/gumjs/gumv8process.h b/bindings/gumjs/gumv8process.h index 29a3a6d68..724aea469 100644 --- a/bindings/gumjs/gumv8process.h +++ b/bindings/gumjs/gumv8process.h @@ -10,8 +10,6 @@ #include "gumv8core.h" #include "gumv8module.h" -#include - struct GumV8ExceptionHandler; struct GumV8Process @@ -20,7 +18,6 @@ struct GumV8Process GumV8Core * core; GumV8ExceptionHandler * exception_handler; - GumModuleDetails * main_module; }; G_GNUC_INTERNAL void _gum_v8_process_init (GumV8Process * self, diff --git a/gum/gumprocess.c b/gum/gumprocess.c index f883a21d8..21210a9be 100644 --- a/gum/gumprocess.c +++ b/gum/gumprocess.c @@ -6,6 +6,7 @@ #include "gumprocess-priv.h" +#include "gum-init.h" #include "gumcloak.h" typedef struct _GumEmitThreadsContext GumEmitThreadsContext; @@ -48,6 +49,7 @@ struct _GumResolveSymbolContext static gboolean gum_emit_thread_if_not_cloaked ( const GumThreadDetails * details, gpointer user_data); +static void gum_deinit_main_module (void); static gboolean gum_try_resolve_module_pointer_from ( const GumModuleDetails * details, gpointer user_data); static gboolean gum_emit_module_if_not_cloaked ( @@ -146,6 +148,37 @@ gum_emit_thread_if_not_cloaked (const GumThreadDetails * details, return ctx->func (details, ctx->user_data); } +/** + * gum_process_get_main_module: + * + * Returns the details of the module representing the main executable + * of the process. + */ +const GumModuleDetails * +gum_process_get_main_module (void) +{ + static gsize cached_result = 0; + + if (g_once_init_enter (&cached_result)) + { + GumModuleDetails * result; + + gum_process_enumerate_modules (_gum_process_match_main_module, &result); + + _gum_register_destructor (gum_deinit_main_module); + + g_once_init_leave (&cached_result, GPOINTER_TO_SIZE (result) + 1); + } + + return GSIZE_TO_POINTER (cached_result) - 1; +} + +static void +gum_deinit_main_module (void) +{ + gum_module_details_free ((GumModuleDetails *) gum_process_get_main_module ()); +} + /** * gum_process_resolve_module_pointer: * @ptr: memory location potentially belonging to a module @@ -214,22 +247,6 @@ gum_process_enumerate_modules (GumFoundModuleFunc func, _gum_process_enumerate_modules (gum_emit_module_if_not_cloaked, &ctx); } -/** - * gum_process_get_main_module: - * - * Returns a copy of the details of the module representing the main executable - * of the process. Result must be freed with gum_module_details_free (); - */ -GumModuleDetails * -gum_process_get_main_module (void) -{ - GumModuleDetails * result; - - gum_process_enumerate_modules (_gum_process_match_main_module, &result); - - return result; -} - static gboolean gum_emit_module_if_not_cloaked (const GumModuleDetails * details, gpointer user_data) diff --git a/gum/gumprocess.h b/gum/gumprocess.h index 230f7305a..1b16bd0ce 100644 --- a/gum/gumprocess.h +++ b/gum/gumprocess.h @@ -205,11 +205,11 @@ GUM_API gboolean gum_process_modify_thread (GumThreadId thread_id, GumModifyThreadFunc func, gpointer user_data, GumModifyThreadFlags flags); GUM_API void gum_process_enumerate_threads (GumFoundThreadFunc func, gpointer user_data); +GUM_API const GumModuleDetails * gum_process_get_main_module (void); GUM_API gboolean gum_process_resolve_module_pointer (gconstpointer ptr, gchar ** path, GumMemoryRange * range); GUM_API void gum_process_enumerate_modules (GumFoundModuleFunc func, gpointer user_data); -GUM_API GumModuleDetails * gum_process_get_main_module (void); GUM_API void gum_process_enumerate_ranges (GumPageProtection prot, GumFoundRangeFunc func, gpointer user_data); GUM_API void gum_process_enumerate_malloc_ranges (