// The compiler adds a new instance method to the class if a base member is accessed using 'base.XXX' // from inside an iterator or async method. That method just calls the real base method. public static bool IsBaseWrapperMethod(DbgModule module, uint token) { var reflectionModule = module.GetReflectionModule(); Debug2.Assert(!(reflectionModule is null)); if (reflectionModule is null) { return(false); } var method = reflectionModule.ResolveMethod((int)token, DmdResolveOptions.None); Debug2.Assert(!(method is null)); if (method is null) { return(false); } if (!method.IsPrivate || method.IsStatic || method.IsAbstract || method.IsVirtual) { return(false); } var name = method.Name; if (string.IsNullOrEmpty(name)) { return(false); } bool okName = false; var c = name[0]; if (c == '<') { // Roslyn C#, eg. "<>n__2" if (name.StartsWith("<>n__", StringComparison.Ordinal)) { okName = true; } // mcs, eg. "<GetString>__BaseCallProxy1" else if (name.IndexOf(">__BaseCallProxy", StringComparison.Ordinal) >= 0) { okName = true; } } // VB, eg. "$VB$ClosureStub_GetString_MyBase" else if (c == '$' && name.StartsWith("$VB$ClosureStub_", StringComparison.Ordinal) && name.EndsWith("_MyBase", StringComparison.Ordinal)) { okName = true; } if (!okName) { return(false); } return(method.IsDefined("System.Runtime.CompilerServices.CompilerGeneratedAttribute", inherit: false)); }
void EnableBreakpoints(ModuleMirror monoModule, DbgModule module, List <DbgDotNetCodeLocation> moduleLocations) { debuggerThread.VerifyAccess(); if (moduleLocations.Count == 0) { return; } var createdBreakpoints = new DbgBoundCodeBreakpointInfo <BoundBreakpointData> [moduleLocations.Count]; var reflectionModule = module.GetReflectionModule(); var state = module.GetOrCreateData <TypeLoadBreakpointState>(); for (int i = 0; i < createdBreakpoints.Length; i++) { var location = moduleLocations[i]; const ulong address = DbgObjectFactory.BoundBreakpointNoAddress; DbgEngineBoundCodeBreakpointMessage msg; var method = reflectionModule.ResolveMethod((int)location.Token, DmdResolveOptions.None); if ((object)method == null) { msg = DbgEngineBoundCodeBreakpointMessage.CreateFunctionNotFound(GetFunctionName(location.Module, location.Token)); } else { msg = state.IsTypeLoaded(method.DeclaringType.MetadataToken) ? DbgEngineBoundCodeBreakpointMessage.CreateCustomWarning(dnSpy_Debugger_DotNet_Mono_Resources.CanNotSetABreakpointWhenProcessIsPaused) : DbgEngineBoundCodeBreakpointMessage.CreateNoError(); } var bpData = new BoundBreakpointData(this, location.Module); createdBreakpoints[i] = new DbgBoundCodeBreakpointInfo <BoundBreakpointData>(location, module, address, msg, bpData); } var boundBreakpoints = objectFactory.Create(createdBreakpoints.ToArray()); foreach (var ebp in boundBreakpoints) { if (!ebp.BoundCodeBreakpoint.TryGetData(out BoundBreakpointData bpData)) { Debug.Assert(ebp.BoundCodeBreakpoint.IsClosed); continue; } bpData.EngineBoundCodeBreakpoint = ebp; if (bpData.Breakpoint != null) { bpData.Breakpoint.Tag = bpData; } } for (int i = 0; i < boundBreakpoints.Length; i++) { var boundBp = boundBreakpoints[i]; var location = (DbgDotNetCodeLocation)boundBp.BoundCodeBreakpoint.Breakpoint.Location; var method = reflectionModule.ResolveMethod((int)location.Token, DmdResolveOptions.None); if ((object)method == null) { continue; } state.AddBreakpoint(method.DeclaringType.MetadataToken, boundBp, () => EnableBreakpointCore(module, method, boundBp, location)); } }