#include <config.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
#include <string.h>
#include <signal.h>
+#include <sys/param.h>
+#include <sys/stat.h>
#include <mono/metadata/metadata.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/rawbuffer.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/debug-mono-symfile.h>
+#include <mono/metadata/mono-endian.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/mono-debug-debugger.h>
#include <fcntl.h>
#include <unistd.h>
static gchar *
get_class_name (MonoClass *klass)
{
- if (klass->nested_in) {
- gchar *parent_name = get_class_name (klass->nested_in);
- gchar *name = g_strdup_printf ("%s.%s", parent_name, klass->name);
+ MonoClass *nested_in = mono_class_get_nesting_type (klass);
+ const char *name_space;
+ if (nested_in) {
+ gchar *parent_name = get_class_name (nested_in);
+ gchar *name = g_strdup_printf ("%s.%s", parent_name, mono_class_get_name (klass));
g_free (parent_name);
return name;
}
- return g_strdup_printf ("%s%s%s", klass->name_space,
- klass->name_space [0] ? "." : "", klass->name);
+ name_space = mono_class_get_namespace (klass);
+ return g_strdup_printf ("%s%s%s", name_space,
+ name_space [0] ? "." : "", mono_class_get_name (klass));
}
static int
load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile)
{
- MonoSymbolFileMethodEntry *me;
- MonoSymbolFileMethodIndexEntry *ie;
const char *ptr, *start;
+ gchar *guid;
guint64 magic;
long version;
- int i;
ptr = start = symfile->raw_contents;
if (!ptr)
return FALSE;
- magic = *((guint64 *) ptr)++;
+ magic = read64(ptr);
+ ptr += sizeof(guint64);
if (magic != MONO_SYMBOL_FILE_MAGIC) {
- g_warning ("Symbol file %s has is not a mono symbol file", handle->image_file);
+ g_warning ("Symbol file %s is not a mono symbol file", symfile->filename);
return FALSE;
}
- version = *((guint32 *) ptr)++;
+ version = read32(ptr);
+ ptr += sizeof(guint32);
if (version != MONO_SYMBOL_FILE_VERSION) {
g_warning ("Symbol file %s has incorrect version "
- "(expected %d, got %ld)", handle->image_file,
+ "(expected %d, got %ld)", symfile->filename,
MONO_SYMBOL_FILE_VERSION, version);
return FALSE;
}
- symfile->offset_table = (MonoSymbolFileOffsetTable *) ptr;
-
- /*
- * Read method table.
- *
- */
-
- symfile->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- (GDestroyNotify) free_method_info);
-
- ie = (MonoSymbolFileMethodIndexEntry *)
- (symfile->raw_contents + symfile->offset_table->method_table_offset);
-
- for (i = 0; i < symfile->offset_table->method_count; i++, me++, ie++) {
- MonoMethod *method;
- MonoDebugMethodInfo *minfo;
+ guid = mono_guid_to_string ((const guint8 *) ptr);
+ ptr += 16;
- me = (MonoSymbolFileMethodEntry *) (symfile->raw_contents + ie->file_offset);
-
- method = mono_get_method (handle->image, me->token, NULL);
-
- if (!method)
- continue;
-
- minfo = g_new0 (MonoDebugMethodInfo, 1);
- minfo->index = i + 1;
- minfo->method = method;
- minfo->handle = handle;
- minfo->num_il_offsets = me->num_line_numbers;
- minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
- (symfile->raw_contents + me->line_number_table_offset);
- minfo->entry = me;
-
- g_hash_table_insert (symfile->method_hash, method, minfo);
+ if (strcmp (handle->image->guid, guid)) {
+ g_warning ("Symbol file %s doesn't match image %s", symfile->filename,
+ handle->image_file);
+ return FALSE;
}
- return TRUE;
-}
+ symfile->offset_table = (MonoSymbolFileOffsetTable *) ptr;
-static gconstpointer
-open_symfile (MonoImage *image, guint32 *size)
-{
- MonoTableInfo *table = &image->tables [MONO_TABLE_MANIFESTRESOURCE];
- guint32 i;
- guint32 cols [MONO_MANIFEST_SIZE];
- const char *val;
-
- for (i = 0; i < table->rows; ++i) {
- mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
- val = mono_metadata_string_heap (image, cols [MONO_MANIFEST_NAME]);
- if (!strcmp (val, "MonoSymbolFile"))
- break;
- }
- if (i == table->rows)
- return NULL;
- g_assert (!cols [MONO_MANIFEST_IMPLEMENTATION]);
+ symfile->method_hash = g_hash_table_new_full (
+ g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) free_method_info);
- return mono_image_get_resource (image, cols [MONO_MANIFEST_OFFSET], size);
+ return TRUE;
}
MonoSymbolFile *
mono_debug_open_mono_symbol_file (MonoDebugHandle *handle, gboolean create_symfile)
{
MonoSymbolFile *symfile;
+ FILE* f;
+ mono_loader_lock ();
symfile = g_new0 (MonoSymbolFile, 1);
- symfile->raw_contents = open_symfile (handle->image, &symfile->raw_contents_size);
-
- if (load_symfile (handle, symfile))
+ symfile->filename = g_strdup_printf ("%s.mdb", mono_image_get_filename (handle->image));
+
+ if ((f = fopen (symfile->filename, "rb")) > 0) {
+ struct stat stat_buf;
+
+ if (fstat (fileno (f), &stat_buf) < 0) {
+ g_warning ("stat of %s failed: %s", symfile->filename, g_strerror (errno));
+ } else {
+ symfile->raw_contents_size = stat_buf.st_size;
+ symfile->raw_contents = mono_raw_buffer_load (fileno (f), FALSE, 0, stat_buf.st_size);
+ }
+
+ fclose (f);
+ }
+
+ if (load_symfile (handle, symfile)) {
+ mono_loader_unlock ();
return symfile;
- else if (!create_symfile) {
+ } else if (!create_symfile) {
mono_debug_close_mono_symbol_file (symfile);
+ mono_loader_unlock ();
return NULL;
}
+ mono_loader_unlock ();
return symfile;
}
if (!symfile)
return;
+ mono_loader_lock ();
if (symfile->method_hash)
g_hash_table_destroy (symfile->method_hash);
+ if (symfile->raw_contents)
+ mono_raw_buffer_free ((gpointer) symfile->raw_contents);
+
g_free (symfile);
+ mono_loader_unlock ();
+}
+
+static int
+read_leb128 (const char *ptr, const char **rptr)
+{
+ int ret = 0;
+ int shift = 0;
+ char b;
+
+ do {
+ b = *ptr++;
+
+ ret = ret | ((b & 0x7f) << shift);
+ shift += 7;
+ } while ((b & 0x80) == 0x80);
+
+ if (rptr)
+ *rptr = ptr;
+
+ return ret;
}
static gchar *
read_string (const char *ptr)
{
- int len = *((guint32 *) ptr)++;
-
+ int len = read_leb128 (ptr, &ptr);
return g_filename_from_utf8 (ptr, len, NULL, NULL, NULL);
}
const char *ptr;
int i;
- if (!symfile->method_hash)
+ mono_loader_lock ();
+ if (!symfile->method_hash) {
+ mono_loader_unlock ();
return NULL;
+ }
minfo = g_hash_table_lookup (symfile->method_hash, method);
- if (!minfo)
+ if (!minfo) {
+ mono_loader_unlock ();
return NULL;
+ }
- if (minfo->entry->source_index) {
- int offset = symfile->offset_table->source_table_offset +
- (minfo->entry->source_index - 1) * sizeof (MonoSymbolFileSourceEntry);
+ if (read32(&(minfo->entry->_source_index))) {
+ int offset = read32(&(symfile->offset_table->_source_table_offset)) +
+ (read32(&(minfo->entry->_source_index)) - 1) * sizeof (MonoSymbolFileSourceEntry);
MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *) (symfile->raw_contents + offset);
- source_file = read_string (symfile->raw_contents + se->name_offset);
+ source_file = read_string (symfile->raw_contents + read32(&(se->_name_offset)));
}
- ptr = symfile->raw_contents + minfo->entry->line_number_table_offset;
+ ptr = symfile->raw_contents + read32(&(minfo->entry->_line_number_table_offset));
lne = (MonoSymbolFileLineNumberEntry *) ptr;
- for (i = 0; i < minfo->entry->num_line_numbers; i++, lne++) {
- if (lne->offset < offset)
+ for (i = 0; i < read32(&(minfo->entry->_num_line_numbers)); i++, lne++) {
+ if (read32(&(lne->_offset)) < offset)
continue;
if (line_number) {
- *line_number = lne->row;
+ *line_number = read32(&(lne->_row));
+ mono_loader_unlock ();
if (source_file)
return source_file;
else
return NULL;
} else if (source_file) {
- gchar *retval = g_strdup_printf ("%s:%d", source_file, lne->row);
+ gchar *retval = g_strdup_printf ("%s:%d", source_file, read32(&(lne->_row)));
g_free (source_file);
+ mono_loader_unlock ();
+ return retval;
+ } else {
+ gchar* retval = g_strdup_printf ("%d", read32(&(lne->_row)));
+ mono_loader_unlock ();
return retval;
- } else
- return g_strdup_printf ("%d", lne->row);
+ }
}
+ mono_loader_unlock ();
return NULL;
}
MonoDebugLineNumberEntry lne = g_array_index (
jit->line_numbers, MonoDebugLineNumberEntry, i);
- if (lne.offset <= il_offset)
- return lne.address;
+ if (lne.il_offset <= il_offset)
+ return lne.native_offset;
}
return -1;
}
+static int
+compare_method (const void *key, const void *object)
+{
+ guint32 token = GPOINTER_TO_UINT (key);
+ MonoSymbolFileMethodIndexEntry *me = (MonoSymbolFileMethodIndexEntry*)object;
+
+ return token - read32(&(me->_token));
+}
+
MonoDebugMethodInfo *
-mono_debug_find_method (MonoSymbolFile *symfile, MonoMethod *method)
+mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
{
+ MonoSymbolFileMethodEntry *me;
+ MonoSymbolFileMethodIndexEntry *first_ie, *ie;
+ MonoDebugMethodInfo *minfo;
+ MonoSymbolFile *symfile = handle->symfile;
+
if (!symfile->method_hash)
return NULL;
- else
- return g_hash_table_lookup (symfile->method_hash, method);
+
+ if (handle->image != mono_class_get_image (mono_method_get_class (method)))
+ return NULL;
+
+ mono_loader_lock ();
+ first_ie = (MonoSymbolFileMethodIndexEntry *)
+ (symfile->raw_contents + read32(&(symfile->offset_table->_method_table_offset)));
+
+ ie = bsearch (GUINT_TO_POINTER (mono_method_get_token (method)), first_ie,
+ read32(&(symfile->offset_table->_method_count)),
+ sizeof (MonoSymbolFileMethodIndexEntry), compare_method);
+
+ if (!ie) {
+ mono_loader_unlock ();
+ return NULL;
+ }
+
+ me = (MonoSymbolFileMethodEntry *) (symfile->raw_contents + read32(&(ie->_file_offset)));
+
+ minfo = g_new0 (MonoDebugMethodInfo, 1);
+ minfo->index = (ie - first_ie) + 1;
+ minfo->method = method;
+ minfo->handle = handle;
+ minfo->num_il_offsets = read32(&(me->_num_line_numbers));
+ minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
+ (symfile->raw_contents + read32(&(me->_line_number_table_offset)));
+ minfo->entry = me;
+
+ g_hash_table_insert (symfile->method_hash, method, minfo);
+
+ mono_loader_unlock ();
+ return minfo;
}