Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mono / mini / image-writer.c
index c5fecf91053629f70180d51dd555b9d0baf0e3ee..e6d6d928142b51340c5c74658219982eb448b4ca 100644 (file)
@@ -53,7 +53,7 @@
  * TARGET_ASM_GAS == GNU assembler
  */
 #if !defined(TARGET_ASM_APPLE) && !defined(TARGET_ASM_GAS)
-#ifdef __MACH__
+#if defined(TARGET_MACH) && !defined(__native_client_codegen__)
 #define TARGET_ASM_APPLE
 #else
 #define TARGET_ASM_GAS
@@ -63,7 +63,7 @@
 /*
  * Defines for the directives used by different assemblers
  */
-#if defined(TARGET_POWERPC) || defined(__MACH__)
+#if defined(TARGET_POWERPC) || defined(TARGET_MACH)
 #define AS_STRING_DIRECTIVE ".asciz"
 #else
 #define AS_STRING_DIRECTIVE ".string"
 #define USE_ELF_RELA 1
 #endif
 
-#if defined(TARGET_X86) && !defined(TARGET_WIN32)
+#if defined(TARGET_X86) && !defined(TARGET_WIN32) && !defined(__APPLE__)
 #define USE_ELF_WRITER 1
 #endif
 
-#if defined(TARGET_ARM) && !defined(__MACH__)
+#if defined(TARGET_ARM) && !defined(TARGET_MACH)
 #define USE_ELF_WRITER 1
 #endif
 
@@ -313,6 +313,11 @@ bin_writer_emit_ensure_buffer (BinSection *section, int size)
                while (new_size <= new_offset)
                        new_size *= 2;
                data = g_malloc0 (new_size);
+#ifdef __native_client_codegen__
+               /* for Native Client, fill empty space with HLT instruction */
+               /* instead of 00.                                           */
+               memset(data, 0xf4, new_size);
+#endif         
                memcpy (data, section->data, section->data_len);
                g_free (section->data);
                section->data = data;
@@ -355,14 +360,32 @@ bin_writer_emit_alignment (MonoImageWriter *acfg, int size)
        }
 }
 
+#ifdef __native_client_codegen__
+static void
+bin_writer_emit_nacl_call_alignment (MonoImageWriter *acfg) {
+  int offset = acfg->cur_section->cur_offset;
+  int padding = kNaClAlignment - (offset & kNaClAlignmentMask) - kNaClLengthOfCallImm;
+  guint8 padc = '\x90';
+
+  if (padding < 0) padding += kNaClAlignment;
+
+  while (padding > 0) {
+    bin_writer_emit_bytes(acfg, &padc, 1);
+    padding -= 1;
+  }
+}
+#endif  /* __native_client_codegen__ */
+
 static void
 bin_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target)
 {
        BinReloc *reloc;
 
-       if (!target)
-               // FIXME:
-               g_assert_not_reached ();
+       if (!target) {
+               acfg->cur_section->cur_offset += sizeof (gpointer);
+               return;
+       }
+
        reloc = g_new0 (BinReloc, 1);
        reloc->val1 = g_strdup (target);
        reloc->section = acfg->cur_section;
@@ -468,9 +491,9 @@ enum {
        SECT_REL_DYN,
        SECT_RELA_DYN,
        SECT_TEXT,
+       SECT_RODATA,
        SECT_DYNAMIC,
        SECT_GOT_PLT,
-       SECT_RODATA,
        SECT_DATA,
        SECT_BSS,
        SECT_DEBUG_FRAME,
@@ -522,9 +545,9 @@ static SectInfo section_info [] = {
        {".rel.dyn", SHT_REL, sizeof (ElfReloc), 2, SIZEOF_VOID_P},
        {".rela.dyn", SHT_RELA, sizeof (ElfRelocA), 2, SIZEOF_VOID_P},
        {".text", SHT_PROGBITS, 0, 6, 4096},
+       {".rodata", SHT_PROGBITS, 0, SHF_ALLOC, 4096},
        {".dynamic", SHT_DYNAMIC, sizeof (ElfDynamic), 3, SIZEOF_VOID_P},
        {".got.plt", SHT_PROGBITS, SIZEOF_VOID_P, 3, SIZEOF_VOID_P},
-       {".rodata", SHT_PROGBITS, 0, 6, 4096},
        {".data", SHT_PROGBITS, 0, 3, 8},
        {".bss", SHT_NOBITS, 0, 3, 8},
        {".debug_frame", SHT_PROGBITS, 0, 0, 8},
@@ -1040,14 +1063,14 @@ bin_writer_fseek (MonoImageWriter *acfg, int offset)
                acfg->out_buf_pos = offset;
 }
 
-static int normal_sections [] = { SECT_RODATA, SECT_DATA, SECT_DEBUG_FRAME, SECT_DEBUG_INFO, SECT_DEBUG_ABBREV, SECT_DEBUG_LINE, SECT_DEBUG_LOC };
+static int normal_sections [] = { SECT_DATA, SECT_DEBUG_FRAME, SECT_DEBUG_INFO, SECT_DEBUG_ABBREV, SECT_DEBUG_LINE, SECT_DEBUG_LOC };
 
 static int
 bin_writer_emit_writeout (MonoImageWriter *acfg)
 {
        FILE *file;
        ElfHeader header;
-       ElfProgHeader progh [3];
+       ElfProgHeader progh [4];
        ElfSectHeader secth [SECT_NUM];
 #ifdef USE_ELF_RELA
        ElfRelocA *relocs;
@@ -1165,6 +1188,17 @@ bin_writer_emit_writeout (MonoImageWriter *acfg)
                file_offset += size;
        }
 
+       file_offset = ALIGN_TO (file_offset, secth [SECT_RODATA].sh_addralign);
+       virt_offset = file_offset;
+       secth [SECT_RODATA].sh_addr = virt_offset;
+       secth [SECT_RODATA].sh_offset = file_offset;
+       if (sections [SECT_RODATA]) {
+               size = sections [SECT_RODATA]->cur_offset;
+               secth [SECT_RODATA].sh_size = size;
+               file_offset += size;
+               virt_offset += size;
+       }
+
        file_offset = ALIGN_TO (file_offset, secth [SECT_DYNAMIC].sh_addralign);
        virt_offset = file_offset;
 
@@ -1187,17 +1221,6 @@ bin_writer_emit_writeout (MonoImageWriter *acfg)
        file_offset += size;
        virt_offset += size;
 
-       file_offset = ALIGN_TO (file_offset, secth [SECT_RODATA].sh_addralign);
-       virt_offset = ALIGN_TO (virt_offset, secth [SECT_RODATA].sh_addralign);
-       secth [SECT_RODATA].sh_addr = virt_offset;
-       secth [SECT_RODATA].sh_offset = file_offset;
-       if (sections [SECT_RODATA]) {
-               size = sections [SECT_RODATA]->cur_offset;
-               secth [SECT_RODATA].sh_size = size;
-               file_offset += size;
-               virt_offset += size;
-       }
-
        file_offset = ALIGN_TO (file_offset, secth [SECT_DATA].sh_addralign);
        virt_offset = ALIGN_TO (virt_offset, secth [SECT_DATA].sh_addralign);
        secth [SECT_DATA].sh_addr = virt_offset;
@@ -1313,7 +1336,7 @@ bin_writer_emit_writeout (MonoImageWriter *acfg)
        header.e_phoff = sizeof (header);
        header.e_ehsize = sizeof (header);
        header.e_phentsize = sizeof (ElfProgHeader);
-       header.e_phnum = 3;
+       header.e_phnum = 4;
        header.e_entry = secth [SECT_TEXT].sh_addr;
        header.e_shstrndx = SECT_SHSTRTAB;
        header.e_shentsize = sizeof (ElfSectHeader);
@@ -1384,6 +1407,13 @@ bin_writer_emit_writeout (MonoImageWriter *acfg)
        progh [2].p_align = SIZEOF_VOID_P;
        progh [2].p_flags = 6;
 
+       progh [3].p_type = PT_GNU_STACK;
+       progh [3].p_offset = secth [SECT_DYNAMIC].sh_offset;
+       progh [3].p_vaddr = progh [3].p_paddr = secth [SECT_DYNAMIC].sh_addr;
+       progh [3].p_filesz = progh [3].p_memsz = secth [SECT_DYNAMIC].sh_size;
+       progh [3].p_align = SIZEOF_VOID_P;
+       progh [3].p_flags = 6;
+
        /* Compute the addresses of the bin sections, so relocation can be done */
        for (i = 0; i < SECT_NUM; ++i) {
                if (sections [i]) {
@@ -1419,16 +1449,24 @@ bin_writer_emit_writeout (MonoImageWriter *acfg)
                bin_writer_fseek (acfg, secth [SECT_TEXT].sh_offset);
                bin_writer_fwrite (acfg, sections [SECT_TEXT]->data, sections [SECT_TEXT]->cur_offset, 1);
        }
+       /* .rodata */
+       if (sections [SECT_RODATA]) {
+               bin_writer_fseek (acfg, secth [SECT_RODATA].sh_offset);
+               bin_writer_fwrite (acfg, sections [SECT_RODATA]->data, sections [SECT_RODATA]->cur_offset, 1);
+       }
        /* .dynamic */
+       bin_writer_fseek (acfg, secth [SECT_DYNAMIC].sh_offset);
        bin_writer_fwrite (acfg, dynamic, sizeof (dynamic), 1);
 
        /* .got.plt */
        size = secth [SECT_DYNAMIC].sh_addr;
+       bin_writer_fseek (acfg, secth [SECT_GOT_PLT].sh_offset);
        bin_writer_fwrite (acfg, &size, sizeof (size), 1);
 
        /* normal sections */
        for (i = 0; i < sizeof (normal_sections) / sizeof (normal_sections [0]); ++i) {
                int sect = normal_sections [i];
+
                if (sections [sect]) {
                        bin_writer_fseek (acfg, secth [sect].sh_offset);
                        bin_writer_fwrite (acfg, sections [sect]->data, sections [sect]->cur_offset, 1);
@@ -1547,7 +1585,7 @@ static void
 asm_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func)
 {
        asm_writer_emit_unset_mode (acfg);
-#if  (defined(__ppc__) && defined(TARGET_ASM_APPLE)) || (defined(HOST_WIN32) && !defined(MONO_CROSS_COMPILE))
+#if  ((defined(__ppc__) || defined(TARGET_X86)) && defined(TARGET_ASM_APPLE)) || (defined(HOST_WIN32) && !defined(MONO_CROSS_COMPILE))
     // mach-o always uses a '_' prefix.
        fprintf (acfg->fp, "\t.globl _%s\n", name);
 #else
@@ -1583,7 +1621,13 @@ static void
 asm_writer_emit_label (MonoImageWriter *acfg, const char *name)
 {
        asm_writer_emit_unset_mode (acfg);
-#if defined(HOST_WIN32) && (defined(TARGET_X86) || defined(TARGET_AMD64))
+#if (defined(TARGET_X86) && defined(TARGET_ASM_APPLE))
+        name = get_label(name);
+        fprintf (acfg->fp, "%s:\n", name);
+        if (name[0] != 'L' && name[0] != '_')
+            fprintf (acfg->fp, "_%s:\n", name);
+
+#elif (defined(HOST_WIN32) && (defined(TARGET_X86) || defined(TARGET_AMD64))) || (defined(TARGET_X86) && defined(TARGET_ASM_APPLE))
        fprintf (acfg->fp, "_%s:\n", name);
 #if defined(HOST_WIN32)
        /* Emit a normal label too */
@@ -1627,6 +1671,20 @@ asm_writer_emit_alignment (MonoImageWriter *acfg, int size)
 #endif
 }
 
+#ifdef __native_client_codegen__
+static void
+asm_writer_emit_nacl_call_alignment (MonoImageWriter *acfg) {
+  int padding = kNaClAlignment - kNaClLengthOfCallImm;
+  guint8 padc = '\x90';
+
+  fprintf (acfg->fp, "\n\t.align %d", kNaClAlignment);
+  while (padding > 0) {
+    fprintf (acfg->fp, "\n\t.byte %d", padc);
+    padding -= 1;
+  }
+}
+#endif  /* __native_client_codegen__ */
+
 static void
 asm_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target)
 {
@@ -1700,7 +1758,7 @@ static void
 asm_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset)
 {
 #ifdef TARGET_ASM_APPLE
-       char symbol [128];
+       //char symbol [128];
 #endif
 
        if (acfg->mode != EMIT_LONG) {
@@ -1728,6 +1786,17 @@ asm_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char*
 #else
        start = get_label (start);
        end = get_label (end);
+
+       if (offset == 0 && strcmp (start, ".") != 0) {
+               char symbol [128];
+               sprintf (symbol, "%sDIFF_SYM%d", AS_TEMP_LABEL_PREFIX, acfg->label_gen);
+               acfg->label_gen ++;
+               fprintf (acfg->fp, "\n%s=%s - %s", symbol, end, start);
+               fprintf (acfg->fp, "\n\t%s ", AS_INT32_DIRECTIVE);
+               fprintf (acfg->fp, "%s", symbol);
+               return;
+       }
+
        if ((acfg->col_count++ % 8) == 0)
                fprintf (acfg->fp, "\n\t%s ", AS_INT32_DIRECTIVE);
        else
@@ -1909,6 +1978,20 @@ img_writer_emit_alignment (MonoImageWriter *acfg, int size)
 #endif
 }
 
+#ifdef __native_client_codegen__
+void
+img_writer_emit_nacl_call_alignment (MonoImageWriter *acfg) {
+#ifdef USE_BIN_WRITER
+       if (acfg->use_bin_writer)
+               bin_writer_emit_nacl_call_alignment (acfg);
+       else
+               asm_writer_emit_nacl_call_alignment (acfg);
+#else
+       g_assert_not_reached();
+#endif
+}
+#endif  /* __native_client_codegen__ */
+
 void
 img_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target)
 {