Span?IDotNetSpanMap.ToSpan(ModuleId module, uint token, uint ilOffset) { if (toMethodDebugInfo == null) { toMethodDebugInfo = new Dictionary <ModuleTokenId, MethodDebugInfo>(methodDebugInfos.Count); foreach (var info in methodDebugInfos) { var tokenId = new ModuleTokenId(moduleIdProvider.Create(info.Method.Module), info.Method.MDToken); if (toMethodDebugInfo.TryGetValue(tokenId, out var otherInfo)) { if (info.Statements.Length < otherInfo.Statements.Length) { continue; } } toMethodDebugInfo[tokenId] = info; } } if (!toMethodDebugInfo.TryGetValue(new ModuleTokenId(module, token), out var info2)) { return(null); } var statement = info2.GetSourceStatementByCodeOffset(ilOffset); if (statement == null) { return(null); } var textSpan = statement.Value.TextSpan; return(new Span(textSpan.Start, textSpan.Length)); }
public static bool GoToIL(IModuleIdProvider moduleIdProvider, IDocumentTabService documentTabService, IDsDocument document, uint token, uint ilOffset, bool newTab) { if (document == null) return false; var method = document.ModuleDef.ResolveToken(token) as MethodDef; if (method == null) return false; var modId = moduleIdProvider.Create(method.Module); var key = new ModuleTokenId(modId, method.MDToken); bool found = documentTabService.DocumentTreeView.FindNode(method.Module) != null; if (found) { documentTabService.FollowReference(method, newTab, true, e => { Debug.Assert(e.Tab.UIContext is IDocumentViewer); if (e.Success && !e.HasMovedCaret) { MoveCaretTo(e.Tab.UIContext as IDocumentViewer, key, ilOffset); e.HasMovedCaret = true; } }); return true; } Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { documentTabService.FollowReference(method, newTab, true, e => { Debug.Assert(e.Tab.UIContext is IDocumentViewer); if (e.Success && !e.HasMovedCaret) { MoveCaretTo(e.Tab.UIContext as IDocumentViewer, key, ilOffset); e.HasMovedCaret = true; } }); })); return true; }
public void Toggle(IDocumentViewer documentViewer, int textPosition) { var statements = documentViewer.GetMethodDebugService().FindByTextPosition(textPosition, sameMethod: false); var ilbps = GetILCodeBreakpoints(documentViewer, statements); if (ilbps.Count > 0) { if (IsEnabled(ilbps)) { foreach (var ilbp in ilbps) { Remove(ilbp); } } else { foreach (var bpm in ilbps) { bpm.IsEnabled = true; } } } else if (statements.Count > 0) { foreach (var methodStatement in statements) { var md = methodStatement.Method; var modId = moduleIdProvider.Create(md.Module); var key = new ModuleTokenId(modId, md.MDToken); Add(new ILCodeBreakpoint(key, methodStatement.Statement.BinSpan.Start)); } documentViewer.MoveCaretToPosition(statements[0].Statement.TextSpan.Start); } }
Span?IDotNetSpanMap.ToSpan(ModuleId module, uint token) { if (toTokenInfo == null) { toTokenInfo = new Dictionary <ModuleTokenId, Span>(); foreach (var data in references) { if (!data.Data.IsDefinition) { continue; } var def = data.Data.Reference as IMemberDef; if (def == null) { continue; } var tokenId = new ModuleTokenId(moduleIdProvider.Create(def.Module), def.MDToken); toTokenInfo[tokenId] = data.Span; } } if (!toTokenInfo.TryGetValue(new ModuleTokenId(module, token), out var span)) { return(null); } return(span); }
public MethodDebugInfo TryGetMethodDebugInfo(ModuleTokenId token) { MethodDebugInfo info; dict.TryGetValue(token, out info); return(info); }
public void GetMethodInfo(ModuleTokenId key, out Parameter[] parameters, out Local[] locals, out SourceLocal[] decompilerLocals) { parameters = null; locals = null; decompilerLocals = null; foreach (var tab in documentTabService.VisibleFirstTabs) { if (parameters != null && decompilerLocals != null) break; var uiContext = tab.UIContext as IDocumentViewer; var methodDebugService = uiContext.TryGetMethodDebugService(); if (methodDebugService == null) continue; var info = methodDebugService.TryGetMethodDebugInfo(key); if (info == null) continue; var method = info.Method; if (info.Locals.Length != 0 && method.Body != null) { locals = method.Body.Variables.ToArray(); decompilerLocals = new SourceLocal[method.Body.Variables.Count]; foreach (var v in info.Locals) { if ((uint)v.Local.Index >= decompilerLocals.Length) continue; decompilerLocals[v.Local.Index] = v; } } parameters = method.Parameters.ToArray(); } }
public IEnumerable <ITagSpan <ITextMarkerTag> > GetTags(ActiveStatementTagger tagger, NormalizedSnapshotSpanCollection spans) { if (activeStatements.Count == 0 || spans.Count == 0) { yield break; } //TODO: This code shouldn't depend on IDocumentViewer var docViewer = tagger.TextView.TextBuffer.TryGetDocumentViewer(); if (docViewer == null) { yield break; } var methodDebugService = docViewer.TryGetMethodDebugService(); if (methodDebugService == null) { yield break; } var snapshot = spans[0].Snapshot; MethodDef method = null; List <uint> ilOffsets = null; foreach (var span in spans) { foreach (var info in methodDebugService.GetStatementsByTextSpan(span.Span)) { if (info.Method != method) { method = info.Method; var moduleTokenId = new ModuleTokenId(moduleIdProvider.Create(method.Module), method.MDToken); if (!activeStatements.TryGetValue(moduleTokenId, out ilOffsets)) { continue; } } else if (ilOffsets == null) { continue; } var textSpan = info.Statement.TextSpan; if (textSpan.End > snapshot.Length) { yield break; // Old data, but we'll get called again } var binSpan = info.Statement.BinSpan; foreach (uint ilOffset in ilOffsets) { if (ilOffset >= binSpan.Start && ilOffset < binSpan.End) { yield return(new TagSpan <ITextMarkerTag>(new SnapshotSpan(snapshot, textSpan.Start, textSpan.Length), activeStatementTextMarkerTag)); } } } } }
public IGlyphTextMethodMarker AddMarker(ModuleTokenId tokenId, uint ilOffset, ImageReference?glyphImage, string markerTypeName, string selectedMarkerTypeName, IClassificationType classificationType, int zIndex, object tag, IGlyphTextMarkerHandler handler, Func <ITextView, bool> textViewFilter) { var marker = new GlyphTextMethodMarker(tokenId, ilOffset, glyphImage, markerTypeName, selectedMarkerTypeName, classificationType, zIndex, tag, handler, textViewFilter); glyphTextMarkers.Add(marker); MarkerAdded?.Invoke(this, new GlyphTextMarkerAddedEventArgs(marker)); return(marker); }
public override IEnumerable <SnapshotSpan> GetFrameSpans(ITextView textView, NormalizedSnapshotSpanCollection spans) { if (activeStatements.Count == 0) { yield break; } var docViewer = textView.TextBuffer.TryGetDocumentViewer(); if (docViewer == null) { yield break; } var methodDebugService = docViewer.TryGetMethodDebugService(); if (methodDebugService == null) { yield break; } var snapshot = spans[0].Snapshot; MethodDef method = null; List <uint> ilOffsets = null; foreach (var span in spans) { foreach (var info in methodDebugService.GetStatementsByTextSpan(span.Span)) { if (info.Method != method) { method = info.Method; var moduleTokenId = new ModuleTokenId(moduleIdProvider.Create(method.Module), method.MDToken); if (!activeStatements.TryGetValue(moduleTokenId, out ilOffsets)) { continue; } } else if (ilOffsets == null) { continue; } var textSpan = info.Statement.TextSpan; if (textSpan.End > snapshot.Length) { yield break; // Old data, but we'll get called again } var ilSpan = info.Statement.ILSpan; foreach (uint ilOffset in ilOffsets) { if (ilOffset >= ilSpan.Start && ilOffset < ilSpan.End) { yield return(new SnapshotSpan(snapshot, textSpan.Start, textSpan.Length)); } } } } }
void LoadInternal() { var section = settingsService.GetOrCreateSection(SETTINGS_GUID); breakpointService.Clear(); foreach (var bpx in section.SectionsWithName("Breakpoint")) { uint? token = bpx.Attribute <uint?>("Token"); string asmFullName = bpx.Attribute <string>("AssemblyFullName"); string moduleName = bpx.Attribute <string>("ModuleName"); bool? isDynamic = bpx.Attribute <bool?>("IsDynamic"); bool? isInMemory = bpx.Attribute <bool?>("IsInMemory"); bool moduleNameOnly = bpx.Attribute <bool?>("ModuleNameOnly") ?? false; uint? ilOffset = bpx.Attribute <uint?>("ILOffset"); bool? isEnabled = bpx.Attribute <bool?>("IsEnabled"); if (token == null) { continue; } if (isDynamic == null || isInMemory == null) { continue; } if (string.IsNullOrEmpty(asmFullName) && !moduleNameOnly) { continue; } if (string.IsNullOrEmpty(moduleName)) { continue; } if (ilOffset == null) { continue; } if (isEnabled == null) { continue; } var moduleId = ModuleId.Create(asmFullName, moduleName, isDynamic.Value, isInMemory.Value, moduleNameOnly); var key = new ModuleTokenId(moduleId, token.Value); if (!isInMemory.Value && !isDynamic.Value) { var s = bpx.Attribute <string>("Method"); if (s == null || s != GetMethodAsString(key)) { continue; } } var bp = new ILCodeBreakpoint(key, ilOffset.Value, isEnabled.Value); breakpointService.Add(bp); } }
IEnumerable <ILCodeBreakpoint> GetILCodeBreakpoints(ModuleTokenId methodToken) { foreach (var ilbp in GetILCodeBreakpoints()) { if (ilbp.MethodToken.Equals(methodToken)) { yield return(ilbp); } } }
IEnumerable <ILCodeBreakpoint> GetILCodeBreakpoints(ModuleTokenId methodToken, uint ilOffset) { foreach (var ilbp in GetILCodeBreakpoints(methodToken)) { if (ilbp.ILOffset == ilOffset) { yield return(ilbp); } } }
public GlyphTextMethodMarker(ModuleTokenId method, uint ilOffset, ImageReference?glyphImage, string markerTypeName, IClassificationType classificationType, int zIndex, object tag, IGlyphTextMarkerHandler handler, Func <ITextView, bool> textViewFilter) { Method = method; ILOffset = ilOffset; GlyphImageReference = glyphImage; MarkerTypeName = markerTypeName; ClassificationType = classificationType; ZIndex = zIndex; Tag = tag; Handler = handler ?? NullGlyphTextMarkerHandler.Instance; TextViewFilter = textViewFilter ?? defaultTextViewFilter; }
public GlyphTextMethodMarker(ModuleId module, uint token, uint ilOffset, ImageReference?glyphImage, string?markerTypeName, string?selectedMarkerTypeName, IClassificationType?classificationType, int zIndex, object?tag, IGlyphTextMarkerHandler?handler, Func <ITextView, bool>?textViewFilter) { Method = new ModuleTokenId(module, token); ILOffset = ilOffset; GlyphImageReference = glyphImage is null || glyphImage.Value.IsDefault ? null : glyphImage; MarkerTypeName = markerTypeName; SelectedMarkerTypeName = selectedMarkerTypeName; ClassificationType = classificationType; ZIndex = zIndex; Tag = tag; Handler = handler ?? NullGlyphTextMarkerHandler.Instance; TextViewFilter = textViewFilter ?? defaultTextViewFilter; }
public static bool MoveCaretTo(IDocumentViewer documentViewer, ModuleTokenId key, uint ilOffset) { if (documentViewer == null) return false; IMethodDebugService methodDebugService; if (!VerifyAndGetCurrentDebuggedMethod(documentViewer, key, out methodDebugService)) return false; var sourceStatement = methodDebugService.TryGetMethodDebugInfo(key).GetSourceStatementByCodeOffset(ilOffset); if (sourceStatement == null) return false; documentViewer.MoveCaretToPosition(sourceStatement.Value.TextSpan.Start); return true; }
public static bool GoToIL(IModuleIdProvider moduleIdProvider, IDocumentTabService documentTabService, IDsDocument document, uint token, uint ilOffset, bool newTab) { if (document == null) { return(false); } var method = document.ModuleDef.ResolveToken(token) as MethodDef; if (method == null) { return(false); } var modId = moduleIdProvider.Create(method.Module); var key = new ModuleTokenId(modId, method.MDToken); bool found = documentTabService.DocumentTreeView.FindNode(method.Module) != null; if (found) { documentTabService.FollowReference(method, newTab, true, e => { Debug.Assert(e.Tab.UIContext is IDocumentViewer); if (e.Success && !e.HasMovedCaret) { MoveCaretTo(e.Tab.UIContext as IDocumentViewer, key, ilOffset); e.HasMovedCaret = true; } }); return(true); } Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { documentTabService.FollowReference(method, newTab, true, e => { Debug.Assert(e.Tab.UIContext is IDocumentViewer); if (e.Success && !e.HasMovedCaret) { MoveCaretTo(e.Tab.UIContext as IDocumentViewer, key, ilOffset); e.HasMovedCaret = true; } }); })); return(true); }
public MethodDebugService(IReadOnlyList <MethodDebugInfo> methodDebugInfos, ITextSnapshot snapshot, IModuleIdProvider moduleIdProvider) { if (methodDebugInfos == null) { throw new ArgumentNullException(nameof(methodDebugInfos)); } if (snapshot == null) { throw new ArgumentNullException(nameof(snapshot)); } if (moduleIdProvider == null) { throw new ArgumentNullException(nameof(moduleIdProvider)); } this.dict = new Dictionary <ModuleTokenId, MethodDebugInfo>(methodDebugInfos.Count); this.snapshot = snapshot; this.moduleIdProvider = moduleIdProvider; var modIdDict = new Dictionary <ModuleDef, ModuleId>(); foreach (var info in methodDebugInfos) { var module = info.Method.Module; if (module == null) { continue; } ModuleId moduleId; if (!modIdDict.TryGetValue(module, out moduleId)) { moduleId = moduleIdProvider.Create(module); modIdDict.Add(module, moduleId); } var key = new ModuleTokenId(moduleId, info.Method.MDToken); MethodDebugInfo oldDebugInfo; if (this.dict.TryGetValue(key, out oldDebugInfo)) { if (info.Statements.Length < oldDebugInfo.Statements.Length) { continue; } } this.dict[key] = info; } }
public void OnNewActiveStatements(List <CorFrame> frames) { var dict = new Dictionary <ModuleTokenId, List <uint> >(); // The first frame is the current statement and it's always visible so there's // no point in adding an active statement there for (int i = 1; i < frames.Count; i++) { var frame = frames[i]; if (!frame.IsILFrame) { continue; } var ip = frame.ILFrameIP; if (!ip.IsExact && !ip.IsApproximate && !ip.IsProlog && !ip.IsEpilog) { continue; } uint token = frame.Token; if (token == 0) { continue; } var mod = frame.DnModuleId; if (mod == null) { continue; } var key = new ModuleTokenId(mod.Value.ToModuleId(), frame.Token); List <uint> list; if (!dict.TryGetValue(key, out list)) { dict.Add(key, list = new List <uint>()); } uint offset = ip.Offset; // The list should be small so Contains() should be fast Debug.Assert(list.Count <= 10, "Perhaps use a hash?"); if (!list.Contains(offset)) { list.Add(offset); } } activeStatements = dict; RaiseTagsChanged(); }
public override void GoToLocation(IDocumentTab tab, MethodDef method, ModuleTokenId module, uint offset, bool newTab) { bool specialIpOffset; if (offset == EPILOG) { specialIpOffset = true; var mod = dbgMetadataService.Value.TryGetMetadata(module.Module, DbgLoadModuleOptions.AutoLoaded); if (mod?.ResolveToken(module.Token) is MethodDef md && md.Body is not null && md.Body.Instructions.Count > 0) { offset = md.Body.Instructions[md.Body.Instructions.Count - 1].Offset; } else { return; } }
public MethodSourceStatement?FindByCodeOffset(ModuleTokenId token, uint codeOffset) { MethodDebugInfo info; if (!dict.TryGetValue(token, out info)) { return(null); } foreach (var sourceStatement in info.Statements) { if (sourceStatement.BinSpan.Start <= codeOffset && codeOffset < sourceStatement.BinSpan.End) { return(new MethodSourceStatement(info.Method, sourceStatement)); } } return(null); }
public override void OnNewFrames(ReadOnlyCollection <DbgStackFrame> frames) { var dict = new Dictionary <ModuleTokenId, List <uint> >(); // The first statement shouldn't be marked (it's always marked by default by other code // since it's the current statement) for (int i = 1; i < frames.Count; i++) { switch (frames[i].Location) { case DbgDotNetCodeLocation loc: switch (loc.ILOffsetMapping) { case DbgILOffsetMapping.Exact: case DbgILOffsetMapping.Approximate: break; case DbgILOffsetMapping.Prolog: case DbgILOffsetMapping.Epilog: case DbgILOffsetMapping.Unknown: case DbgILOffsetMapping.NoInfo: case DbgILOffsetMapping.UnmappedAddress: default: continue; } var key = new ModuleTokenId(loc.Module, loc.Token); if (!dict.TryGetValue(key, out var list)) { dict.Add(key, list = new List <uint>()); } uint offset = loc.Offset; // The list should be small so Contains() should be fast if (!list.Contains(offset)) { list.Add(offset); } break; default: continue; } } activeStatements = dict; }
public Span?ToSpan(ModuleTokenId method, uint ilOffset) { MethodDebugInfo info; if (!toMethodDebugInfo.TryGetValue(method, out info)) { return(null); } var statement = info.GetSourceStatementByCodeOffset(ilOffset); if (statement == null) { return(null); } var textSpan = statement.Value.TextSpan; return(new Span(textSpan.Start, textSpan.Length)); }
public void GetMethodInfo(ModuleTokenId key, out Parameter[] parameters, out Local[] locals, out SourceLocal[] decompilerLocals) { parameters = null; locals = null; decompilerLocals = null; foreach (var tab in documentTabService.VisibleFirstTabs) { if (parameters != null && decompilerLocals != null) { break; } var uiContext = tab.UIContext as IDocumentViewer; var methodDebugService = uiContext.TryGetMethodDebugService(); if (methodDebugService == null) { continue; } var info = methodDebugService.TryGetMethodDebugInfo(key); if (info == null) { continue; } var method = info.Method; if (info.Locals.Length != 0 && method.Body != null) { locals = method.Body.Variables.ToArray(); decompilerLocals = new SourceLocal[method.Body.Variables.Count]; foreach (var v in info.Locals) { if ((uint)v.Local.Index >= decompilerLocals.Length) { continue; } decompilerLocals[v.Local.Index] = v; } } parameters = method.Parameters.ToArray(); } }
public MethodDebugInfoMethodOffsetSpanMap(IModuleIdProvider moduleIdProvider, ReadOnlyCollection <MethodDebugInfo> methodDebugInfos) { if (methodDebugInfos == null) { throw new ArgumentNullException(nameof(methodDebugInfos)); } this.moduleIdProvider = moduleIdProvider; toMethodDebugInfo = new Dictionary <ModuleTokenId, MethodDebugInfo>(methodDebugInfos.Count); foreach (var info in methodDebugInfos) { var token = new ModuleTokenId(moduleIdProvider.Create(info.Method.Module), info.Method.MDToken); MethodDebugInfo otherInfo; if (toMethodDebugInfo.TryGetValue(token, out otherInfo)) { if (info.Statements.Length < otherInfo.Statements.Length) { continue; } } toMethodDebugInfo[token] = info; } }
public static bool MoveCaretTo(IDocumentViewer documentViewer, ModuleTokenId key, uint ilOffset) { if (documentViewer == null) { return(false); } IMethodDebugService methodDebugService; if (!VerifyAndGetCurrentDebuggedMethod(documentViewer, key, out methodDebugService)) { return(false); } var sourceStatement = methodDebugService.TryGetMethodDebugInfo(key).GetSourceStatementByCodeOffset(ilOffset); if (sourceStatement == null) { return(false); } documentViewer.MoveCaretToPosition(sourceStatement.Value.TextSpan.Start); return(true); }
public static bool VerifyAndGetCurrentDebuggedMethod(IDocumentViewer documentViewer, ModuleTokenId serToken, out IMethodDebugService methodDebugService) { methodDebugService = documentViewer.GetMethodDebugService(); return methodDebugService.TryGetMethodDebugInfo(serToken) != null; }
MethodDebugInfo IMethodDebugService.TryGetMethodDebugInfo(ModuleTokenId token) => null;
MethodSourceStatement? IMethodDebugService.FindByCodeOffset(ModuleTokenId token, uint codeOffset) => null;
public ILCodeBreakpoint(ModuleTokenId methodKey, uint ilOffset, bool isEnabled = true) : base(isEnabled) { MethodToken = methodKey; ILOffset = ilOffset; }
public static bool VerifyAndGetCurrentDebuggedMethod(IDocumentViewer documentViewer, ModuleTokenId serToken, out IMethodDebugService methodDebugService) { methodDebugService = documentViewer.GetMethodDebugService(); return(methodDebugService.TryGetMethodDebugInfo(serToken) != null); }
Span?IMethodOffsetSpanMap.ToSpan(ModuleTokenId method, uint ilOffset) { Debug.Fail($"Shouldn't be called"); return(null); }
string GetMethodAsString(ModuleTokenId key) { var file = moduleLoader.Value.LoadModule(key.Module, canLoadDynFile: true, diskFileOk: true, isAutoLoaded: true); var method = file?.ModuleDef?.ResolveToken(key.Token) as MethodDef; return method?.ToString(); }
MethodDebugInfo?IMethodDebugService.TryGetMethodDebugInfo(ModuleTokenId token) => null;
IEnumerable<ILCodeBreakpoint> GetILCodeBreakpoints(ModuleTokenId methodToken, uint ilOffset) { foreach (var ilbp in GetILCodeBreakpoints(methodToken)) { if (ilbp.ILOffset == ilOffset) yield return ilbp; } }
public void Toggle(IDocumentViewer documentViewer, int textPosition) { var statements = documentViewer.GetMethodDebugService().FindByTextPosition(textPosition, sameMethod: false); var ilbps = GetILCodeBreakpoints(documentViewer, statements); if (ilbps.Count > 0) { if (IsEnabled(ilbps)) { foreach (var ilbp in ilbps) Remove(ilbp); } else { foreach (var bpm in ilbps) bpm.IsEnabled = true; } } else if (statements.Count > 0) { foreach (var methodStatement in statements) { var md = methodStatement.Method; var modId = moduleIdProvider.Create(md.Module); var key = new ModuleTokenId(modId, md.MDToken); Add(new ILCodeBreakpoint(key, methodStatement.Statement.BinSpan.Start)); } documentViewer.MoveCaretToPosition(statements[0].Statement.TextSpan.Start); } }
MethodSourceStatement?IMethodDebugService.FindByCodeOffset(ModuleTokenId token, uint codeOffset) => null;
IGlyphTextMethodMarker IGlyphTextMarkerService.AddMarker(ModuleTokenId tokenId, uint ilOffset, ImageReference?glyphImage, string?markerTypeName, string?selectedMarkerTypeName, IClassificationType?classificationType, int zIndex, object?tag, IGlyphTextMarkerHandler?handler, Func <ITextView, bool>?textViewFilter) => AddMarker(tokenId.Module, tokenId.Token, ilOffset, glyphImage, markerTypeName, selectedMarkerTypeName, classificationType, zIndex, tag, handler, textViewFilter);
public abstract void GoToLocation(IDocumentTab tab, MethodDef method, ModuleTokenId module, uint offset, bool newTab);
IEnumerable<ILCodeBreakpoint> GetILCodeBreakpoints(ModuleTokenId methodToken) { foreach (var ilbp in GetILCodeBreakpoints()) { if (ilbp.MethodToken.Equals(methodToken)) yield return ilbp; } }
void LoadInternal() { var section = settingsService.GetOrCreateSection(SETTINGS_GUID); breakpointService.Clear(); foreach (var bpx in section.SectionsWithName("Breakpoint")) { uint? token = bpx.Attribute<uint?>("Token"); string asmFullName = bpx.Attribute<string>("AssemblyFullName"); string moduleName = bpx.Attribute<string>("ModuleName"); bool? isDynamic = bpx.Attribute<bool?>("IsDynamic"); bool? isInMemory = bpx.Attribute<bool?>("IsInMemory"); bool moduleNameOnly = bpx.Attribute<bool?>("ModuleNameOnly") ?? false; uint? ilOffset = bpx.Attribute<uint?>("ILOffset"); bool? isEnabled = bpx.Attribute<bool?>("IsEnabled"); if (token == null) continue; if (isDynamic == null || isInMemory == null) continue; if (string.IsNullOrEmpty(asmFullName) && !moduleNameOnly) continue; if (string.IsNullOrEmpty(moduleName)) continue; if (ilOffset == null) continue; if (isEnabled == null) continue; var moduleId = ModuleId.Create(asmFullName, moduleName, isDynamic.Value, isInMemory.Value, moduleNameOnly); var key = new ModuleTokenId(moduleId, token.Value); if (!isInMemory.Value && !isDynamic.Value) { var s = bpx.Attribute<string>("Method"); if (s == null || s != GetMethodAsString(key)) continue; } var bp = new ILCodeBreakpoint(key, ilOffset.Value, isEnabled.Value); breakpointService.Add(bp); } }