+
+ 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)
+ return;
+}
+
+static guint32
+get_token (MonoClass *klass)
+{
+ while (klass->rank)
+ klass = klass->element_class;
+
+ return klass->type_token;
+}
+
+static void
+mono_debug_add_type (MonoClass *klass)
+{
+ MonoDebugHandle *handle;
+ MonoDebugClassEntry *entry;
+ char buffer [BUFSIZ];
+ guint8 *ptr, *oldptr;
+ guint32 token, size, total_size, max_size;
+ int base_offset = 0;
+
+ handle = _mono_debug_get_image (klass->image);
+ if (!handle)
+ return;
+
+ if (klass->generic_class ||
+ (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
+ return;
+
+ max_size = 12 + sizeof (gpointer);
+ if (max_size > BUFSIZ)
+ ptr = oldptr = g_malloc (max_size);
+ else
+ ptr = oldptr = buffer;
+
+ token = get_token (klass);
+ if (!token)
+ return;
+
+ if (klass->valuetype)
+ base_offset = - (int)(sizeof (MonoObject));
+
+ write_leb128 (token, ptr, &ptr);
+ write_leb128 (klass->rank, ptr, &ptr);
+ write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
+ WRITE_UNALIGNED (gpointer, ptr, klass);
+ ptr += sizeof (gpointer);
+
+ size = ptr - oldptr;
+ g_assert (size < max_size);
+ total_size = size + sizeof (MonoDebugClassEntry);
+
+ 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.
+ return;
+ }
+
+ entry = (MonoDebugClassEntry *) allocate_data_item (MONO_DEBUG_DATA_ITEM_CLASS, total_size);
+
+ entry->size = total_size;
+ entry->symfile_id = handle->index;
+
+ memcpy (&entry->data, oldptr, size);
+
+ if (max_size > BUFSIZ)
+ g_free (oldptr);
+
+ mono_debugger_start_add_type (handle, klass);
+}
+
+static MonoDebugMethodJitInfo *
+find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
+{
+ MethodHashEntry lookup;
+ MonoDebugMethodAddress *address;
+
+ lookup.symfile_id = minfo->handle->index;
+ lookup.domain_id = mono_domain_get_id (domain);
+ lookup.method_id = minfo->index;
+
+ address = g_hash_table_lookup (method_hash, &lookup);
+ if (!address)
+ return NULL;
+
+ return mono_debug_read_method (address);