internal void AddModule(Module module) { module.OrderOfLoading = lastAssignedModuleOrderOfLoading; lastAssignedModuleOrderOfLoading++; moduleCollection.Add(module); debugger.SetBreakpointsInModule(module); OnModuleLoaded(module); }
void AddModule(Module module) { dynamic obj = new ExpandoObject(); obj.Tag = module; RefreshItem(obj); module.SymbolsUpdated += delegate { RefreshItem(obj); }; loadedModulesList.ItemCollection.Add(obj); }
public void SetBreakpoint(Module module) { foreach(var symbolSource in module.Process.Debugger.SymbolSources) { foreach (var seq in symbolSource.GetSequencePoints(module, this.FileName, this.Line, this.Column)) { ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken); ICorDebugFunctionBreakpoint corBreakpoint = corFunction.GetILCode().CreateBreakpoint((uint)seq.ILOffset); corBreakpoint.Activate(enabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); } } }
public DebuggerProcessEntityModelContext(Process process, Module currentModule) { if (process == null) { throw new ArgumentNullException("process"); } if (currentModule == null) { throw new ArgumentNullException("currentModule"); } this.process = process; this.currentModule = currentModule; }
public ModuleItem(Module module) { this.Name = module.Name; this.Address = string.Format("{0:X8}", module.BaseAdress); if (module.IsDynamic) { this.Path = StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.DynamicModule}"); } else if (module.IsInMemory) { this.Path = StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.InMemoryModule}"); } else { this.Path = module.FullPath; } this.Order = module.OrderOfLoading.ToString(); this.Symbols = module.HasSymbols ? StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.HasSymbols}") : StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.HasNoSymbols}"); }
public IEnumerable<Debugger.SequencePoint> GetSequencePoints(Module module, string filename, int line, int column) { var name = DecompiledTypeReference.FromFileName(filename); if (name == null || !FileUtility.IsEqualFileName(module.FullPath, name.AssemblyFile)) yield break; var file = SD.ParserService.ParseFile(name.ToFileName()) as ILSpyUnresolvedFile; if (file == null) yield break; TextLocation loc = new TextLocation(line, column); foreach(var symbols in file.DebugSymbols.Values.Where(s => s.StartLocation <= loc && loc <= s.EndLocation)) { Decompiler.SequencePoint seq = null; if (column != 0) seq = symbols.SequencePoints.FirstOrDefault(p => p.StartLocation <= loc && loc <= p.EndLocation); if (seq == null) seq = symbols.SequencePoints.FirstOrDefault(p => line <= p.StartLocation.Line); if (seq != null) yield return seq.ToDebugger(symbols, filename); } }
public IEnumerable<SequencePoint> GetSequencePoints(Module module, string filename, int line, int column) { // Do not use ISymUnmanagedReader.GetDocument! It is broken if two files have the same name // Do not use ISymUnmanagedMethod.GetOffset! It sometimes returns negative offset ISymUnmanagedReader symReader = module.SymReader; if (symReader == null) yield break; // No symbols // Find ISymUnmanagedDocument which excactly matches the filename. var symDoc = module.SymDocuments.FirstOrDefault(d => string.Equals(filename, d.GetURL(), StringComparison.OrdinalIgnoreCase)); // Find the file even if the symbol is relative or if the file was moved var symDocs = module.SymDocuments.Where(d => string.Equals(Path.GetFileName(filename), Path.GetFileName(d.GetURL()), StringComparison.OrdinalIgnoreCase)); symDoc = symDoc ?? symDocs.FirstOrDefault(d => string.Equals(GetSourceCodePath(module.Process, d.GetURL()), filename, StringComparison.OrdinalIgnoreCase)); if (symDoc == null) yield break; // Document not found ISymUnmanagedMethod[] symMethods; try { uint validLine = symDoc.FindClosestLine((uint)line); symMethods = symReader.GetMethodsFromDocumentPosition(symDoc, validLine, (uint)column); } catch { yield break; //Not found } foreach (ISymUnmanagedMethod symMethod in symMethods) { var corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); int codesize = (int)corFunction.GetILCode().GetSize(); var seqPoints = symMethod.GetSequencePoints(codesize).Where(s => s.StartLine != 0xFEEFEE); SequencePoint seqPoint = null; if (column != 0) { seqPoint = seqPoints.FirstOrDefault(s => (s.StartLine < line || (s.StartLine == line && s.StartColumn <= column)) && (line < s.EndLine || (line == s.EndLine && column <= s.EndColumn))); } seqPoint = seqPoint ?? seqPoints.FirstOrDefault(s => line <= s.StartLine); if (seqPoint != null) yield return seqPoint; } }
public override bool SetBreakpoint(Module module) { bool okMod = MethodKey.IsSameModule(module.FullPath); Debug.Assert(okMod, "Trying to set a BP that belongs in another module"); if (!okMod) return false; SourcecodeSegment segment = SourcecodeSegment.CreateForIL(module, this.Location.Line, (int)MethodKey.Token, (int)ILOffset); if (segment == null) return false; try { ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); corBreakpoint.Activate(Enabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); OnSet(new BreakpointEventArgs(this)); return true; } catch { return false; } }
internal void OnModuleUnloaded(Module module) { module.Dispose(); if (this.ModuleUnloaded != null) { this.ModuleUnloaded(this, new ModuleEventArgs(module)); } }
// Returns true if found internal bool GetFunctionAndOffset(Module module, bool normailize, out ICorDebugFunction function, out int ilOffset) { function = null; ilOffset = 0; ISymUnmanagedReader symReader = module.SymReader; if (symReader == null) { return false; // No symbols } ISymUnmanagedDocument symDoc = null; symDoc = symReader.GetDocument(SourceFullFilename, Guid.Empty, Guid.Empty, Guid.Empty); if (symDoc == null) { return false; // Does not use source file } uint validLine; try { validLine = symDoc.FindClosestLine((uint)StartLine); } catch { return false; // Not on a vaild point } if (validLine != StartLine && normailize) { StartLine = (int)validLine; EndLine = (int)validLine; StartColumn = 0; EndColumn = 0; } ISymUnmanagedMethod symMethod; try { symMethod = symReader.GetMethodFromDocumentPosition(symDoc, validLine, 0); } catch { return false; //Not found } // Check that StartLine is within the method uint start = uint.MaxValue; uint end = uint.MinValue; foreach(SequencePoint sqPoint in symMethod.SequencePoints) { if (sqPoint.Line == 0xFEEFEE) continue; start = Math.Min(start, sqPoint.Line); end = Math.Max(end, sqPoint.EndLine); } if (StartLine < start || StartLine > end) return false; function = module.CorModule.GetFunctionFromToken(symMethod.Token); ilOffset = (int)symMethod.GetOffset(symDoc, validLine, 0); return true; }
public DebuggerProcessEntityModelContext(Process process, Module currentModule) { if (process == null) throw new ArgumentNullException("process"); if (currentModule == null) throw new ArgumentNullException("currentModule"); this.process = process; this.currentModule = currentModule; }
static IAssemblyModel CreateAssemblyModel(Module module) { IEntityModelContext context = new DebuggerProcessEntityModelContext(module.Process, module); IUpdateableAssemblyModel model = SD.GetRequiredService<IModelFactory>().CreateAssemblyModel(context); var types = module.Assembly.TopLevelTypeDefinitions.SelectMany(td => td.Parts).ToList(); model.AssemblyName = module.UnresolvedAssembly.AssemblyName; model.FullAssemblyName = module.UnresolvedAssembly.FullAssemblyName; model.Update(EmptyList<IUnresolvedTypeDefinition>.Instance, types); model.References = module.GetReferences().Select(r => new DomAssemblyName(r)).ToArray(); return model; }
public static SourcecodeSegment CreateForIL(Module module, int line, int metadataToken, int iLOffset) { try { SourcecodeSegment segment = new SourcecodeSegment(); segment.module = module; segment.typename = null; segment.checkSum = null; segment.startLine = line; segment.startColumn = 0; segment.endLine = line; segment.endColumn = 0; segment.corFunction = module.CorModule.GetFunctionFromToken((uint)metadataToken); segment.ilStart = iLOffset; segment.ilEnd = iLOffset; segment.stepRanges = null; return segment; } catch { return null; } }
/// <summary> /// 'ILStart <= ILOffset <= ILEnd' and this range includes at least /// the returned area of source code. (May incude some extra compiler generated IL too) /// </summary> internal static SourcecodeSegment Resolve(Module module, ICorDebugFunction corFunction, int offset) { ISymUnmanagedReader symReader = module.SymReader; if (symReader == null) return null; // No symbols ISymUnmanagedMethod symMethod; try { symMethod = symReader.GetMethod(corFunction.GetToken()); } catch (COMException) { // Can not find the method // eg. Compiler generated constructors are not in symbol store return null; } if (symMethod == null) return null; uint sequencePointCount = symMethod.GetSequencePointCount(); SequencePoint[] sequencePoints = symMethod.GetSequencePoints(); // Get i for which: offsets[i] <= offset < offsets[i + 1] // or fallback to first element if offset < offsets[0] for (int i = (int)sequencePointCount - 1; i >= 0; i--) { // backwards if ((int)sequencePoints[i].Offset <= offset || i == 0) { // Set inforamtion about current IL range int codeSize = (int)corFunction.GetILCode().GetSize(); int ilStart = (int)sequencePoints[i].Offset; int ilEnd = (i + 1 < sequencePointCount) ? (int)sequencePoints[i+1].Offset : codeSize; // 0xFeeFee means "code generated by compiler" // If we are in generated sequence use to closest real one instead, // extend the ILStart and ILEnd to include the 'real' sequence // Look ahead for 'real' sequence while (i + 1 < sequencePointCount && sequencePoints[i].Line == 0xFeeFee) { i++; ilEnd = (i + 1 < sequencePointCount) ? (int)sequencePoints[i+1].Offset : codeSize; } // Look back for 'real' sequence while (i - 1 >= 0 && sequencePoints[i].Line == 0xFeeFee) { i--; ilStart = (int)sequencePoints[i].Offset; } // Wow, there are no 'real' sequences if (sequencePoints[i].Line == 0xFeeFee) { return null; } List<int> stepRanges = new List<int>(); for (int j = 0; j < sequencePointCount; j++) { // Step over compiler generated sequences and current statement // 0xFeeFee means "code generated by compiler" if (sequencePoints[j].Line == 0xFeeFee || j == i) { // Add start offset or remove last end (to connect two ranges into one) if (stepRanges.Count > 0 && stepRanges[stepRanges.Count - 1] == sequencePoints[j].Offset) { stepRanges.RemoveAt(stepRanges.Count - 1); } else { stepRanges.Add((int)sequencePoints[j].Offset); } // Add end offset | handle last sequence point if (j + 1 < sequencePointCount) { stepRanges.Add((int)sequencePoints[j+1].Offset); } else { stepRanges.Add(codeSize); } } } SourcecodeSegment segment = new SourcecodeSegment(); segment.module = module; segment.filename = GetFilenameFromSymDocument(module, sequencePoints[i].Document); segment.checkSum = sequencePoints[i].Document.GetCheckSum(); segment.startLine = (int)sequencePoints[i].Line; segment.startColumn = (int)sequencePoints[i].Column; segment.endLine = (int)sequencePoints[i].EndLine; segment.endColumn = (int)sequencePoints[i].EndColumn; segment.corFunction = corFunction; segment.ilStart = ilStart; segment.ilEnd = ilEnd; segment.stepRanges = stepRanges.ToArray(); // VB.NET sometimes produces temporary files which it then deletes // (eg 17d14f5c-a337-4978-8281-53493378c1071.vb) string filename = Path.GetFileName(segment.filename); if (filename.Length == 40 && filename.EndsWith(".vb")) { bool guidName = true; foreach(char c in filename.Substring(0, filename.Length - 3)) { if (('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') || (c == '-')) { guidName = true; } else { guidName = false; break; } } if (guidName) return null; } return segment; } } return null; }
static string GetFilenameFromSymDocument(Module module, ISymUnmanagedDocument symDoc) { foreach (string filename in RelocateSymURL(module, symDoc.GetURL())) { if (File.Exists(filename)) return filename; } return symDoc.GetURL(); }
public static SourcecodeSegment Resolve(Module module, string fileName, byte[] checkSum, int line, int column) { // Do not use ISymUnmanagedReader.GetDocument! It is broken if two files have the same name // Do not use ISymUnmanagedMethod.GetOffset! It sometimes returns negative offset ISymUnmanagedReader symReader = module.SymReader; if (symReader == null) return null; // No symbols ISymUnmanagedDocument symDoc = GetSymDocumentFromFilename(module, fileName, checkSum); if (symDoc == null) return null; // Document not found ISymUnmanagedMethod symMethod; try { uint validLine = symDoc.FindClosestLine((uint)line); symMethod = symReader.GetMethodFromDocumentPosition(symDoc, (uint)validLine, (uint)column); } catch { return null; //Not found } SequencePoint[] seqPoints = symMethod.GetSequencePoints(); Array.Sort(seqPoints); if (seqPoints.Length == 0) return null; if (line < seqPoints[0].Line) return null; foreach(SequencePoint sqPoint in seqPoints) { if (sqPoint.Line == 0xFEEFEE) continue; // If the desired breakpoint position is before the end of the sequence point if (line < sqPoint.EndLine || (line == sqPoint.EndLine && column < sqPoint.EndColumn)) { SourcecodeSegment segment = new SourcecodeSegment(); segment.module = module; segment.filename = symDoc.GetURL(); segment.checkSum = symDoc.GetCheckSum(); segment.startLine = (int)sqPoint.Line; segment.startColumn = (int)sqPoint.Column; segment.endLine = (int)sqPoint.EndLine; segment.endColumn = (int)sqPoint.EndColumn; segment.corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); segment.ilStart = (int)sqPoint.Offset; segment.ilEnd = (int)sqPoint.Offset; segment.stepRanges = null; return segment; } } return null; }
static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename, byte[] checksum) { if (filename == null) throw new ArgumentNullException("filename"); if (Path.IsPathRooted(filename)) { foreach(ISymUnmanagedDocument symDoc in module.SymDocuments) { foreach (string url in RelocateSymURL(module, symDoc.GetURL())) { if (string.Equals(url, filename, StringComparison.OrdinalIgnoreCase)) return symDoc; } } } else { foreach(ISymUnmanagedDocument symDoc in module.SymDocuments) { if (filename.StartsWith(@".\")) filename = filename.Substring(2); if (filename.StartsWith(@"\")) filename = filename.Substring(1); if (symDoc.GetURL().ToLowerInvariant().EndsWith(@"\" + filename.ToLowerInvariant())) { return symDoc; } } } return null; }
public void LoadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule) { EnterCallback(PausedReason.Other, "LoadModule " + pModule.GetName(), pAppDomain); Module module = new Module(process.AppDomains[pAppDomain], pModule); process.Modules.Add(module); ExitCallback(); }
public static SourcecodeSegment ResolveForIL(Module module, ICorDebugFunction corFunction, int line, int offset, int[] ranges) { try { SourcecodeSegment segment = new SourcecodeSegment(); segment.module = module; segment.typename = null; segment.checkSum = null; segment.startLine = line; segment.startColumn = 0; segment.endLine = line; segment.endColumn = 0; segment.corFunction = corFunction; segment.ilStart = offset; segment.ilEnd = ranges[1]; segment.stepRanges = ranges; return segment; } catch { return null; } }
public DebuggerModuleModel(Module module) { if (module == null) throw new ArgumentNullException("module"); this.module = module; this.assemblyModel = CreateAssemblyModel(module); }
/// <summary> /// Use the module path to figure out where to look for the source file /// </summary> static IEnumerable<string> RelocateSymURL(Module module, string symUrl) { string modulePath = module.Process.WorkingDirectory; if (module.IsInMemory || module.IsDynamic) { // Just use any module with symboles foreach(Module m in module.Process.Modules) { if (m.HasSymbols) { if (!string.IsNullOrEmpty(m.FullPath)) { modulePath = Path.GetDirectoryName(m.FullPath); break; } } } } else { if (!string.IsNullOrEmpty(module.FullPath)) modulePath = Path.GetDirectoryName(module.FullPath); } if (string.IsNullOrEmpty(modulePath)) { yield return symUrl; yield break; } if (Path.IsPathRooted(symUrl)) { Dictionary<string, object> returned = new Dictionary<string, object>(); // Try without relocating returned.Add(symUrl, null); yield return symUrl; // The two paths to combine string[] moduleDirs = modulePath.Split('\\'); string[] urlDirs = symUrl.Split('\\'); // Join the paths at some point (joining directry must match) for (int i = 0; i < moduleDirs.Length; i++) { for (int j = 0; j < urlDirs.Length; j++) { if (!string.IsNullOrEmpty(moduleDirs[i]) && !string.IsNullOrEmpty(urlDirs[j]) && string.Equals(moduleDirs[i], urlDirs[j], StringComparison.OrdinalIgnoreCase)) { // Join the paths string[] joinedDirs = new string[i + (urlDirs.Length - j)]; Array.Copy(moduleDirs, joinedDirs, i); Array.Copy(urlDirs, j, joinedDirs, i, urlDirs.Length - j); string joined = string.Join(@"\", joinedDirs); // Return joined path if (!returned.ContainsKey(joined)) { returned.Add(joined, null); yield return joined; } } } } } else { if (symUrl.StartsWith(@".\")) symUrl = symUrl.Substring(2); if (symUrl.StartsWith(@"\")) symUrl = symUrl.Substring(1); // Try 0, 1 and 2 levels above the module directory string dir = modulePath; if (!string.IsNullOrEmpty(dir)) yield return Path.Combine(dir, symUrl); dir = Path.GetDirectoryName(dir); if (!string.IsNullOrEmpty(dir)) yield return Path.Combine(dir, symUrl); dir = Path.GetDirectoryName(dir); if (!string.IsNullOrEmpty(dir)) yield return Path.Combine(dir, symUrl); } }
public DebuggerModuleTreeNode(DebuggerModuleModel model) : base(model.AssemblyModel) { this.module = model.Module; }
public ModuleEventArgs(Module module): base(module.Process) { this.module = module; }
public override bool SetBreakpoint(Module module) { SourcecodeSegment segment = SourcecodeSegment.CreateForIL(module, this.Line, MemberMetadataToken, ILOffset); if (segment == null) return false; try { ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); corBreakpoint.Activate(Enabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); OnSet(new BreakpointEventArgs(this)); return true; } catch #if DEBUG (System.Exception) #endif { return false; } }
internal void OnModuleLoaded(Module module) { module.OrderOfLoading = lastAssignedModuleOrderOfLoading++; module.AppDomain.InvalidateCompilation(); if (BreakInMain) { try { // create a BP at entry point uint entryPoint = module.GetEntryPoint(); if (entryPoint != 0) { // no EP var corBreakpoint = module.CorModule .GetFunctionFromToken(entryPoint) .CreateBreakpoint(); corBreakpoint.Activate(1); tempBreakpoints.Add(corBreakpoint); BreakInMain = false; } } catch { // the app does not have an entry point - COM exception } } if (this.ModuleLoaded != null) { this.ModuleLoaded(this, new ModuleEventArgs(module)); } }
internal void RemoveModule(Module module) { moduleCollection.Remove(module); OnModuleUnloaded(module); module.Dispose(); }
static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename, byte[] checksum) { if (filename == null) throw new ArgumentNullException("filename"); filename = filename.ToLower(); ISymUnmanagedDocument[] symDocs = module.SymDocuments; // "c:\project\file.cs" N/A if (Path.IsPathRooted(filename) && checksum == null) { foreach(ISymUnmanagedDocument symDoc in symDocs) { if (symDoc.URL.ToLower() == filename) return symDoc; } if (module.IsDynamic) { foreach(ISymUnmanagedDocument symDoc in symDocs) { string url = symDoc.URL.ToLower(); if (!String.IsNullOrEmpty(url) && !Path.IsPathRooted(url)) { string workingDir = Path.GetFullPath(module.Process.WorkingDirectory).ToLower(); url = Path.GetFullPath(Path.Combine(workingDir, url)); } if (url == filename) return symDoc; } } return null; // Not found } // "c:\project\file.cs" 0123456789 if (Path.IsPathRooted(filename) && checksum != null) { foreach(ISymUnmanagedDocument symDoc in symDocs) { if (symDoc.URL.ToLower() == filename) return symDoc; } // Not found - try to find using checksum filename = Path.GetFileName(filename); } // "file.cs" N/A if (!Path.IsPathRooted(filename) && checksum == null) { if (!filename.StartsWith(@"\")) { filename = @"\" + filename; } foreach(ISymUnmanagedDocument symDoc in symDocs) { if (symDoc.URL.ToLower().EndsWith(filename)) return symDoc; } return null; // Not found } // "file.cs" 0123456789 if (!Path.IsPathRooted(filename) && checksum != null) { if (!filename.StartsWith(@"\")) { filename = @"\" + filename; } foreach(ISymUnmanagedDocument symDoc in symDocs) { if (!symDoc.URL.ToLower().EndsWith(filename)) continue; byte[] symDocCheckSum = symDoc.CheckSum; if (symDocCheckSum.Length != checksum.Length) continue; for (int i = 0; i < checksum.Length; i++) { if (symDocCheckSum[i] != checksum[i]) continue; } return symDoc; } return null; // Not found } return null; }
public static DebugType Create(Module module, uint token, params DebugType[] typeArguments) { List<ICorDebugType> gen_args = new List<ICorDebugType>(); if (typeArguments != null && typeArguments.Length > 0) { for (int i=0; i<typeArguments.Length; i++) gen_args.Add(typeArguments[i].CorType); } if ((token & 0xFF000000) == (uint)CorTokenType.mdtTypeDef) { return Create(module.Process, module.CorModule.GetClassFromToken(token),gen_args.ToArray()); } else if ((token & 0xFF000000) == (uint)CorTokenType.mdtTypeRef) { string fullName = module.MetaData.GetTypeRefProps(token).Name; return Create(module.Process, module.AppDomainID, fullName); } else { throw new DebuggerException("Unknown token type"); } }
public virtual bool SetBreakpoint(Module module) { if (this.fileName == null) return false; SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, CheckSum, Line, Column); if (segment == null) return false; originalLocation = segment; ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); corBreakpoint.Activate(enabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); OnSet(new BreakpointEventArgs(this)); return true; }
uint GetEntryPointMethodToken(Module module) { if (module.SymReader != null) return module.SymReader.GetUserEntryPoint(); if (module.IsDynamic) return 0; if (module.IsInMemory) return 0;//TODO: Support reading it from memory try { //TODO: You could get this from dnSpy's MainWindow using (var mod = ModuleDefMD.Load(module.FullPath)) { var ep = mod.EntryPoint; if (ep != null) return ep.MDToken.ToUInt32(); } } catch (IOException) { } catch (BadImageFormatException) { } return 0; }
public void LoadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule) { EnterCallback("LoadModule " + pModule.GetName(), pAppDomain); Module module = new Module(process.GetAppDomain(pAppDomain), pModule); process.modules.Add(module); process.OnModuleLoaded(module); ExitCallback(); }
DebugType(Process process, ICorDebugType corType) { if (corType == null) throw new ArgumentNullException("corType"); this.process = process; this.corType = corType; this.corElementType = (CorElementType)corType.Type; if (this.IsClass || this.IsValueType) { this.corClass = corType.Class; this.module = process.GetModule(corClass.Module); this.classProps = module.MetaData.GetTypeDefProps(corClass.Token); } if (this.IsClass || this.IsValueType || this.IsArray || this.IsPointer) { foreach(ICorDebugType t in corType.EnumerateTypeParameters().Enumerator) { typeArguments.Add(DebugType.Create(process, t)); } } this.fullName = GetFullName(); }