First set of licensing changes
[mono.git] / mono / metadata / debug-mono-ppdb.c
index 46cf3468e5db286e541bc687d15daa36a15249d2..e6d9cc95e2f578977f80362f5ce971b5ef15c42e 100644 (file)
@@ -7,6 +7,7 @@
  *     Mono Project (http://www.mono-project.com)
  *
  * Copyright 2015 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -97,7 +98,7 @@ doc_free (gpointer key)
 MonoPPDBFile*
 mono_ppdb_load_file (MonoImage *image, const guint8 *raw_contents, int size)
 {
-       MonoImage *ppdb_image;
+       MonoImage *ppdb_image = NULL;
        const char *filename;
        char *s, *ppdb_filename;
        MonoImageOpenStatus status;
@@ -107,7 +108,8 @@ mono_ppdb_load_file (MonoImage *image, const guint8 *raw_contents, int size)
        MonoPPDBFile *ppdb;
 
        if (raw_contents) {
-               ppdb_image = mono_image_open_from_data_internal ((char*)raw_contents, size, TRUE, &status, FALSE, TRUE, NULL);
+               if (size > 4 && strncmp ((char*)raw_contents, "BSJB", 4) == 0)
+                       ppdb_image = mono_image_open_from_data_internal ((char*)raw_contents, size, TRUE, &status, FALSE, TRUE, NULL);
        } else {
                /* ppdb files drop the .exe/.dll extension */
                filename = mono_image_get_filename (image);
@@ -291,7 +293,8 @@ mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
        gboolean first = TRUE, first_non_hidden = TRUE;
        MonoDebugSourceLocation *location;
 
-       g_assert (method->token);
+       if (!method->token)
+               return NULL;
 
        idx = mono_metadata_token_index (method->token);
 
@@ -518,16 +521,39 @@ mono_ppdb_lookup_locals (MonoDebugMethodInfo *minfo)
        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 (scope_idx == tables [MONO_TABLE_LOCALSCOPE].rows) {
+
+       // https://github.com/dotnet/roslyn/blob/2ae8d5fed96ab3f1164031f9b4ac827f53289159/docs/specs/PortablePdb-Metadata.md#LocalScopeTable
+       //
+       // The variableList attribute in the pdb metadata table is a contiguous array that starts at a
+       // given offset (locals_idx) above and
+       //
+       // """
+       // continues to the smaller of:
+       //
+       // the last row of the LocalVariable table
+       // the next run of LocalVariables, found by inspecting the VariableList of the next row in this LocalScope table.
+       // """
+       // this endpoint becomes locals_end_idx below
+
+       // March to the last scope that is in this method
+       while (scope_idx <= tables [MONO_TABLE_LOCALSCOPE].rows) {
                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 ++;
        }
+       // The number of scopes is the difference in the indices
+       // for the first and last scopes
        nscopes = scope_idx - start_scope_idx;
-       if (scope_idx == tables [MONO_TABLE_LOCALSCOPE].rows) {
-               locals_end_idx = tables [MONO_TABLE_LOCALVARIABLE].rows;
+
+       // Ends with "the last row of the LocalVariable table"
+       // this happens if the above loop marched one past the end
+       // of the rows
+       if (scope_idx > tables [MONO_TABLE_LOCALSCOPE].rows) {
+               locals_end_idx = tables [MONO_TABLE_LOCALVARIABLE].rows + 1;
        } else {
+               // Ends with "the next run of LocalVariables,
+               // found by inspecting the VariableList of the next row in this LocalScope table."
                locals_end_idx = cols [MONO_LOCALSCOPE_VARIABLELIST];
        }
 
@@ -544,7 +570,7 @@ mono_ppdb_lookup_locals (MonoDebugMethodInfo *minfo)
 
                locals_idx = cols [MONO_LOCALSCOPE_VARIABLELIST];
                if (scope_idx == tables [MONO_TABLE_LOCALSCOPE].rows) {
-                       locals_end_idx = tables [MONO_TABLE_LOCALVARIABLE].rows;
+                       locals_end_idx = tables [MONO_TABLE_LOCALVARIABLE].rows + 1;
                } else {
                        locals_end_idx = mono_metadata_decode_row_col (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1 + 1, MONO_LOCALSCOPE_VARIABLELIST);
                }