From 1baa396e21c272cc9cc1fea4e5d372ae1979fb9f Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Fri, 6 Jun 2025 06:46:14 +0900 Subject: fix `rp(obj)` for any object Now `rp(obj)` doesn't work if the `obj` is out-of-heap because of `asan_unpoisoning_object()`, so this patch solves it. Also add pointer information and type information to show. --- gc.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'gc.c') diff --git a/gc.c b/gc.c index 7b7e31e9ca..7dee915fab 100644 --- a/gc.c +++ b/gc.c @@ -4770,6 +4770,7 @@ rb_raw_obj_info_common(char *const buff, const size_t buff_size, const VALUE obj // const int age = RVALUE_AGE_GET(obj); if (rb_gc_impl_pointer_to_heap_p(rb_gc_get_objspace(), (void *)obj)) { + APPEND_F("%p %s/", (void *)obj, obj_type_name(obj)); // TODO: fixme // APPEND_F("%p [%d%s%s%s%s%s%s] %s ", // (void *)obj, age, @@ -4797,7 +4798,7 @@ rb_raw_obj_info_common(char *const buff, const size_t buff_size, const VALUE obj else if (RTEST(RBASIC(obj)->klass)) { VALUE class_path = rb_class_path_cached(RBASIC(obj)->klass); if (!NIL_P(class_path)) { - APPEND_F("(%s)", RSTRING_PTR(class_path)); + APPEND_F("%s ", RSTRING_PTR(class_path)); } } } @@ -5032,15 +5033,35 @@ rb_asan_poisoned_object_p(VALUE obj) return __asan_region_is_poisoned(ptr, rb_gc_obj_slot_size(obj)); } +static void +raw_obj_info(char *const buff, const size_t buff_size, VALUE obj) +{ + size_t pos = rb_raw_obj_info_common(buff, buff_size, obj); + pos = rb_raw_obj_info_buitin_type(buff, buff_size, obj, pos); + if (pos >= buff_size) {} // truncated +} + const char * rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj) { - asan_unpoisoning_object(obj) { - size_t pos = rb_raw_obj_info_common(buff, buff_size, obj); - pos = rb_raw_obj_info_buitin_type(buff, buff_size, obj, pos); - if (pos >= buff_size) {} // truncated - } + void *objspace = rb_gc_get_objspace(); + if (SPECIAL_CONST_P(obj)) { + raw_obj_info(buff, buff_size, obj); + } + else if (!rb_gc_impl_pointer_to_heap_p(objspace, (const void *)obj)) { + snprintf(buff, buff_size, "out-of-heap:%p", (void *)obj); + } +#if 0 // maybe no need to check it? + else if (0 && rb_gc_impl_garbage_object_p(objspace, obj)) { + snprintf(buff, buff_size, "garbage:%p", (void *)obj); + } +#endif + else { + asan_unpoisoning_object(obj) { + raw_obj_info(buff, buff_size, obj); + } + } return buff; } -- cgit v1.2.3