diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index b07e58569160c..3e9ca497336ab 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -144,7 +144,6 @@ set(mini_common_sources dwarfwriter.c mini-gc.h mini-gc.c - xdebug.c mini-llvm.h mini-llvm-cpp.h llvm-jit.h diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index ba1c7ea043c7e..369016e11892d 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -14299,7 +14299,7 @@ emit_aot_image (MonoAotCompile *acfg) return 1; } if (acfg->fp) - acfg->w = mono_img_writer_create (acfg->fp, FALSE); + acfg->w = mono_img_writer_create (acfg->fp); /* Compute symbols for methods */ for (i = 0; i < acfg->nmethods; ++i) { diff --git a/src/mono/mono/mini/driver.c b/src/mono/mono/mini/driver.c index f2792e4e6a4e4..3e7a07c17c674 100644 --- a/src/mono/mono/mini/driver.c +++ b/src/mono/mono/mini/driver.c @@ -216,9 +216,6 @@ parse_debug_options (const char* p) } else if (!strncmp (p, "mdb-optimizations", 17)) { opt->mdb_optimizations = TRUE; p += 17; - } else if (!strncmp (p, "gdb", 3)) { - opt->gdb = TRUE; - p += 3; } else if (!strncmp (p, "ignore", 6)) { opt->enabled = FALSE; p += 6; diff --git a/src/mono/mono/mini/image-writer.c b/src/mono/mono/mini/image-writer.c index 97d1a042c0fd8..cc81ac7b070dc 100644 --- a/src/mono/mono/mini/image-writer.c +++ b/src/mono/mono/mini/image-writer.c @@ -22,33 +22,13 @@ #include #include #include -#ifndef HOST_WIN32 -#include -#else -#include -#include -#endif - #include #include -#include /* for PAGESIZE */ -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif #include "image-writer.h" -#ifndef HOST_WIN32 -#include -#include -#endif - #include "mini.h" -#define TV_DECLARE(name) gint64 name -#define TV_GETTIME(tv) tv = mono_100ns_ticks () -#define TV_ELAPSED(start,end) (((end) - (start)) / 10) - /* * The used assembler dialect * TARGET_ASM_APPLE == apple assembler on OSX @@ -122,14 +102,6 @@ #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1)) -#ifdef USE_BIN_WRITER - -typedef struct _BinSymbol BinSymbol; -typedef struct _BinReloc BinReloc; -typedef struct _BinSection BinSection; - -#endif - /* emit mode */ enum { EMIT_NONE, @@ -141,24 +113,12 @@ enum { struct _MonoImageWriter { MonoMemPool *mempool; char *outfile; - gboolean use_bin_writer; const char *current_section; int current_subsection; const char *section_stack [16]; int subsection_stack [16]; int stack_pos; FILE *fp; - /* Bin writer */ -#ifdef USE_BIN_WRITER - BinSymbol *symbols; - BinSection *sections; - BinSection *cur_section; - BinReloc *relocations; - GHashTable *labels; - int num_relocs; - guint8 *out_buf; - int out_buf_size, out_buf_pos; -#endif /* Asm writer */ char *tmpfname; int mode; /* emit mode */ @@ -175,1482 +135,6 @@ ilog2(int value) return count; } -#ifdef USE_BIN_WRITER - -typedef struct _BinLabel BinLabel; -struct _BinLabel { - char *name; - BinSection *section; - int offset; -}; - -struct _BinReloc { - BinReloc *next; - char *val1; - char *val2; - BinSection *val2_section; - int val2_offset; - int offset; - BinSection *section; - int section_offset; - int reloc_type; -}; - -struct _BinSymbol { - BinSymbol *next; - char *name; - BinSection *section; - int offset; - gboolean is_function; - gboolean is_global; - char *end_label; -}; - -struct _BinSection { - BinSection *next; - BinSection *parent; - char *name; - int subsection; - guint8 *data; - int data_len; - int cur_offset; - int file_offset; - int virt_offset; - int shidx; - guint64 addr; - gboolean has_addr; -}; - -static void -bin_writer_emit_start (MonoImageWriter *acfg) -{ - acfg->labels = g_hash_table_new (g_str_hash, g_str_equal); -} - -static void -bin_writer_emit_section_change (MonoImageWriter *acfg, const char *section_name, int subsection_index) -{ - BinSection *section; - - if (acfg->cur_section && acfg->cur_section->subsection == subsection_index - && strcmp (acfg->cur_section->name, section_name) == 0) - return; - for (section = acfg->sections; section; section = section->next) { - if (section->subsection == subsection_index && strcmp (section->name, section_name) == 0) { - acfg->cur_section = section; - return; - } - } - if (!section) { - section = g_new0 (BinSection, 1); - section->name = g_strdup (section_name); - section->subsection = subsection_index; - section->next = acfg->sections; - acfg->sections = section; - acfg->cur_section = section; - } -} - -static void -bin_writer_set_section_addr (MonoImageWriter *acfg, guint64 addr) -{ - acfg->cur_section->addr = addr; - acfg->cur_section->has_addr = TRUE; -} - -static void -bin_writer_emit_symbol_inner (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean is_global, gboolean func) -{ - BinSymbol *symbol = g_new0 (BinSymbol, 1); - symbol->name = g_strdup (name); - if (end_label) - symbol->end_label = g_strdup (end_label); - symbol->is_function = func; - symbol->is_global = is_global; - symbol->section = acfg->cur_section; - /* FIXME: we align after this call... */ - symbol->offset = symbol->section->cur_offset; - symbol->next = acfg->symbols; - acfg->symbols = symbol; -} - -static void -bin_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func) -{ - bin_writer_emit_symbol_inner (acfg, name, NULL, TRUE, func); -} - -static void -bin_writer_emit_local_symbol (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean func) -{ - bin_writer_emit_symbol_inner (acfg, name, end_label, FALSE, func); -} - -static void -bin_writer_emit_label (MonoImageWriter *acfg, const char *name) -{ - BinLabel *label = g_new0 (BinLabel, 1); - label->name = g_strdup (name); - label->section = acfg->cur_section; - label->offset = acfg->cur_section->cur_offset; - g_hash_table_insert (acfg->labels, label->name, label); -} - -static void -bin_writer_emit_ensure_buffer (BinSection *section, int size) -{ - int new_offset = section->cur_offset + size; - if (new_offset >= section->data_len) { - int new_size = section->data_len? section->data_len * 2: 256; - guint8 *data; - while (new_size <= new_offset) - new_size *= 2; - data = (guint8 *)g_malloc0 (new_size); - memcpy (data, section->data, section->data_len); - g_free (section->data); - section->data = data; - section->data_len = new_size; - } -} - -static void -bin_writer_emit_bytes (MonoImageWriter *acfg, const guint8* buf, int size) -{ - bin_writer_emit_ensure_buffer (acfg->cur_section, size); - memcpy (acfg->cur_section->data + acfg->cur_section->cur_offset, buf, size); - acfg->cur_section->cur_offset += size; -} - -static void -bin_writer_emit_string (MonoImageWriter *acfg, const char *value) -{ - int size = strlen (value) + 1; - bin_writer_emit_bytes (acfg, (const guint8*)value, size); -} - -static void -bin_writer_emit_line (MonoImageWriter *acfg) -{ - /* Nothing to do in binary writer */ -} - -static void -bin_writer_emit_alignment (MonoImageWriter *acfg, int size) -{ - int offset = acfg->cur_section->cur_offset; - int add; - offset += (size - 1); - offset &= ~(size - 1); - add = offset - acfg->cur_section->cur_offset; - if (add) { - bin_writer_emit_ensure_buffer (acfg->cur_section, add); - acfg->cur_section->cur_offset += add; - } -} - -static void -bin_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) -{ - BinReloc *reloc; - - 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; - reloc->section_offset = acfg->cur_section->cur_offset; - reloc->next = acfg->relocations; - acfg->relocations = reloc; - if (strcmp (reloc->section->name, ".data") == 0) { - acfg->num_relocs++; - //g_print ("reloc: %s at %d\n", target, acfg->cur_section->cur_offset); - } - acfg->cur_section->cur_offset += sizeof (gpointer); -} - -static void -bin_writer_emit_pointer (MonoImageWriter *acfg, const char *target) -{ - bin_writer_emit_alignment (acfg, sizeof (gpointer)); - bin_writer_emit_pointer_unaligned (acfg, target); -} - -static void -bin_writer_emit_int16 (MonoImageWriter *acfg, int value) -{ - guint8 *data; - bin_writer_emit_ensure_buffer (acfg->cur_section, 2); - data = acfg->cur_section->data + acfg->cur_section->cur_offset; - acfg->cur_section->cur_offset += 2; - /* FIXME: little endian */ - data [0] = value; - data [1] = value >> 8; -} - -static void -bin_writer_emit_int32 (MonoImageWriter *acfg, int value) -{ - guint8 *data; - bin_writer_emit_ensure_buffer (acfg->cur_section, 4); - data = acfg->cur_section->data + acfg->cur_section->cur_offset; - acfg->cur_section->cur_offset += 4; - /* FIXME: little endian */ - data [0] = value; - data [1] = value >> 8; - data [2] = value >> 16; - data [3] = value >> 24; -} - -static BinReloc* -create_reloc (MonoImageWriter *acfg, const char *end, const char* start, int offset) -{ - BinReloc *reloc; - reloc = (BinReloc *)mono_mempool_alloc0 (acfg->mempool, sizeof (BinReloc)); - reloc->val1 = mono_mempool_strdup (acfg->mempool, end); - if (start) - { - if (strcmp (start, ".") == 0) { - reloc->val2_section = acfg->cur_section; - reloc->val2_offset = acfg->cur_section->cur_offset; - } else { - reloc->val2 = mono_mempool_strdup (acfg->mempool, start); - } - } - reloc->offset = offset; - reloc->section = acfg->cur_section; - reloc->section_offset = acfg->cur_section->cur_offset; - reloc->next = acfg->relocations; - acfg->relocations = reloc; - return reloc; -} - -static void -bin_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) -{ - create_reloc (acfg, symbol, NULL, 0); - acfg->cur_section->cur_offset += 4; -} - -static void -bin_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) -{ - create_reloc (acfg, end, start, offset); - acfg->cur_section->cur_offset += 4; - /*if (strcmp (reloc->section->name, ".data") == 0) { - acfg->num_relocs++; - g_print ("reloc: %s - %s + %d at %d\n", end, start, offset, acfg->cur_section->cur_offset - 4); - }*/ -} - -/* - * Emit a relocation entry of type RELOC_TYPE against symbol SYMBOL at the current PC. - * Do not advance PC. - */ -static G_GNUC_UNUSED void -bin_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *symbol, int addend) -{ - BinReloc *reloc = create_reloc (acfg, symbol, ".", addend); - reloc->reloc_type = reloc_type; -} - -static void -bin_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) -{ - bin_writer_emit_ensure_buffer (acfg->cur_section, 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 { - SECT_NULL, - SECT_HASH, - SECT_DYNSYM, - SECT_DYNSTR, - SECT_REL_DYN, - SECT_RELA_DYN, - SECT_TEXT, - SECT_RODATA, - SECT_DYNAMIC, - SECT_GOT_PLT, - SECT_DATA, - SECT_BSS, - SECT_DEBUG_FRAME, - SECT_DEBUG_INFO, - SECT_DEBUG_ABBREV, - SECT_DEBUG_LINE, - SECT_DEBUG_LOC, - SECT_SHSTRTAB, - SECT_SYMTAB, - SECT_STRTAB, - SECT_NUM -}; - -#if TARGET_SIZEOF_VOID_P == 4 - -typedef Elf32_Ehdr ElfHeader; -typedef Elf32_Shdr ElfSectHeader; -typedef Elf32_Phdr ElfProgHeader; -typedef Elf32_Sym ElfSymbol; -typedef Elf32_Rel ElfReloc; -typedef Elf32_Rela ElfRelocA; -typedef Elf32_Dyn ElfDynamic; - -#else - -typedef Elf64_Ehdr ElfHeader; -typedef Elf64_Shdr ElfSectHeader; -typedef Elf64_Phdr ElfProgHeader; -typedef Elf64_Sym ElfSymbol; -typedef Elf64_Rel ElfReloc; -typedef Elf64_Rela ElfRelocA; -typedef Elf64_Dyn ElfDynamic; - -#endif - -typedef struct { - const char *name; - int type; - int esize; - int flags; - int align; -} SectInfo; - -static SectInfo section_info [] = { - {"", 0, 0, 0, 0}, - {".hash", SHT_HASH, 4, 2, TARGET_SIZEOF_VOID_P}, - {".dynsym", SHT_DYNSYM, sizeof (ElfSymbol), 2, TARGET_SIZEOF_VOID_P}, - {".dynstr", SHT_STRTAB, 0, 2, 1}, - {".rel.dyn", SHT_REL, sizeof (ElfReloc), 2, TARGET_SIZEOF_VOID_P}, - {".rela.dyn", SHT_RELA, sizeof (ElfRelocA), 2, TARGET_SIZEOF_VOID_P}, - {".text", SHT_PROGBITS, 0, 6, 4096}, - {".rodata", SHT_PROGBITS, 0, SHF_ALLOC, 4096}, - {".dynamic", SHT_DYNAMIC, sizeof (ElfDynamic), 3, TARGET_SIZEOF_VOID_P}, - {".got.plt", SHT_PROGBITS, TARGET_SIZEOF_VOID_P, 3, TARGET_SIZEOF_VOID_P}, - {".data", SHT_PROGBITS, 0, 3, 8}, - {".bss", SHT_NOBITS, 0, 3, 8}, - {".debug_frame", SHT_PROGBITS, 0, 0, 8}, - {".debug_info", SHT_PROGBITS, 0, 0, 1}, - {".debug_abbrev", SHT_PROGBITS, 0, 0, 1}, - {".debug_line", SHT_PROGBITS, 0, 0, 1}, - {".debug_loc", SHT_PROGBITS, 0, 0, 1}, - {".shstrtab", SHT_STRTAB, 0, 0, 1}, - {".symtab", SHT_SYMTAB, sizeof (ElfSymbol), 0, TARGET_SIZEOF_VOID_P}, - {".strtab", SHT_STRTAB, 0, 0, 1} -}; - -typedef struct { - GString *data; - GHashTable *hash; -} ElfStrTable; - -static int -str_table_add (ElfStrTable *table, const char* value) -{ - int idx; - if (!table->data) { - table->data = g_string_new_len ("", 1); - table->hash = g_hash_table_new (g_str_hash, g_str_equal); - } - idx = GPOINTER_TO_UINT (g_hash_table_lookup (table->hash, value)); - if (idx) - return idx; - idx = table->data->len; - g_string_append (table->data, value); - g_string_append_c (table->data, 0); - g_hash_table_insert (table->hash, (void*)value, GUINT_TO_POINTER (idx)); - return idx; -} - -static void -append_subsection (MonoImageWriter *acfg, ElfSectHeader *sheaders, BinSection *sect, BinSection *add) -{ - int offset = sect->cur_offset; - /*offset += (sheaders [sect->shidx].sh_addralign - 1); - offset &= ~(sheaders [sect->shidx].sh_addralign - 1);*/ - /* - * FIXME: we shouldn't align subsections at all, but if we don't then the - * stuff inside the subsections which is aligned won't get aligned. - */ - if (strcmp (sect->name, ".debug_line") != 0) { - offset += (8 - 1); - offset &= ~(8 - 1); - } - bin_writer_emit_ensure_buffer (sect, offset); - //g_print ("section %s aligned to %d from %d\n", sect->name, offset, sect->cur_offset); - sect->cur_offset = offset; - - bin_writer_emit_ensure_buffer (sect, add->cur_offset); - memcpy (sect->data + sect->cur_offset, add->data, add->cur_offset); - add->parent = sect; - sect->cur_offset += add->cur_offset; - add->cur_offset = offset; /* it becomes the offset in the parent section */ - //g_print ("subsection %d of %s added at offset %d (align: %d)\n", add->subsection, sect->name, add->cur_offset, (int)sheaders [sect->shidx].sh_addralign); - add->data = NULL; - add->data_len = 0; -} - -/* merge the subsections */ -static int -collect_sections (MonoImageWriter *acfg, ElfSectHeader *sheaders, BinSection **out, int num) -{ - int i, j, maxs, num_sections; - BinSection *sect; - - num_sections = 0; - maxs = 0; - for (sect = acfg->sections; sect; sect = sect->next) { - if (sect->subsection == 0) { - out [num_sections++] = sect; - g_assert (num_sections < num); - } - maxs = MAX (maxs, sect->subsection); - } - for (i = 0; i < num_sections; i++) { - for (j = 1; j <= maxs; ++j) { - for (sect = acfg->sections; sect; sect = sect->next) { - if (sect->subsection == j && strcmp (out [i]->name, sect->name) == 0) { - append_subsection (acfg, sheaders, out [i], sect); - } - } - } - } - return num_sections; -} - -static unsigned long -elf_hash (const unsigned char *name) -{ - unsigned long h = 0, g; - while (*name) { - h = (h << 4) + *name++; - if ((g = h & 0xf0000000)) - h ^= g >> 24; - h &= ~g; - } - return h; -} - -#define NUM_BUCKETS 17 - -static int* -build_hash (MonoImageWriter *acfg, int num_sections, ElfStrTable *dynstr) -{ - int *data; - int num_symbols = 1 + num_sections + 3; - BinSymbol *symbol; - - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - if (!symbol->is_global) - continue; - num_symbols++; - str_table_add (dynstr, symbol->name); - /*g_print ("adding sym: %s\n", symbol->name);*/ - } - str_table_add (dynstr, "__bss_start"); - str_table_add (dynstr, "_edata"); - str_table_add (dynstr, "_end"); - - data = g_new0 (int, num_symbols + 2 + NUM_BUCKETS); - data [0] = NUM_BUCKETS; - data [1] = num_symbols; - - return data; -} - -static gsize -get_label_addr (MonoImageWriter *acfg, const char *name) -{ - int offset; - BinLabel *lab; - BinSection *section; - gsize value; - - lab = (BinLabel *)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 ElfSymbol* -collect_syms (MonoImageWriter *acfg, int *hash, ElfStrTable *strtab, ElfSectHeader *sheaders, int *num_syms) -{ - ElfSymbol *symbols; - BinSymbol *symbol; - BinSection *section; - int i; - int *bucket; - int *chain; - unsigned long hashc; - - if (hash) - symbols = g_new0 (ElfSymbol, hash [1]); - else { - i = 0; - for (symbol = acfg->symbols; symbol; symbol = symbol->next) - i ++; - - symbols = g_new0 (ElfSymbol, i + SECT_NUM + 10); /* FIXME */ - } - - /* the first symbol is undef, all zeroes */ - i = 1; - if (sheaders) { - int j; - for (j = 1; j < SECT_NUM; ++j) { - symbols [i].st_info = ELF32_ST_INFO (STB_LOCAL, STT_SECTION); - symbols [i].st_shndx = j; - symbols [i].st_value = sheaders [j].sh_addr; - ++i; - } - } else { - for (section = acfg->sections; section; section = section->next) { - if (section->parent) - continue; - symbols [i].st_info = ELF32_ST_INFO (STB_LOCAL, STT_SECTION); - if (strcmp (section->name, ".text") == 0) { - symbols [i].st_shndx = SECT_TEXT; - section->shidx = SECT_TEXT; - section->file_offset = 4096; - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".rodata") == 0) { - symbols [i].st_shndx = SECT_RODATA; - section->shidx = SECT_RODATA; - section->file_offset = 4096; - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".data") == 0) { - symbols [i].st_shndx = SECT_DATA; - section->shidx = SECT_DATA; - section->file_offset = 4096 + 28; /* FIXME */ - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".bss") == 0) { - symbols [i].st_shndx = SECT_BSS; - section->shidx = SECT_BSS; - section->file_offset = 4096 + 28 + 8; /* FIXME */ - symbols [i].st_value = section->virt_offset; - } - ++i; - } - } - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - int offset; - BinLabel *lab; - if (!symbol->is_global && hash) - continue; - symbols [i].st_info = ELF32_ST_INFO (symbol->is_global ? STB_GLOBAL : STB_LOCAL, symbol->is_function? STT_FUNC : STT_OBJECT); - symbols [i].st_name = str_table_add (strtab, symbol->name); - /*g_print ("sym name %s tabled to %d\n", symbol->name, symbols [i].st_name);*/ - section = symbol->section; - symbols [i].st_shndx = section->parent? section->parent->shidx: section->shidx; - lab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->name); - offset = lab->offset; - if (section->parent) { - symbols [i].st_value = section->parent->virt_offset + section->cur_offset + offset; - } else { - symbols [i].st_value = section->virt_offset + offset; - } - - if (symbol->end_label) { - BinLabel *elab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->end_label); - g_assert (elab); - symbols [i].st_size = elab->offset - lab->offset; - } - ++i; - } - /* add special symbols */ - symbols [i].st_name = str_table_add (strtab, "__bss_start"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - symbols [i].st_name = str_table_add (strtab, "_edata"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - symbols [i].st_name = str_table_add (strtab, "_end"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - - if (num_syms) - *num_syms = i; - - /* add to hash table */ - if (hash) { - bucket = hash + 2; - chain = hash + 2 + hash [0]; - for (i = 0; i < hash [1]; ++i) { - int slot; - /*g_print ("checking %d '%s' (sym %d)\n", symbols [i].st_name, strtab->data->str + symbols [i].st_name, i);*/ - if (!symbols [i].st_name) - continue; - hashc = elf_hash ((guint8*)strtab->data->str + symbols [i].st_name); - slot = hashc % hash [0]; - /*g_print ("hashing '%s' at slot %d (sym %d)\n", strtab->data->str + symbols [i].st_name, slot, i);*/ - if (bucket [slot]) { - chain [i] = bucket [slot]; - bucket [slot] = i; - } else { - bucket [slot] = i; - } - } - } - return symbols; -} - -static void -reloc_symbols (MonoImageWriter *acfg, ElfSymbol *symbols, ElfSectHeader *sheaders, ElfStrTable *strtab, gboolean dynamic) -{ - BinSection *section; - BinSymbol *symbol; - int i; - - i = 1; - if (dynamic) { - for (section = acfg->sections; section; section = section->next) { - if (section->parent) - continue; - symbols [i].st_value = sheaders [section->shidx].sh_addr; - ++i; - } - } else { - for (i = 1; i < SECT_NUM; ++i) { - symbols [i].st_value = sheaders [i].sh_addr; - } - } - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - int offset; - BinLabel *lab; - if (dynamic && !symbol->is_global) - continue; - section = symbol->section; - lab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->name); - offset = lab->offset; - if (section->parent) { - symbols [i].st_value = sheaders [section->parent->shidx].sh_addr + section->cur_offset + offset; - } else { - symbols [i].st_value = sheaders [section->shidx].sh_addr + offset; - } - ++i; - } - /* __bss_start */ - symbols [i].st_value = sheaders [SECT_BSS].sh_addr; - ++i; - /* _edata */ - symbols [i].st_value = sheaders [SECT_DATA].sh_addr + sheaders [SECT_DATA].sh_size; - ++i; - /* _end */ - symbols [i].st_value = sheaders [SECT_BSS].sh_addr + sheaders [SECT_BSS].sh_size; - ++i; -} - -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; -} - -#ifdef USE_ELF_RELA - -static ElfRelocA* -resolve_relocations (MonoImageWriter *acfg) -{ - BinReloc *reloc; - guint8 *data; - gsize end_val, start_val; - ElfRelocA *rr; - int i; - gsize vaddr; - - rr = g_new0 (ElfRelocA, acfg->num_relocs); - i = 0; - - for (reloc = acfg->relocations; reloc; reloc = reloc->next) { - resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); - /* FIXME: little endian */ - data [0] = end_val; - data [1] = end_val >> 8; - data [2] = end_val >> 16; - data [3] = end_val >> 24; - // FIXME: - if (start_val == 0 && reloc->val1 [0] != '.') { - rr [i].r_offset = vaddr; - rr [i].r_info = R_X86_64_RELATIVE; - rr [i].r_addend = end_val; - ++i; - g_assert (i <= acfg->num_relocs); - } - } - return rr; -} - -#else /* USE_ELF_RELA */ - -static void -do_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 *data, gssize addr) -{ -#ifdef TARGET_ARM - /* - * We use the official ARM relocation types, but implement only the stuff actually - * needed by the code we generate. - */ - switch (reloc->reloc_type) { - case R_ARM_CALL: - case R_ARM_JUMP24: { - guint32 *code = (guint32*)(gpointer)data; - guint32 ins = *code; - int diff = addr; - - if (reloc->reloc_type == R_ARM_CALL) - /* bl */ - g_assert (data [3] == 0xeb); - else - /* b */ - g_assert (data [3] == 0xea); - if (diff >= 0 && diff <= 33554431) { - diff >>= 2; - ins = (ins & 0xff000000) | diff; - *code = ins; - } else if (diff <= 0 && diff >= -33554432) { - diff >>= 2; - ins = (ins & 0xff000000) | (diff & ~0xff000000); - *code = ins; - } else { - g_assert_not_reached (); - } - break; - } - case R_ARM_ALU_PC_G0_NC: { - /* Generated by emit_plt () */ - guint8 *code = data; - guint32 val = addr; - - g_assert (val <= 0xffffff); - if (val & 0xff0000) - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_PC, (val & 0xFF0000) >> 16, 16); - else - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_PC, 0, 0); - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_IP, (val & 0xFF00) >> 8, 24); - ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, val & 0xFF); - break; - } - default: - g_assert_not_reached (); - } -#else - g_assert_not_reached (); -#endif -} - -static ElfReloc* -resolve_relocations (MonoImageWriter *acfg) -{ - BinReloc *reloc; - guint8 *data; - gsize end_val, start_val; - ElfReloc *rr; - int i; - gsize vaddr; - - rr = g_new0 (ElfReloc, acfg->num_relocs); - i = 0; - - for (reloc = acfg->relocations; reloc; reloc = reloc->next) { - resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); - /* FIXME: little endian */ - if (reloc->reloc_type) { - /* Must be static */ - g_assert (start_val > 0); - do_reloc (acfg, reloc, data, end_val); - } else { - data [0] = end_val; - data [1] = end_val >> 8; - data [2] = end_val >> 16; - data [3] = end_val >> 24; - } - // FIXME: - if (start_val == 0 && reloc->val1 [0] != '.') { - rr [i].r_offset = vaddr; - rr [i].r_info = R_386_RELATIVE; - ++i; - g_assert (i <= acfg->num_relocs); - } - } - return rr; -} - -#endif /* USE_ELF_RELA */ - -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) -{ - ElfHeader header; - ElfProgHeader progh [4]; - ElfSectHeader secth [SECT_NUM]; -#ifdef USE_ELF_RELA - ElfRelocA *relocs; -#else - ElfReloc *relocs; -#endif - ElfStrTable str_table = {NULL, NULL}; - ElfStrTable sh_str_table = {NULL, NULL}; - ElfStrTable dyn_str_table = {NULL, NULL}; - BinSection* all_sections [32]; - BinSection* sections [SECT_NUM]; - ElfSymbol *dynsym; - ElfSymbol *symtab; - ElfDynamic dynamic [14]; - int *hash; - int i, num_sections, file_offset, virt_offset, size; - int num_local_syms; - - /* Section headers */ - memset (§h, 0, sizeof (secth)); - memset (&dynamic, 0, sizeof (dynamic)); - memset (&header, 0, sizeof (header)); - - for (i = 1; i < SECT_NUM; ++i) { - secth [i].sh_name = str_table_add (&sh_str_table, section_info [i].name); - secth [i].sh_type = section_info [i].type; - secth [i].sh_addralign = section_info [i].align; - secth [i].sh_flags = section_info [i].flags; - secth [i].sh_entsize = section_info [i].esize; - } - secth [SECT_DYNSYM].sh_info = TARGET_SIZEOF_VOID_P == 4 ? 4 : 2; - secth [SECT_SYMTAB].sh_info = TARGET_SIZEOF_VOID_P == 4 ? 20 : 17; - secth [SECT_HASH].sh_link = SECT_DYNSYM; - secth [SECT_DYNSYM].sh_link = SECT_DYNSTR; - secth [SECT_REL_DYN].sh_link = SECT_DYNSYM; - secth [SECT_RELA_DYN].sh_link = SECT_DYNSYM; - secth [SECT_DYNAMIC].sh_link = SECT_DYNSTR; - secth [SECT_SYMTAB].sh_link = SECT_STRTAB; - - num_sections = collect_sections (acfg, secth, all_sections, 16); - hash = build_hash (acfg, num_sections, &dyn_str_table); -#if 0 - g_print ("num_sections: %d\n", num_sections); - g_print ("dynsym: %d, dynstr size: %d\n", hash [1], (int)dyn_str_table.data->len); - for (i = 0; i < num_sections; ++i) { - g_print ("section %s, size: %d, %x\n", all_sections [i]->name, all_sections [i]->cur_offset, all_sections [i]->cur_offset); - } -#endif - /* Associate the bin sections with the ELF sections */ - memset (sections, 0, sizeof (sections)); - for (i = 0; i < num_sections; ++i) { - BinSection *sect = all_sections [i]; - int j; - - for (j = 0; j < SECT_NUM; ++j) { - if (strcmp (sect->name, section_info [j].name) == 0) { - sect->shidx = j; - break; - } - } - - sections [all_sections [i]->shidx] = sect; - } - - /* at this point we know where in the file the first segment sections go */ - dynsym = collect_syms (acfg, hash, &dyn_str_table, NULL, NULL); - num_local_syms = hash [1]; - symtab = collect_syms (acfg, NULL, &str_table, secth, &num_local_syms); - - file_offset = virt_offset = sizeof (header) + sizeof (progh); - secth [SECT_HASH].sh_addr = secth [SECT_HASH].sh_offset = file_offset; - size = sizeof (int) * (2 + hash [0] + hash [1]); - virt_offset = (file_offset += size); - secth [SECT_HASH].sh_size = size; - secth [SECT_DYNSYM].sh_addr = secth [SECT_DYNSYM].sh_offset = file_offset; - size = sizeof (ElfSymbol) * hash [1]; - virt_offset = (file_offset += size); - secth [SECT_DYNSYM].sh_size = size; - secth [SECT_DYNSTR].sh_addr = secth [SECT_DYNSTR].sh_offset = file_offset; - size = dyn_str_table.data->len; - virt_offset = (file_offset += size); - secth [SECT_DYNSTR].sh_size = size; - file_offset += 4-1; - file_offset &= ~(4-1); - secth [SECT_REL_DYN].sh_addr = secth [SECT_REL_DYN].sh_offset = file_offset; -#ifndef USE_ELF_RELA - size = sizeof (ElfReloc) * acfg->num_relocs; -#else - size = 0; -#endif - virt_offset = (file_offset += size); - secth [SECT_REL_DYN].sh_size = size; - secth [SECT_RELA_DYN].sh_addr = secth [SECT_RELA_DYN].sh_offset = file_offset; -#ifdef USE_ELF_RELA - size = sizeof (ElfRelocA) * acfg->num_relocs; -#else - size = 0; -#endif - virt_offset = (file_offset += size); - secth [SECT_RELA_DYN].sh_size = size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_TEXT].sh_addralign); - virt_offset = file_offset; - secth [SECT_TEXT].sh_addr = secth [SECT_TEXT].sh_offset = file_offset; - if (sections [SECT_TEXT]) { - if (sections [SECT_TEXT]->has_addr) { - secth [SECT_TEXT].sh_addr = sections [SECT_TEXT]->addr; - secth [SECT_TEXT].sh_flags &= ~SHF_ALLOC; - } - size = sections [SECT_TEXT]->cur_offset; - secth [SECT_TEXT].sh_size = size; - 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; - - /* .dynamic, .got.plt, .data, .bss here */ - /* Have to increase the virt offset since these go to a separate segment */ - virt_offset += PAGESIZE; - secth [SECT_DYNAMIC].sh_addr = virt_offset; - secth [SECT_DYNAMIC].sh_offset = file_offset; - size = sizeof (dynamic); - secth [SECT_DYNAMIC].sh_size = size; - file_offset += size; - virt_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_GOT_PLT].sh_addralign); - virt_offset = ALIGN_TO (virt_offset, secth [SECT_GOT_PLT].sh_addralign); - secth [SECT_GOT_PLT].sh_addr = virt_offset; - secth [SECT_GOT_PLT].sh_offset = file_offset; - size = 3 * TARGET_SIZEOF_VOID_P; - secth [SECT_GOT_PLT].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; - secth [SECT_DATA].sh_offset = file_offset; - if (sections [SECT_DATA]) { - size = sections [SECT_DATA]->cur_offset; - secth [SECT_DATA].sh_size = size; - file_offset += size; - virt_offset += size; - } - - file_offset = ALIGN_TO (file_offset, secth [SECT_BSS].sh_addralign); - virt_offset = ALIGN_TO (virt_offset, secth [SECT_BSS].sh_addralign); - secth [SECT_BSS].sh_addr = virt_offset; - secth [SECT_BSS].sh_offset = file_offset; - if (sections [SECT_BSS]) { - size = sections [SECT_BSS]->cur_offset; - secth [SECT_BSS].sh_size = size; - } - - /* virtual doesn't matter anymore */ - file_offset = ALIGN_TO (file_offset, secth [SECT_DEBUG_FRAME].sh_addralign); - secth [SECT_DEBUG_FRAME].sh_offset = file_offset; - if (sections [SECT_DEBUG_FRAME]) - size = sections [SECT_DEBUG_FRAME]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_FRAME].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_INFO].sh_offset = file_offset; - if (sections [SECT_DEBUG_INFO]) - size = sections [SECT_DEBUG_INFO]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_INFO].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_ABBREV].sh_offset = file_offset; - if (sections [SECT_DEBUG_ABBREV]) - size = sections [SECT_DEBUG_ABBREV]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_ABBREV].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_LINE].sh_offset = file_offset; - if (sections [SECT_DEBUG_LINE]) - size = sections [SECT_DEBUG_LINE]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_LINE].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_LOC].sh_offset = file_offset; - if (sections [SECT_DEBUG_LOC]) - size = sections [SECT_DEBUG_LOC]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_LOC].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_SHSTRTAB].sh_addralign); - secth [SECT_SHSTRTAB].sh_offset = file_offset; - size = sh_str_table.data->len; - secth [SECT_SHSTRTAB].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_SYMTAB].sh_addralign); - secth [SECT_SYMTAB].sh_offset = file_offset; - size = sizeof (ElfSymbol) * num_local_syms; - secth [SECT_SYMTAB].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_STRTAB].sh_addralign); - secth [SECT_STRTAB].sh_offset = file_offset; - size = str_table.data->len; - secth [SECT_STRTAB].sh_size = size; - file_offset += size; - - for (i = 1; i < SECT_NUM; ++i) { - if (section_info [i].esize != 0) - g_assert (secth [i].sh_size % section_info [i].esize == 0); - } - - file_offset += 4-1; - file_offset &= ~(4-1); - - header.e_ident [EI_MAG0] = ELFMAG0; - header.e_ident [EI_MAG1] = ELFMAG1; - header.e_ident [EI_MAG2] = ELFMAG2; - header.e_ident [EI_MAG3] = ELFMAG3; - header.e_ident [EI_CLASS] = TARGET_SIZEOF_VOID_P == 4 ? ELFCLASS32 : ELFCLASS64; - header.e_ident [EI_DATA] = ELFDATA2LSB; - header.e_ident [EI_VERSION] = EV_CURRENT; - header.e_ident [EI_OSABI] = ELFOSABI_NONE; - header.e_ident [EI_ABIVERSION] = 0; - for (i = EI_PAD; i < EI_NIDENT; ++i) - header.e_ident [i] = 0; - - header.e_type = ET_DYN; -#if defined(TARGET_X86) - header.e_machine = EM_386; -#elif defined(TARGET_AMD64) - header.e_machine = EM_X86_64; -#elif defined(TARGET_ARM) - header.e_machine = EM_ARM; -#else - g_assert_not_reached (); -#endif - header.e_version = 1; - - header.e_phoff = sizeof (header); - header.e_ehsize = sizeof (header); - header.e_phentsize = sizeof (ElfProgHeader); - header.e_phnum = 4; - header.e_entry = secth [SECT_TEXT].sh_addr; - header.e_shstrndx = SECT_SHSTRTAB; - header.e_shentsize = sizeof (ElfSectHeader); - header.e_shnum = SECT_NUM; - header.e_shoff = file_offset; - - /* dynamic data */ - i = 0; - dynamic [i].d_tag = DT_HASH; - dynamic [i].d_un.d_val = secth [SECT_HASH].sh_offset; - ++i; - dynamic [i].d_tag = DT_STRTAB; - dynamic [i].d_un.d_val = secth [SECT_DYNSTR].sh_offset; - ++i; - dynamic [i].d_tag = DT_SYMTAB; - dynamic [i].d_un.d_val = secth [SECT_DYNSYM].sh_offset; - ++i; - dynamic [i].d_tag = DT_STRSZ; - dynamic [i].d_un.d_val = dyn_str_table.data->len; - ++i; - dynamic [i].d_tag = DT_SYMENT; - dynamic [i].d_un.d_val = sizeof (ElfSymbol); - ++i; -#ifdef USE_ELF_RELA - dynamic [i].d_tag = DT_RELA; - dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_offset; - ++i; - dynamic [i].d_tag = DT_RELASZ; - dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_size; - ++i; - dynamic [i].d_tag = DT_RELAENT; - dynamic [i].d_un.d_val = sizeof (ElfRelocA); - ++i; -#else - dynamic [i].d_tag = DT_REL; - dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_offset; - ++i; - dynamic [i].d_tag = DT_RELSZ; - dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_size; - ++i; - dynamic [i].d_tag = DT_RELENT; - dynamic [i].d_un.d_val = sizeof (ElfReloc); - ++i; -#endif - dynamic [i].d_tag = DT_RELCOUNT; - dynamic [i].d_un.d_val = acfg->num_relocs; - ++i; - - /* Program header */ - memset (&progh, 0, sizeof (progh)); - progh [0].p_type = PT_LOAD; - progh [0].p_filesz = progh [0].p_memsz = secth [SECT_DYNAMIC].sh_offset; - progh [0].p_align = 4096; - progh [0].p_flags = 5; - - progh [1].p_type = PT_LOAD; - progh [1].p_offset = secth [SECT_DYNAMIC].sh_offset; - progh [1].p_vaddr = progh [1].p_paddr = secth [SECT_DYNAMIC].sh_addr; - progh [1].p_filesz = secth [SECT_BSS].sh_offset - secth [SECT_DYNAMIC].sh_offset; - progh [1].p_memsz = secth [SECT_BSS].sh_addr + secth [SECT_BSS].sh_size - secth [SECT_DYNAMIC].sh_addr; - progh [1].p_align = 4096; - progh [1].p_flags = 6; - - progh [2].p_type = PT_DYNAMIC; - progh [2].p_offset = secth [SECT_DYNAMIC].sh_offset; - progh [2].p_vaddr = progh [2].p_paddr = secth [SECT_DYNAMIC].sh_addr; - progh [2].p_filesz = progh [2].p_memsz = secth [SECT_DYNAMIC].sh_size; - progh [2].p_align = TARGET_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 = TARGET_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]) { - sections [i]->file_offset = secth [i].sh_offset; - sections [i]->virt_offset = secth [i].sh_addr; - } - } - - reloc_symbols (acfg, dynsym, secth, &dyn_str_table, TRUE); - reloc_symbols (acfg, symtab, secth, &str_table, FALSE); - relocs = resolve_relocations (acfg); - - if (!acfg->fp) { - acfg->out_buf_size = file_offset + sizeof (secth); - acfg->out_buf = (guint8 *)g_malloc (acfg->out_buf_size); - } - - bin_writer_fwrite (acfg, &header, sizeof (header), 1); - bin_writer_fwrite (acfg, &progh, sizeof (progh), 1); - bin_writer_fwrite (acfg, hash, sizeof (int) * (hash [0] + hash [1] + 2), 1); - bin_writer_fwrite (acfg, dynsym, sizeof (ElfSymbol) * hash [1], 1); - bin_writer_fwrite (acfg, dyn_str_table.data->str, dyn_str_table.data->len, 1); - /* .rel.dyn */ - bin_writer_fseek (acfg, secth [SECT_REL_DYN].sh_offset); - bin_writer_fwrite (acfg, relocs, sizeof (ElfReloc), acfg->num_relocs); - - /* .rela.dyn */ - bin_writer_fseek (acfg, secth [SECT_RELA_DYN].sh_offset); - bin_writer_fwrite (acfg, relocs, secth [SECT_RELA_DYN].sh_size, 1); - - /* .text */ - if (sections [SECT_TEXT]) { - 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); - } - } - - bin_writer_fseek (acfg, secth [SECT_SHSTRTAB].sh_offset); - bin_writer_fwrite (acfg, sh_str_table.data->str, sh_str_table.data->len, 1); - bin_writer_fseek (acfg, secth [SECT_SYMTAB].sh_offset); - bin_writer_fwrite (acfg, symtab, sizeof (ElfSymbol) * num_local_syms, 1); - bin_writer_fseek (acfg, secth [SECT_STRTAB].sh_offset); - bin_writer_fwrite (acfg, str_table.data->str, str_table.data->len, 1); - /*g_print ("file_offset %d vs %d\n", file_offset, ftell (file));*/ - /*g_assert (file_offset >= ftell (file));*/ - bin_writer_fseek (acfg, file_offset); - bin_writer_fwrite (acfg, §h, sizeof (secth), 1); - - if (acfg->fp) - fclose (acfg->fp); - - return 0; -} - -#endif /* USE_ELF_WRITER */ - -#endif /* USE_BIN_WRITER */ - /* ASM WRITER */ static void @@ -1852,7 +336,6 @@ asm_writer_emit_alignment (MonoImageWriter *acfg, int size) #endif } -#ifndef USE_BIN_WRITER static void asm_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) { @@ -1863,7 +346,6 @@ asm_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) asm_writer_emit_alignment (acfg, size); #endif } -#endif static void asm_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) @@ -2019,27 +501,13 @@ asm_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) void mono_img_writer_emit_start (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_start (acfg); - else - asm_writer_emit_start (acfg); -#else asm_writer_emit_start (acfg); -#endif } void mono_img_writer_emit_section_change (MonoImageWriter *acfg, const char *section_name, int subsection_index) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_section_change (acfg, section_name, subsection_index); - else - asm_writer_emit_section_change (acfg, section_name, subsection_index); -#else asm_writer_emit_section_change (acfg, section_name, subsection_index); -#endif acfg->current_section = section_name; acfg->current_subsection = subsection_index; @@ -2067,229 +535,109 @@ mono_img_writer_emit_pop_section (MonoImageWriter *acfg) void mono_img_writer_set_section_addr (MonoImageWriter *acfg, guint64 addr) { -#ifdef USE_BIN_WRITER - if (!acfg->use_bin_writer) - NOT_IMPLEMENTED; - else - bin_writer_set_section_addr (acfg, addr); -#else NOT_IMPLEMENTED; -#endif } void mono_img_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_global (acfg, name, func); - else - asm_writer_emit_global (acfg, name, func); -#else asm_writer_emit_global (acfg, name, func); -#endif } void mono_img_writer_emit_local_symbol (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean func) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_local_symbol (acfg, name, end_label, func); - else - asm_writer_emit_local_symbol (acfg, name, end_label, func); -#else asm_writer_emit_local_symbol (acfg, name, end_label, func); -#endif } void mono_img_writer_emit_symbol_size (MonoImageWriter *acfg, const char *name, const char *end_label) { - if (!acfg->use_bin_writer) - asm_writer_emit_symbol_size (acfg, name, end_label); + asm_writer_emit_symbol_size (acfg, name, end_label); } void mono_img_writer_emit_label (MonoImageWriter *acfg, const char *name) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_label (acfg, name); - else - asm_writer_emit_label (acfg, name); -#else asm_writer_emit_label (acfg, name); -#endif } void mono_img_writer_emit_bytes (MonoImageWriter *acfg, const guint8* buf, int size) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_bytes (acfg, buf, size); - else - asm_writer_emit_bytes (acfg, buf, size); -#else asm_writer_emit_bytes (acfg, buf, size); -#endif } void mono_img_writer_emit_string (MonoImageWriter *acfg, const char *value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_string (acfg, value); - else - asm_writer_emit_string (acfg, value); -#else asm_writer_emit_string (acfg, value); -#endif } void mono_img_writer_emit_line (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_line (acfg); - else - asm_writer_emit_line (acfg); -#else - asm_writer_emit_line (acfg); -#endif + asm_writer_emit_line (acfg); } void mono_img_writer_emit_alignment (MonoImageWriter *acfg, int size) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_alignment (acfg, size); - else - asm_writer_emit_alignment (acfg, size); -#else asm_writer_emit_alignment (acfg, size); -#endif } void mono_img_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_alignment (acfg, size); - else - asm_writer_emit_alignment (acfg, size); -#else asm_writer_emit_alignment_fill (acfg, size, fill); -#endif } void mono_img_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_pointer_unaligned (acfg, target); - else - asm_writer_emit_pointer_unaligned (acfg, target); -#else asm_writer_emit_pointer_unaligned (acfg, target); -#endif } void mono_img_writer_emit_pointer (MonoImageWriter *acfg, const char *target) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_pointer (acfg, target); - else - asm_writer_emit_pointer (acfg, target); -#else asm_writer_emit_pointer (acfg, target); -#endif } void mono_img_writer_emit_int16 (MonoImageWriter *acfg, int value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_int16 (acfg, value); - else - asm_writer_emit_int16 (acfg, value); -#else asm_writer_emit_int16 (acfg, value); -#endif } void mono_img_writer_emit_int32 (MonoImageWriter *acfg, int value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_int32 (acfg, value); - else - asm_writer_emit_int32 (acfg, value); -#else asm_writer_emit_int32 (acfg, value); -#endif } void mono_img_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_symbol (acfg, symbol); - else - asm_writer_emit_symbol (acfg, symbol); -#else asm_writer_emit_symbol (acfg, symbol); -#endif } void mono_img_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_symbol_diff (acfg, end, start, offset); - else - asm_writer_emit_symbol_diff (acfg, end, start, offset); -#else asm_writer_emit_symbol_diff (acfg, end, start, offset); -#endif } void mono_img_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_zero_bytes (acfg, num); - else - asm_writer_emit_zero_bytes (acfg, num); -#else asm_writer_emit_zero_bytes (acfg, num); -#endif } int mono_img_writer_emit_writeout (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - return bin_writer_emit_writeout (acfg); - else - return asm_writer_emit_writeout (acfg); -#else - return asm_writer_emit_writeout (acfg); -#endif + return asm_writer_emit_writeout (acfg); } void @@ -2305,15 +653,7 @@ mono_img_writer_emit_byte (MonoImageWriter *acfg, guint8 val) void mono_img_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *symbol, int addend) { - /* This is only supported by the bin writer */ -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_reloc (acfg, reloc_type, symbol, addend); - else - g_assert_not_reached (); -#else - g_assert_not_reached (); -#endif + g_assert_not_reached (); } /* @@ -2325,8 +665,7 @@ mono_img_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *s void mono_img_writer_emit_unset_mode (MonoImageWriter *acfg) { - if (!acfg->use_bin_writer) - asm_writer_emit_unset_mode (acfg); + asm_writer_emit_unset_mode (acfg); } /* @@ -2338,55 +677,23 @@ mono_img_writer_emit_unset_mode (MonoImageWriter *acfg) guint8* mono_img_writer_get_output (MonoImageWriter *acfg, guint32 *size) { -#ifdef USE_BIN_WRITER - guint8 *buf; - - g_assert (acfg->use_bin_writer); - - buf = acfg->out_buf; - *size = acfg->out_buf_size; - acfg->out_buf = NULL; - return buf; -#else g_assert_not_reached (); return NULL; -#endif -} - -/* - * Return whenever the binary writer is supported on this platform. - */ -gboolean -mono_bin_writer_supported (void) -{ -#ifdef USE_BIN_WRITER - return TRUE; -#else - return FALSE; -#endif } /* * mono_img_writer_create: * - * Create an image writer writing to FP. If USE_BIN_WRITER is TRUE, FP can be NULL, - * in this case the image writer will write to a memory buffer obtainable by calling - * mono_img_writer_get_output (). + * Create an image writer writing to FP. */ MonoImageWriter* -mono_img_writer_create (FILE *fp, gboolean use_bin_writer) +mono_img_writer_create (FILE *fp) { MonoImageWriter *w = g_new0 (MonoImageWriter, 1); - -#ifndef USE_BIN_WRITER - g_assert (!use_bin_writer); -#endif - if (!use_bin_writer) - g_assert (fp); + g_assert (fp); w->fp = fp; - w->use_bin_writer = use_bin_writer; w->mempool = mono_mempool_new (); return w; @@ -2404,7 +711,7 @@ gboolean mono_img_writer_subsections_supported (MonoImageWriter *acfg) { #ifdef TARGET_ASM_APPLE - return acfg->use_bin_writer; + return FALSE; #else return TRUE; #endif diff --git a/src/mono/mono/mini/image-writer.h b/src/mono/mono/mini/image-writer.h index 309ec37c059a7..c6d855fa1b410 100644 --- a/src/mono/mono/mini/image-writer.h +++ b/src/mono/mono/mini/image-writer.h @@ -22,39 +22,7 @@ typedef struct _MonoImageWriter MonoImageWriter; -#if defined(TARGET_AMD64) && !defined(HOST_WIN32) && !defined(__APPLE__) -#define USE_ELF_WRITER 1 -#define USE_ELF_RELA 1 -#endif - -#if defined(TARGET_X86) && !defined(HOST_WIN32) && !defined(__APPLE__) -#define USE_ELF_WRITER 1 -#endif - -#if defined(TARGET_ARM) && !defined(TARGET_MACH) && !defined(HOST_WIN32) -//#define USE_ELF_WRITER 1 -#endif - -#if defined(__mips__) -#define USE_ELF_WRITER 1 -#endif - -#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 - -/* Relocation types */ -#define R_ARM_CALL 28 -#define R_ARM_JUMP24 29 -#define R_ARM_ALU_PC_G0_NC 59 - -gboolean mono_bin_writer_supported (void); - -MonoImageWriter* mono_img_writer_create (FILE *fp, gboolean use_bin_writer); +MonoImageWriter* mono_img_writer_create (FILE *fp); void mono_img_writer_destroy (MonoImageWriter *w); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 36400c7e9fdbb..bea43f236a65c 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -523,7 +523,6 @@ mono_tramp_info_register_internal (MonoTrampInfo *info, MonoMemoryManager *mem_m copy->uw_info_len = info->uw_info_len; } - mono_save_trampoline_xdebug_info (info); mono_lldb_save_trampoline_info (info); #ifdef MONO_ARCH_HAVE_UNWIND_TABLE @@ -3934,7 +3933,7 @@ mini_parse_debug_option (const char *option) else if (!strcmp (option, "dyn-runtime-invoke")) mini_debug_options.dyn_runtime_invoke = TRUE; else if (!strcmp (option, "gdb")) - mini_debug_options.gdb = TRUE; + fprintf (stderr, "MONO_DEBUG=gdb is deprecated."); else if (!strcmp (option, "lldb")) mini_debug_options.lldb = TRUE; else if (!strcmp (option, "llvm-disable-inlining")) @@ -4431,21 +4430,6 @@ mini_init (const char *filename, const char *runtime_version) mono_dont_free_domains = TRUE; } -#ifdef XDEBUG_ENABLED - char *mono_xdebug = g_getenv ("MONO_XDEBUG"); - if (mono_xdebug) { - mono_xdebug_init (mono_xdebug); - g_free (mono_xdebug); - /* So methods for multiple domains don't have the same address */ - mono_dont_free_domains = TRUE; - mono_using_xdebug = TRUE; - } else if (mini_debug_options.gdb) { - mono_xdebug_init ((char*)"gdb"); - mono_dont_free_domains = TRUE; - mono_using_xdebug = TRUE; - } -#endif - #ifdef ENABLE_LLVM if (mono_use_llvm) mono_llvm_init (!mono_compile_aot); diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index 2e349a35ed031..562d98eb5357d 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -245,7 +245,6 @@ typedef struct MonoDebugOptions { gboolean suspend_on_exception; gboolean suspend_on_unhandled; gboolean dyn_runtime_invoke; - gboolean gdb; gboolean lldb; /* @@ -571,10 +570,6 @@ MONO_API char *mono_pmip (void *ip); MONO_API int mono_ee_api_version (void); gboolean mono_debug_count (void); -#ifdef __linux__ -#define XDEBUG_ENABLED 1 -#endif - #ifdef __linux__ /* maybe enable also for other systems? */ #define ENABLE_JIT_MAP 1 diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 28ce38aa7b6b7..f3cfa3895e67a 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -83,7 +83,6 @@ int mono_inject_async_exc_pos; MonoMethodDesc *mono_break_at_bb_method; int mono_break_at_bb_bb_num; gboolean mono_do_x86_stack_align = TRUE; -gboolean mono_using_xdebug; /* Counters */ static guint32 discarded_code; @@ -2046,19 +2045,9 @@ mono_codegen (MonoCompile *cfg) MonoBasicBlock *bb; int max_epilog_size; guint8 *code; - MonoMemoryManager *code_mem_manager; + MonoMemoryManager *code_mem_manager = cfg->mem_manager; guint unwindlen = 0; - if (mono_using_xdebug) - /* - * Recent gdb versions have trouble processing symbol files containing - * overlapping address ranges, so allocate all code from the code manager - * of the root domain. (#666152). - */ - code_mem_manager = get_default_mem_manager (); - else - code_mem_manager = cfg->mem_manager; - for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { cfg->spill_count = 0; /* we reuse dfn here */ @@ -2133,11 +2122,7 @@ mono_codegen (MonoCompile *cfg) g_hash_table_insert (jit_mm->dynamic_code_hash, cfg->method, cfg->dynamic_info); jit_mm_unlock (jit_mm); - if (mono_using_xdebug) - /* See the comment for cfg->code_domain */ - code = (guint8 *)mono_mem_manager_code_reserve (code_mem_manager, cfg->code_size + cfg->thunk_area + unwindlen); - else - code = (guint8 *)mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen); + code = (guint8 *)mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen); } else { code = (guint8 *)mono_mem_manager_code_reserve (code_mem_manager, cfg->code_size + cfg->thunk_area + unwindlen); } @@ -2220,10 +2205,7 @@ mono_codegen (MonoCompile *cfg) } if (cfg->method->dynamic) { - if (mono_using_xdebug) - mono_mem_manager_code_commit (code_mem_manager, cfg->native_code, cfg->code_size, cfg->code_len); - else - mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len); + mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len); } else { mono_mem_manager_code_commit (code_mem_manager, cfg->native_code, cfg->code_size, cfg->code_len); } @@ -3381,18 +3363,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts cfg->disable_out_of_line_bblocks = TRUE; } - if (mono_using_xdebug) { - /* - * Make each variable use its own register/stack slot and extend - * their liveness to cover the whole method, making them displayable - * in gdb even after they are dead. - */ - cfg->disable_reuse_registers = TRUE; - cfg->disable_reuse_stack_slots = TRUE; - cfg->extend_live_ranges = TRUE; - cfg->compute_precise_live_ranges = TRUE; - } - mini_gc_init_cfg (cfg); if (method->wrapper_type == MONO_WRAPPER_OTHER) { @@ -3932,10 +3902,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts MONO_TIME_TRACK (mono_jit_stats.jit_gc_create_gc_map, mini_gc_create_gc_map (cfg)); MONO_TIME_TRACK (mono_jit_stats.jit_save_seq_point_info, mono_save_seq_point_info (cfg, cfg->jit_info)); - if (!cfg->compile_aot) { - mono_save_xdebug_info (cfg); + if (!cfg->compile_aot) mono_lldb_save_method_info (cfg); - } if (cfg->verbose_level >= 2) { char *id = mono_method_full_name (cfg->method, TRUE); diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index e454d89ef41b8..5001ee38ddd09 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -365,7 +365,6 @@ extern int mono_inject_async_exc_pos; extern MonoMethodDesc *mono_break_at_bb_method; extern int mono_break_at_bb_bb_num; extern gboolean mono_do_x86_stack_align; -extern gboolean mono_using_xdebug; extern int mini_verbose; extern int valgrind_register; @@ -2206,12 +2205,6 @@ void mono_liveness_handle_exception_clauses (MonoCompile *cfg); gpointer mono_realloc_native_code (MonoCompile *cfg); -void mono_xdebug_init (const char *xdebug_opts); -void mono_save_xdebug_info (MonoCompile *cfg); -void mono_save_trampoline_xdebug_info (MonoTrampInfo *info); -/* This is an exported function */ -void mono_xdebug_flush (void); - void mono_register_opcode_emulation (int opcode, const char* name, MonoMethodSignature *sig, gpointer func, gboolean no_throw); void mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options); void mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst); diff --git a/src/mono/mono/mini/xdebug.c b/src/mono/mono/mini/xdebug.c deleted file mode 100644 index 868acaafacb01..0000000000000 --- a/src/mono/mono/mini/xdebug.c +++ /dev/null @@ -1,398 +0,0 @@ -/** - * \file - * Support for emitting gdb debug info for JITted code. - * - * Author: - * Zoltan Varga (vargaz@gmail.com) - * - * (C) 2010 Novell, Inc. - */ - -/* - * This works as follows: - * - the runtime writes out an xdb.s file containing DWARF debug info. - * - the user calls a gdb macro - * - the macro compiles and loads this shared library using add-symbol-file. - * - * This is based on the xdebug functionality in the Kaffe Java VM. - * - * We emit assembly code instead of using the ELF writer, so we can emit debug info - * incrementally as each method is JITted, and the debugger doesn't have to call - * into the runtime to emit the shared library, which would cause all kinds of - * complications, like threading issues, and the fact that the ELF writer's - * emit_writeout () function cannot be called more than once. - * GDB 7.0 and later has a JIT interface. - */ - -#include "config.h" -#include -#include "mini.h" -#include "mini-runtime.h" - -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include -#include -#ifndef HOST_WIN32 -#include -#else -#include -#include -#endif - -#include -#include - -#include "image-writer.h" - -#if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) && USE_BIN_WRITER - -#include "dwarfwriter.h" - -#include "mono/utils/mono-compiler.h" - -#define USE_GDB_JIT_INTERFACE - -/* The recommended gdb macro is: */ -/* - define xdb - shell rm -f xdb.so && as --64 -o xdb.o xdb.s && ld -shared -o xdb.so xdb.o - add-symbol-file xdb.so 0 - end -*/ - -/* - * GDB JIT interface definitions. - * - * http://sources.redhat.com/gdb/onlinedocs/gdb_30.html - */ -typedef enum -{ - JIT_NOACTION = 0, - JIT_REGISTER_FN, - JIT_UNREGISTER_FN -} jit_actions_t; - -struct jit_code_entry; -typedef struct jit_code_entry jit_code_entry; - -struct jit_code_entry -{ - jit_code_entry *next_entry; - jit_code_entry *prev_entry; - const char *symfile_addr; - /* - * The gdb code in gdb/jit.c which reads this structure ignores alignment - * requirements, so use two 32 bit fields. - */ - guint32 symfile_size1, symfile_size2; -}; - -typedef struct jit_descriptor -{ - guint32 version; - /* This type should be jit_actions_t, but we use guint32 - to be explicit about the bitwidth. */ - guint32 action_flag; - jit_code_entry *relevant_entry; - jit_code_entry *first_entry; -} jit_descriptor; - -G_BEGIN_DECLS - -/* GDB puts a breakpoint in this function. */ -void MONO_NEVER_INLINE __jit_debug_register_code(void); - -#if defined(ENABLE_LLVM) && !defined(MONO_CROSS_COMPILE) - -/* LLVM already defines these */ - -extern jit_descriptor __jit_debug_descriptor; - -#else - -/* gcc seems to inline/eliminate calls to noinline functions, thus the asm () */ -void MONO_NEVER_INLINE __jit_debug_register_code(void) { -#if defined(__GNUC__) - asm (""); -#endif -} - -/* Make sure to specify the version statically, because the - debugger may check the version before we can set it. */ -jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; - -#endif - -G_END_DECLS - -static MonoImageWriter *xdebug_w; -static MonoDwarfWriter *xdebug_writer; -static FILE *xdebug_fp, *il_file; -static gboolean use_gdb_interface, save_symfiles; -static int il_file_line_index; -static GHashTable *xdebug_syms; - -void -mono_xdebug_init (const char *options) -{ - MonoImageWriter *w; - char **args, **ptr; - - args = g_strsplit (options, ",", -1); - for (ptr = args; ptr && *ptr; ptr ++) { - char *arg = *ptr; - - if (!strcmp (arg, "gdb")) - use_gdb_interface = TRUE; - if (!strcmp (arg, "save-symfiles")) - save_symfiles = TRUE; - } - - /* This file will contain the IL code for methods which don't have debug info */ - il_file = fopen ("xdb.il", "w"); - if (il_file == NULL) { - use_gdb_interface = FALSE; - g_warning ("** Unable to create xdb.il. Managed symbol names won't be available."); - return; - } - - if (use_gdb_interface) - return; - - unlink ("xdb.s"); - xdebug_fp = fopen ("xdb.s", "w"); - - w = mono_img_writer_create (xdebug_fp, FALSE); - - mono_img_writer_emit_start (w); - - xdebug_writer = mono_dwarf_writer_create (w, il_file, 0, TRUE); - - /* Emit something so the file has a text segment */ - mono_img_writer_emit_section_change (w, ".text", 0); - mono_img_writer_emit_string (w, ""); - - mono_dwarf_writer_emit_base_info (xdebug_writer, "JITted code", mono_unwind_get_cie_program ()); -} - -static void -xdebug_begin_emit (MonoImageWriter **out_w, MonoDwarfWriter **out_dw) -{ - MonoImageWriter *w; - MonoDwarfWriter *dw; - - w = mono_img_writer_create (NULL, TRUE); - - mono_img_writer_emit_start (w); - - /* This file will contain the IL code for methods which don't have debug info */ - if (!il_file) - il_file = fopen ("xdb.il", "w"); - - dw = mono_dwarf_writer_create (w, il_file, il_file_line_index, TRUE); - - mono_dwarf_writer_emit_base_info (dw, "JITted code", mono_unwind_get_cie_program ()); - - *out_w = w; - *out_dw = dw; -} - -static void -xdebug_end_emit (MonoImageWriter *w, MonoDwarfWriter *dw, MonoMethod *method) -{ - guint8 *img; - guint32 img_size; - jit_code_entry *entry; - guint64 *psize; - - il_file_line_index = mono_dwarf_writer_get_il_file_line_index (dw); - mono_dwarf_writer_close (dw); - - mono_img_writer_emit_writeout (w); - - img = mono_img_writer_get_output (w, &img_size); - - mono_img_writer_destroy (w); - - if (FALSE) { - /* Save the symbol files to help debugging */ - FILE *fp; - char *file_name; - static int file_counter; - - file_counter ++; - file_name = g_strdup_printf ("xdb-%d.o", file_counter); - printf ("%s %p %d\n", file_name, img, img_size); - - fp = fopen (file_name, "w"); - fwrite (img, img_size, 1, fp); - fclose (fp); - g_free (file_name); - } - - /* Register the image with GDB */ - - entry = g_malloc0 (sizeof (jit_code_entry)); - - entry->symfile_addr = (const char*)img; - psize = (guint64*)&entry->symfile_size1; - *psize = img_size; - - entry->next_entry = __jit_debug_descriptor.first_entry; - if (__jit_debug_descriptor.first_entry) - __jit_debug_descriptor.first_entry->prev_entry = entry; - __jit_debug_descriptor.first_entry = entry; - - __jit_debug_descriptor.relevant_entry = entry; - __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; - - __jit_debug_register_code (); -} - -/* - * mono_xdebug_flush: - * - * This could be called from inside gdb to flush the debugging information not yet - * registered with gdb. - */ -void -mono_xdebug_flush (void) -{ - if (xdebug_w) - xdebug_end_emit (xdebug_w, xdebug_writer, NULL); - - xdebug_begin_emit (&xdebug_w, &xdebug_writer); -} - -static int xdebug_method_count; - -/* - * mono_save_xdebug_info: - * - * Emit debugging info for METHOD into an assembly file which can be assembled - * and loaded into gdb to provide debugging info for JITted code. - * LOCKING: Acquires the loader lock. - */ -void -mono_save_xdebug_info (MonoCompile *cfg) -{ - MonoDebugMethodJitInfo *dmji; - - if (use_gdb_interface) { - mono_loader_lock (); - - if (!xdebug_syms) - xdebug_syms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - /* - * gdb is not designed to handle 1000s of symbol files (one per method). So we - * group them into groups of 100. - */ - if ((xdebug_method_count % 100) == 0) - mono_xdebug_flush (); - - xdebug_method_count ++; - - dmji = mono_debug_find_method (jinfo_get_method (cfg->jit_info), mono_domain_get ()); - mono_dwarf_writer_emit_method (xdebug_writer, cfg, jinfo_get_method (cfg->jit_info), NULL, NULL, NULL, - (guint8*)cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji); - mono_debug_free_method_jit_info (dmji); - -#if 0 - /* - * Emit a symbol for the code by emitting it at the beginning of the text - * segment, and setting the text segment to have an absolute address. - * This symbol can be used to set breakpoints in gdb. - * FIXME: This doesn't work when multiple methods are emitted into the same file. - */ - sym = get_debug_sym (cfg->jit_info->method, "", xdebug_syms); - mono_img_writer_emit_section_change (w, ".text", 0); - if (!xdebug_text_addr) { - xdebug_text_addr = cfg->jit_info->code_start; - mono_img_writer_set_section_addr (w, (gssize)xdebug_text_addr); - } - mono_img_writer_emit_global_with_size (w, sym, cfg->jit_info->code_size, TRUE); - mono_img_writer_emit_label (w, sym); - mono_img_writer_emit_bytes (w, cfg->jit_info->code_start, cfg->jit_info->code_size); - g_free (sym); -#endif - - mono_loader_unlock (); - } else { - if (!xdebug_writer) - return; - - mono_loader_lock (); - dmji = mono_debug_find_method (jinfo_get_method (cfg->jit_info), mono_domain_get ()); - mono_dwarf_writer_emit_method (xdebug_writer, cfg, jinfo_get_method (cfg->jit_info), NULL, NULL, NULL, - (guint8*)cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji); - mono_debug_free_method_jit_info (dmji); - fflush (xdebug_fp); - mono_loader_unlock (); - } - -} - -/* - * mono_save_trampoline_xdebug_info: - * - * Same as mono_save_xdebug_info, but for trampolines. - * LOCKING: Acquires the loader lock. - */ -void -mono_save_trampoline_xdebug_info (MonoTrampInfo *info) -{ - const char *info_name = info->name; - if (info_name == NULL) - info_name = ""; - - if (use_gdb_interface) { - MonoImageWriter *w; - MonoDwarfWriter *dw; - - /* This can be called before the loader lock is initialized */ - mono_loader_lock_if_inited (); - - xdebug_begin_emit (&w, &dw); - - mono_dwarf_writer_emit_trampoline (dw, info_name, NULL, NULL, info->code, info->code_size, info->unwind_ops); - - xdebug_end_emit (w, dw, NULL); - - mono_loader_unlock_if_inited (); - } else { - if (!xdebug_writer) - return; - - mono_loader_lock_if_inited (); - mono_dwarf_writer_emit_trampoline (xdebug_writer, info_name, NULL, NULL, info->code, info->code_size, info->unwind_ops); - fflush (xdebug_fp); - mono_loader_unlock_if_inited (); - } -} - -#else /* !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */ - -void -mono_xdebug_init (const char *options) -{ -} - -void -mono_save_xdebug_info (MonoCompile *cfg) -{ -} - -void -mono_save_trampoline_xdebug_info (MonoTrampInfo *info) -{ -} - -#endif