* Adding the test I realized that I need to move one more function.
* Adding line.
* Adding space.
return bp->method && m_class_get_image (bp->method->klass)->assembly == assembly;
}
-static MonoMethod*
-get_object_id_for_debugger_method (MonoClass* async_builder_class)
-{
- ERROR_DECL (error);
- GPtrArray *array = mono_class_get_methods_by_name (async_builder_class, "get_ObjectIdForDebugger", 0x24, 1, FALSE, error);
- mono_error_assert_ok (error);
- if (array->len != 1) {
- g_ptr_array_free (array, TRUE);
- //if we don't find method get_ObjectIdForDebugger we try to find the property Task to continue async debug.
- MonoProperty *prop = mono_class_get_property_from_name_internal (async_builder_class, "Task");
- if (!prop) {
- DEBUG_PRINTF (1, "Impossible to debug async methods.\n");
- return NULL;
- }
- return prop->get;
- }
- MonoMethod *method = (MonoMethod *)g_ptr_array_index (array, 0);
- g_ptr_array_free (array, TRUE);
- return method;
-}
-
//This ID is used to figure out if breakpoint hit on resumeOffset belongs to us or not
//since thread probably changed...
static int
return TRUE;
}
+MonoMethod*
+get_object_id_for_debugger_method (MonoClass* async_builder_class)
+{
+ ERROR_DECL (error);
+ GPtrArray *array = mono_class_get_methods_by_name (async_builder_class, "get_ObjectIdForDebugger", 0x24, 1, FALSE, error);
+ mono_error_assert_ok (error);
+ if (array->len != 1) {
+ g_ptr_array_free (array, TRUE);
+ //if we don't find method get_ObjectIdForDebugger we try to find the property Task to continue async debug.
+ MonoProperty *prop = mono_class_get_property_from_name_internal (async_builder_class, "Task");
+ if (!prop) {
+ DEBUG_PRINTF (1, "Impossible to debug async methods.\n");
+ return NULL;
+ }
+ return prop->get;
+ }
+ MonoMethod *method = (MonoMethod *)g_ptr_array_index (array, 0);
+ g_ptr_array_free (array, TRUE);
+ return method;
+}
+
gpointer
get_this_addr (DbgEngineStackFrame *the_frame)
{
gpointer get_async_method_builder (DbgEngineStackFrame *frame);
MonoMethod* get_set_notification_method (MonoClass* async_builder_class);
MonoMethod* get_notify_debugger_of_wait_completion_method (void);
+MonoMethod* get_object_id_for_debugger_method (MonoClass* async_builder_class);
#endif
if (!mono_find_prev_seq_point_for_native_offset (mono_get_root_domain (), method, info->native_offset, NULL, &sp))
DEBUG_PRINTF (2, "collect_frames: Failed to lookup sequence point. method: %s, native_offset: %d \n", method->name, info->native_offset);
- DbgEngineStackFrame *frame = g_new0 (DbgEngineStackFrame, 1);
-
- frame->ji = info->ji;
- frame->domain = info->domain;
- frame->method = method;
- frame->native_offset = info->native_offset;
-
+
+ StackFrame *frame = g_new0 (StackFrame, 1);
+ frame->de.ji = info->ji;
+ frame->de.domain = info->domain;
+ frame->de.method = method;
+ frame->de.native_offset = info->native_offset;
+
+ frame->il_offset = info->il_offset;
+ frame->interp_frame = info->interp_frame;
+ frame->frame_addr = info->frame_addr;
+
g_ptr_array_add (frames, frame);
return FALSE;
return DE_ERR_NONE;
}
+static int
+get_object_id (MonoObject *obj)
+{
+ ObjRef *ref;
+ if (!obj)
+ return 0;
+
+ ref = (ObjRef *)g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)));
+ if (ref)
+ return ref->id;
+ ref = g_new0 (ObjRef, 1);
+ ref->id = mono_atomic_inc_i32 (&objref_id);
+ ref->handle = mono_gchandle_new_weakref_internal (obj, FALSE);
+ g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref);
+ g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref);
+ return ref->id;
+}
+
+
static int
-get_this_async_id (DbgEngineStackFrame *f)
+get_this_async_id (DbgEngineStackFrame *frame)
{
- g_error ("get_this_async_id");
- return 0;
+ MonoClassField *builder_field;
+ gpointer builder;
+ MonoMethod *method;
+ MonoObject *ex;
+ ERROR_DECL (error);
+ MonoObject *obj;
+
+ /*
+ * FRAME points to a method in a state machine class/struct.
+ * Call the ObjectIdForDebugger method of the associated method builder type.
+ */
+ builder = get_async_method_builder (frame);
+ if (!builder)
+ return 0;
+
+ builder_field = mono_class_get_field_from_name_full (get_class_to_get_builder_field(frame), "<>t__builder", NULL);
+ if (!builder_field)
+ return 0;
+
+ method = get_object_id_for_debugger_method (mono_class_from_mono_type_internal (builder_field->type));
+ if (!method) {
+ return 0;
+ }
+
+ obj = mono_runtime_try_invoke (method, builder, NULL, &ex, error);
+ mono_error_assert_ok (error);
+
+ return get_object_id (obj);
}
typedef struct {
return isBPOnNativeCode;
}
-static int
-get_object_id(MonoObject *obj)
-{
- ObjRef *ref;
- if (!obj)
- return 0;
-
- ref = (ObjRef *)g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)));
- if (ref)
- return ref->id;
- ref = g_new0 (ObjRef, 1);
- ref->id = mono_atomic_inc_i32 (&objref_id);
- ref->handle = mono_gchandle_new_weakref_internal (obj, FALSE);
- g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref);
- g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref);
- return ref->id;
-}
-
static void
handle_exception (MonoException *exc, MonoContext *throw_ctx, MonoContext *catch_ctx, StackFrameInfo *catch_frame)
{
});
[Fact]
+ public async Task StepOverAsyncMethod()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var bp = await SetBreakpointInMethod("debugger-test.dll", "AsyncStepClass", "TestAsyncStepOut2", 2);
+ System.Console.WriteLine(bp);
+ await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_static_method_async('[debugger-test] AsyncStepClass:TestAsyncStepOut'); }, 1);",
+ "dotnet://debugger-test.dll/debugger-async-step.cs", 19, 8,
+ "MoveNext");
+
+ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-step.cs", 21, 8, "MoveNext");
+
+ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-step.cs", 22, 4, "MoveNext");
+
+ await StepAndCheck(StepKind.Over, null, 0, 0, "get_IsCompletedSuccessfully"); //not check the line number and the file name because this can be changed
+
+ });
+ }
+
+ [Fact]
public async Task PreviousFrameForAReflectedCall() => await CheckInspectLocalsAtBreakpointSite(
"DebuggerTests.GetPropertiesTests.CloneableStruct", "SimpleStaticMethod", 1, "SimpleStaticMethod",
"window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerTests.GetPropertiesTests.TestWithReflection:run'); })",
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Threading.Tasks;
+using System.Net;
+using System.Net.Http;
+
+public class AsyncStepClass
+{
+ static HttpClient client = new HttpClient();
+ public static async Task TestAsyncStepOut()
+ {
+ await TestAsyncStepOut2("foobar");
+ }
+
+ public static async Task<int> TestAsyncStepOut2(string some)
+ {
+ var resp = await client.GetAsync("http://localhost:9400/debugger-driver.html");
+ Console.WriteLine($"resp: {resp}"); /// BP at this line
+
+ return 10;
+ }
+}