Skip to content

Commit

Permalink
[WIP] Wire up some more
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 19, 2023
1 parent 2cd478a commit 38890d6
Showing 1 changed file with 159 additions and 33 deletions.
192 changes: 159 additions & 33 deletions gum/gumswiftapiresolver.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
#define GUM_GENERIC_DESCRIPTOR_FLAGS_HAS_TYPE_PACKS(flags) \
((flags & GUM_GENERIC_DESCRIPTOR_HAS_TYPE_PACKS) != 0)

#define GUM_METHOD_DESCRIPTOR_IS_ASYNC(desc) \
(((desc)->flags & GUM_METHOD_ASYNC) != 0)

#define GUM_ALIGN(ptr, type) \
GUM_ALIGN_POINTER (type *, ptr, G_ALIGNOF (type))

Expand Down Expand Up @@ -96,6 +99,7 @@ struct _GumModuleMetadata

GumAddress base_address;
GArray * functions;
GHashTable * vtables;
GumSwiftApiResolver * resolver;
};

Expand Down Expand Up @@ -239,6 +243,11 @@ struct _GumMethodDescriptor
GumRelativeDirectPtr impl;
};

enum _GumMethodDescriptorFlags
{
GUM_METHOD_ASYNC = (1 << 6),
};

struct _GumOverrideTableHeader
{
guint32 num_entries;
Expand Down Expand Up @@ -269,11 +278,14 @@ 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 void gum_module_metadata_collect_function (GumModuleMetadata * self,
const gchar * label, gconstpointer impl,
static void gum_module_metadata_collect_method (GumModuleMetadata * self,
const GumMethodDescriptor * method, gint vtable_index,
const GumTypeContextDescriptor * holder);
static gboolean gum_module_metadata_collect_export (
const GumExportDetails * details, gpointer user_data);
static gchar * gum_extract_class_name (const gchar * full_name);
static const gchar * gum_find_character_backwards (const gchar * starting_point,
char needle, const gchar * start);

static void gum_function_metadata_free (GumFunctionMetadata * function);

Expand Down Expand Up @@ -339,6 +351,8 @@ gum_swift_api_resolver_init (GumSwiftApiResolver * self)
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, g_free);
module->resolver = self;

g_hash_table_insert (self->module_by_name, g_strdup (module->name), module);
Expand Down Expand Up @@ -512,6 +526,9 @@ gum_module_metadata_unref (GumModuleMetadata * module)
module->ref_count--;
if (module->ref_count == 0)
{
if (module->vtables != NULL)
g_hash_table_unref (module->vtables);

if (module->functions != NULL)
g_array_unref (module->functions);

Expand All @@ -527,10 +544,10 @@ 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_sections (self->path,
gum_module_metadata_collect_section, self);
gum_module_enumerate_exports (self->path,
gum_module_metadata_collect_export, self);
gum_module_enumerate_sections (self->path,
gum_module_metadata_collect_section, self);
}

return self->functions;
Expand Down Expand Up @@ -599,22 +616,29 @@ gum_module_metadata_collect_class (GumModuleMetadata * self,
methods = GUM_ALIGN ((const GumMethodDescriptor *) (vth + 1),
GumMethodDescriptor);

#if 0
g_printerr ("\n=== %s\n",
(const char *) gum_resolve_relative_direct_ptr (&type->name));
#endif

for (i = 0; i != vth->vtable_size; i++)
{
const GumMethodDescriptor * method = &methods[i];
gchar * label;

label = g_strdup_printf ("vtable[%u]", i);

gum_module_metadata_collect_function (self, label,
gum_resolve_relative_direct_ptr (&method->impl), type);
#if 0
g_printerr ("\tvtable[%u]: flags=0x%08x impl=%p\n",
i,
method->flags,
gum_resolve_relative_direct_ptr (&method->impl));
#endif

g_free (label);
gum_module_metadata_collect_method (self, method, i, type);
}

trailer = methods + vth->vtable_size;
}

#if 0
if (GUM_TYPE_FLAGS_CLASS_HAS_OVERRIDE_TABLE (type_flags))
{
const GumOverrideTableHeader * oth;
Expand All @@ -628,33 +652,38 @@ gum_module_metadata_collect_class (GumModuleMetadata * self,
for (i = 0; i != oth->num_entries; i++)
{
const GumMethodOverrideDescriptor * method = &methods[i];
gchar * label;

label = g_strdup_printf ("overrides[%u]", i);

gum_module_metadata_collect_function (self, label,
gum_resolve_relative_direct_ptr (&method->impl), type);

g_free (label);
gum_module_metadata_collect_function (self,
gum_resolve_relative_direct_ptr (&method->impl), -1, 0, type);
}

trailer = methods + oth->num_entries;
}
#endif
}

static void
gum_module_metadata_collect_function (GumModuleMetadata * self,
const gchar * label,
gconstpointer impl,
const GumTypeContextDescriptor * holder)
gum_module_metadata_collect_method (GumModuleMetadata * self,
const GumMethodDescriptor * method,
gint vtable_index,
const GumTypeContextDescriptor * holder)
{
gconstpointer impl;
GString * scope;
GumFunctionMetadata func;
const GumContextDescriptor * cur;
GPtrArray * vtable;

impl = gum_resolve_relative_direct_ptr (&method->impl);
if (impl == NULL)
return;

if (GUM_METHOD_DESCRIPTOR_IS_ASYNC (method))
{
impl = gum_resolve_relative_direct_ptr (
(const GumRelativeDirectPtr *) impl);
}

scope = g_string_sized_new (16);

for (cur = gum_resolve_relative_indirectable_ptr (&holder->context.parent);
Expand Down Expand Up @@ -704,12 +733,35 @@ gum_module_metadata_collect_function (GumModuleMetadata * self,

g_string_append (scope, gum_resolve_relative_direct_ptr (&holder->name));

func.name = g_strdup_printf (
"%s.%s(%s+0x%" G_GINT64_MODIFIER "x)",
scope->str,
label,
self->name,
GUM_ADDRESS (impl) - self->base_address);
func.name = NULL;

if (vtable_index != -1)
{
vtable = g_hash_table_lookup (self->vtables, scope->str);
if (vtable != NULL)
{
if (vtable_index < vtable->len)
{
func.name = g_strdup (g_ptr_array_index (vtable, vtable_index));
#if 0
if (func.name != NULL)
g_printerr ("\t\t<matched with: %s>\n", func.name);
#endif
}
}
}

if (func.name == NULL)
{
func.name = g_strdup_printf (
"%s.%s[%d](%s+0x%" G_GINT64_MODIFIER "x)",
scope->str,
(vtable_index != -1) ? "vtable" : "overrides",
vtable_index,
self->name,
GUM_ADDRESS (impl) - self->base_address);
}

func.address = GUM_ADDRESS (impl);

g_array_append_val (self->functions, func);
Expand All @@ -721,21 +773,21 @@ static gboolean
gum_module_metadata_collect_export (const GumExportDetails * details,
gpointer user_data)
{
GumModuleMetadata * module = user_data;
GumModuleMetadata * self = user_data;
gchar name[512];
size_t len;
GumFunctionMetadata func;

if (details->type != GUM_EXPORT_FUNCTION)
return TRUE;

len = module->resolver->demangle (details->name, name, sizeof (name));
len = self->resolver->demangle (details->name, name, sizeof (name));
if (len == 0)
return TRUE;

func.name = g_strdup (name);
func.address = details->address;
g_array_append_val (module->functions, func);
g_array_append_val (self->functions, func);

if (g_str_has_prefix (func.name, "dispatch thunk of "))
{
Expand All @@ -757,7 +809,15 @@ gum_module_metadata_collect_export (const GumExportDetails * details,

insn = cs_malloc (capstone);

g_printerr ("\n=== %s\n", func.name + strlen ("dispatch thunk of "));
gboolean should_log = FALSE; //strstr (func.name, "CoreDevice.RemoteDevice") != NULL;

if (should_log)
{
g_printerr ("\n=== %s (%s+0x%" G_GINT64_MODIFIER "x)\n",
func.name + strlen ("dispatch thunk of "),
self->name,
details->address - self->base_address);
}

vtable_index = -1;
end_of_block = FALSE;
Expand Down Expand Up @@ -818,17 +878,83 @@ gum_module_metadata_collect_export (const GumExportDetails * details,

if (vtable_index != -1)
{
g_printerr (" => SUCCESS, vtable_index=%d\n", vtable_index);
const gchar * full_name;
gchar * class_name;
GPtrArray * vtable;

full_name = func.name + strlen ("dispatch thunk of ");
class_name = gum_extract_class_name (full_name);

vtable = g_hash_table_lookup (self->vtables, class_name);
if (vtable == NULL)
{
vtable = g_ptr_array_new_full (64, g_free);
g_hash_table_insert (self->vtables, g_steal_pointer (&class_name), vtable);
}

if (vtable_index >= vtable->len)
g_ptr_array_set_size (vtable, vtable_index + 1);
g_free (g_ptr_array_index (vtable, vtable_index));
g_ptr_array_index (vtable, vtable_index) = g_strdup (full_name);

//g_printerr (" => SUCCESS, class_name=\"%s\", vtable_index=%d\n", class_name, vtable_index);

g_free (class_name);
}
else
{
g_printerr (" => FAILURE, vtable_index not determined\n");
if (should_log)
g_printerr (" => FAILURE, vtable_index not determined\n");
}
}

return TRUE;
}

static gchar *
gum_extract_class_name (const gchar * full_name)
{
const gchar * ch;

ch = strstr (full_name, " : ");
if (ch != NULL)
{
ch = gum_find_character_backwards (ch, '.', full_name);
if (ch == NULL)
return NULL;
}
else
{
ch = strchr (full_name, '(');
if (ch == NULL)
return NULL;
}

ch = gum_find_character_backwards (ch, '.', full_name);
if (ch == NULL)
return NULL;

return g_strndup (full_name, ch - full_name);
}

static const gchar *
gum_find_character_backwards (const gchar * starting_point,
char needle,
const gchar * start)
{
const gchar * ch = starting_point;

do
{
ch--;
if (*ch == needle)
return ch;
}
while (ch != start);

return NULL;
}

static void
gum_function_metadata_free (GumFunctionMetadata * function)
{
Expand Down

0 comments on commit 38890d6

Please sign in to comment.