X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fimage-writer.c;h=a5d7488da85df18fb35a763a4bb6a2e3db902080;hb=f060b9998928275154c8cc426850cad5f6f23003;hp=de9413a871dcde746f3965788e0afb8f1598f300;hpb=d0baa99bcb8ef12231e24432d0b5710b3a0a4380;p=mono.git diff --git a/mono/mini/image-writer.c b/mono/mini/image-writer.c index de9413a871d..a5d7488da85 100644 --- a/mono/mini/image-writer.c +++ b/mono/mini/image-writer.c @@ -108,7 +108,7 @@ #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1))) #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1)) -#if defined(TARGET_AMD64) && !defined(HOST_WIN32) +#if defined(TARGET_AMD64) && !defined(HOST_WIN32) && !defined(__APPLE__) #define USE_ELF_WRITER 1 #define USE_ELF_RELA 1 #endif @@ -125,7 +125,11 @@ #define USE_ELF_WRITER 1 #endif -#if defined(USE_ELF_WRITER) +#if defined(TARGET_X86) && defined(__APPLE__) +//#define USE_MACH_WRITER +#endif + +#if defined(USE_ELF_WRITER) || defined(USE_MACH_WRITER) #define USE_BIN_WRITER 1 #endif @@ -481,6 +485,206 @@ bin_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) acfg->cur_section->cur_offset += num; } +static void +bin_writer_fwrite (MonoImageWriter *acfg, void *val, size_t size, size_t nmemb) +{ + if (acfg->fp) + fwrite (val, size, nmemb, acfg->fp); + else { + g_assert (acfg->out_buf_pos + (size * nmemb) <= acfg->out_buf_size); + memcpy (acfg->out_buf + acfg->out_buf_pos, val, size * nmemb); + acfg->out_buf_pos += (size * nmemb); + } +} + +static void +bin_writer_fseek (MonoImageWriter *acfg, int offset) +{ + if (acfg->fp) + fseek (acfg->fp, offset, SEEK_SET); + else + acfg->out_buf_pos = offset; +} + +#ifdef USE_MACH_WRITER + +/* + * This is a minimal implementation designed to support xdebug on 32 bit osx + * FIXME: 64 bit support + */ + +#include + +static gsize +get_label_addr (MonoImageWriter *acfg, const char *name) +{ + int offset; + BinLabel *lab; + BinSection *section; + gsize value; + + lab = g_hash_table_lookup (acfg->labels, name); + if (!lab) + g_error ("Undefined label: '%s'.\n", name); + section = lab->section; + offset = lab->offset; + if (section->parent) { + value = section->parent->virt_offset + section->cur_offset + offset; + } else { + value = section->virt_offset + offset; + } + return value; +} + + +static void +resolve_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 **out_data, gsize *out_vaddr, gsize *out_start_val, gsize *out_end_val) +{ + guint8 *data; + gssize end_val, start_val; + gsize vaddr; + + end_val = get_label_addr (acfg, reloc->val1); + if (reloc->val2) { + start_val = get_label_addr (acfg, reloc->val2); + } else if (reloc->val2_section) { + start_val = reloc->val2_offset; + if (reloc->val2_section->parent) + start_val += reloc->val2_section->parent->virt_offset + reloc->val2_section->cur_offset; + else + start_val += reloc->val2_section->virt_offset; + } else { + start_val = 0; + } + end_val = end_val - start_val + reloc->offset; + if (reloc->section->parent) { + data = reloc->section->parent->data; + data += reloc->section->cur_offset; + data += reloc->section_offset; + vaddr = reloc->section->parent->virt_offset; + vaddr += reloc->section->cur_offset; + vaddr += reloc->section_offset; + } else { + data = reloc->section->data; + data += reloc->section_offset; + vaddr = reloc->section->virt_offset; + vaddr += reloc->section_offset; + } + + *out_start_val = start_val; + *out_end_val = end_val; + *out_data = data; + *out_vaddr = vaddr; +} + +static void +resolve_relocations (MonoImageWriter *acfg) +{ + BinReloc *reloc; + guint8 *data; + gsize end_val, start_val; + gsize vaddr; + + /* Only resolve static relocations */ + for (reloc = acfg->relocations; reloc; reloc = reloc->next) { + resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); + data [0] = end_val; + data [1] = end_val >> 8; + data [2] = end_val >> 16; + data [3] = end_val >> 24; + } +} + +static int +bin_writer_emit_writeout (MonoImageWriter *acfg) +{ + BinSection *s; + int sindex, file_size, nsections, file_offset, vmaddr; + struct mach_header header; + struct segment_command segment; + struct section *sections; + + /* Assing vm addresses to sections */ + nsections = 0; + vmaddr = 0; + for (s = acfg->sections; s; s = s->next) { + s->virt_offset = vmaddr; + vmaddr += s->cur_offset; + nsections ++; + } + + resolve_relocations (acfg); + + file_offset = 0; + + memset (&header, 0, sizeof (header)); + header.magic = MH_MAGIC; + header.cputype = CPU_TYPE_X86; + header.cpusubtype = CPU_SUBTYPE_X86_ALL; + header.filetype = MH_OBJECT; + header.ncmds = 0; + header.sizeofcmds = 0; + header.flags = 0; + + file_offset += sizeof (header); + + memset (&segment, 0, sizeof (segment)); + segment.cmd = LC_SEGMENT; + segment.cmdsize = sizeof (segment); + segment.maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE; + segment.initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE; + + file_offset += sizeof (segment); + file_offset += nsections * sizeof (struct section); + + sections = g_new0 (struct section, nsections); + sindex = 0; + for (s = acfg->sections; s; s = s->next) { + s->file_offset = file_offset; + + /* .debug_line -> __debug_line */ + sprintf (sections [sindex].sectname, "__%s", s->name + 1); + sprintf (sections [sindex].segname, "%s", "__DWARF"); + sections [sindex].addr = s->virt_offset; + sections [sindex].size = s->cur_offset; + sections [sindex].offset = s->file_offset; + + file_offset += s->cur_offset; + + segment.nsects ++; + segment.cmdsize += sizeof (struct section); + + sindex ++; + } + + header.ncmds ++; + header.sizeofcmds += segment.cmdsize; + + /* Emit data */ + file_size = file_offset; + + if (!acfg->fp) { + acfg->out_buf_size = file_size; + acfg->out_buf = g_malloc (acfg->out_buf_size); + } + + bin_writer_fwrite (acfg, &header, sizeof (header), 1); + bin_writer_fwrite (acfg, &segment, sizeof (segment), 1); + bin_writer_fwrite (acfg, sections, sizeof (struct section), nsections); + for (s = acfg->sections; s; s = s->next) { + if (!acfg->fp) + g_assert (acfg->out_buf_pos == s->file_offset); + bin_writer_fwrite (acfg, s->data, s->cur_offset, 1); + } + + if (acfg->fp) + fclose (acfg->fp); + + return 0; +} + +#endif + #ifdef USE_ELF_WRITER enum { @@ -1042,27 +1246,6 @@ resolve_relocations (MonoImageWriter *acfg) #endif /* USE_ELF_RELA */ -static void -bin_writer_fwrite (MonoImageWriter *acfg, void *val, size_t size, size_t nmemb) -{ - if (acfg->fp) - fwrite (val, size, nmemb, acfg->fp); - else { - g_assert (acfg->out_buf_pos + (size * nmemb) <= acfg->out_buf_size); - memcpy (acfg->out_buf + acfg->out_buf_pos, val, size * nmemb); - acfg->out_buf_pos += (size * nmemb); - } -} - -static void -bin_writer_fseek (MonoImageWriter *acfg, int offset) -{ - if (acfg->fp) - fseek (acfg->fp, offset, SEEK_SET); - else - acfg->out_buf_pos = offset; -} - static int normal_sections [] = { SECT_DATA, SECT_DEBUG_FRAME, SECT_DEBUG_INFO, SECT_DEBUG_ABBREV, SECT_DEBUG_LINE, SECT_DEBUG_LOC }; static int @@ -1585,12 +1768,8 @@ static void asm_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func) { asm_writer_emit_unset_mode (acfg); -#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 + fprintf (acfg->fp, "\t.globl %s\n", name); -#endif asm_writer_emit_symbol_type (acfg, name, func); } @@ -1621,22 +1800,7 @@ static void asm_writer_emit_label (MonoImageWriter *acfg, const char *name) { asm_writer_emit_unset_mode (acfg); -#if (defined(TARGET_X86) && defined(TARGET_ASM_APPLE)) - name = get_label(name); - fprintf (acfg->fp, "%s:\n", name); - if (name[0] != 'L') - 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 */ - fprintf (acfg->fp, "%s:\n", name); -#endif -#else fprintf (acfg->fp, "%s:\n", get_label (name)); -#endif - } static void @@ -1789,7 +1953,7 @@ asm_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* if (offset == 0 && strcmp (start, ".") != 0) { char symbol [128]; - sprintf (symbol, ".LDIFF_SYM%d", acfg->label_gen); + 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);