private void RewriteInspectMemoryGraph(MethodDefinition method, ILProcessor il, Instruction call, IWorkSession session, ArgumentMethods argumentMethods) { var sequencePoint = FindClosestSequencePoint(method, call); if (sequencePoint == null) { return; } var arguments = _languages[session.LanguageName] .GetCallArgumentIdentifiers(session, sequencePoint.StartLine, sequencePoint.StartColumn); if (arguments.Length == 0) { return; } il.InsertBefore(call, il.CreateLdcI4Best(arguments.Length)); il.InsertBefore(call, il.CreateCall(argumentMethods.AllocateNext)); foreach (var argument in arguments) { il.InsertBefore(call, argument != null ? il.Create(OpCodes.Ldstr, argument) : il.Create(OpCodes.Ldnull)); il.InsertBefore(call, il.CreateCall(argumentMethods.AddToNext)); } }
private void InsertReportValue( ILProcessor il, Instruction instruction, Instruction getValue, TypeReference valueType, string valueName, int line, ReportMethods flow, ref int index ) { il.InsertBefore(instruction, getValue); il.InsertBefore(instruction, valueName != null ? il.Create(OpCodes.Ldstr, valueName) : il.Create(OpCodes.Ldnull)); il.InsertBefore(instruction, il.CreateLdcI4Best(line)); if (valueType is RequiredModifierType requiredType) { valueType = requiredType.ElementType; // not the same as GetElementType() which unwraps nested ref-types etc } var report = PrepareReportValue(valueType, flow.ReportValue, flow.ReportSpanValue, flow.ReportReadOnlySpanValue); if (valueType is ByReferenceType byRef) { report = PrepareReportValue(byRef.ElementType, flow.ReportRefValue, flow.ReportRefSpanValue, flow.ReportRefReadOnlySpanValue); } il.InsertBefore(instruction, il.CreateCall(report)); index += 4; }
private void RewriteFinally(ExceptionHandler handler, ref int handlerIndex, ILProcessor il, ReportMethods flow) { var oldTryLeave = handler.TryEnd.Previous; var newTryLeave = il.Create(OpCodes.Leave_S, (Instruction)oldTryLeave.Operand); var reportCall = il.CreateCall(flow.ReportException); var catchHandler = il.Create(OpCodes.Pop); InsertBeforeAndRetargetAll(il, oldTryLeave, newTryLeave); il.InsertBefore(oldTryLeave, reportCall); il.InsertBefore(oldTryLeave, il.Create(OpCodes.Ldc_I4_0)); il.InsertBefore(oldTryLeave, il.Create(OpCodes.Endfilter)); il.InsertBefore(oldTryLeave, catchHandler); for (var i = 0; i < handlerIndex; i++) { il.Body.ExceptionHandlers[i].RetargetAll(oldTryLeave.Next, newTryLeave.Next); } il.Body.ExceptionHandlers.Insert(handlerIndex, new ExceptionHandler(ExceptionHandlerType.Filter) { TryStart = handler.TryStart, TryEnd = reportCall, FilterStart = reportCall, HandlerStart = catchHandler, HandlerEnd = oldTryLeave.Next }); handlerIndex += 1; }
private void InsertReportValue( ILProcessor il, Instruction instruction, Instruction getValue, TypeReference valueType, string valueName, int line, ReportMethods flow, ref int index ) { il.InsertBefore(instruction, getValue); il.InsertBefore(instruction, valueName != null ? il.Create(OpCodes.Ldstr, valueName) : il.Create(OpCodes.Ldnull)); il.InsertBefore(instruction, il.CreateLdcI4Best(line)); var report = flow.ReportValue; if (valueType is RequiredModifierType requiredType) { valueType = requiredType.ElementType; // not the same as GetElementType() which unwraps nested ref-types etc } if (valueType.IsByReference) { report = flow.ReportRefValue; valueType = valueType.GetElementType(); } il.InsertBefore(instruction, il.CreateCall(new GenericInstanceMethod(report) { GenericArguments = { valueType } })); index += 4; }
private void InsertReportValue(ILProcessor il, Instruction instruction, Instruction getValue, TypeReference valueType, string valueName, int line, ReportMethods flow, ref int index) { il.InsertBefore(instruction, getValue); il.InsertBefore(instruction, valueName != null ? il.Create(OpCodes.Ldstr, valueName) : il.Create(OpCodes.Ldnull)); il.InsertBefore(instruction, il.CreateLdcI4Best(line)); il.InsertBefore(instruction, il.CreateCall(new GenericInstanceMethod(flow.ReportValue) { GenericArguments = { valueType } })); index += 4; }
private void RewriteFinally(ExceptionHandler handler, ref int handlerIndex, ILProcessor il, ReportMethods flow) { // for try/finally, the only thing we can do is to // wrap internals of try into a new try+filter+catch var outerTryLeave = handler.TryEnd.Previous; if (!outerTryLeave.OpCode.Code.IsLeave()) { // in some cases (e.g. exception throw) outer handler does // not end with `leave` -- but we do need it once we wrap // that throw // if the handler is the last thing in the method if (handler.HandlerEnd == null) { var finalReturn = il.Create(OpCodes.Ret); il.Append(finalReturn); handler.HandlerEnd = finalReturn; } outerTryLeave = il.Create(OpCodes.Leave, handler.HandlerEnd); il.InsertBefore(handler.TryEnd, outerTryLeave); } var innerTryLeave = il.Create(OpCodes.Leave_S, outerTryLeave); var reportCall = il.CreateCall(flow.ReportException); var catchHandler = il.Create(OpCodes.Pop); il.InsertBeforeAndRetargetAll(outerTryLeave, innerTryLeave); il.InsertBefore(outerTryLeave, reportCall); il.InsertBefore(outerTryLeave, il.Create(OpCodes.Ldc_I4_0)); il.InsertBefore(outerTryLeave, il.Create(OpCodes.Endfilter)); il.InsertBefore(outerTryLeave, catchHandler); il.InsertBefore(outerTryLeave, il.Create(OpCodes.Leave_S, outerTryLeave)); for (var i = 0; i < handlerIndex; i++) { il.Body.ExceptionHandlers[i].RetargetAll(outerTryLeave.Next, innerTryLeave.Next); } il.Body.ExceptionHandlers.Insert(handlerIndex, new ExceptionHandler(ExceptionHandlerType.Filter) { TryStart = handler.TryStart, TryEnd = reportCall, FilterStart = reportCall, HandlerStart = catchHandler, HandlerEnd = outerTryLeave }); handlerIndex += 1; }
private void RewriteCatch(Instruction start, ILProcessor il, ReportMethods flow) { il.InsertBeforeAndRetargetAll(start, il.Create(OpCodes.Dup)); il.InsertBefore(start, il.CreateCall(flow.ReportException)); }