Merge pull request #853 from echampet/onclick
[mono.git] / mono / metadata / debug-mono-ppdb.c
index 0bdd39cfb5e7020584306accdb36f16c05c60e57..d8da52cfb04fb1d35165a4ec67e4a3022a332322 100644 (file)
@@ -33,33 +33,41 @@ struct _MonoPPDBFile {
 };
 
 MonoPPDBFile*
-mono_ppdb_load_file (MonoImage *image)
+mono_ppdb_load_file (MonoImage *image, const guint8 *raw_contents, int size)
 {
        MonoImage *ppdb_image;
        const char *filename;
        char *s, *ppdb_filename;
        MonoImageOpenStatus status;
+#if 0
        MonoTableInfo *tables;
        guint32 cols [MONO_MODULE_SIZE];
        const char *guid, *ppdb_guid;
+#endif
        MonoPPDBFile *ppdb;
 
-       /* ppdb files drop the .exe/.dll extension */
-       filename = mono_image_get_filename (image);
-       if (strlen (filename) > 4 && (!strcmp (filename + strlen (filename) - 4, ".exe"))) {
-               s = g_strdup (filename);
-               s [strlen (filename) - 4] = '\0';
-               ppdb_filename = g_strdup_printf ("%s.pdb", s);
-               g_free (s);
+       if (raw_contents) {
+               ppdb_image = mono_image_open_from_data_internal ((char*)raw_contents, size, TRUE, NULL, FALSE, TRUE, NULL);
        } else {
-               ppdb_filename = g_strdup_printf ("%s.pdb", filename);
-       }
+               /* ppdb files drop the .exe/.dll extension */
+               filename = mono_image_get_filename (image);
+               if (strlen (filename) > 4 && (!strcmp (filename + strlen (filename) - 4, ".exe"))) {
+                       s = g_strdup (filename);
+                       s [strlen (filename) - 4] = '\0';
+                       ppdb_filename = g_strdup_printf ("%s.pdb", s);
+                       g_free (s);
+               } else {
+                       ppdb_filename = g_strdup_printf ("%s.pdb", filename);
+               }
 
-       ppdb_image = mono_image_open_metadata_only (ppdb_filename, &status);
+               ppdb_image = mono_image_open_metadata_only (ppdb_filename, &status);
+       }
        if (!ppdb_image)
                return NULL;
 
+#if 0
        /* Check that the images match */
+       // FIXME: ppdb files no longer have a MODULE table */
        tables = image->tables;
        g_assert (tables [MONO_TABLE_MODULE].rows);
        mono_metadata_decode_row (&tables [MONO_TABLE_MODULE], 0, cols, MONO_MODULE_SIZE);
@@ -76,6 +84,7 @@ mono_ppdb_load_file (MonoImage *image)
                mono_image_close (ppdb_image);
                return NULL;
        }
+#endif
 
        ppdb = g_new0 (MonoPPDBFile, 1);
        ppdb->image = ppdb_image;
@@ -195,6 +204,7 @@ mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
        const char *end;
        char *docname;
        int idx, size, docidx, iloffset, delta_il, delta_lines, delta_cols, start_line, start_col, adv_line, adv_col;
+       gboolean first = TRUE, first_non_hidden = TRUE;
        MonoDebugSourceLocation *location;
 
        g_assert (method->token);
@@ -210,26 +220,26 @@ mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
        size = mono_metadata_decode_blob_size (ptr, &ptr);
        end = ptr + size;
 
-       /* First record */
+       /* Header */
+       /* LocalSignature */
+       mono_metadata_decode_value (ptr, &ptr);
        docidx = mono_metadata_decode_value (ptr, &ptr);
        docname = get_docname (ppdb, image, docidx);
-       iloffset = mono_metadata_decode_value (ptr, &ptr);
-       delta_lines = mono_metadata_decode_value (ptr, &ptr);
-       if (delta_lines == 0)
-               delta_cols = mono_metadata_decode_value (ptr, &ptr);
-       else
-               delta_cols = mono_metadata_decode_signed_value (ptr, &ptr);
-       start_line = mono_metadata_decode_value (ptr, &ptr);
-       start_col = mono_metadata_decode_value (ptr, &ptr);
 
+       iloffset = 0;
+       start_line = 0;
+       start_col = 0;
        while (ptr < end) {
-               if (iloffset > offset)
-                       break;
-
                delta_il = mono_metadata_decode_value (ptr, &ptr);
-               if (delta_il == 0)
+               if (!first && delta_il == 0) {
+                       /* Document record */
                        // FIXME:
                        g_assert_not_reached ();
+               }
+               if (!first && iloffset + delta_il > offset)
+                       break;
+               iloffset += delta_il;
+               first = FALSE;
 
                delta_lines = mono_metadata_decode_value (ptr, &ptr);
                if (delta_lines == 0)
@@ -239,15 +249,16 @@ mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
                if (delta_lines == 0 && delta_cols == 0)
                        // FIXME:
                        g_assert_not_reached ();
-               adv_line = mono_metadata_decode_signed_value (ptr, &ptr);
-               adv_col = mono_metadata_decode_signed_value (ptr, &ptr);
-
-               if (iloffset + delta_il > offset)
-                       break;
-
-               iloffset += delta_il;
-               start_line += adv_line;
-               start_col += adv_col;
+               if (first_non_hidden) {
+                       start_line = mono_metadata_decode_value (ptr, &ptr);
+                       start_col = mono_metadata_decode_value (ptr, &ptr);
+               } else {
+                       adv_line = mono_metadata_decode_signed_value (ptr, &ptr);
+                       adv_col = mono_metadata_decode_signed_value (ptr, &ptr);
+                       start_line += adv_line;
+                       start_col += adv_col;
+               }
+               first_non_hidden = TRUE;
        }
 
        location = g_new0 (MonoDebugSourceLocation, 1);
@@ -270,6 +281,7 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr
        const char *end;
        MonoDebugSourceInfo *docinfo;
        int i, method_idx, size, docidx, iloffset, delta_il, delta_lines, delta_cols, start_line, start_col, adv_line, adv_col;
+       gboolean first = TRUE, first_non_hidden = TRUE;
        GArray *sps;
        MonoSymSeqPoint sp;
        GPtrArray *sfiles = NULL;
@@ -307,35 +319,20 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr
 
        sps = g_array_new (FALSE, TRUE, sizeof (MonoSymSeqPoint));
 
-       /* First record */
+       /* Header */
+       /* LocalSignature */
+       mono_metadata_decode_value (ptr, &ptr);
        docidx = mono_metadata_decode_value (ptr, &ptr);
        docinfo = get_docinfo (ppdb, image, docidx);
-       iloffset = mono_metadata_decode_value (ptr, &ptr);
-       delta_lines = mono_metadata_decode_value (ptr, &ptr);
-       if (delta_lines == 0)
-               delta_cols = mono_metadata_decode_value (ptr, &ptr);
-       else
-               delta_cols = mono_metadata_decode_signed_value (ptr, &ptr);
-       start_line = mono_metadata_decode_value (ptr, &ptr);
-       start_col = mono_metadata_decode_value (ptr, &ptr);
-
        if (sfiles)
                g_ptr_array_add (sfiles, docinfo);
-       if (source_files)
-               g_ptr_array_add (sindexes, GUINT_TO_POINTER (sfiles->len - 1));
-
-       memset (&sp, 0, sizeof (sp));
-       sp.il_offset = iloffset;
-       sp.line = start_line;
-       sp.column = start_col;
-       sp.end_line = start_line + delta_lines;
-       sp.end_column = start_col + delta_cols;
-
-       g_array_append_val (sps, sp);
 
+       iloffset = 0;
+       start_line = 0;
+       start_col = 0;
        while (ptr < end) {
                delta_il = mono_metadata_decode_value (ptr, &ptr);
-               if (delta_il == 0) {
+               if (!first && delta_il == 0) {
                        /* subsequent-document-record */
                        docidx = mono_metadata_decode_value (ptr, &ptr);
                        docinfo = get_docinfo (ppdb, image, docidx);
@@ -343,6 +340,9 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr
                                g_ptr_array_add (sfiles, docinfo);
                        continue;
                }
+               iloffset += delta_il;
+               first = FALSE;
+
                delta_lines = mono_metadata_decode_value (ptr, &ptr);
                if (delta_lines == 0)
                        delta_cols = mono_metadata_decode_value (ptr, &ptr);
@@ -351,16 +351,19 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr
 
                if (delta_lines == 0 && delta_cols == 0) {
                        /* Hidden sequence point */
-                       // FIXME: This seems to be followed by garbage
                        continue;
                }
 
-               adv_line = mono_metadata_decode_signed_value (ptr, &ptr);
-               adv_col = mono_metadata_decode_signed_value (ptr, &ptr);
-
-               iloffset += delta_il;
-               start_line += adv_line;
-               start_col += adv_col;
+               if (first_non_hidden) {
+                       start_line = mono_metadata_decode_value (ptr, &ptr);
+                       start_col = mono_metadata_decode_value (ptr, &ptr);
+               } else {
+                       adv_line = mono_metadata_decode_signed_value (ptr, &ptr);
+                       adv_col = mono_metadata_decode_signed_value (ptr, &ptr);
+                       start_line += adv_line;
+                       start_col += adv_col;
+               }
+               first_non_hidden = TRUE;
 
                memset (&sp, 0, sizeof (sp));
                sp.il_offset = iloffset;
@@ -392,3 +395,88 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr
 
        g_array_free (sps, TRUE);
 }
+
+MonoDebugLocalsInfo*
+mono_ppdb_lookup_locals (MonoDebugMethodInfo *minfo)
+{
+       MonoPPDBFile *ppdb = minfo->handle->ppdb;
+       MonoImage *image = ppdb->image;
+       MonoTableInfo *tables = image->tables;
+       MonoMethod *method = minfo->method;
+       guint32 cols [MONO_LOCALSCOPE_SIZE];
+       guint32 locals_cols [MONO_LOCALVARIABLE_SIZE];
+       int i, lindex, sindex, method_idx, start_scope_idx, scope_idx, locals_idx, locals_end_idx, nscopes;
+       MonoDebugLocalsInfo *res;
+       MonoMethodSignature *sig;
+
+       if (!method->token)
+               return NULL;
+
+       sig = mono_method_signature (method);
+       if (!sig)
+               return NULL;
+
+       method_idx = mono_metadata_token_index (method->token);
+
+       start_scope_idx = mono_metadata_localscope_from_methoddef (image, method_idx);
+
+       if (!start_scope_idx)
+               return NULL;
+
+       /* Compute number of locals and scopes */
+       scope_idx = start_scope_idx;
+       mono_metadata_decode_row (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1, cols, MONO_LOCALSCOPE_SIZE);
+       locals_idx = cols [MONO_LOCALSCOPE_VARIABLELIST];
+       while (TRUE) {
+               mono_metadata_decode_row (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1, cols, MONO_LOCALSCOPE_SIZE);
+               if (cols [MONO_LOCALSCOPE_METHOD] != method_idx)
+                       break;
+               scope_idx ++;
+       }
+       nscopes = scope_idx - start_scope_idx;
+       if (scope_idx == tables [MONO_TABLE_LOCALSCOPE].rows) {
+               // FIXME:
+               g_assert_not_reached ();
+               locals_end_idx = -1;
+       } else {
+               locals_end_idx = cols [MONO_LOCALSCOPE_VARIABLELIST];
+       }
+
+       res = g_new0 (MonoDebugLocalsInfo, 1);
+       res->num_blocks = nscopes;
+       res->code_blocks = g_new0 (MonoDebugCodeBlock, res->num_blocks);
+       res->num_locals = locals_end_idx - locals_idx;
+       res->locals = g_new0 (MonoDebugLocalVar, res->num_locals);
+
+       lindex = 0;
+       for (sindex = 0; sindex < nscopes; ++sindex) {
+               scope_idx = start_scope_idx + sindex;
+               mono_metadata_decode_row (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1, cols, MONO_LOCALSCOPE_SIZE);
+
+               locals_idx = cols [MONO_LOCALSCOPE_VARIABLELIST];
+               if (scope_idx == tables [MONO_TABLE_LOCALSCOPE].rows) {
+                       // FIXME:
+                       g_assert_not_reached ();
+               } else {
+                       locals_end_idx = mono_metadata_decode_row_col (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1 + 1, MONO_LOCALSCOPE_VARIABLELIST);
+               }
+
+               res->code_blocks [sindex].start_offset = cols [MONO_LOCALSCOPE_STARTOFFSET];
+               res->code_blocks [sindex].end_offset = cols [MONO_LOCALSCOPE_STARTOFFSET] + cols [MONO_LOCALSCOPE_LENGTH];
+
+               //printf ("Scope: %s %d %d %d-%d\n", mono_method_full_name (method, 1), cols [MONO_LOCALSCOPE_STARTOFFSET], cols [MONO_LOCALSCOPE_LENGTH], locals_idx, locals_end_idx);
+
+               for (i = locals_idx; i < locals_end_idx; ++i) {
+                       mono_metadata_decode_row (&tables [MONO_TABLE_LOCALVARIABLE], i - 1, locals_cols, MONO_LOCALVARIABLE_SIZE);
+
+                       res->locals [lindex].name = g_strdup (mono_metadata_string_heap (image, locals_cols [MONO_LOCALVARIABLE_NAME]));
+                       res->locals [lindex].index = locals_cols [MONO_LOCALVARIABLE_INDEX];
+                       res->locals [lindex].block = &res->code_blocks [sindex];
+                       lindex ++;
+
+                       //printf ("\t %s %d\n", mono_metadata_string_heap (image, locals_cols [MONO_LOCALVARIABLE_NAME]), locals_cols [MONO_LOCALVARIABLE_INDEX]);
+               }
+       }
+
+       return res;
+}