Skip to content

Commit

Permalink
[WIP] Implement Darwin-specific optimization
Browse files Browse the repository at this point in the history
Co-authored-by: Håvard Sørbø <[email protected]>
  • Loading branch information
oleavr and hsorbo committed Sep 21, 2023
1 parent 35c4e42 commit 4dd9bff
Showing 1 changed file with 170 additions and 57 deletions.
227 changes: 170 additions & 57 deletions gum/gumswiftapiresolver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <capstone.h>
Expand Down Expand Up @@ -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
Expand All @@ -105,6 +113,10 @@ struct _GumModuleMetadata
GArray * functions;
GHashTable * vtables;
GumSwiftApiResolver * resolver;

#ifdef HAVE_DARWIN
GumDarwinModule * darwin_module;
#endif
};

struct _GumFunctionMetadata
Expand Down Expand Up @@ -283,19 +295,28 @@ 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,
gpointer user_data, GError ** error);

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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 = "<unused>";
section.name = details->section_name;
section.address = details->vm_address;
section.size = details->size;

return gum_module_metadata_collect_section (&section, 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)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 4dd9bff

Please sign in to comment.