--- /dev/null
+# Stepping implementation in NetcoreDBG.\r
+\r
+## Async method stepping.\r
+\r
+Overal info about async/await:</br>\r
+https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/</br>\r
+https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/async</br>\r
+\r
+Good article about async/await realization in Russian:</br>\r
+https://m.habr.com/ru/post/260217/\r
+\r
+Main points about async/await in perspective of debugger work:\r
+* At compilation time, async method "converted" to state machine.\r
+* All user code moved into `MoveNext` method.\r
+* PDB provide asyncMethodSteppingInformationBlob with all information debugger need (yield and resume offsets).\r
+* During await execution, thread could be changed.\r
+* Since we have code changed into state machine and thread could be changed, debugger can't use ICorDebugStepper directly.\r
+* State machine's task builder provide `ObjectIdForDebugger` property's getter, that could be called by debugger on yield and resume offsets in order to get unique "async id".\r
+\r
+So, main difference that for async method stepping in case method have await block are breakpoints (for yield and resume offsets) and ICorDebugStepper usage instead of ICorDebugStepper only usage. In the same time, since debugger in case of async stepping use breakpoints and could have different thread at resume offset, plus, debuggee process could have parallel execution for same async method, `ObjectIdForDebugger` property's getter must be used in order to track and detect proper thread.\r
+\r
+## Yield and resume offsets.\r
+\r
+**Yield offset** is point at the beginning of await block code, could be used in order to detect await related code start.\r
+**Resume offset** is point at the end of await block code, where debugger could use ICorDebugStepper for finish step (step from internal await code to closest user code line IL offset).\r
+\r
+Example of simple code with async `Main`:\r
+\r
+```csharp\r
+static async Task Main(string[] args)\r
+{\r
+ Console.WriteLine("Before await.");\r
+ await Task.Delay(1000);\r
+ Console.WriteLine("After await.");\r
+}\r
+```\r
+\r
+`Main` "converted" during compilation into state machine with `MoveNext` method (disassembled by ildasm):\r
+\r
+```\r
+.method private hidebysig newslot virtual final \r
+ instance void MoveNext() cil managed\r
+{\r
+ .override [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext\r
+ // Code size 181 (0xb5)\r
+ .maxstack 3\r
+ .locals init (int32 V_0,\r
+ valuetype [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter V_1,\r
+ class test.Program/'<Main>d__0' V_2,\r
+ class [System.Runtime]System.Exception V_3)\r
+ IL_0000: ldarg.0\r
+ IL_0001: ldfld int32 test.Program/'<Main>d__0'::'<>1__state'\r
+ IL_0006: stloc.0\r
+ .try\r
+ {\r
+ IL_0007: ldloc.0\r
+ IL_0008: brfalse.s IL_000c\r
+ IL_000a: br.s IL_000e\r
+ IL_000c: br.s IL_0057\r
+ IL_000e: nop\r
+ IL_000f: ldstr "Before await."\r
+ IL_0014: call void [System.Console]System.Console::WriteLine(string)\r
+ IL_0019: nop\r
+ IL_001a: ldc.i4 0x3e8\r
+ IL_001f: call class [System.Runtime]System.Threading.Tasks.Task [System.Runtime]System.Threading.Tasks.Task::Delay(int32)\r
+ IL_0024: callvirt instance valuetype [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter [System.Runtime]System.Threading.Tasks.Task::GetAwaiter()\r
+ IL_0029: stloc.1\r
+ IL_002a: ldloca.s V_1\r
+ IL_002c: call instance bool [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter::get_IsCompleted()\r
+ IL_0031: brtrue.s IL_0073\r
+ IL_0033: ldarg.0\r
+ IL_0034: ldc.i4.0\r
+ IL_0035: dup\r
+ IL_0036: stloc.0\r
+ IL_0037: stfld int32 test.Program/'<Main>d__0'::'<>1__state'\r
+ IL_003c: ldarg.0\r
+ IL_003d: ldloc.1\r
+ IL_003e: stfld valuetype [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter test.Program/'<Main>d__0'::'<>u__1'\r
+ IL_0043: ldarg.0\r
+ IL_0044: stloc.2\r
+ IL_0045: ldarg.0\r
+ IL_0046: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder test.Program/'<Main>d__0'::'<>t__builder'\r
+ IL_004b: ldloca.s V_1\r
+ IL_004d: ldloca.s V_2\r
+ IL_004f: call instance void [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::AwaitUnsafeOnCompleted<valuetype [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter,class test.Program/'<Main>d__0'>(!!0&,\r
+ !!1&)\r
+ IL_0054: nop\r
+ IL_0055: leave.s IL_00b4\r
+ IL_0057: ldarg.0\r
+ IL_0058: ldfld valuetype [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter test.Program/'<Main>d__0'::'<>u__1'\r
+ IL_005d: stloc.1\r
+ IL_005e: ldarg.0\r
+ IL_005f: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter test.Program/'<Main>d__0'::'<>u__1'\r
+ IL_0064: initobj [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter\r
+ IL_006a: ldarg.0\r
+ IL_006b: ldc.i4.m1\r
+ IL_006c: dup\r
+ IL_006d: stloc.0\r
+ IL_006e: stfld int32 test.Program/'<Main>d__0'::'<>1__state'\r
+ IL_0073: ldloca.s V_1\r
+ IL_0075: call instance void [System.Runtime]System.Runtime.CompilerServices.TaskAwaiter::GetResult()\r
+ IL_007a: nop\r
+ IL_007b: ldstr "After await."\r
+ IL_0080: call void [System.Console]System.Console::WriteLine(string)\r
+ IL_0085: nop\r
+ IL_0086: leave.s IL_00a0\r
+ } // end .try\r
+ catch [System.Runtime]System.Exception \r
+ {\r
+ IL_0088: stloc.3\r
+ IL_0089: ldarg.0\r
+ IL_008a: ldc.i4.s -2\r
+ IL_008c: stfld int32 test.Program/'<Main>d__0'::'<>1__state'\r
+ IL_0091: ldarg.0\r
+ IL_0092: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder test.Program/'<Main>d__0'::'<>t__builder'\r
+ IL_0097: ldloc.3\r
+ IL_0098: call instance void [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::SetException(class [System.Runtime]System.Exception)\r
+ IL_009d: nop\r
+ IL_009e: leave.s IL_00b4\r
+ } // end handler\r
+ IL_00a0: ldarg.0\r
+ IL_00a1: ldc.i4.s -2\r
+ IL_00a3: stfld int32 test.Program/'<Main>d__0'::'<>1__state'\r
+ IL_00a8: ldarg.0\r
+ IL_00a9: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder test.Program/'<Main>d__0'::'<>t__builder'\r
+ IL_00ae: call instance void [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::SetResult()\r
+ IL_00b3: nop\r
+ IL_00b4: ret\r
+} // end of method '<Main>d__0'::MoveNext\r
+```\r
+\r
+In this case, PDB provide `yield` offset 60 (hex 3C, see `IL_003c` in IL code above) and `resume` offset 87 (hex 57, see `IL_0057` in IL code above).\r
+\r
+## Stepping logic, protocol related part block-scheme.\r
+\r
+## Stepping logic, runtime callbacks related part block-scheme.\r
+\r
+## Sequence diagram for step over await line in async method.\r
+\r