[debugger] Improve debug after hot reload (#55869)
authorThays Grazia <thaystg@gmail.com>
Thu, 29 Jul 2021 14:41:43 +0000 (11:41 -0300)
committerGitHub <noreply@github.com>
Thu, 29 Jul 2021 14:41:43 +0000 (11:41 -0300)
* Creating more test for hot reload debugging.

* Fixing step on android after hot reload.

* Fix get document information from enc pdb.

* Addressing Aleksey comments.

* Addressing @lambdageek comments and fixing implementation of mono_ppdb_lookup_location

* Fixing compilation on ios.

* Fix android compilation.

12 files changed:
src/mono/mono/component/debugger-agent.c
src/mono/mono/component/hot_reload.c
src/mono/mono/metadata/debug-mono-ppdb.c
src/mono/mono/metadata/debug-mono-ppdb.h
src/mono/mono/metadata/mono-debug.c
src/mono/mono/metadata/mono-debug.h
src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs
src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/ApplyUpdateReferencedAssembly.csproj
src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody0.cs [new file with mode: 0644]
src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1.cs
src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs
src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs

index 45daa04..fbe89da 100644 (file)
@@ -8449,7 +8449,7 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g
                ERROR_DECL (error);
                MonoDebugMethodInfo *minfo;
                char *source_file;
-               int i, j, n_il_offsets, n_il_offsets_original;
+               int i, j, n_il_offsets;
                int *source_files;
                GPtrArray *source_file_list;
                MonoSymSeqPoint *sym_seq_points;
@@ -8472,8 +8472,7 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g
                        break;
                }
 
-               mono_debug_get_seq_points (minfo, &source_file, &source_file_list, &source_files, NULL, &n_il_offsets_original);
-               mono_debug_get_seq_points (minfo, NULL, NULL, NULL, &sym_seq_points, &n_il_offsets);
+               mono_debug_get_seq_points (minfo,&source_file, &source_file_list, &source_files, &sym_seq_points, &n_il_offsets);
                buffer_add_int (buf, header->code_size);
                if (CHECK_PROTOCOL_VERSION (2, 13)) {
                        buffer_add_int (buf, source_file_list->len);
@@ -8496,8 +8495,6 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g
 
                        if (source_files [i] != -1) {
                                int idx = i;
-                               if (i >= n_il_offsets_original)
-                                       idx = 0;
                                MonoDebugSourceInfo *sinfo = (MonoDebugSourceInfo *)g_ptr_array_index (source_file_list, source_files [idx]);
                                srcfile = sinfo->source_file;
                        }
@@ -8505,7 +8502,7 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g
                        buffer_add_int (buf, sp->il_offset);
                        buffer_add_int (buf, sp->line);
                        if (CHECK_PROTOCOL_VERSION (2, 13))
-                               buffer_add_int (buf, i >= n_il_offsets_original ? source_files [0] : source_files [i]);
+                               buffer_add_int (buf, source_files [i]);
                        if (CHECK_PROTOCOL_VERSION (2, 19))
                                buffer_add_int (buf, sp->column);
                        if (CHECK_PROTOCOL_VERSION (2, 32)) {
index d76fc8c..1d7bc77 100644 (file)
@@ -19,7 +19,9 @@
 #include "mono/utils/mono-lazy-init.h"
 #include "mono/utils/mono-logger-internals.h"
 #include "mono/utils/mono-path.h"
+#include "mono/metadata/debug-internals.h"
 #include "mono/metadata/mono-debug.h"
+#include "mono/metadata/debug-mono-ppdb.h"
 
 
 #include <mono/component/hot_reload.h>
@@ -161,6 +163,8 @@ typedef struct _DeltaInfo {
        // for each table, the row in the EncMap table that has the first token for remapping it?
        uint32_t enc_recs [MONO_TABLE_NUM];
        delta_row_count count [MONO_TABLE_NUM];
+       
+       MonoPPDBFile *ppdb_file;
 } DeltaInfo;
 
 
@@ -320,7 +324,7 @@ baseline_info_lookup (MonoImage *base_image)
 }
 
 static DeltaInfo*
-delta_info_init (MonoImage *image_dmeta, MonoImage *image_base, BaselineInfo *base_info, uint32_t generation);
+delta_info_init (MonoImage *image_dmeta, MonoImage *image_base, MonoPPDBFile *ppdb_file, BaselineInfo *base_info, uint32_t generation);
 
 static void
 free_ppdb_entry (gpointer key, gpointer val, gpointer user_data)
@@ -337,6 +341,7 @@ delta_info_destroy (DeltaInfo *dinfo)
                g_hash_table_foreach (dinfo->method_ppdb_table_update, free_ppdb_entry, NULL);
                g_hash_table_destroy (dinfo->method_ppdb_table_update);
        }
+       mono_ppdb_close (dinfo->ppdb_file);
        g_free (dinfo);
 }
 
@@ -918,7 +923,7 @@ hot_reload_relative_delta_index (MonoImage *image_dmeta, int token)
 
 /* LOCKING: assumes publish_lock is held */
 static DeltaInfo*
-delta_info_init (MonoImage *image_dmeta, MonoImage *image_base, BaselineInfo *base_info, uint32_t generation)
+delta_info_init (MonoImage *image_dmeta, MonoImage *image_base, MonoPPDBFile *ppdb_file, BaselineInfo *base_info, uint32_t generation)
 {
        MonoTableInfo *encmap = &image_dmeta->tables [MONO_TABLE_ENCMAP];
        g_assert (!delta_info_lookup (image_dmeta));
@@ -929,6 +934,7 @@ delta_info_init (MonoImage *image_dmeta, MonoImage *image_base, BaselineInfo *ba
        DeltaInfo *delta_info = g_malloc0 (sizeof (DeltaInfo));
 
        delta_info->generation = generation;
+       delta_info->ppdb_file = ppdb_file;
 
        table_to_image_lock ();
        g_hash_table_insert (delta_image_to_info, image_dmeta, delta_info);
@@ -1201,11 +1207,12 @@ set_update_method (MonoImage *image_base, BaselineInfo *base_info, uint32_t gene
 }
 
 static MonoDebugInformationEnc *
-hot_reload_get_method_debug_information (MonoImage *image_dppdb, int idx)
+hot_reload_get_method_debug_information (MonoPPDBFile *ppdb_file, int idx)
 {
-       if (!image_dppdb)
+       if (!ppdb_file)
                return NULL;
-               
+
+       MonoImage *image_dppdb = ppdb_file->image;
        MonoTableInfo *table_encmap = &image_dppdb->tables [MONO_TABLE_ENCMAP];
        int rows = table_info_get_rows (table_encmap);
        for (int i = 0; i < rows ; ++i) {
@@ -1217,8 +1224,8 @@ hot_reload_get_method_debug_information (MonoImage *image_dppdb, int idx)
                        int token_index = mono_metadata_token_index (map_token);
                        if (token_index == idx) {
                                MonoDebugInformationEnc *encDebugInfo = g_new0 (MonoDebugInformationEnc, 1);
-                               encDebugInfo->idx = i;
-                               encDebugInfo->image = image_dppdb;                              
+                               encDebugInfo->idx = i + 1;
+                               encDebugInfo->ppdb_file = ppdb_file;
                                return encDebugInfo;
                        }
                }
@@ -1228,7 +1235,7 @@ hot_reload_get_method_debug_information (MonoImage *image_dppdb, int idx)
 
 /* do actuall enclog application */
 static gboolean
-apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, MonoImage *image_dmeta, MonoImage *image_dppdb, DeltaInfo *delta_info, gconstpointer dil_data, uint32_t dil_length, MonoError *error)
+apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, MonoImage *image_dmeta, DeltaInfo *delta_info, gconstpointer dil_data, uint32_t dil_length, MonoError *error)
 {
        MonoTableInfo *table_enclog = &image_dmeta->tables [MONO_TABLE_ENCLOG];
        int rows = table_info_get_rows (table_enclog);
@@ -1307,7 +1314,7 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen
                        int rva = mono_metadata_decode_row_col (&image_dmeta->tables [MONO_TABLE_METHOD], mapped_token - 1, MONO_METHOD_RVA);
                        if (rva < dil_length) {
                                char *il_address = ((char *) dil_data) + rva;
-                               MonoDebugInformationEnc *method_debug_information = hot_reload_get_method_debug_information (image_dppdb, token_index);
+                               MonoDebugInformationEnc *method_debug_information = hot_reload_get_method_debug_information (delta_info->ppdb_file, token_index);
                                set_update_method (image_base, base_info, generation, image_dmeta, delta_info, token_index, il_address, method_debug_information);
                        } else {
                                /* rva points probably into image_base IL stream. can this ever happen? */
@@ -1396,19 +1403,20 @@ hot_reload_apply_changes (int origin, MonoImage *image_base, gconstpointer dmeta
        /* makes a copy of dil_bytes_orig */
        gpointer dil_bytes = open_dil_data (image_base, dil_bytes_orig, dil_length);
 
-       MonoImage *image_dpdb = NULL;
+       MonoPPDBFile *ppdb_file = NULL;
        if (dpdb_length > 0)
        {
-               image_dpdb = image_open_dmeta_from_data (image_base, generation, dpdb_bytes_orig, dpdb_length);
+               MonoImage *image_dpdb = image_open_dmeta_from_data (image_base, generation, dpdb_bytes_orig, dpdb_length);
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "pdb image string size: 0x%08x", image_dpdb->heap_strings.size);
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "pdb image user string size: 0x%08x", image_dpdb->heap_us.size);
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "pdb image blob heap addr: %p", image_dpdb->heap_blob.data);
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "pdb image blob heap size: 0x%08x", image_dpdb->heap_blob.size);
+               ppdb_file = mono_create_ppdb_file (image_dpdb, FALSE);
        }
 
        BaselineInfo *base_info = baseline_info_lookup_or_add (image_base);
 
-       DeltaInfo *delta_info = delta_info_init (image_dmeta, image_base, base_info, generation);
+       DeltaInfo *delta_info = delta_info_init (image_dmeta, image_base, ppdb_file, base_info, generation);
 
 
        if (image_dmeta->minimal_delta) {
@@ -1460,7 +1468,7 @@ hot_reload_apply_changes (int origin, MonoImage *image_base, gconstpointer dmeta
        if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE))
                dump_update_summary (image_base, image_dmeta);
 
-       if (!apply_enclog_pass2 (image_base, base_info, generation, image_dmeta, image_dpdb, delta_info, dil_bytes, dil_length, error)) {
+       if (!apply_enclog_pass2 (image_base, base_info, generation, image_dmeta, delta_info, dil_bytes, dil_length, error)) {
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "Error applying delta image to base=%s, due to: %s", basename, mono_error_get_message (error));
                hot_reload_update_cancel (generation);
                return;
index 101e583..d7df94f 100644 (file)
 
 #include "debug-mono-ppdb.h"
 
-struct _MonoPPDBFile {
-       MonoImage *image;
-       GHashTable *doc_hash;
-       GHashTable *method_hash;
-       gboolean is_embedded;
-};
-
 typedef struct {
        gint32 signature;
        guint8 guid [16];
@@ -130,8 +123,8 @@ doc_free (gpointer key)
        g_free (info);
 }
 
-static MonoPPDBFile*
-create_ppdb_file (MonoImage *ppdb_image, gboolean is_embedded_ppdb)
+MonoPPDBFile*
+mono_create_ppdb_file (MonoImage *ppdb_image, gboolean is_embedded_ppdb)
 {
        MonoPPDBFile *ppdb;
 
@@ -161,7 +154,7 @@ mono_ppdb_load_file (MonoImage *image, const guint8 *raw_contents, int size)
        if (table_info_get_rows (&image->tables [MONO_TABLE_DOCUMENT])) {
                /* Embedded ppdb */
                mono_image_addref (image);
-               return create_ppdb_file (image, TRUE);
+               return mono_create_ppdb_file (image, TRUE);
        }
 
        if (!get_pe_debug_info (image, pe_guid, &pe_age, &pe_timestamp, &ppdb_data, &ppdb_size, &ppdb_compressed_size)) {
@@ -236,14 +229,12 @@ mono_ppdb_load_file (MonoImage *image, const guint8 *raw_contents, int size)
                return NULL;
        }
 
-       return create_ppdb_file (ppdb_image, is_embedded_ppdb);
+       return mono_create_ppdb_file (ppdb_image, is_embedded_ppdb);
 }
 
 void
-mono_ppdb_close (MonoDebugHandle *handle)
+mono_ppdb_close (MonoPPDBFile *ppdb)
 {
-       MonoPPDBFile *ppdb = handle->ppdb;
-
        mono_image_close (ppdb->image);
        g_hash_table_destroy (ppdb->doc_hash);
        g_hash_table_destroy (ppdb->method_hash);
@@ -290,10 +281,11 @@ get_docinfo (MonoPPDBFile *ppdb, MonoImage *image, int docidx)
        int size, part_size, partidx, nparts;
        char sep;
        GString *s;
-       MonoDebugSourceInfo *res, *cached;
+       MonoDebugSourceInfo *res, *cached = NULL;
 
        mono_debugger_lock ();
-       cached = (MonoDebugSourceInfo *)g_hash_table_lookup (ppdb->doc_hash, GUINT_TO_POINTER (docidx));
+       if (ppdb)
+               cached = (MonoDebugSourceInfo *)g_hash_table_lookup (ppdb->doc_hash, GUINT_TO_POINTER (docidx));
        mono_debugger_unlock ();
        if (cached)
                return cached;
@@ -360,26 +352,18 @@ get_docname (MonoPPDBFile *ppdb, MonoImage *image, int docidx)
  * already looked up the method and also already did the
  * native address -> IL offset mapping.
  */
-MonoDebugSourceLocation *
-mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
+static MonoDebugSourceLocation *
+mono_ppdb_lookup_location_internal (MonoImage *image, int idx, uint32_t offset, MonoPPDBFile *ppdb)
 {
-       MonoPPDBFile *ppdb = minfo->handle->ppdb;
-       MonoImage *image = ppdb->image;
-       MonoMethod *method = minfo->method;
        MonoTableInfo *tables = image->tables;
        guint32 cols [MONO_METHODBODY_SIZE];
        const char *ptr;
        const char *end;
-       char *docname;
-       int idx, size, docidx, iloffset, delta_il, delta_lines, delta_cols, start_line, start_col, adv_line, adv_col;
+       char *docname = NULL;
+       int 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;
 
-       if (!method->token)
-               return NULL;
-
-       idx = mono_metadata_token_index (method->token);
-
        mono_metadata_decode_row (&tables [MONO_TABLE_METHODBODY], idx-1, cols, MONO_METHODBODY_SIZE);
 
        docidx = cols [MONO_METHODBODY_DOCUMENT];
@@ -396,7 +380,6 @@ mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
        if (docidx == 0)
                docidx = mono_metadata_decode_value (ptr, &ptr);
        docname = get_docname (ppdb, image, docidx);
-
        iloffset = 0;
        start_line = 0;
        start_col = 0;
@@ -443,6 +426,24 @@ mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
        return location;
 }
 
+
+MonoDebugSourceLocation *
+mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
+{
+       MonoPPDBFile *ppdb = minfo->handle->ppdb;
+       MonoImage *image = ppdb->image;
+       MonoMethod *method = minfo->method;
+       if (!method->token)
+               return NULL;
+       return mono_ppdb_lookup_location_internal (image, mono_metadata_token_index (method->token), offset, ppdb);
+}
+
+MonoDebugSourceLocation *
+mono_ppdb_lookup_location_enc (MonoPPDBFile *ppdb_file, int idx, uint32_t offset)
+{
+       return mono_ppdb_lookup_location_internal (ppdb_file->image, idx, offset, ppdb_file);
+}
+
 MonoImage *
 mono_ppdb_get_image (MonoPPDBFile *ppdb)
 {
@@ -456,57 +457,90 @@ mono_ppdb_is_embedded (MonoPPDBFile *ppdb)
        return ppdb->is_embedded;
 }
 
-static int 
-mono_ppdb_get_seq_points_internal (const char* ptr, MonoSymSeqPoint **seq_points, int *n_seq_points, int docidx, MonoImage *image, MonoPPDBFile *ppdb, GPtrArray **sfiles, char **source_file, int **source_files, GPtrArray **sindexes, gboolean read_doc_value)
+static int
+mono_ppdb_get_seq_points_internal (MonoImage *image, MonoPPDBFile *ppdb, MonoMethod* method, int method_idx, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
 {
+       MonoTableInfo *tables = image->tables;
+       guint32 cols [MONO_METHODBODY_SIZE];
+       const char *ptr;
+       const char *end;
+       MonoDebugSourceInfo *docinfo;
+       int i, 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;
-       int iloffset = 0;
-       int start_line = 0;
-       int start_col = 0;
-       int delta_cols = 0;
-       gboolean first_non_hidden = TRUE;
-       int adv_line, adv_col;
-       int size = mono_metadata_decode_blob_size (ptr, &ptr);
-       const char* end = ptr + size;
-       MonoDebugSourceInfo *docinfo;
-       gboolean first = TRUE;
+       GPtrArray *sfiles = NULL;
+       GPtrArray *sindexes = NULL;
+       if (source_file)
+               *source_file = NULL;
+       if (source_file_list)
+               *source_file_list = NULL;
+       if (source_files)
+               *source_files = NULL;
+       if (seq_points)
+               *seq_points = NULL;
+       if (n_seq_points)
+               *n_seq_points = 0;
+
+       if (source_file_list)
+               *source_file_list = sfiles = g_ptr_array_new ();
+       if (source_files)
+               sindexes = g_ptr_array_new ();
+
+       if (!method->token || table_info_get_rows (&tables [MONO_TABLE_METHODBODY]) == 0)
+               return -1;
+
+       MonoTableInfo *methodbody_table = &tables [MONO_TABLE_METHODBODY];
+       if (G_UNLIKELY (method_idx - 1 >= table_info_get_rows (methodbody_table))) {
+               char *method_name = mono_method_full_name (method, FALSE);
+               g_error ("Method idx %d is greater than number of rows (%d) in PPDB MethodDebugInformation table, for method %s in '%s'. Likely a malformed PDB file.",
+                method_idx - 1, table_info_get_rows (methodbody_table), method_name, image->name);
+               g_free (method_name);
+       }
+
+       mono_metadata_decode_row (methodbody_table, method_idx - 1, cols, MONO_METHODBODY_SIZE);
+
+       docidx = cols [MONO_METHODBODY_DOCUMENT];
+
+       if (!cols [MONO_METHODBODY_SEQ_POINTS])
+               return -1;
+
+       ptr = mono_metadata_blob_heap (image, cols [MONO_METHODBODY_SEQ_POINTS]);
+       size = mono_metadata_decode_blob_size (ptr, &ptr);
+       end = ptr + size;
 
        sps = g_array_new (FALSE, TRUE, sizeof (MonoSymSeqPoint));
 
        /* Header */
        /* LocalSignature */
        mono_metadata_decode_value (ptr, &ptr);
-       if (docidx == 0  && read_doc_value)
+       if (docidx == 0)
                docidx = mono_metadata_decode_value (ptr, &ptr);
-       if (sfiles && *sfiles)
-       {
-               docinfo = get_docinfo (ppdb, image, docidx);
-               g_ptr_array_add (*sfiles, docinfo);
-       }
+       docinfo = get_docinfo (ppdb, image, docidx);
+
+       if (sfiles)
+               g_ptr_array_add (sfiles, docinfo);
 
-       if (source_file && *source_file)
+       if (source_file)
                *source_file = g_strdup (docinfo->source_file);
 
        iloffset = 0;
        start_line = 0;
        start_col = 0;
        while (ptr < end) {
-               int delta_il = mono_metadata_decode_value (ptr, &ptr);
-               if (!first && delta_il == 0 && read_doc_value) {
+               delta_il = mono_metadata_decode_value (ptr, &ptr);
+               if (!first && delta_il == 0) {
                        /* subsequent-document-record */
                        docidx = mono_metadata_decode_value (ptr, &ptr);
                        docinfo = get_docinfo (ppdb, image, docidx);
-                       if (sfiles && *sfiles)
-                       {
-                               g_ptr_array_add (*sfiles, docinfo);
-                       }
+                       if (sfiles)
+                               g_ptr_array_add (sfiles, docinfo);
                        continue;
                }
                iloffset += delta_il;
                first = FALSE;
 
-               int delta_lines = 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
@@ -536,36 +570,36 @@ mono_ppdb_get_seq_points_internal (const char* ptr, MonoSymSeqPoint **seq_points
                sp.end_column = start_col + delta_cols;
 
                g_array_append_val (sps, sp);
-               if (sindexes && *sindexes) {
-                       g_ptr_array_add (*sindexes, GUINT_TO_POINTER ((*sfiles)->len - 1));
-               }
+               if (source_files)
+                       g_ptr_array_add (sindexes, GUINT_TO_POINTER (sfiles->len - 1));
        }
 
        if (n_seq_points) {
                *n_seq_points = sps->len;
-               if (seq_points) {
-                       *seq_points = g_new (MonoSymSeqPoint, sps->len);
-                       memcpy (*seq_points, sps->data, sps->len * sizeof (MonoSymSeqPoint));
-               }
+               g_assert (seq_points);
+               *seq_points = g_new (MonoSymSeqPoint, sps->len);
+               memcpy (*seq_points, sps->data, sps->len * sizeof (MonoSymSeqPoint));
        }
-       int sps_len = sps->len;
+
+       if (source_files) {
+               *source_files = g_new (int, sps->len);
+               for (i = 0; i < sps->len; ++i)
+                       (*source_files)[i] = GPOINTER_TO_INT (g_ptr_array_index (sindexes, i));
+               g_ptr_array_free (sindexes, TRUE);
+       }
+       int n_seqs = sps->len;
        g_array_free (sps, TRUE);
-       return sps_len;
+
+       return n_seqs;
 }
 
 gboolean 
-mono_ppdb_get_seq_points_enc (MonoImage *image, int idx, MonoSymSeqPoint **seq_points, int *n_seq_points)
+mono_ppdb_get_seq_points_enc (MonoDebugMethodInfo *minfo, MonoPPDBFile *ppdb_file, int idx, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
 {
-       guint32 cols [MONO_METHODBODY_SIZE];
-       MonoTableInfo *tables = image->tables;
-       MonoTableInfo *methodbody_table = &tables [MONO_TABLE_METHODBODY];
-       mono_metadata_decode_row (methodbody_table, idx, cols, MONO_METHODBODY_SIZE);
-       if (!cols [MONO_METHODBODY_SEQ_POINTS])
-               return FALSE;
-
-       const char *ptr = mono_metadata_blob_heap (image, cols [MONO_METHODBODY_SEQ_POINTS]);
-       mono_ppdb_get_seq_points_internal (ptr, seq_points, n_seq_points, 0, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
-       return TRUE;
+       MonoMethod *method = minfo->method;
+       if (mono_ppdb_get_seq_points_internal (ppdb_file->image, ppdb_file, method, idx, source_file, source_file_list, source_files, seq_points, n_seq_points) > 0)
+               return TRUE;
+       return FALSE;
 }
 
 void
@@ -574,63 +608,14 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr
        MonoPPDBFile *ppdb = minfo->handle->ppdb;
        MonoImage *image = ppdb->image;
        MonoMethod *method = minfo->method;
-       MonoTableInfo *tables = image->tables;
-       guint32 cols [MONO_METHODBODY_SIZE];
-       const char *ptr;
-       int i, method_idx, docidx;
-       GPtrArray *sfiles = NULL;
-       GPtrArray *sindexes = NULL;
-
-       if (source_file)
-               *source_file = NULL;
-       if (source_file_list)
-               *source_file_list = NULL;
-       if (source_files)
-               *source_files = NULL;
-       if (seq_points)
-               *seq_points = NULL;
-       if (n_seq_points)
-               *n_seq_points = 0;
 
-       if (source_file_list)
-               *source_file_list = sfiles = g_ptr_array_new ();
-       if (source_files)
-               sindexes = g_ptr_array_new ();
-
-       if (!method->token || table_info_get_rows (&tables [MONO_TABLE_METHODBODY]) == 0)
-               return;
-
-       method_idx = mono_metadata_token_index (method->token);
-
-       MonoTableInfo *methodbody_table = &tables [MONO_TABLE_METHODBODY];
-       if (G_UNLIKELY (method_idx - 1 >= table_info_get_rows (methodbody_table))) {
-               char *method_name = mono_method_full_name (method, FALSE);
-               g_error ("Method idx %d is greater than number of rows (%d) in PPDB MethodDebugInformation table, for method %s in '%s'. Likely a malformed PDB file.",
-                method_idx - 1, table_info_get_rows (methodbody_table), method_name, image->name);
-               g_free (method_name);
-       }
-       mono_metadata_decode_row (methodbody_table, method_idx - 1, cols, MONO_METHODBODY_SIZE);
-
-       docidx = cols [MONO_METHODBODY_DOCUMENT];
-
-       if (!cols [MONO_METHODBODY_SEQ_POINTS])
-               return;
-
-       ptr = mono_metadata_blob_heap (image, cols [MONO_METHODBODY_SEQ_POINTS]);
+       int method_idx = mono_metadata_token_index (method->token);
        
-       int sps_len = mono_ppdb_get_seq_points_internal (ptr, seq_points, n_seq_points, docidx, image, ppdb, &sfiles, source_file, source_files, &sindexes, TRUE);
-
-       if (source_files) {
-               *source_files = g_new (int, sps_len);
-               for (i = 0; i < sps_len; ++i)
-                       (*source_files)[i] = GPOINTER_TO_INT (g_ptr_array_index (sindexes, i));
-               g_ptr_array_free (sindexes, TRUE);
-       }
-
+       mono_ppdb_get_seq_points_internal (image, ppdb, method, method_idx, source_file, source_file_list, source_files, seq_points, n_seq_points);
 }
 
 static MonoDebugLocalsInfo*
-mono_ppdb_lookup_locals_internal (MonoImage *image, int method_idx, gboolean is_enc)
+mono_ppdb_lookup_locals_internal (MonoImage *image, int method_idx)
 {
        MonoDebugLocalsInfo *res;
        MonoTableInfo *tables = image->tables;
@@ -727,7 +712,7 @@ mono_ppdb_lookup_locals_internal (MonoImage *image, int method_idx, gboolean is_
 MonoDebugLocalsInfo*
 mono_ppdb_lookup_locals_enc (MonoImage *image, int method_idx)
 {
-       return mono_ppdb_lookup_locals_internal (image, method_idx + 1, TRUE);
+       return mono_ppdb_lookup_locals_internal (image, method_idx);
 }
 
 MonoDebugLocalsInfo*
@@ -749,7 +734,7 @@ mono_ppdb_lookup_locals (MonoDebugMethodInfo *minfo)
        method_idx = mono_metadata_token_index (method->token);
 
        
-       return mono_ppdb_lookup_locals_internal (image, method_idx, FALSE);
+       return mono_ppdb_lookup_locals_internal (image, method_idx);
 }
 
 /*
index b44637e..d26c164 100644 (file)
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/mono-debug.h>
 
+typedef struct _MonoDebugInformationEnc                MonoDebugInformationEnc;
+
+
+struct _MonoPPDBFile {
+       MonoImage *image;
+       GHashTable *doc_hash;
+       GHashTable *method_hash;
+       gboolean is_embedded;
+};
+
+struct _MonoDebugInformationEnc {
+       MonoPPDBFile *ppdb_file;
+       int idx;
+};
+
 MonoPPDBFile*
 mono_ppdb_load_file (MonoImage *image, const guint8 *raw_contents, int size);
 
-void
-mono_ppdb_close (MonoDebugHandle *handle);
+MONO_COMPONENT_API void
+mono_ppdb_close (MonoPPDBFile *ppdb_file);
 
 MonoDebugMethodInfo *
 mono_ppdb_lookup_method (MonoDebugHandle *handle, MonoMethod *method);
@@ -29,11 +44,14 @@ mono_ppdb_lookup_method (MonoDebugHandle *handle, MonoMethod *method);
 MonoDebugSourceLocation *
 mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset);
 
+MonoDebugSourceLocation *
+mono_ppdb_lookup_location_enc (MonoPPDBFile *ppdb_file, int idx, uint32_t offset);
+
 void
 mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points);
 
 gboolean 
-mono_ppdb_get_seq_points_enc (MonoImage *image, int idx, MonoSymSeqPoint **seq_points, int *n_seq_points);
+mono_ppdb_get_seq_points_enc (MonoDebugMethodInfo *minfo, MonoPPDBFile *ppdb_file, int idx, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points);
 
 MonoDebugLocalsInfo*
 mono_ppdb_lookup_locals (MonoDebugMethodInfo *minfo);
@@ -53,4 +71,7 @@ mono_ppdb_get_sourcelink (MonoDebugHandle *handle);
 gboolean 
 mono_ppdb_is_embedded (MonoPPDBFile *ppdb);
 
+MONO_COMPONENT_API MonoPPDBFile*
+mono_create_ppdb_file (MonoImage *ppdb_image, gboolean is_embedded_ppdb);
+
 #endif
index 372114e..b9bea0e 100644 (file)
@@ -124,7 +124,7 @@ static void
 free_debug_handle (MonoDebugHandle *handle)
 {
        if (handle->ppdb)
-               mono_ppdb_close (handle);
+               mono_ppdb_close (handle->ppdb);
        if (handle->symfile)
                mono_debug_close_mono_symbol_file (handle->symfile);
        /* decrease the refcount added with mono_image_addref () */
@@ -838,6 +838,17 @@ mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset,
 MonoDebugSourceLocation *
 mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset)
 {
+       MonoImage* img = m_class_get_image (minfo->method->klass);
+       if (img->has_updates) {
+               int idx = mono_metadata_token_index (minfo->method->token);
+               MonoDebugInformationEnc *mdie = (MonoDebugInformationEnc *) mono_metadata_update_get_updated_method_ppdb (img, idx);
+               if (mdie != NULL) {
+                       MonoDebugSourceLocation * ret = mono_ppdb_lookup_location_enc (mdie->ppdb_file, mdie->idx, il_offset);
+                       if (ret)
+                               return ret;
+               }
+       } 
+
        MonoDebugSourceLocation *location;
 
        mono_debugger_lock ();
@@ -866,7 +877,7 @@ mono_debug_lookup_locals (MonoMethod *method, mono_bool ignore_pdb)
                int idx = mono_metadata_token_index (method->token);
                MonoDebugInformationEnc *mdie = (MonoDebugInformationEnc *) mono_metadata_update_get_updated_method_ppdb (img, idx);
                if (mdie != NULL) {
-                       res = mono_ppdb_lookup_locals_enc (mdie->image, mdie->idx);
+                       res = mono_ppdb_lookup_locals_enc (mdie->ppdb_file->image, mdie->idx);
                        if (res != NULL)
                                return res;
                }
@@ -1128,11 +1139,11 @@ void
 mono_debug_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
 {
        MonoImage* img = m_class_get_image (minfo->method->klass);
-       if (img->has_updates && !source_file_list) {
+       if (img->has_updates) {
                int idx = mono_metadata_token_index (minfo->method->token);
                MonoDebugInformationEnc *mdie = (MonoDebugInformationEnc *) mono_metadata_update_get_updated_method_ppdb (img, idx);
                if (mdie != NULL) {
-                       if (mono_ppdb_get_seq_points_enc (mdie->image, mdie->idx, seq_points, n_seq_points))
+                       if (mono_ppdb_get_seq_points_enc (minfo, mdie->ppdb_file, mdie->idx, source_file, source_file_list, source_files, seq_points, n_seq_points))
                                return;
                }
        } 
index ccc9d3a..2ddbce0 100644 (file)
@@ -33,7 +33,6 @@ typedef struct _MonoDebugMethodInfo           MonoDebugMethodInfo;
 typedef struct _MonoDebugLocalsInfo            MonoDebugLocalsInfo;
 typedef struct _MonoDebugMethodAsyncInfo       MonoDebugMethodAsyncInfo;
 typedef struct _MonoDebugSourceLocation                MonoDebugSourceLocation;
-typedef struct _MonoDebugInformationEnc                MonoDebugInformationEnc;
 
 typedef struct _MonoDebugList                  MonoDebugList;
 
@@ -111,12 +110,6 @@ struct _MonoDebugSourceLocation {
        uint32_t il_offset;
 };
 
-
-struct _MonoDebugInformationEnc {
-       MonoImage *image;
-       int idx;
-};
-
 MONO_API mono_bool mono_debug_enabled (void);
 
 /*
index 77a3317..7bfc088 100644 (file)
@@ -343,7 +343,81 @@ namespace DebuggerTests
             pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 30, 12, "StaticMethod3");
             locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
             CheckBool(locals, "c", true);
+
+            await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 31, 12, "StaticMethod3",
+            locals_fn: (locals) =>
+                {
+                    CheckNumber(locals, "d", 10);
+                }
+            );
+            await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 32, 12, "StaticMethod3",
+            locals_fn: (locals) =>
+                {
+                    CheckNumber(locals, "d", 10);
+                    CheckNumber(locals, "e", 20);
+                }
+            );
+            await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 33, 8, "StaticMethod3",
+            locals_fn: (locals) =>
+                {
+                    CheckNumber(locals, "d", 10);
+                    CheckNumber(locals, "e", 20);
+                    CheckNumber(locals, "f", 50);
+                }
+            );
         }
 
+
+        [Fact]
+        public async Task DebugHotReloadMethodEmpty()
+        {
+            int line = 38;
+            await SetBreakpoint(".*/MethodBody1.cs$", line, 0, use_regex: true);
+            var pause_location = await LoadAssemblyAndTestHotReload(
+                    Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"),
+                    Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"),
+                    Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"),
+                    "MethodBody4", "StaticMethod4");
+
+            var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+            pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 38, 12, "StaticMethod4");
+            locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+            await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 39, 12, "StaticMethod4",
+            locals_fn: (locals) =>
+                {
+                    CheckNumber(locals, "a", 10);
+                }
+            );
+            await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 40, 12, "StaticMethod4",
+            locals_fn: (locals) =>
+                {
+                    CheckNumber(locals, "a", 10);
+                    CheckNumber(locals, "b", 20);
+                }
+            );
+            await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 41, 12, "StaticMethod4",
+            locals_fn: (locals) =>
+                {
+                    CheckNumber(locals, "a", 10);
+                    CheckNumber(locals, "b", 20);
+                }
+            );
+            await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 42, 12, "StaticMethod4",
+            locals_fn: (locals) =>
+                {
+                    CheckNumber(locals, "a", 10);
+                    CheckNumber(locals, "b", 20);
+                }
+            );
+            await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 43, 8, "StaticMethod4",
+            locals_fn: (locals) =>
+                {
+                    CheckNumber(locals, "a", 10);
+                    CheckNumber(locals, "b", 20);
+                }
+            );
+            pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 38, 8, "StaticMethod4");
+            locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+        }
     }
 }
diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody0.cs b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody0.cs
new file mode 100644 (file)
index 0000000..833ac95
--- /dev/null
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System;
+
+namespace ApplyUpdateReferencedAssembly
+{
+    public class MethodBodyUnchangedAssembly {
+        public static string StaticMethod1 () {
+            Console.WriteLine("original");
+            return "ok";
+        }
+    }
+}
index b2b8f4d..d092ec0 100644 (file)
@@ -31,4 +31,11 @@ namespace ApplyUpdateReferencedAssembly
             return "OLD STRING";
         }
     }
+
+
+
+    public class MethodBody4 {
+        public static void StaticMethod4 () {
+        }
+    }
 }
index 03a4d33..6ce229d 100644 (file)
@@ -31,4 +31,16 @@ namespace ApplyUpdateReferencedAssembly
             return "NEW STRING";
         }
     }
+
+
+
+    public class MethodBody4 {
+        public static void StaticMethod4 () {
+            int a = 10;
+            int b = 20;
+            Console.WriteLine(a + b);
+            Console.WriteLine(a + b);
+            Console.WriteLine(a + b);
+        }
+    }
 }
index 4cd88d6..1ced5fd 100644 (file)
@@ -27,8 +27,15 @@ namespace ApplyUpdateReferencedAssembly
     public class MethodBody3 {
         public static string StaticMethod3 () {
             bool c = true;
-            Console.WriteLine("v2");
+            int d = 10;
+            int e = 20;
+            int f = 50;
             return "NEWEST STRING";
         }
     }
+
+    public class MethodBody4 {
+        public static void StaticMethod4 () {
+        }
+    }
 }