+ }
+
+ g_string_append_printf (s, "%s_", label);
+}
+
+static char *
+sanitize_mangled_string (const char *input)
+{
+ GString *s = g_string_new ("");
+
+ for (int i=0; input [i] != '\0'; i++) {
+ char c = input [i];
+ switch (c) {
+ case '.':
+ g_string_append (s, "_dot_");
+ break;
+ case ' ':
+ g_string_append (s, "_");
+ break;
+ case '`':
+ g_string_append (s, "_bt_");
+ break;
+ case '<':
+ g_string_append (s, "_le_");
+ break;
+ case '>':
+ g_string_append (s, "_gt_");
+ break;
+ case '/':
+ g_string_append (s, "_sl_");
+ break;
+ case '[':
+ g_string_append (s, "_lbrack_");
+ break;
+ case ']':
+ g_string_append (s, "_rbrack_");
+ break;
+ case '(':
+ g_string_append (s, "_lparen_");
+ break;
+ case '-':
+ g_string_append (s, "_dash_");
+ break;
+ case ')':
+ g_string_append (s, "_rparen_");
+ break;
+ case ',':
+ g_string_append (s, "_comma_");
+ break;
+ default:
+ g_string_append_c (s, c);
+ }
+ }
+
+ return g_string_free (s, FALSE);
+}
+
+static gboolean
+append_mangled_klass (GString *s, MonoClass *klass)
+{
+ char *klass_desc = mono_class_full_name (klass);
+ g_string_append_printf (s, "_%s_%s_", klass->name_space, klass_desc);
+ g_free (klass_desc);
+
+ // Success
+ return TRUE;
+}
+
+static gboolean
+append_mangled_method (GString *s, MonoMethod *method);
+
+static gboolean
+append_mangled_wrapper (GString *s, MonoMethod *method)
+{
+ gboolean success = TRUE;
+ WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+ g_string_append_printf (s, "wrapper_");
+
+ append_mangled_wrapper_type (s, method->wrapper_type);
+
+ switch (method->wrapper_type) {
+ case MONO_WRAPPER_REMOTING_INVOKE:
+ case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
+ case MONO_WRAPPER_XDOMAIN_INVOKE: {
+ MonoMethod *m = mono_marshal_method_from_wrapper (method);
+ g_assert (m);
+ success = success && append_mangled_method (s, m);
+ break;
+ }
+ case MONO_WRAPPER_PROXY_ISINST:
+ case MONO_WRAPPER_LDFLD:
+ case MONO_WRAPPER_LDFLDA:
+ case MONO_WRAPPER_STFLD: {
+ g_assert (info);
+ success = success && append_mangled_klass (s, info->d.proxy.klass);
+ break;
+ }
+ case MONO_WRAPPER_ALLOC: {
+ /* The GC name is saved once in MonoAotFileInfo */
+ g_assert (info->d.alloc.alloc_type != -1);
+ g_string_append_printf (s, "%d_", info->d.alloc.alloc_type);
+ // SlowAlloc, etc
+ g_string_append_printf (s, "%s_", method->name);
+ break;
+ }
+ case MONO_WRAPPER_WRITE_BARRIER: {
+ break;
+ }
+ case MONO_WRAPPER_STELEMREF: {
+ append_mangled_wrapper_subtype (s, info->subtype);
+ if (info->subtype == WRAPPER_SUBTYPE_VIRTUAL_STELEMREF)
+ g_string_append_printf (s, "%d", info->d.virtual_stelemref.kind);
+ break;
+ }
+ case MONO_WRAPPER_UNKNOWN: {
+ append_mangled_wrapper_subtype (s, info->subtype);
+ if (info->subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE ||
+ info->subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR)
+ success = success && append_mangled_klass (s, method->klass);
+ else if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
+ success = success && append_mangled_method (s, info->d.synchronized_inner.method);
+ else if (info->subtype == WRAPPER_SUBTYPE_ARRAY_ACCESSOR)
+ success = success && append_mangled_method (s, info->d.array_accessor.method);
+ else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG)
+ append_mangled_signature (s, info->d.gsharedvt.sig);
+ else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)
+ append_mangled_signature (s, info->d.gsharedvt.sig);
+ break;
+ }
+ case MONO_WRAPPER_MANAGED_TO_NATIVE: {
+ append_mangled_wrapper_subtype (s, info->subtype);
+ if (info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
+ g_string_append_printf (s, "%s", method->name);
+ } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) {
+ success = success && append_mangled_method (s, info->d.managed_to_native.method);
+ } else {
+ g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE);
+ success = success && append_mangled_method (s, info->d.managed_to_native.method);
+ }
+ break;
+ }
+ case MONO_WRAPPER_SYNCHRONIZED: {
+ MonoMethod *m;
+
+ m = mono_marshal_method_from_wrapper (method);
+ g_assert (m);
+ g_assert (m != method);
+ success = success && append_mangled_method (s, m);
+ break;
+ }
+ case MONO_WRAPPER_MANAGED_TO_MANAGED: {
+ append_mangled_wrapper_subtype (s, info->subtype);
+
+ if (info->subtype == WRAPPER_SUBTYPE_ELEMENT_ADDR) {
+ g_string_append_printf (s, "%d_", info->d.element_addr.rank);
+ g_string_append_printf (s, "%d_", info->d.element_addr.elem_size);
+ } else if (info->subtype == WRAPPER_SUBTYPE_STRING_CTOR) {
+ success = success && append_mangled_method (s, info->d.string_ctor.method);
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ }
+ case MONO_WRAPPER_CASTCLASS: {
+ append_mangled_wrapper_subtype (s, info->subtype);
+ break;
+ }
+ case MONO_WRAPPER_RUNTIME_INVOKE: {
+ append_mangled_wrapper_subtype (s, info->subtype);
+ if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT || info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL)
+ success = success && append_mangled_method (s, info->d.runtime_invoke.method);
+ else if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL)
+ success = success && append_mangled_signature (s, info->d.runtime_invoke.sig);
+ break;
+ }
+ case MONO_WRAPPER_DELEGATE_INVOKE:
+ case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
+ case MONO_WRAPPER_DELEGATE_END_INVOKE: {
+ if (method->is_inflated) {
+ /* These wrappers are identified by their class */
+ g_string_append_printf (s, "i_");
+ success = success && append_mangled_klass (s, method->klass);
+ } else {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+ g_string_append_printf (s, "u_");
+ if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
+ append_mangled_wrapper_subtype (s, info->subtype);
+ g_string_append_printf (s, "u_sigstart");
+ }