2009-10-24 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Sat, 24 Oct 2009 02:19:15 +0000 (02:19 -0000)
committerZoltan Varga <vargaz@gmail.com>
Sat, 24 Oct 2009 02:19:15 +0000 (02:19 -0000)
* reflection.c (resolve_object): Set handle_class for strings too.
(mono_reflection_create_custom_attr_data_args): New helper function to decode
a cattr blob into a set of arrays and structures without creating the custom
attributes themselves.
(create_custom_attr_data): Simplify using create_custom_attr_data_args.

* mono-debug.c (mono_debug_il_offset_from_address): New helper function.

* debug-mono-symfile.c (mono_debug_symfile_get_line_numbers): New helper
function.

svn path=/trunk/mono/; revision=144777

mono/metadata/ChangeLog
mono/metadata/debug-mono-symfile.c
mono/metadata/debug-mono-symfile.h
mono/metadata/mono-debug.c
mono/metadata/mono-debug.h
mono/metadata/object-internals.h
mono/metadata/reflection.c

index 94ee180ad7bad1f089b5a27b813a1643aff1891e..d88415f4b1b3211b87b90e196a1bdc80d9d4ea36 100644 (file)
@@ -1,3 +1,16 @@
+2009-10-24  Zoltan Varga  <vargaz@gmail.com>
+
+       * reflection.c (resolve_object): Set handle_class for strings too.
+       (mono_reflection_create_custom_attr_data_args): New helper function to decode
+       a cattr blob into a set of arrays and structures without creating the custom
+       attributes themselves.
+       (create_custom_attr_data): Simplify using create_custom_attr_data_args.
+
+       * mono-debug.c (mono_debug_il_offset_from_address): New helper function.
+
+       * debug-mono-symfile.c (mono_debug_symfile_get_line_numbers): New helper
+       function.
+
 2009-10-23  Rodrigo Kumpera  <rkumpera@novell.com>
 
        * verify.c: Replace calls to mono_class_inflate_generic_type with
index 5898ce5f94969ef4bee2a1f0f378b8e4b2540580..ab04bcb90b71817fbcc6c14b9d138e0efa3fddd4 100644 (file)
@@ -205,7 +205,7 @@ typedef struct {
        int line_base, line_range, max_address_incr;
        guint8 opcode_base;
        guint32 last_line, last_file, last_offset;
-       guint32 line, file, offset;
+       int line, file, offset;
 } StatementMachine;
 
 static gboolean
@@ -361,6 +361,138 @@ mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, guint32 offset)
        return location;
 }
 
+static void
+add_line (StatementMachine *stm, GPtrArray *il_offset_array, GPtrArray *line_number_array)
+{
+       if (stm->line > 0) {
+               g_ptr_array_add (il_offset_array, GUINT_TO_POINTER (stm->offset));
+               g_ptr_array_add (line_number_array, GUINT_TO_POINTER (stm->line));
+       }
+}
+
+/*
+ * mono_debug_symfile_get_line_numbers:
+ *
+ *   All the output parameters can be NULL.
+ */ 
+void
+mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_file, int *n_il_offsets, int **il_offsets, int **line_numbers)
+{
+       // FIXME: Unify this with mono_debug_symfile_lookup_location
+       MonoSymbolFile *symfile;
+       const unsigned char *ptr;
+       StatementMachine stm;
+       guint32 i;
+       GPtrArray *il_offset_array, *line_number_array;
+
+       if (source_file)
+               *source_file = NULL;
+       if (n_il_offsets)
+               *n_il_offsets = 0;
+
+       if ((symfile = minfo->handle->symfile) == NULL)
+               return;
+
+       il_offset_array = g_ptr_array_new ();
+       line_number_array = g_ptr_array_new ();
+
+       stm.line_base = read32 (&symfile->offset_table->_line_number_table_line_base);
+       stm.line_range = read32 (&symfile->offset_table->_line_number_table_line_range);
+       stm.opcode_base = (guint8) read32 (&symfile->offset_table->_line_number_table_opcode_base);
+       stm.max_address_incr = (255 - stm.opcode_base) / stm.line_range;
+
+       mono_debugger_lock ();
+
+       ptr = symfile->raw_contents + minfo->lnt_offset;
+
+       stm.symfile = symfile;
+       stm.offset = stm.last_offset = 0;
+       stm.last_file = 0;
+       stm.last_line = 0;
+       stm.file = 1;
+       stm.line = 1;
+
+       while (TRUE) {
+               guint8 opcode = *ptr++;
+
+               if (opcode == 0) {
+                       guint8 size = *ptr++;
+                       const unsigned char *end_ptr = ptr + size;
+
+                       opcode = *ptr++;
+
+                       if (opcode == DW_LNE_end_sequence) {
+                               add_line (&stm, il_offset_array, line_number_array);
+                               break;
+                       } else if (opcode == DW_LNE_MONO_negate_is_hidden) {
+                               ;
+                       } else if ((opcode >= DW_LNE_MONO__extensions_start) &&
+                                  (opcode <= DW_LNE_MONO__extensions_end)) {
+                               ; // reserved for future extensions
+                       } else {
+                               g_warning ("Unknown extended opcode %x in LNT", opcode);
+                       }
+
+                       ptr = end_ptr;
+                       continue;
+               } else if (opcode < stm.opcode_base) {
+                       switch (opcode) {
+                       case DW_LNS_copy:
+                               add_line (&stm, il_offset_array, line_number_array);
+                               break;
+                       case DW_LNS_advance_pc:
+                               stm.offset += read_leb128 (ptr, &ptr);
+                               break;
+                       case DW_LNS_advance_line:
+                               stm.line += read_leb128 (ptr, &ptr);
+                               break;
+                       case DW_LNS_set_file:
+                               stm.file = read_leb128 (ptr, &ptr);
+                               break;
+                       case DW_LNS_const_add_pc:
+                               stm.offset += stm.max_address_incr;
+                               break;
+                       default:
+                               g_warning ("Unknown standard opcode %x in LNT", opcode);
+                               g_assert_not_reached ();
+                       }
+               } else {
+                       opcode -= stm.opcode_base;
+
+                       stm.offset += opcode / stm.line_range;
+                       stm.line += stm.line_base + (opcode % stm.line_range);
+
+                       add_line (&stm, il_offset_array, line_number_array);
+               }
+       }
+
+       if (stm.file) {
+               int offset = read32(&(stm.symfile->offset_table->_source_table_offset)) +
+                       (stm.file - 1) * sizeof (MonoSymbolFileSourceEntry);
+               MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *)
+                       (stm.symfile->raw_contents + offset);
+
+               if (source_file)
+                       *source_file = read_string (stm.symfile->raw_contents + read32(&(se->_data_offset)));
+       }
+
+       if (n_il_offsets)
+               *n_il_offsets = il_offset_array->len;
+       if (il_offsets && line_numbers) {
+               *il_offsets = g_malloc (il_offset_array->len * sizeof (int));
+               *line_numbers = g_malloc (il_offset_array->len * sizeof (int));
+               for (i = 0; i < il_offset_array->len; ++i) {
+                       (*il_offsets) [i] = GPOINTER_TO_UINT (g_ptr_array_index (il_offset_array, i));
+                       (*line_numbers) [i] = GPOINTER_TO_UINT (g_ptr_array_index (line_number_array, i));
+               }
+       }
+       g_ptr_array_free (il_offset_array, TRUE);
+       g_ptr_array_free (line_number_array, TRUE);
+
+       mono_debugger_unlock ();
+       return;
+}
+
 gint32
 _mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offset)
 {
index a9bd5473f5b496599321ed34ff4f42ce795175c2..9bf2a4f7dbc384311042e9d131e33368113e7b3e 100644 (file)
@@ -124,6 +124,9 @@ int
 mono_debug_symfile_lookup_locals (MonoDebugMethodInfo *minfo, char ***names, 
                                                                  int **indexes);
 
+void
+mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_file, int *n_il_offsets, int **il_offsets, int **line_numbers);
+
 G_END_DECLS
 
 #endif /* __MONO_SYMFILE_H__ */
index 82722ca453fc55f6f67e0cd32d56cb070b10cbdf..c773158e722ef7afbf802bf6202181e461ea6472 100644 (file)
@@ -991,6 +991,26 @@ cleanup_and_fail:
        return -1;
 }
 
+/**
+ * mono_debug_il_offset_from_address:
+ *
+ *   Compute the IL offset corresponding to NATIVE_OFFSET inside the native
+ * code of METHOD in DOMAIN.
+ */
+gint32
+mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
+{
+       gint32 res;
+
+       mono_debugger_lock ();
+
+       res = il_offset_from_address (method, domain, native_offset);
+
+       mono_debugger_unlock ();
+
+       return res;
+}
+
 /**
  * mono_debug_lookup_source_location:
  * @address: Native offset within the @method's machine code.
index b9551771267f7aaca3f3801b32faa6cc30b55327..b8a8bb231ab39c065514ff6518d5481353510962 100644 (file)
@@ -181,6 +181,9 @@ mono_debug_lookup_locals (MonoMethod *method, char ***names, int **indexes);
 MonoDebugSourceLocation *
 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain);
 
+gint32
+mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset);
+
 void
 mono_debug_free_source_location (MonoDebugSourceLocation *location);
 
index 9540f0ed89c2def06891dad71645458f68c7bd72..7dcaa5dae836bca189cee4dc3dcee23670d34d86 100644 (file)
@@ -1255,6 +1255,12 @@ typedef enum {
        GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK    = 28
 } GenericParameterAttributes;
 
+typedef struct {
+       MonoType *type;
+       MonoClassField *field;
+       MonoProperty *prop;
+} CattrNamedArg;
+
 void          mono_image_create_pefile (MonoReflectionModuleBuilder *module, HANDLE file) MONO_INTERNAL;
 void          mono_image_basic_init (MonoReflectionAssemblyBuilder *assembly) MONO_INTERNAL;
 MonoReflectionModule * mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *assembly, MonoString *file_name) MONO_INTERNAL;
@@ -1283,6 +1289,7 @@ void mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb) MO
 
 void        mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam) MONO_INTERNAL;
 void        mono_reflection_create_unmanaged_type (MonoReflectionType *type) MONO_INTERNAL;
+void        mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info) MONO_INTERNAL;
 
 MonoArray* mono_param_get_objects_internal  (MonoDomain *domain, MonoMethod *method, MonoClass *refclass) MONO_INTERNAL;
 
index 4367d401d57b871fe2ac3e45441d314e97a5a70d..39de52f57c091b108404d68dc05c0a026f417d84 100644 (file)
@@ -7956,51 +7956,48 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
 
        return attr;
 }
-
-static MonoObject*
-create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
+       
+/*
+ * mono_reflection_create_custom_attr_data_args:
+ *
+ *   Create an array of typed and named arguments from the cattr blob given by DATA.
+ * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
+ * NAMED_ARG_INFO will contain information about the named arguments.
+ */
+void
+mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info)
 {
        MonoArray *typedargs, *namedargs;
        MonoClass *attrklass;
-       static MonoMethod *ctor;
        MonoDomain *domain;
-       MonoObject *attr;
        const char *p = (const char*)data;
        const char *named;
        guint32 i, j, num_named;
-       void *params [3];
+       CattrNamedArg *arginfo = NULL;
 
        mono_class_init (method->klass);
 
-       if (!ctor)
-               ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
-
+       *typed_args = NULL;
+       *named_args = NULL;
+       *named_arg_info = NULL;
+       
        domain = mono_domain_get ();
-       if (len == 0) {
-               /* This is for Attributes with no parameters */
-               attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
-               params [0] = mono_method_get_object (domain, method, NULL);
-               params [1] = params [2] = NULL;
-               mono_runtime_invoke (method, attr, params, NULL);
-               return attr;
-       }
 
        if (len < 2 || read16 (p) != 0x0001) /* Prolog */
-               return NULL;
+               return;
 
        typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
        
        /* skip prolog */
        p += 2;
        for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
-               MonoObject *obj, *typedarg;
+               MonoObject *obj;
                void *val;
 
                val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
                obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
                        val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
-               typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
-               mono_array_setref (typedargs, i, typedarg);
+               mono_array_setref (typedargs, i, obj);
 
                if (!type_is_reference (mono_method_signature (method)->params [i]))
                        g_free (val);
@@ -8011,6 +8008,10 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
        namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
        named += 2;
        attrklass = method->klass;
+
+       arginfo = g_new0 (CattrNamedArg, num_named);
+       *named_arg_info = arginfo;
+
        for (j = 0; j < num_named; j++) {
                gint name_len;
                char *name, named_type, data_type;
@@ -8035,36 +8036,96 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
                name [name_len] = 0;
                named += name_len;
                if (named_type == 0x53) {
-                       MonoObject *obj, *typedarg, *namedarg;
+                       MonoObject *obj;
                        MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
-                       void *minfo, *val = load_cattr_value (image, field->type, named, &named);
-                       
-                       minfo = mono_field_get_object (domain, NULL, field);
+                       void *val;
+
+                       arginfo [j].type = field->type;
+                       arginfo [j].field = field;
+
+                       val = load_cattr_value (image, field->type, named, &named);
                        obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
-                       typedarg = create_cattr_typed_arg (field->type, obj);
-                       namedarg = create_cattr_named_arg (minfo, typedarg);
-                       mono_array_setref (namedargs, j, namedarg);
+                       mono_array_setref (namedargs, j, obj);
                        if (!type_is_reference (field->type))
                                g_free (val);
                } else if (named_type == 0x54) {
-                       MonoObject *obj, *typedarg, *namedarg;
+                       MonoObject *obj;
                        MonoType *prop_type;
-                       void *val, *minfo;
                        MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
+                       void *val;
 
                        prop_type = prop->get? mono_method_signature (prop->get)->ret :
                             mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
-                       minfo =  mono_property_get_object (domain, NULL, prop);
+
+                       arginfo [j].type = prop_type;
+                       arginfo [j].prop = prop;
+
                        val = load_cattr_value (image, prop_type, named, &named);
                        obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
-                       typedarg = create_cattr_typed_arg (prop_type, obj);
-                       namedarg = create_cattr_named_arg (minfo, typedarg);
-                       mono_array_setref (namedargs, j, namedarg);
+                       mono_array_setref (namedargs, j, obj);
                        if (!type_is_reference (prop_type))
                                g_free (val);
                }
                g_free (name);
        }
+
+       *typed_args = typedargs;
+       *named_args = namedargs;
+}
+
+static MonoObject*
+create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
+{
+       MonoArray *typedargs, *namedargs;
+       static MonoMethod *ctor;
+       MonoDomain *domain;
+       MonoObject *attr;
+       void *params [3];
+       CattrNamedArg *arginfo;
+       int i;
+
+       mono_class_init (method->klass);
+
+       if (!ctor)
+               ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
+
+       domain = mono_domain_get ();
+       if (len == 0) {
+               /* This is for Attributes with no parameters */
+               attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
+               params [0] = mono_method_get_object (domain, method, NULL);
+               params [1] = params [2] = NULL;
+               mono_runtime_invoke (method, attr, params, NULL);
+               return attr;
+       }
+
+       mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
+       if (!typedargs || !namedargs)
+               return NULL;
+
+       for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
+               MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
+               MonoObject *typedarg;
+
+               typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
+               mono_array_setref (typedargs, i, typedarg);
+       }
+
+       for (i = 0; i < mono_array_length (namedargs); ++i) {
+               MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
+               MonoObject *typedarg, *namedarg, *minfo;
+
+               if (arginfo [i].prop)
+                       minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
+               else
+                       minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
+
+               typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
+               namedarg = create_cattr_named_arg (minfo, typedarg);
+
+               mono_array_setref (namedargs, i, namedarg);
+       }
+
        attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
        params [0] = mono_method_get_object (domain, method, NULL);
        params [1] = typedargs;
@@ -10935,7 +10996,7 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
 
        if (strcmp (obj->vtable->klass->name, "String") == 0) {
                result = mono_string_intern ((MonoString*)obj);
-               *handle_class = NULL;
+               *handle_class = mono_defaults.string_class;
                g_assert (result);
        } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
                MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);