2009-08-25 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / aot-compiler.c
index 49ae040dcaf60d03783ab10308d1e11cf242a1ca..58d9bea5d9175e66f733004e136e42e018e6ccb1 100644 (file)
@@ -99,6 +99,7 @@ typedef struct MonoAotOptions {
        int nthreads;
        int ntrampolines;
        gboolean print_skipped_methods;
+       char *tool_prefix;
 } MonoAotOptions;
 
 typedef struct MonoAotStats {
@@ -1001,15 +1002,15 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
 
        /* The IMT method is in v5 */
 
-       /* Only IP is available, but we need at least two free registers */
-       ARM_PUSH1 (code, ARMREG_R1);
+       /* Need at least two free registers, plus a slot for storing the pc */
+       ARM_PUSH (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_R2));
        labels [0] = code;
        /* Load the parameter from the GOT */
-       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
-       ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
+       ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R0);
 
        labels [1] = code;
-       ARM_LDR_IMM (code, ARMREG_R1, ARMREG_IP, 0);
+       ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R0, 0);
        ARM_CMP_REG_REG (code, ARMREG_R1, ARMREG_V5);
        labels [2] = code;
        ARM_B_COND (code, ARMCOND_EQ, 0);
@@ -1020,16 +1021,19 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
        ARM_B_COND (code, ARMCOND_EQ, 0);
 
        /* Loop footer */
-       ARM_ADD_REG_IMM8 (code, ARMREG_IP, ARMREG_IP, sizeof (gpointer) * 2);
+       ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (gpointer) * 2);
        labels [4] = code;
        ARM_B (code, 0);
        arm_patch (labels [4], labels [1]);
 
        /* Match */
        arm_patch (labels [2], code);
-       ARM_POP1 (code, ARMREG_R1);
-       ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 4);
-       ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, 0);
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 0);
+       /* Save it to the third stack slot */
+       ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
+       /* Restore the registers and branch */
+       ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
 
        /* No match */
        arm_patch (labels [3], code);
@@ -1037,7 +1041,7 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
 
        /* Fixup offset */
        code2 = labels [0];
-       ARM_LDR_IMM (code2, ARMREG_IP, ARMREG_PC, (code - (labels [0] + 8)));
+       ARM_LDR_IMM (code2, ARMREG_R0, ARMREG_PC, (code - (labels [0] + 8)));
 
        emit_bytes (acfg, buf, code - buf);
        emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + (code - (labels [0] + 8)) - 4);
@@ -2035,6 +2039,14 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
                add_extra_method (acfg, method);
        }
 
+       if (klass->delegate) {
+               method = mono_get_delegate_invoke (klass);
+
+               method = mono_marshal_get_delegate_invoke (method, NULL);
+
+               add_method (acfg, method);
+       }
+
        /* 
         * For ICollection<T>, where T is a vtype, add instances of the helper methods
         * in Array, since a T[] could be cast to ICollection<T>.
@@ -2076,6 +2088,18 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
        }
 }
 
+static void
+add_array_wrappers (MonoAotCompile *acfg, MonoClass *klass)
+{
+       int i;
+
+       mono_class_setup_methods (klass);
+       for (i = 0; i < klass->method.count; ++i) {
+               if (klass->methods [i]->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED)
+                       add_extra_method (acfg, klass->methods [i]);
+       }
+}
+
 /*
  * add_generic_instances:
  *
@@ -2144,6 +2168,157 @@ add_generic_instances (MonoAotCompile *acfg)
                                        add_generic_class (acfg, mono_class_from_mono_type (header->locals [j]));
                }
        }
+
+       if (acfg->image == mono_defaults.corlib) {
+               /* Add GenericComparer<T> instances for primitive types for Enum.ToString () */
+               MonoClass *klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericComparer`1");
+
+               if (klass) {
+                       MonoGenericContext ctx;
+                       MonoType *args [16];
+
+                       memset (&ctx, 0, sizeof (ctx));
+
+                       args [0] = &mono_defaults.byte_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.sbyte_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.int16_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.uint16_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.int32_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.uint32_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.int64_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.uint64_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+               }
+
+               /* Add GenericEqualityComparer<T> instances for primitive types */
+               klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1");
+
+               if (klass) {
+                       MonoGenericContext ctx;
+                       MonoType *args [16];
+
+                       memset (&ctx, 0, sizeof (ctx));
+
+                       args [0] = &mono_defaults.byte_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.sbyte_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.int16_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.uint16_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.int32_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.uint32_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.int64_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+                       args [0] = &mono_defaults.uint64_class->byval_arg;
+                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+                       add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+               }
+
+               /* Emit the array wrapper methods for arrays of primitive types */
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.byte_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.sbyte_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int16_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.uint16_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int32_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.uint32_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int64_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.single_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.double_class, 1));
+               /* These are not handled by generic sharing */
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.object_class, 1));
+               add_array_wrappers (acfg, mono_array_class_get (mono_defaults.string_class, 1));
+
+               /* Add instances of Array.GetGenericValueImpl */
+               {
+                       MonoGenericContext ctx;
+                       MonoType *args [16];
+                       MonoMethod *method;
+
+                       memset (&ctx, 0, sizeof (ctx));
+
+                       /* 
+                        * managed-to-native wrappers are not shared, so have to generate 
+                        * these for ref types too.
+                        */
+                       klass = mono_array_class_get (mono_defaults.int_class, 1)->parent;
+                       method = mono_class_get_method_from_name (klass, "GetGenericValueImpl", 2);
+
+                       if (method) {
+                               /* String */
+                               args [0] = &mono_defaults.string_class->byval_arg;
+                               ctx.method_inst = mono_metadata_get_generic_inst (1, args);
+                               add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (method, &ctx), TRUE, TRUE));
+                       }
+               }
+       }
+}
+
+/*
+ * is_direct_callable:
+ *
+ *   Return whenever the method identified by JI is directly callable without 
+ * going through the PLT.
+ */
+static gboolean
+is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patch_info)
+{
+       if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
+               MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
+               if (callee_cfg) {
+                       gboolean direct_callable = TRUE;
+
+                       if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+                               direct_callable = FALSE;
+                       if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
+                               // FIXME: Maybe call the wrapper directly ?
+                               direct_callable = FALSE;
+
+                       if (direct_callable)
+                               return TRUE;
+               }
+       }
+
+       return FALSE;
 }
 
 /*
@@ -2210,23 +2385,14 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                 * the same assembly and requires no initialization.
                                 */
                                direct_call = FALSE;
-                               if (!got_only && (patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == method->klass->image)) {
-                                       MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
-                                       if (callee_cfg) {
-                                               gboolean direct_callable = TRUE;
-
-                                               if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
-                                                       direct_callable = FALSE;
-                                               if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED)
-                                                       // FIXME: Maybe call the wrapper directly ?
-                                                       direct_callable = FALSE;
-                                               if (direct_callable) {
-                                                       //printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE));
-                                                       direct_call = TRUE;
-                                                       sprintf (direct_call_target, "%sm_%x", acfg->temp_prefix, get_method_index (acfg, callee_cfg->orig_method));
-                                                       patch_info->type = MONO_PATCH_INFO_NONE;
-                                                       acfg->stats.direct_calls ++;
-                                               }
+                               if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
+                                       if (!got_only && is_direct_callable (acfg, method, patch_info)) {
+                                               MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
+                                               //printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE));
+                                               direct_call = TRUE;
+                                               sprintf (direct_call_target, "%sm_%x", acfg->temp_prefix, get_method_index (acfg, callee_cfg->orig_method));
+                                               patch_info->type = MONO_PATCH_INFO_NONE;
+                                               acfg->stats.direct_calls ++;
                                        }
 
                                        acfg->stats.all_calls ++;
@@ -2283,6 +2449,21 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
        }
 }
 
+/*
+ * sanitize_symbol:
+ *
+ *   Modify SYMBOL so it only includes characters permissible in symbols.
+ */
+static void
+sanitize_symbol (char *symbol)
+{
+       int i, len = strlen (symbol);
+
+       for (i = 0; i < len; ++i)
+               if (!isalnum (symbol [i]) && (symbol [i] != '_'))
+                       symbol [i] = '_';
+}
+
 static char*
 get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache)
 {
@@ -2711,7 +2892,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
        use_unwind_ops = cfg->unwind_ops != NULL;
 #endif
 
-       flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0);
+       flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0);
 
        encode_value (jinfo->code_size, p, &p);
        encode_value (flags, p, &p);
@@ -2732,19 +2913,28 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
        }
 
        /* Exception table */
-       if (header->num_clauses) {
-               for (k = 0; k < header->num_clauses; ++k) {
-                       MonoJitExceptionInfo *ei = &jinfo->clauses [k];
+       if (jinfo->num_clauses)
+               encode_value (jinfo->num_clauses, p, &p);
 
-                       encode_value (ei->exvar_offset, p, &p);
+       for (k = 0; k < jinfo->num_clauses; ++k) {
+               MonoJitExceptionInfo *ei = &jinfo->clauses [k];
 
-                       if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
-                               encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
+               encode_value (ei->exvar_offset, p, &p);
 
-                       encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
-                       encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
-                       encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
+               if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
+                       encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
+               else {
+                       if (ei->data.catch_class) {
+                               encode_value (1, p, &p);
+                               encode_klass_ref (acfg, ei->data.catch_class, p, &p);
+                       } else {
+                               encode_value (0, p, &p);
+                       }
                }
+
+               encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
+               encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
+               encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
        }
 
        if (jinfo->has_generic_jit_info) {
@@ -2896,13 +3086,45 @@ emit_plt (MonoAotCompile *acfg)
                emit_label (acfg, label);
 
                if (acfg->aot_opts.write_symbols) {
-                       MonoJumpInfo *patch_info = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
+                       MonoJumpInfo *ji = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
+                       char *debug_sym = NULL;
 
-                       if (patch_info && patch_info->type == MONO_PATCH_INFO_METHOD) {
-                               char *debug_sym = get_debug_sym (patch_info->data.method, "plt_", cache);
+                       if (ji) {
+                               switch (ji->type) {
+                               case MONO_PATCH_INFO_METHOD:
+                                       debug_sym = get_debug_sym (ji->data.method, "plt_", cache);
+                                       break;
+                               case MONO_PATCH_INFO_INTERNAL_METHOD:
+                                       debug_sym = g_strdup_printf ("plt__jit_icall_%s", ji->data.name);
+                                       break;
+                               case MONO_PATCH_INFO_CLASS_INIT:
+                                       debug_sym = g_strdup_printf ("plt__class_init_%s", mono_type_get_name (&ji->data.klass->byval_arg));
+                                       sanitize_symbol (debug_sym);
+                                       break;
+                               case MONO_PATCH_INFO_RGCTX_FETCH:
+                                       debug_sym = g_strdup_printf ("plt__rgctx_fetch_%d", acfg->label_generator ++);
+                                       break;
+                               case MONO_PATCH_INFO_ICALL_ADDR: {
+                                       char *s = get_debug_sym (ji->data.method, "", cache);
+                                       
+                                       debug_sym = g_strdup_printf ("plt__icall_native_%s", s);
+                                       g_free (s);
+                                       break;
+                               }
+                               case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+                                       debug_sym = g_strdup_printf ("plt__jit_icall_native_%s", ji->data.name);
+                                       break;
+                               case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
+                                       debug_sym = g_strdup_printf ("plt__generic_class_init");
+                                       break;
+                               default:
+                                       break;
+                               }
 
-                               emit_local_symbol (acfg, debug_sym, NULL, TRUE);
-                               emit_label (acfg, debug_sym);
+                               if (debug_sym) {
+                                       emit_local_symbol (acfg, debug_sym, NULL, TRUE);
+                                       emit_label (acfg, debug_sym);
+                               }
                        }
                }
 
@@ -3224,6 +3446,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->nodebug = TRUE;
                } else if (str_begins_with (arg, "ntrampolines=")) {
                        opts->ntrampolines = atoi (arg + strlen ("ntrampolines="));
+               } else if (str_begins_with (arg, "tool-prefix=")) {
+                       opts->tool_prefix = g_strdup (arg + strlen ("tool-prefix="));
                } else {
                        fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
                        exit (1);
@@ -3482,6 +3706,13 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                        }
                        break;
                }
+               case MONO_PATCH_INFO_VTABLE: {
+                       MonoClass *klass = patch_info->data.klass;
+
+                       if (klass->generic_class && !mono_generic_context_is_sharable (&klass->generic_class->context, FALSE))
+                               add_generic_class (acfg, klass);
+                       break;
+               }
                default:
                        break;
                }
@@ -4496,7 +4727,7 @@ emit_got (MonoAotCompile *acfg)
        char symbol [256];
 
        /* Don't make GOT global so accesses to it don't need relocations */
-       sprintf (symbol, acfg->got_symbol);
+       sprintf (symbol, "%s", acfg->got_symbol);
        emit_section_change (acfg, ".bss", 0);
        emit_alignment (acfg, 8);
        emit_local_symbol (acfg, symbol, "got_end", FALSE);
@@ -4635,6 +4866,7 @@ emit_file_info (MonoAotCompile *acfg)
        emit_int32 (acfg, acfg->plt_got_offset_base);
        emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
        emit_int32 (acfg, acfg->plt_offset);
+       emit_int32 (acfg, acfg->nmethods);
 
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                emit_int32 (acfg, acfg->num_trampolines [i]);
@@ -4771,6 +5003,7 @@ compile_asm (MonoAotCompile *acfg)
 {
        char *command, *objfile;
        char *outfile_name, *tmp_outfile_name;
+       const char *tool_prefix = acfg->aot_opts.tool_prefix ? acfg->aot_opts.tool_prefix : "";
 
 #if defined(TARGET_AMD64)
 #define AS_OPTIONS "--64"
@@ -4802,7 +5035,7 @@ compile_asm (MonoAotCompile *acfg)
        } else {
                objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
        }
-       command = g_strdup_printf ("as %s %s -o %s", AS_OPTIONS, acfg->tmpfname, objfile);
+       command = g_strdup_printf ("%sas %s %s -o %s", tool_prefix, AS_OPTIONS, acfg->tmpfname, objfile);
        printf ("Executing the native assembler: %s\n", command);
        if (system (command) != 0) {
                g_free (command);
@@ -4833,7 +5066,7 @@ compile_asm (MonoAotCompile *acfg)
 #elif defined(PLATFORM_WIN32)
        command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
 #else
-       command = g_strdup_printf ("ld %s -shared -o %s %s.o", LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
+       command = g_strdup_printf ("%sld %s -shared -o %s %s.o", tool_prefix, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
 #endif
        printf ("Executing the native linker: %s\n", command);
        if (system (command) != 0) {
@@ -4856,7 +5089,7 @@ compile_asm (MonoAotCompile *acfg)
         * gas generates 'mapping symbols' each time code and data is mixed, which 
         * happens a lot in emit_and_reloc_code (), so we need to get rid of them.
         */
-       command = g_strdup_printf ("strip --strip-symbol=\\$a --strip-symbol=\\$d %s", tmp_outfile_name);
+       command = g_strdup_printf ("%sstrip --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name);
        printf ("Stripping the binary: %s\n", command);
        if (system (command) != 0) {
                g_free (tmp_outfile_name);