#include <mono/metadata/verify.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/mono-debug.h>
-/* mono-debug-debugger.h nneds config.h to work... */
+#include <mono/metadata/appdomain.h>
+/* mono-debug-debugger.h needs config.h to work... */
#include "config.h"
#include <mono/metadata/mono-debug-debugger.h>
-static void
+#ifdef HAVE_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
+
+static inline void
record_line_number (MonoDebugMethodJitInfo *jit, guint32 address, guint32 offset)
{
- MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
+ MonoDebugLineNumberEntry lne;
- lne->address = address;
- lne->offset = offset;
+ lne.address = address;
+ lne.offset = offset;
- g_array_append_val (jit->line_numbers, *lne);
+ g_array_append_val (jit->line_numbers, lne);
}
typedef struct
}
}
+/*
+ * mono_debug_add_vg_method:
+ *
+ * Register symbol information for the method with valgrind
+ */
+static void
+mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit)
+{
+#ifdef VALGRIND_ADD_LINE_INFO
+ MonoMethodHeader *header;
+ int i;
+ char *filename = NULL;
+ guint32 address, line_number;
+ const char *full_name;
+ guint32 *addresses;
+ guint32 *lines;
+
+ if (!RUNNING_ON_VALGRIND)
+ return;
+
+ header = ((MonoMethodNormal*)method)->header;
+
+ full_name = mono_method_full_name (method, TRUE);
+
+ addresses = g_new0 (guint32, header->code_size + 1);
+ lines = g_new0 (guint32, header->code_size + 1);
+
+ /*
+ * Very simple code to convert the addr->offset mappings that mono has
+ * into [addr-addr] ->line number mappings.
+ */
+
+ /* Create offset->line number mapping */
+ for (i = 0; i < header->code_size; ++i) {
+ char *fname;
+
+ fname = mono_debug_source_location_from_il_offset (method, i, &lines [i]);
+ if (!filename)
+ filename = fname;
+ }
+
+ /* Create address->offset mapping */
+ for (i = 0; i < jit->line_numbers->len; ++i) {
+ MonoDebugLineNumberEntry *lne = &g_array_index (jit->line_numbers, MonoDebugLineNumberEntry, i);
+
+ g_assert (lne->offset <= header->code_size);
+
+ if ((addresses [lne->offset] == 0) || (lne->address < addresses [lne->offset]))
+ addresses [lne->offset] = lne->address;
+ }
+ /* Fill out missing addresses */
+ address = 0;
+ for (i = 0; i < header->code_size; ++i) {
+ if (addresses [i] == 0)
+ addresses [i] = address;
+ else
+ address = addresses [i];
+ }
+
+ address = 0;
+ line_number = 0;
+ i = 0;
+ while (i < header->code_size) {
+ if (lines [i] == line_number)
+ i ++;
+ else {
+ if (line_number > 0) {
+ //g_assert (addresses [i] - 1 >= address);
+
+ if (addresses [i] - 1 >= address) {
+ VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + addresses [i] - 1, filename, line_number);
+ //printf ("[%d-%d] -> %d.\n", address, addresses [i] - 1, line_number);
+ }
+ }
+ address = addresses [i];
+ line_number = lines [i];
+ }
+ }
+
+ if (line_number > 0) {
+ VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + jit->code_size - 1, filename, line_number);
+ //printf ("[%d-%d] -> %d.\n", address, jit->code_size - 1, line_number);
+ }
+
+ VALGRIND_ADD_SYMBOL (jit->code_start, jit->code_size, full_name);
+
+ g_free (addresses);
+ g_free (lines);
+#endif /* VALGRIND_ADD_LINE_INFO */
+}
+
void
mono_debug_close_method (MonoCompile *cfg)
{
mono_debug_add_method (method, jit, cfg->domain);
+ mono_debug_add_vg_method (method, jit);
+
if (info->breakpoint_id)
mono_debugger_breakpoint_callback (method, info->breakpoint_id);
}
}
static inline void
-encode_value (guint32 value, char *buf, char **endbuf)
+encode_value (gint32 value, char *buf, char **endbuf)
{
char *p = buf;
* Same encoding as the one used in the metadata, extended to handle values
* greater than 0x1fffffff.
*/
- if (value <= 127)
+ if ((value >= 0) && (value <= 127))
*p++ = value;
- else if (value <= 16384) {
+ else if ((value >= 0) && (value <= 16384)) {
p [0] = 0x80 | (value >> 8);
p [1] = value & 0xff;
p += 2;
- } else if (value <= 0x1fffffff) {
+ } else if ((value >= 0) && (value <= 0x1fffffff)) {
p [0] = (value >> 24) | 0xc0;
p [1] = (value >> 16) & 0xff;
p [2] = (value >> 8) & 0xff;
*endbuf = p;
}
-static inline guint32
+static inline gint32
decode_value (char *_ptr, char **rptr)
{
unsigned char *ptr = (unsigned char *) _ptr;
unsigned char b = *ptr;
- guint32 len;
+ gint32 len;
if ((b & 0x80) == 0){
len = b;
ptr += 4;
}
else {
- len = (ptr [0] << 24) | (ptr [1] << 16) | (ptr [2] << 8) | ptr [3];
+ len = (ptr [1] << 24) | (ptr [2] << 16) | (ptr [3] << 8) | ptr [4];
ptr += 5;
}
if (rptr)
prev_offset = 0;
prev_native_offset = 0;
for (i = 0; i < jit->line_numbers->len; ++i) {
+ /* Sometimes, the offset values are not in increasing order */
MonoDebugLineNumberEntry *lne = &g_array_index (jit->line_numbers,
MonoDebugLineNumberEntry,
i);
{
MonoMethodHeader *header;
MonoDebugMethodJitInfo *jit;
- guint32 offset, native_offset, prev_offset, prev_native_offset, len;
+ gint32 offset, native_offset, prev_offset, prev_native_offset, len;
char *p;
int i;
debug_info_len);
mono_debug_add_method (method, jit, domain);
+
+ mono_debug_add_vg_method (method, jit);
}
MonoDomain *
mono_init_debugger (const char *file, const char *opt_flags)
{
MonoDomain *domain;
- const char *error;
+ const guchar *error;
int opt;
g_set_prgname (file);
mono_config_parse (NULL);
- error = mono_verify_corlib ();
+ error = mono_check_corlib_version ();
if (error) {
fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
+ fprintf (stderr, "Download a newer corlib or a newer runtime at http://www.go-mono.com/daily.\n");
exit (1);
}