[sgen] Don't crash on canaries when called from `mono_gc_scan_for_specific_ref()`.
authorMark Probst <mark.probst@gmail.com>
Thu, 16 Jul 2015 20:46:32 +0000 (13:46 -0700)
committerMark Probst <mark.probst@gmail.com>
Thu, 16 Jul 2015 20:48:28 +0000 (13:48 -0700)
This function is only ever called from the debugger, and we don't want
it to crash when a canary has been overwritten.

mono/metadata/sgen-mono.c
mono/sgen/sgen-debug.c
mono/sgen/sgen-gc.c
mono/sgen/sgen-gc.h

index 4e147406783b30d20684758cb77ef20727852b99..bb44f590762d61a3903b3500e8fb4f1d65b8aadf 100644 (file)
@@ -870,7 +870,7 @@ mono_gc_clear_domain (MonoDomain * domain)
                sgen_remove_finalizers_if (object_in_domain_predicate, domain, i);
 
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                       (IterateObjectCallbackFunc)clear_domain_process_minor_object_callback, domain, FALSE);
+                       (IterateObjectCallbackFunc)clear_domain_process_minor_object_callback, domain, FALSE, TRUE);
 
        /* We need two passes over major and large objects because
           freeing such objects might give their memory back to the OS
@@ -1845,7 +1845,7 @@ mono_gc_set_string_length (MonoString *str, gint32 new_length)
         * the space to be reclaimed by SGen. */
 
        if (nursery_canaries_enabled () && sgen_ptr_in_nursery (str)) {
-               CHECK_CANARY_FOR_OBJECT ((GCObject*)str);
+               CHECK_CANARY_FOR_OBJECT ((GCObject*)str, TRUE);
                memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2) + CANARY_SIZE);
                memcpy (new_end + 1 , CANARY_STRING, CANARY_SIZE);
        } else {
@@ -2144,7 +2144,7 @@ mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data)
        hwi.data = data;
 
        sgen_clear_nursery_fragments ();
-       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, walk_references, &hwi, FALSE);
+       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, walk_references, &hwi, FALSE, TRUE);
 
        major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, walk_references, &hwi);
        sgen_los_iterate_objects (walk_references, &hwi);
index 5b4f7fe3ce4851feb66109b5ff9af19532c51524..79e23ed453bea3003b1ed3947e7fdc786770ec73 100644 (file)
@@ -336,7 +336,7 @@ setup_valid_nursery_objects (void)
        if (!valid_nursery_objects)
                valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "debugging data");
        valid_nursery_object_count = 0;
-       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE);
+       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE, FALSE);
 }
 
 static gboolean
@@ -469,7 +469,7 @@ sgen_check_whole_heap (gboolean allow_missing_pinned)
        setup_valid_nursery_objects ();
 
        broken_heap = FALSE;
-       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE);
+       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE, TRUE);
        major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
        sgen_los_iterate_objects (verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
 
@@ -623,7 +623,7 @@ sgen_check_nursery_objects_pinned (gboolean pinned)
 {
        sgen_clear_nursery_fragments ();
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                       (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE);
+                       (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE, TRUE);
 }
 
 static void
@@ -679,7 +679,7 @@ sgen_debug_verify_nursery (gboolean do_dump_nursery_content)
                                        is_array_fill);
                }
                if (nursery_canaries_enabled () && !is_array_fill) {
-                       CHECK_CANARY_FOR_OBJECT ((GCObject*)cur);
+                       CHECK_CANARY_FOR_OBJECT ((GCObject*)cur, TRUE);
                        CANARIFY_SIZE (size);
                }
                cur += size;
@@ -844,7 +844,7 @@ mono_gc_scan_for_specific_ref (GCObject *key, gboolean precise)
        scan_object_for_specific_ref_precise = precise;
 
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                       (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE);
+                       (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE, FALSE);
 
        major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key);
 
@@ -1041,7 +1041,7 @@ sgen_check_for_xdomain_refs (void)
        LOSObject *bigobj;
 
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                       (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE);
+                       (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE, TRUE);
 
        major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL);
 
@@ -1216,7 +1216,7 @@ sgen_find_object_for_ptr (char *ptr)
        if (ptr >= nursery_section->data && ptr < nursery_section->end_data) {
                found_obj = NULL;
                sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                               find_object_for_ptr_callback, ptr, TRUE);
+                               find_object_for_ptr_callback, ptr, TRUE, FALSE);
                if (found_obj)
                        return found_obj;
        }
index a24badfaf7c185d8a870932a9ed92ad26f23face..4b1a1ac16169849b72bd9bc8b630e45592caa29f 100644 (file)
@@ -465,7 +465,7 @@ gray_queue_enable_redirect (SgenGrayQueue *queue)
 }
 
 void
-sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags)
+sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags, gboolean fail_on_canaries)
 {
        while (start < end) {
                size_t size;
@@ -484,7 +484,7 @@ sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc
                }
 
                if (!sgen_client_object_is_array_fill ((GCObject*)obj)) {
-                       CHECK_CANARY_FOR_OBJECT ((GCObject*)obj);
+                       CHECK_CANARY_FOR_OBJECT ((GCObject*)obj, fail_on_canaries);
                        size = ALIGN_UP (safe_object_get_size ((GCObject*)obj));
                        callback ((GCObject*)obj, size, data);
                        CANARIFY_SIZE (size);
@@ -664,7 +664,7 @@ pin_objects_from_nursery_pin_queue (gboolean do_scan_objects, ScanCopyContext ct
                         * either.
                         */
                        if (!sgen_client_object_is_array_fill ((GCObject*)search_start)) {
-                               CHECK_CANARY_FOR_OBJECT (search_start);
+                               CHECK_CANARY_FOR_OBJECT (search_start, TRUE);
                                CANARIFY_SIZE (canarified_obj_size);
 
                                if (addr >= search_start && (char*)addr < (char*)search_start + obj_size) {
@@ -1685,7 +1685,7 @@ static void
 scan_nursery_objects (ScanCopyContext ctx)
 {
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                       (IterateObjectCallbackFunc)scan_nursery_objects_callback, (void*)&ctx, FALSE);
+                       (IterateObjectCallbackFunc)scan_nursery_objects_callback, (void*)&ctx, FALSE, TRUE);
 }
 
 typedef enum {
index bc1b131f508a1a0adf327a9d07ad26a0f2a5a8e3..49fb4c1fac132347f01575b8c0130dfaefe5b8aa 100644 (file)
@@ -384,7 +384,7 @@ void sgen_deregister_root (char* addr);
 
 typedef void (*IterateObjectCallbackFunc) (GCObject*, size_t, void*);
 
-void sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags);
+void sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags, gboolean fail_on_canaries);
 
 /* eventually share with MonoThread? */
 /*
@@ -1056,13 +1056,16 @@ gboolean nursery_canaries_enabled (void);
 
 #define CANARY_VALID(addr) (strncmp ((char*) (addr), CANARY_STRING, CANARY_SIZE) == 0)
 
-#define CHECK_CANARY_FOR_OBJECT(addr) if (nursery_canaries_enabled ()) {       \
+#define CHECK_CANARY_FOR_OBJECT(addr,fail) if (nursery_canaries_enabled ()) {  \
                                char* canary_ptr = (char*) (addr) + sgen_safe_object_get_size_unaligned ((GCObject *) (addr));  \
                                if (!CANARY_VALID(canary_ptr)) {        \
                                        char canary_copy[CANARY_SIZE +1];       \
                                        strncpy (canary_copy, canary_ptr, CANARY_SIZE); \
                                        canary_copy[CANARY_SIZE] = 0;   \
-                                       g_error ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE ((addr))), CANARY_STRING, canary_copy);      \
+                                       if ((fail))                     \
+                                               g_error ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE ((addr))), CANARY_STRING, canary_copy); \
+                                       else                            \
+                                               g_warning ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE ((addr))), CANARY_STRING, canary_copy); \
                                } }
 
 #endif /* HAVE_SGEN_GC */