Skip to content

Commit 127b402

Browse files
thaystgUnityAlex
authored andcommitted
[debugger] Assert when async debug a generic method (mono#17727)
* When we try to call a method to get the async_id to do an async debug and we are trying to do this in a generic method like this: async Task<T> ExecuteAsync_Broken<T>() { await Task.Delay(2); return default; } We need to inflate the generic type before call the method or we will get the error: Could not execute the method because the containing type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[T_REF]’, is not fully instantiated. Fixes mono#17549 Fixes mono#17569 Cherry-picked by Alex Thibodeau -- some light massaging required
1 parent 4487f30 commit 127b402

File tree

5 files changed

+60
-9
lines changed

5 files changed

+60
-9
lines changed

mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ public static int Main (String[] args) {
366366
new Tests ().invoke_abort ();
367367
new Tests ().evaluate_method ();
368368

369+
test_async_debug_generics();
369370
test_invalid_argument_assembly_get_type ();
370371

371372
return 3;
@@ -558,6 +559,17 @@ public static void ss_nested () {
558559
ss_nested_3 ();
559560
}
560561

562+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
563+
public static void test_async_debug_generics () {
564+
ExecuteAsync_Broken<object>().Wait ();
565+
}
566+
567+
async static Task<T> ExecuteAsync_Broken<T>()
568+
{
569+
await Task.Delay(2);
570+
return default;
571+
}
572+
561573
[MethodImplAttribute (MethodImplOptions.NoInlining)]
562574
public static void ss_nested_1 (int i) {
563575
}

mcs/class/Mono.Debugger.Soft/Test/dtest.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4444,5 +4444,14 @@ public void InvalidArgumentAssemblyGetType () {
44444444
}
44454445
}
44464446

4447+
[Test]
4448+
public void TestAsyncDebugGenerics () {
4449+
Event e = run_until ("test_async_debug_generics");
4450+
e = step_in_await ("test_async_debug_generics", e);
4451+
e = step_in_await ("MoveNext", e);
4452+
e = step_in_await ("MoveNext", e);
4453+
e = step_in_await ("MoveNext", e);
4454+
e = step_in_await ("MoveNext", e);
4455+
}
44474456
} // class DebuggerTests
44484457
} // namespace

mono/mini/debugger-agent.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5448,6 +5448,30 @@ get_object_id_for_debugger_method (MonoClass* async_builder_class)
54485448
return method;
54495449
}
54505450

5451+
static MonoClass *
5452+
get_class_to_get_builder_field(StackFrame *frame)
5453+
{
5454+
MonoError error;
5455+
gpointer this_addr = get_this_addr (frame);
5456+
MonoClass *original_class = frame->method->klass;
5457+
MonoClass *ret;
5458+
if (!mono_class_is_valuetype(original_class) && mono_class_is_open_constructed_type (&original_class->byval_arg)) {
5459+
MonoObject *this_obj = *(MonoObject**)this_addr;
5460+
MonoGenericContext context;
5461+
MonoType *inflated_type;
5462+
5463+
g_assert (this_obj);
5464+
context = mono_get_generic_context_from_stack_frame (frame->ji, this_obj->vtable);
5465+
inflated_type = mono_class_inflate_generic_type_checked (&original_class->byval_arg, &context, &error);
5466+
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
5467+
5468+
ret = mono_class_from_mono_type (inflated_type);
5469+
mono_metadata_free_type (inflated_type);
5470+
return ret;
5471+
}
5472+
return original_class;
5473+
}
5474+
54515475
/* Return the address of the AsyncMethodBuilder struct belonging to the state machine method pointed to by FRAME */
54525476
static gpointer
54535477
get_async_method_builder (StackFrame *frame)
@@ -5456,15 +5480,17 @@ get_async_method_builder (StackFrame *frame)
54565480
MonoClassField *builder_field;
54575481
gpointer builder;
54585482
guint8 *this_addr;
5483+
MonoClass* klass = frame->method->klass;
54595484

5460-
builder_field = mono_class_get_field_from_name (frame->method->klass, "<>t__builder");
5485+
klass = get_class_to_get_builder_field(frame);
5486+
builder_field = mono_class_get_field_from_name_full (klass, "<>t__builder", NULL);
54615487
g_assert (builder_field);
54625488

54635489
this_addr = get_this_addr (frame);
54645490
if (!this_addr)
54655491
return NULL;
54665492

5467-
if (mono_class_is_valuetype (frame->method->klass)) {
5493+
if (mono_class_is_valuetype (klass)) {
54685494
guint8 *vtaddr = *(guint8**)this_addr;
54695495
builder = (char*)vtaddr + mono_field_get_offset (builder_field) - sizeof (MonoObject);
54705496
} else {
@@ -5497,7 +5523,7 @@ get_this_async_id (StackFrame *frame)
54975523
if (!builder)
54985524
return 0;
54995525

5500-
builder_field = mono_class_get_field_from_name (frame->method->klass, "<>t__builder");
5526+
builder_field = mono_class_get_field_from_name (get_class_to_get_builder_field(frame), "<>t__builder");
55015527
g_assert (builder_field);
55025528

55035529
tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id);
@@ -5521,7 +5547,7 @@ get_this_async_id (StackFrame *frame)
55215547
static gboolean
55225548
set_set_notification_for_wait_completion_flag (StackFrame *frame)
55235549
{
5524-
MonoClassField *builder_field = mono_class_get_field_from_name (frame->method->klass, "<>t__builder");
5550+
MonoClassField *builder_field = mono_class_get_field_from_name (get_class_to_get_builder_field(frame), "<>t__builder");
55255551
g_assert (builder_field);
55265552
gpointer builder = get_async_method_builder (frame);
55275553
g_assert (builder);

mono/mini/mini-exceptions.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -805,8 +805,8 @@ get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx)
805805
/*
806806
* generic_info is either a MonoMethodRuntimeGenericContext or a MonoVTable.
807807
*/
808-
static MonoGenericContext
809-
get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
808+
MonoGenericContext
809+
mono_get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
810810
{
811811
MonoGenericContext context = { NULL, NULL };
812812
MonoClass *klass, *method_container_class;
@@ -851,6 +851,7 @@ get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
851851
return context;
852852
}
853853

854+
854855
static MonoMethod*
855856
get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
856857
{
@@ -860,7 +861,7 @@ get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
860861

861862
if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
862863
return jinfo_get_method (ji);
863-
context = get_generic_context_from_stack_frame (ji, generic_info);
864+
context = mono_get_generic_context_from_stack_frame (ji, generic_info);
864865

865866
method = jinfo_get_method (ji);
866867
method = mono_method_get_declaring_generic_method (method);
@@ -1386,7 +1387,7 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex
13861387

13871388
if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
13881389
return catch_class;
1389-
context = get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx));
1390+
context = mono_get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx));
13901391

13911392
/* FIXME: we shouldn't inflate but instead put the
13921393
type in the rgctx and fetch it from there. It
@@ -3473,7 +3474,7 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg
34733474
MonoType *inflated_type;
34743475

34753476
g_assert (rgctx || this_obj);
3476-
context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
3477+
context = mono_get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
34773478
inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
34783479
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
34793480

mono/mini/mini.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,4 +2883,7 @@ gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal);
28832883

28842884
#endif
28852885

2886+
MonoGenericContext
2887+
mono_get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info);
2888+
28862889
#endif /* __MONO_MINI_H__ */

0 commit comments

Comments
 (0)