diff --git a/gum/gumswiftapiresolver.c b/gum/gumswiftapiresolver.c index d3ef04243..85588c04a 100644 --- a/gum/gumswiftapiresolver.c +++ b/gum/gumswiftapiresolver.c @@ -17,7 +17,11 @@ #include "gumswiftapiresolver.h" -#include "gummodulemap.h" +#ifdef HAVE_DARWIN +# include "gumdarwin.h" +#else +# include "gummodulemap.h" +#endif #include "gumprocess.h" #include @@ -90,8 +94,12 @@ struct _GumSwiftApiResolver GRegex * query_pattern; + GHashTable * modules; +#ifdef HAVE_DARWIN + GumDarwinModuleResolver * module_resolver; +#else GumModuleMap * all_modules; - GHashTable * module_by_name; +#endif }; struct _GumModuleMetadata @@ -105,6 +113,10 @@ struct _GumModuleMetadata GArray * functions; GHashTable * vtables; GumSwiftApiResolver * resolver; + +#ifdef HAVE_DARWIN + GumDarwinModule * darwin_module; +#endif }; struct _GumFunctionMetadata @@ -283,6 +295,9 @@ struct _GumMethodOverrideDescriptor static void gum_swift_api_resolver_iface_init (gpointer g_iface, gpointer iface_data); +static GumModuleMetadata * gum_swift_api_resolver_register_module ( + GumSwiftApiResolver * self, const gchar * name, const gchar * path, + GumAddress base_address); static void gum_swift_api_resolver_finalize (GObject * object); static void gum_swift_api_resolver_enumerate_matches ( GumApiResolver * resolver, const gchar * query, GumFoundApiFunc func, @@ -290,12 +305,18 @@ static void gum_swift_api_resolver_enumerate_matches ( static void gum_module_metadata_unref (GumModuleMetadata * module); static GArray * gum_module_metadata_get_functions (GumModuleMetadata * self); +#ifdef HAVE_DARWIN +static gboolean gum_module_metadata_collect_darwin_export ( + const GumDarwinExportDetails * details, gpointer user_data); +static gboolean gum_module_metadata_collect_darwin_section ( + const GumDarwinSectionDetails * details, gpointer user_data); +#endif +static gboolean gum_module_metadata_collect_export ( + const GumExportDetails * details, gpointer user_data); static gboolean gum_module_metadata_collect_section ( const GumSectionDetails * details, gpointer user_data); static void gum_module_metadata_collect_class (GumModuleMetadata * self, const GumTypeContextDescriptor * type); -static gboolean gum_module_metadata_collect_export ( - const GumExportDetails * details, gpointer user_data); static void gum_module_metadata_maybe_ingest_thunk (GumModuleMetadata * self, const gchar * name, GumAddress address); #ifdef HAVE_ARM64 @@ -367,43 +388,88 @@ gum_swift_api_resolver_iface_init (gpointer g_iface, static void gum_swift_api_resolver_init (GumSwiftApiResolver * self) { - GArray * entries; - guint i; - self->query_pattern = g_regex_new ("(.+)!([^\\n\\r\\/]+)(\\/i)?", 0, 0, NULL); - self->all_modules = gum_module_map_new (); - self->module_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + self->modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) gum_module_metadata_unref); - entries = gum_module_map_get_values (self->all_modules); - for (i = 0; i != entries->len; i++) { - GumModuleDetails * d = &g_array_index (entries, GumModuleDetails, i); - GumModuleMetadata * module; - - module = g_slice_new (GumModuleMetadata); - module->ref_count = 2; - module->name = d->name; - module->path = d->path; - module->base_address = d->range->base_address; - module->functions = NULL; - module->vtables = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify) g_ptr_array_unref); - module->resolver = self; - - g_hash_table_insert (self->module_by_name, g_strdup (module->name), module); - g_hash_table_insert (self->module_by_name, g_strdup (module->path), module); +#ifdef HAVE_DARWIN + GHashTableIter iter; + const gchar * name_or_path; + GumDarwinModule * dm; + + self->module_resolver = + gum_darwin_module_resolver_new (mach_task_self (), NULL); + + g_hash_table_iter_init (&iter, self->module_resolver->modules); + + while (g_hash_table_iter_next (&iter, (gpointer *) &name_or_path, + (gpointer *) &dm)) + { + GumModuleMetadata * module; + + if (name_or_path[0] == '/') + continue; + + module = gum_swift_api_resolver_register_module (self, name_or_path, + dm->name, dm->base_address); + module->darwin_module = dm; + } +#else + GArray * entries; + guint i; + + self->all_modules = gum_module_map_new (); + + entries = gum_module_map_get_values (self->all_modules); + for (i = 0; i != entries->len; i++) + { + GumModuleDetails * d = &g_array_index (entries, GumModuleDetails, i); + + gum_swift_api_resolver_register_module (self, d->name, d->path, + d->range->base_address); + } +#endif } } +static GumModuleMetadata * +gum_swift_api_resolver_register_module (GumSwiftApiResolver * self, + const gchar * name, + const gchar * path, + GumAddress base_address) +{ + GumModuleMetadata * module; + + module = g_slice_new0 (GumModuleMetadata); + module->ref_count = 2; + module->name = name; + module->path = path; + module->base_address = base_address; + module->functions = NULL; + module->vtables = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) g_ptr_array_unref); + module->resolver = self; + + g_hash_table_insert (self->modules, g_strdup (name), module); + g_hash_table_insert (self->modules, g_strdup (path), module); + + return module; +} + static void gum_swift_api_resolver_finalize (GObject * object) { GumSwiftApiResolver * self = GUM_SWIFT_API_RESOLVER (object); - g_hash_table_unref (self->module_by_name); +#ifdef HAVE_DARWIN + g_object_unref (self->module_resolver); +#else g_object_unref (self->all_modules); +#endif + + g_hash_table_unref (self->modules); g_regex_unref (self->query_pattern); @@ -471,7 +537,7 @@ gum_swift_api_resolver_enumerate_matches (GumApiResolver * resolver, module_spec = g_pattern_spec_new (module_query); func_spec = g_pattern_spec_new (func_query); - g_hash_table_iter_init (&module_iter, self->module_by_name); + g_hash_table_iter_init (&module_iter, self->modules); seen_modules = g_hash_table_new (NULL, NULL); carry_on = TRUE; @@ -578,15 +644,87 @@ gum_module_metadata_get_functions (GumModuleMetadata * self) self->functions = g_array_new (FALSE, FALSE, sizeof (GumFunctionMetadata)); g_array_set_clear_func (self->functions, (GDestroyNotify) gum_function_metadata_free); - gum_module_enumerate_exports (self->path, - gum_module_metadata_collect_export, self); - gum_module_enumerate_sections (self->path, - gum_module_metadata_collect_section, self); + + { +#ifdef HAVE_DARWIN + gum_darwin_module_enumerate_exports (self->darwin_module, + gum_module_metadata_collect_darwin_export, self); + gum_darwin_module_enumerate_sections (self->darwin_module, + gum_module_metadata_collect_darwin_section, self); +#else + gum_module_enumerate_exports (self->path, + gum_module_metadata_collect_export, self); + gum_module_enumerate_sections (self->path, + gum_module_metadata_collect_section, self); +#endif + } } return self->functions; } +#ifdef HAVE_DARWIN + +static gboolean +gum_module_metadata_collect_darwin_export ( + const GumDarwinExportDetails * details, + gpointer user_data) +{ + GumModuleMetadata * self = user_data; + GumExportDetails export; + + if (!gum_darwin_module_resolver_resolve_export ( + self->resolver->module_resolver, self->darwin_module, + details, &export)) + { + return TRUE; + } + + return gum_module_metadata_collect_export (&export, user_data); +} + +static gboolean +gum_module_metadata_collect_darwin_section ( + const GumDarwinSectionDetails * details, + gpointer user_data) +{ + GumSectionDetails section; + + section.id = ""; + section.name = details->section_name; + section.address = details->vm_address; + section.size = details->size; + + return gum_module_metadata_collect_section (§ion, user_data); +} + +#endif + +static gboolean +gum_module_metadata_collect_export (const GumExportDetails * details, + gpointer user_data) +{ + GumModuleMetadata * self = user_data; + gchar * name; + GumFunctionMetadata func; + + if (details->type != GUM_EXPORT_FUNCTION) + goto skip; + + name = gum_demangle (details->name); + if (name == NULL) + goto skip; + + func.name = name; + func.address = details->address; + g_array_append_val (self->functions, func); + + gum_module_metadata_maybe_ingest_thunk (self, name, func.address); + +skip: + return TRUE; +} + static gboolean gum_module_metadata_collect_section (const GumSectionDetails * details, gpointer user_data) @@ -702,31 +840,6 @@ gum_module_metadata_collect_class (GumModuleMetadata * self, gum_class_clear (&klass); } -static gboolean -gum_module_metadata_collect_export (const GumExportDetails * details, - gpointer user_data) -{ - GumModuleMetadata * self = user_data; - gchar * name; - GumFunctionMetadata func; - - if (details->type != GUM_EXPORT_FUNCTION) - goto skip; - - name = gum_demangle (details->name); - if (name == NULL) - goto skip; - - func.name = name; - func.address = details->address; - g_array_append_val (self->functions, func); - - gum_module_metadata_maybe_ingest_thunk (self, name, func.address); - -skip: - return TRUE; -} - #ifdef HAVE_ARM64 static void