From 8438cc6238f82d3cd5f33d5a1cc32e8c7843b78a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Wed, 20 Sep 2023 12:25:26 +0200 Subject: [PATCH] [WIP] Handle extensions --- gum/gumswiftapiresolver.c | 159 +++++++++++++++++++++++++++++++++----- 1 file changed, 138 insertions(+), 21 deletions(-) diff --git a/gum/gumswiftapiresolver.c b/gum/gumswiftapiresolver.c index 676256540..5a1f91a5b 100644 --- a/gum/gumswiftapiresolver.c +++ b/gum/gumswiftapiresolver.c @@ -53,8 +53,8 @@ typedef struct _GumModuleMetadata GumModuleMetadata; typedef struct _GumFunctionMetadata GumFunctionMetadata; -typedef size_t (* GumSwiftDemangle) (const char * name, char * output, - size_t length); +typedef gsize (* GumSwiftDemangle) (const gchar * name, gchar * output, + gsize length); typedef struct _GumClass GumClass; @@ -78,6 +78,7 @@ typedef struct _GumOverrideTableHeader GumOverrideTableHeader; typedef struct _GumMethodOverrideDescriptor GumMethodOverrideDescriptor; typedef gint32 GumRelativeDirectPtr; +typedef gint32 GumRelativeIndirectPtr; typedef gint32 GumRelativeIndirectablePtr; struct _GumSwiftApiResolver @@ -88,8 +89,6 @@ struct _GumSwiftApiResolver GumModuleMap * all_modules; GHashTable * module_by_name; - - GumSwiftDemangle demangle; }; struct _GumModuleMetadata @@ -306,6 +305,8 @@ static gconstpointer gum_resolve_method_implementation ( static gchar * gum_compute_context_descriptor_name ( const GumContextDescriptor * cd); +static void gum_append_demangled_context_name (GString * result, + const gchar * mangled_name); static void gum_skip_generic_type_trailers (gconstpointer * trailer_ptr, const GumTypeContextDescriptor * t); @@ -316,9 +317,13 @@ static void gum_skip_metadata_initialization_trailers ( static gconstpointer gum_resolve_relative_direct_ptr ( const GumRelativeDirectPtr * delta); +static gconstpointer gum_resolve_relative_indirect_ptr ( + const GumRelativeIndirectPtr * delta); static gconstpointer gum_resolve_relative_indirectable_ptr ( const GumRelativeIndirectablePtr * delta); +static gchar * gum_demangle (const gchar * name); + G_DEFINE_TYPE_EXTENDED (GumSwiftApiResolver, gum_swift_api_resolver, G_TYPE_OBJECT, @@ -326,12 +331,17 @@ G_DEFINE_TYPE_EXTENDED (GumSwiftApiResolver, G_IMPLEMENT_INTERFACE (GUM_TYPE_API_RESOLVER, gum_swift_api_resolver_iface_init)) +static GumSwiftDemangle gum_demangle_impl; + static void gum_swift_api_resolver_class_init (GumSwiftApiResolverClass * klass) { GObjectClass * object_class = G_OBJECT_CLASS (klass); object_class->finalize = gum_swift_api_resolver_finalize; + + gum_demangle_impl = GUM_POINTER_TO_FUNCPTR (GumSwiftDemangle, + gum_module_find_export_by_name (NULL, "swift_demangle_getDemangledName")); } static void @@ -374,9 +384,6 @@ gum_swift_api_resolver_init (GumSwiftApiResolver * 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); } - - self->demangle = GUM_POINTER_TO_FUNCPTR (GumSwiftDemangle, - gum_module_find_export_by_name (NULL, "swift_demangle_getDemangledName")); } static void @@ -423,7 +430,7 @@ gum_swift_api_resolver_enumerate_matches (GumApiResolver * resolver, gboolean carry_on; GumModuleMetadata * module; - if (self->demangle == NULL) + if (gum_demangle_impl == NULL) goto unsupported_runtime; g_regex_match (self->query_pattern, query, 0, &query_info); @@ -689,22 +696,21 @@ gum_module_metadata_collect_export (const GumExportDetails * details, gpointer user_data) { GumModuleMetadata * self = user_data; - gchar name[512]; - size_t len; + gchar * name; GumFunctionMetadata func; if (details->type != GUM_EXPORT_FUNCTION) goto skip; - len = self->resolver->demangle (details->name, name, sizeof (name)); - if (len == 0) + name = gum_demangle (details->name); + if (name == NULL) goto skip; - func.name = g_strdup (name); + func.name = name; func.address = details->address; g_array_append_val (self->functions, func); - gum_module_metadata_maybe_ingest_thunk (self, func.name, func.address); + gum_module_metadata_maybe_ingest_thunk (self, name, func.address); skip: return TRUE; @@ -1030,11 +1036,12 @@ gum_compute_context_descriptor_name (const GumContextDescriptor * cd) { GString * name; const GumContextDescriptor * cur; + gboolean reached_toplevel; name = g_string_sized_new (16); - for (cur = cd; - cur != NULL; + for (cur = cd, reached_toplevel = FALSE; + cur != NULL && !reached_toplevel; cur = gum_resolve_relative_indirectable_ptr (&cur->parent)) { GumContextDescriptorKind kind = GUM_DESCRIPTOR_FLAGS_KIND (cur->flags); @@ -1050,18 +1057,37 @@ gum_compute_context_descriptor_name (const GumContextDescriptor * cd) g_string_prepend (name, gum_resolve_relative_direct_ptr (&m->name)); break; } -#if 0 case GUM_CONTEXT_DESCRIPTOR_EXTENSION: { const GumExtensionContextDescriptor * e = (const GumExtensionContextDescriptor *) cur; - if (name->len != 0) - g_string_prepend_c (name, '.'); - g_string_prepend (name, + GString * part; + gchar * parent; + + part = g_string_sized_new (64); + g_string_append (part, "(extension in "); + + parent = gum_compute_context_descriptor_name ( + gum_resolve_relative_indirectable_ptr (&cur->parent)); + g_string_append (part, parent); + g_free (parent); + + g_string_append (part, "):"); + + gum_append_demangled_context_name (part, gum_resolve_relative_direct_ptr (&e->extended_context)); + + if (name->len != 0) + g_string_append_c (part, '.'); + + g_string_prepend (name, part->str); + + g_string_free (part, TRUE); + + reached_toplevel = TRUE; + break; } -#endif case GUM_CONTEXT_DESCRIPTOR_ANONYMOUS: break; default: @@ -1083,6 +1109,65 @@ gum_compute_context_descriptor_name (const GumContextDescriptor * cd) return g_string_free (name, FALSE); } +static void +gum_append_demangled_context_name (GString * result, + const gchar * mangled_name) +{ + switch (mangled_name[0]) + { + case '\x01': + { + const GumContextDescriptor * cd; + gchar * name; + + cd = gum_resolve_relative_direct_ptr ( + (const GumRelativeDirectPtr *) (mangled_name + 1)); + name = gum_compute_context_descriptor_name (cd); + g_string_append (result, name); + g_free (name); + + break; + } + case '\x02': + { + const GumContextDescriptor * cd; + gchar * name; + + cd = gum_resolve_relative_indirect_ptr ( + (const GumRelativeIndirectPtr *) (mangled_name + 1)); + name = gum_compute_context_descriptor_name (cd); + g_string_append (result, name); + g_free (name); + + break; + } + default: + { + GString * buf; + gchar * name; + + buf = g_string_sized_new (32); + g_string_append (buf, "$s"); + g_string_append (buf, mangled_name); + + name = gum_demangle (buf->str); + if (name != NULL) + { + g_string_append (result, name); + g_free (name); + } + else + { + g_string_append (result, ""); + } + + g_string_free (buf, TRUE); + + break; + } + } +} + static void gum_skip_generic_type_trailers (gconstpointer * trailer_ptr, const GumTypeContextDescriptor * t) @@ -1171,6 +1256,17 @@ gum_resolve_relative_direct_ptr (const GumRelativeDirectPtr * delta) return (const guint8 *) delta + val; } +static gconstpointer +gum_resolve_relative_indirect_ptr (const GumRelativeIndirectPtr * delta) +{ + GumRelativeIndirectablePtr val = *delta; + gconstpointer * target; + + target = (gconstpointer *) ((const guint8 *) delta + val); + + return *target; +} + static gconstpointer gum_resolve_relative_indirectable_ptr (const GumRelativeIndirectablePtr * delta) { @@ -1185,4 +1281,25 @@ gum_resolve_relative_indirectable_ptr (const GumRelativeIndirectablePtr * delta) return *target; } +static gchar * +gum_demangle (const gchar * name) +{ + gchar buf[512]; + gsize n, capacity; + gchar * dbuf; + + n = gum_demangle_impl (name, buf, sizeof (buf)); + if (n == 0) + return NULL; + + if (n < sizeof (buf)) + return g_strdup (buf); + + capacity = n + 1; + dbuf = g_malloc (capacity); + gum_demangle_impl (name, dbuf, capacity); + + return dbuf; +} + #endif