+ (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
+ (method->wrapper_type != MONO_WRAPPER_NONE)) {
+ mono_debug_add_wrapper (method, jit);
+ return NULL;
+ }
+
+ mono_debugger_lock ();
+
+ handle = _mono_debug_get_image (method->klass->image);
+ if (!handle || !handle->symfile || !handle->symfile->offset_table) {
+ mono_debugger_unlock ();
+ return NULL;
+ }
+
+ minfo = _mono_debug_lookup_method (method);
+ if (!minfo) {
+ mono_debugger_unlock ();
+ return NULL;
+ }
+
+ max_size = 24 + 8 * jit->num_line_numbers + 16 * minfo->num_lexical_blocks + 20 * (1 + jit->num_params + jit->num_locals);
+ if (max_size > BUFSIZ)
+ ptr = oldptr = g_malloc (max_size);
+ else
+ ptr = oldptr = buffer;
+
+ write_leb128 (jit->prologue_end, ptr, &ptr);
+ write_leb128 (jit->epilogue_begin, ptr, &ptr);
+
+ write_leb128 (jit->num_line_numbers, ptr, &ptr);
+ for (i = 0; i < jit->num_line_numbers; i++) {
+ MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
+
+ write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
+ write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
+
+ last_il_offset = lne->il_offset;
+ last_native_offset = lne->native_offset;
+ }
+
+ jit->num_lexical_blocks = minfo->num_lexical_blocks;
+ jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
+ for (i = 0; i < jit->num_lexical_blocks; i ++) {
+ MonoDebugLexicalBlockEntry *jit_lbe = &jit->lexical_blocks [i];
+ MonoSymbolFileLexicalBlockEntry *minfo_lbe = &minfo->lexical_blocks [i];
+ jit_lbe->il_start_offset = minfo_lbe->_start_offset;
+ jit_lbe->native_start_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_start_offset);
+
+ jit_lbe->il_end_offset = minfo_lbe->_end_offset;
+ jit_lbe->native_end_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_end_offset);
+ }
+
+ last_il_offset = 0;
+ last_native_offset = 0;
+ write_leb128 (jit->num_lexical_blocks, ptr, &ptr);
+ for (i = 0; i < jit->num_lexical_blocks; i++) {
+ MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
+
+ write_sleb128 (lbe->il_start_offset - last_il_offset, ptr, &ptr);
+ write_sleb128 (lbe->native_start_offset - last_native_offset, ptr, &ptr);
+
+ last_il_offset = lbe->il_start_offset;
+ last_native_offset = lbe->native_start_offset;
+
+ write_sleb128 (lbe->il_end_offset - last_il_offset, ptr, &ptr);
+ write_sleb128 (lbe->native_end_offset - last_native_offset, ptr, &ptr);
+
+ last_il_offset = lbe->il_end_offset;
+ last_native_offset = lbe->native_end_offset;
+ }
+
+ *ptr++ = jit->this_var ? 1 : 0;
+ if (jit->this_var)
+ write_variable (jit->this_var, ptr, &ptr);
+
+ write_leb128 (jit->num_params, ptr, &ptr);
+ for (i = 0; i < jit->num_params; i++)
+ write_variable (&jit->params [i], ptr, &ptr);
+
+ write_leb128 (jit->num_locals, ptr, &ptr);
+ for (i = 0; i < jit->num_locals; i++)
+ write_variable (&jit->locals [i], ptr, &ptr);
+
+ size = ptr - oldptr;
+ g_assert (size < max_size);
+ total_size = size + sizeof (MonoDebugMethodAddress);
+
+ if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
+ // FIXME: Maybe we should print a warning here.
+ // This should only happen for very big methods, for instance
+ // with more than 40.000 line numbers and more than 5.000
+ // local variables.
+ mono_debugger_unlock ();
+ return NULL;
+ }
+
+ address = (MonoDebugMethodAddress *) allocate_data_item (MONO_DEBUG_DATA_ITEM_METHOD, total_size);
+
+ address->size = total_size;
+ address->symfile_id = handle->index;
+ address->domain_id = mono_domain_get_id (domain);
+ address->method_id = minfo->index;
+ address->code_start = jit->code_start;
+ address->code_size = jit->code_size;
+ address->wrapper_addr = jit->wrapper_addr;
+
+ memcpy (&address->data, oldptr, size);
+
+ if (max_size > BUFSIZ)
+ g_free (oldptr);
+
+ hash = g_new0 (MethodHashEntry, 1);
+ hash->symfile_id = address->symfile_id;
+ hash->domain_id = address->domain_id;
+ hash->method_id = address->method_id;
+
+ g_hash_table_insert (method_hash, hash, address);
+
+ mono_debugger_unlock ();
+
+ return address;
+}
+
+static inline guint32
+read_leb128 (guint8 *ptr, guint8 **rptr)
+{
+ guint32 result = 0, shift = 0;
+
+ while (TRUE) {
+ guint8 byte = *ptr++;
+
+ result |= (byte & 0x7f) << shift;
+ if ((byte & 0x80) == 0)
+ break;
+ shift += 7;
+ }
+
+ *rptr = ptr;
+ return result;
+}
+
+static inline gint32
+read_sleb128 (guint8 *ptr, guint8 **rptr)
+{
+ gint32 result = 0;
+ guint32 shift = 0;
+
+ while (TRUE) {
+ guint8 byte = *ptr++;
+
+ result |= (byte & 0x7f) << shift;
+ shift += 7;
+
+ if (byte & 0x80)
+ continue;
+
+ if ((shift < 32) && (byte & 0x40))
+ result |= - (1 << shift);
+ break;
+ }
+
+ *rptr = ptr;
+ return result;
+}
+
+static void
+read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
+{
+ var->index = read_leb128 (ptr, &ptr);
+ var->offset = read_sleb128 (ptr, &ptr);
+ var->size = read_leb128 (ptr, &ptr);
+ var->begin_scope = read_leb128 (ptr, &ptr);
+ var->end_scope = read_leb128 (ptr, &ptr);
+ *rptr = ptr;
+}
+
+MonoDebugMethodJitInfo *
+mono_debug_read_method (MonoDebugMethodAddress *address)
+{
+ MonoDebugMethodJitInfo *jit;
+ guint32 i, il_offset = 0, native_offset = 0;
+ guint8 *ptr;
+
+ if (address->jit)
+ return address->jit;
+
+ jit = address->jit = g_new0 (MonoDebugMethodJitInfo, 1);
+ jit->code_start = address->code_start;
+ jit->code_size = address->code_size;
+ jit->wrapper_addr = address->wrapper_addr;
+
+ ptr = (guint8 *) &address->data;
+
+ jit->prologue_end = read_leb128 (ptr, &ptr);
+ jit->epilogue_begin = read_leb128 (ptr, &ptr);
+
+ jit->num_line_numbers = read_leb128 (ptr, &ptr);
+ jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
+ for (i = 0; i < jit->num_line_numbers; i++) {
+ MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
+
+ il_offset += read_sleb128 (ptr, &ptr);
+ native_offset += read_sleb128 (ptr, &ptr);
+
+ lne->il_offset = il_offset;
+ lne->native_offset = native_offset;
+ }
+
+ il_offset = 0;
+ native_offset = 0;
+ jit->num_lexical_blocks = read_leb128 (ptr, &ptr);
+ jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
+ for (i = 0; i < jit->num_lexical_blocks; i ++) {
+ MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
+
+ il_offset += read_sleb128 (ptr, &ptr);
+ native_offset += read_sleb128 (ptr, &ptr);
+
+ lbe->il_start_offset = il_offset;
+ lbe->native_start_offset = native_offset;
+
+ il_offset += read_sleb128 (ptr, &ptr);
+ native_offset += read_sleb128 (ptr, &ptr);
+
+ lbe->il_end_offset = il_offset;
+ lbe->native_end_offset = native_offset;
+ }
+
+ if (*ptr++) {
+ jit->this_var = g_new0 (MonoDebugVarInfo, 1);
+ read_variable (jit->this_var, ptr, &ptr);
+ }
+
+ jit->num_params = read_leb128 (ptr, &ptr);
+ jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
+ for (i = 0; i < jit->num_params; i++)
+ read_variable (&jit->params [i], ptr, &ptr);
+
+ jit->num_locals = read_leb128 (ptr, &ptr);
+ jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
+ for (i = 0; i < jit->num_locals; i++)
+ read_variable (&jit->locals [i], ptr, &ptr);
+
+ return jit;
+}
+
+void
+mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
+{
+ if (jit->address)
+ jit->address->jit = NULL;
+
+ g_free (jit->line_numbers);
+ g_free (jit->this_var);
+ g_free (jit->params);
+ g_free (jit->locals);
+ g_free (jit);
+}
+
+/*
+ * This is called via the `mono_debugger_class_init_func' from mono_class_init() each time
+ * a new class is initialized.
+ */
+static void
+mono_debug_start_add_type (MonoClass *klass)
+{
+ MonoDebugHandle *handle;
+
+ handle = _mono_debug_get_image (klass->image);
+ if (!handle)