#define DATA_TABLE_PTR_CHUNK_SIZE 256
#define DATA_TABLE_CHUNK_SIZE 32768
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+#if NO_UNALIGNED_ACCESS
+#define RETURN_UNALIGNED(type, addr) \
+ { \
+ type val; \
+ memcpy(&val, p + offset, sizeof(val)); \
+ return val; \
+ }
+#define WRITE_UNALIGNED(type, addr, val) \
+ memcpy(addr, &val, sizeof(type))
+#else
+#define RETURN_UNALIGNED(type, addr) \
+ return *(type*)(p + offset);
+#define WRITE_UNALIGNED(type, addr, val) \
+ (*(type *)(addr) = (val))
+#endif
+
MonoSymbolTable *mono_symbol_table = NULL;
MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
mono_debug_format = format;
in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER;
- if (in_the_mono_debugger)
- mono_debugger_initialize ();
+ mono_debugger_initialize (in_the_mono_debugger);
mono_debugger_lock ();
mono_debugger_start_class_init_func = mono_debug_start_add_type;
mono_debugger_class_init_func = mono_debug_add_type;
mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
+
+ if (!in_the_mono_debugger)
+ mono_debugger_unlock ();
}
void
mono_debug_open_image (mono_assembly_get_image (assembly));
}
+gboolean
+mono_debug_using_mono_debugger (void)
+{
+ return in_the_mono_debugger;
+}
+
void
mono_debug_cleanup (void)
{
g_assert (mono_symbol_table);
- if (size + 12 < DATA_TABLE_CHUNK_SIZE)
+ size = ALIGN_TO (size, sizeof (gpointer));
+
+ if (size + 16 < DATA_TABLE_CHUNK_SIZE)
chunk_size = DATA_TABLE_CHUNK_SIZE;
else
- chunk_size = size + 12;
+ chunk_size = size + 16;
/* Initialize things if necessary. */
if (!mono_symbol_table->current_data_table) {
mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
mono_symbol_table->current_data_table_size = chunk_size;
- mono_symbol_table->current_data_table_offset = 4;
+ mono_symbol_table->current_data_table_offset = sizeof (gpointer);
* ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
}
/* .... allocate a new current_data_table. */
mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
mono_symbol_table->current_data_table_size = chunk_size;
- mono_symbol_table->current_data_table_offset = 4;
+ mono_symbol_table->current_data_table_offset = sizeof (gpointer);
* ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
goto again;
*rptr = ptr;
}
+static MonoDebugWrapperData *
+mono_debug_add_wrapper (MonoMethod *method, MonoDebugMethodJitInfo *jit)
+{
+ MonoMethodHeader *header;
+ MonoDebugWrapperData *wrapper;
+ char buffer [BUFSIZ];
+ guint8 *ptr, *oldptr;
+ guint32 i, size, total_size, max_size;
+ gint32 last_il_offset = 0, last_native_offset = 0;
+
+ if (!in_the_mono_debugger)
+ return NULL;
+
+ mono_debugger_lock ();
+
+ header = ((MonoMethodNormal *) method)->header;
+
+ max_size = 28 * jit->num_line_numbers;
+ 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;
+ }
+
+ write_leb128 (method->wrapper_type, ptr, &ptr);
+
+ size = ptr - oldptr;
+ g_assert (size < max_size);
+ total_size = size + sizeof (MonoDebugWrapperData);
+
+ 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;
+ }
+
+ wrapper = (MonoDebugWrapperData *) allocate_data_item (MONO_DEBUG_DATA_ITEM_WRAPPER, total_size);
+
+ wrapper->method = method;
+ wrapper->size = total_size;
+ wrapper->code_start = jit->code_start;
+ wrapper->code_size = jit->code_size;
+ wrapper->name = mono_method_full_name (method, TRUE);
+
+ wrapper->cil_code = mono_disasm_code (
+ NULL, method, header->code, header->code + header->code_size);
+
+ memcpy (&wrapper->data, oldptr, size);
+
+ if (max_size > BUFSIZ)
+ g_free (oldptr);
+
+ mono_debugger_unlock ();
+
+ return wrapper;
+}
+
/*
* This is called by the JIT to tell the debugging code about a newly
* compiled method.
MonoDebugMethodInfo *minfo;
MethodHashEntry *hash;
+ if (method->is_inflated)
+ return NULL;
+
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
- (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
- return NULL;
-
- if (method->wrapper_type != MONO_WRAPPER_NONE)
+ (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_debug_add_wrapper (method, jit);
mono_debugger_unlock ();
return NULL;
}
return NULL;
}
- max_size = 24 + 8 * jit->num_line_numbers + 20 * (1 + jit->num_params + jit->num_locals);
+ 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
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);
// 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;
}
g_hash_table_insert (method_hash, hash, address);
- if (in_the_mono_debugger)
- mono_debugger_add_method (jit);
-
mono_debugger_unlock ();
return address;
guint32 i, il_offset = 0, native_offset = 0;
guint8 *ptr;
- jit = g_new0 (MonoDebugMethodJitInfo, 1);
+ 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;
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);
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.
handle = _mono_debug_get_image (klass->image);
if (!handle)
return;
-
- if (in_the_mono_debugger)
- mono_debugger_add_type (handle, klass);
-}
-
-static guint32
-get_token (MonoClass *klass)
-{
- while (klass->rank)
- klass = klass->element_class;
-
- return klass->type_token;
}
static void
MonoDebugClassEntry *entry;
char buffer [BUFSIZ];
guint8 *ptr, *oldptr;
- guint32 token, size, total_size, max_size;
+ guint32 size, total_size, max_size;
int base_offset = 0;
handle = _mono_debug_get_image (klass->image);
if (!handle)
return;
- if (klass->generic_class ||
+ if (klass->generic_class || klass->rank ||
(klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
return;
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->type_token, ptr, &ptr);
write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
- * ((gpointer *) ptr) = klass;
+ 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;
- }
+ g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
entry = (MonoDebugClassEntry *) allocate_data_item (MONO_DEBUG_DATA_ITEM_CLASS, total_size);
char *res = NULL;
gint32 offset;
- mono_loader_lock ();
+ if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+ return NULL;
+
+ mono_debugger_lock ();
minfo = _mono_debug_lookup_method (method);
if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return NULL;
}
if (offset >= 0)
res = mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number);
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return res;
}
char *res;
MonoDebugMethodInfo *minfo;
- mono_loader_lock ();
+ if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+ return NULL;
+
+ mono_debugger_lock ();
minfo = _mono_debug_lookup_method (method);
if (!minfo || !minfo->handle || !minfo->handle->symfile) {
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return NULL;
}
res = mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number);
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return res;
}
MonoDebugMethodInfo *minfo;
gint32 res;
- if (address < 0)
+ if ((address < 0) || (mono_debug_format == MONO_DEBUG_FORMAT_NONE))
return -1;
- mono_loader_lock ();
+ mono_debugger_lock ();
minfo = _mono_debug_lookup_method (method);
if (!minfo || !minfo->il_offsets || !minfo->handle || !minfo->handle->symfile ||
!minfo->handle->symfile->offset_table) {
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return -1;
}
res = il_offset_from_address (minfo, domain, address);
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return res;
}
MonoDebugMethodJitInfo *jit;
gint32 res;
- if (il_offset < 0)
+ if ((il_offset < 0) || (mono_debug_format == MONO_DEBUG_FORMAT_NONE))
return -1;
- mono_loader_lock ();
+ mono_debugger_lock ();
minfo = _mono_debug_lookup_method (method);
if (!minfo || !minfo->il_offsets || !minfo->handle || !minfo->handle->symfile ||
!minfo->handle->symfile->offset_table) {
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return -1;
}
jit = find_method (minfo, domain);
if (!jit) {
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return -1;
}
res = _mono_debug_address_from_il_offset (jit, il_offset);
- mono_loader_unlock ();
+ mono_debugger_unlock ();
return res;
}