78 lines
2.7 KiB
C#
78 lines
2.7 KiB
C#
|
// dnlib: See LICENSE.txt for more info
|
||
|
|
||
|
using System.Collections.Generic;
|
||
|
using System.Diagnostics;
|
||
|
using dnlib.DotNet.Emit;
|
||
|
using dnlib.DotNet.MD;
|
||
|
using dnlib.DotNet.Pdb.Symbols;
|
||
|
|
||
|
namespace dnlib.DotNet.Pdb.WindowsPdb {
|
||
|
static class PseudoCustomDebugInfoFactory {
|
||
|
public static PdbAsyncMethodCustomDebugInfo TryCreateAsyncMethod(ModuleDef module, MethodDef method, CilBody body, int asyncKickoffMethod, IList<SymbolAsyncStepInfo> asyncStepInfos, uint? asyncCatchHandlerILOffset) {
|
||
|
var kickoffToken = new MDToken(asyncKickoffMethod);
|
||
|
if (kickoffToken.Table != Table.Method)
|
||
|
return null;
|
||
|
var kickoffMethod = module.ResolveToken(kickoffToken) as MethodDef;
|
||
|
|
||
|
var asyncMethod = new PdbAsyncMethodCustomDebugInfo(asyncStepInfos.Count);
|
||
|
asyncMethod.KickoffMethod = kickoffMethod;
|
||
|
|
||
|
if (asyncCatchHandlerILOffset is not null) {
|
||
|
asyncMethod.CatchHandlerInstruction = GetInstruction(body, asyncCatchHandlerILOffset.Value);
|
||
|
Debug.Assert(asyncMethod.CatchHandlerInstruction is not null);
|
||
|
}
|
||
|
|
||
|
int count = asyncStepInfos.Count;
|
||
|
for (int i = 0; i < count; i++) {
|
||
|
var rawInfo = asyncStepInfos[i];
|
||
|
var yieldInstruction = GetInstruction(body, rawInfo.YieldOffset);
|
||
|
Debug.Assert(yieldInstruction is not null);
|
||
|
if (yieldInstruction is null)
|
||
|
continue;
|
||
|
MethodDef breakpointMethod;
|
||
|
Instruction breakpointInstruction;
|
||
|
if (method.MDToken.Raw == rawInfo.BreakpointMethod) {
|
||
|
breakpointMethod = method;
|
||
|
breakpointInstruction = GetInstruction(body, rawInfo.BreakpointOffset);
|
||
|
}
|
||
|
else {
|
||
|
var breakpointMethodToken = new MDToken(rawInfo.BreakpointMethod);
|
||
|
Debug.Assert(breakpointMethodToken.Table == Table.Method);
|
||
|
if (breakpointMethodToken.Table != Table.Method)
|
||
|
continue;
|
||
|
breakpointMethod = module.ResolveToken(breakpointMethodToken) as MethodDef;
|
||
|
Debug.Assert(breakpointMethod is not null);
|
||
|
if (breakpointMethod is null)
|
||
|
continue;
|
||
|
breakpointInstruction = GetInstruction(breakpointMethod.Body, rawInfo.BreakpointOffset);
|
||
|
}
|
||
|
Debug.Assert(breakpointInstruction is not null);
|
||
|
if (breakpointInstruction is null)
|
||
|
continue;
|
||
|
|
||
|
asyncMethod.StepInfos.Add(new PdbAsyncStepInfo(yieldInstruction, breakpointMethod, breakpointInstruction));
|
||
|
}
|
||
|
|
||
|
return asyncMethod;
|
||
|
}
|
||
|
|
||
|
static Instruction GetInstruction(CilBody body, uint offset) {
|
||
|
if (body is null)
|
||
|
return null;
|
||
|
var instructions = body.Instructions;
|
||
|
int lo = 0, hi = instructions.Count - 1;
|
||
|
while (lo <= hi && hi != -1) {
|
||
|
int i = (lo + hi) / 2;
|
||
|
var instr = instructions[i];
|
||
|
if (instr.Offset == offset)
|
||
|
return instr;
|
||
|
if (offset < instr.Offset)
|
||
|
hi = i - 1;
|
||
|
else
|
||
|
lo = i + 1;
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
}
|