public int OpenSession(out IDiaSession session) { session = null; IntPtr _session; int hr = S.StdCall<int>(GetVTableMember(8), Punk, out _session); GC.KeepAlive(this); if (hr != S_OK) return hr; session = new IDiaSession(_session); return hr; }
public int OpenSession(out IDiaSession session) { session = null; IntPtr _session; int hr = S.StdCall <int>(GetVTableMember(8), Punk, out _session); GC.KeepAlive(this); if (hr != S_OK) { return(hr); } session = new IDiaSession(_session); return(hr); }
// // Retrieve the source fileName, line number, and column // private static void TryGetSourceLineInfo(IDiaSession session, int rva, out string fileName, out int lineNumber, out int columnNumber) { fileName = null; lineNumber = 0; columnNumber = 0; IDiaEnumLineNumbers lineNumbers; int hr = session.FindLinesByRVA(rva, 1, out lineNumbers); if (hr == S_OK) { int numLineNumbers; hr = lineNumbers.Count(out numLineNumbers); if (hr == S_OK && numLineNumbers > 0) { IDiaLineNumber ln; hr = lineNumbers.Item(0, out ln); if (hr == S_OK) { IDiaSourceFile sourceFile; hr = ln.SourceFile(out sourceFile); if (hr == S_OK) { hr = sourceFile.FileName(out fileName); if (hr == S_OK) { hr = ln.LineNumber(out lineNumber); if (hr == S_OK) { hr = ln.ColumnNumber(out columnNumber); } } } } } } }
private static String ToTypeStringWorker(this IDiaSymbol parameterType, IDiaSession session, int recursionLevel, out bool isValueTypeOrByRef) { int hr; isValueTypeOrByRef = false; // Block runaway recursions. if (recursionLevel++ > 10) return "?"; SymTagEnum symTag; hr = parameterType.GetSymTag(out symTag); if (hr != S_OK) return "?"; if (symTag == SymTagEnum.SymTagPointerType) { bool isReference; hr = parameterType.GetReference(out isReference); if (hr != S_OK) return "?"; if (isReference) { // An isReference pointer can mean one of two things: // 1. ELEMENT_TYPE_BYREF // 2. An indication that the UDT that follows is actually a class, not a struct. // isValueTypeOrByRef = true; IDiaSymbol targetType; hr = parameterType.GetType(out targetType); if (hr != S_OK) return "?"; bool targetIsValueTypeOrByRef; String targetTypeString = targetType.ToTypeStringWorker(session, recursionLevel, out targetIsValueTypeOrByRef); if (targetIsValueTypeOrByRef) return targetTypeString + "&"; else return targetTypeString; } else { // A non-isReference pointer means an ELEMENT_TYPE_PTR IDiaSymbol targetType; hr = parameterType.GetType(out targetType); if (hr != S_OK) return "?"; bool ignore; return targetType.ToTypeStringWorker(session, recursionLevel, out ignore) + "*"; } } else if (symTag == SymTagEnum.SymTagArrayType) { // Note: We don't actually hit this case in NUTC-generated PDB's as NUTC emits arrays as if they were UDT's with square brackets in the name. // But just in case NUTC ever changes its PDB emission, we'll print out the most obvious interpretation and hope we're right. IDiaSymbol elementType; hr = parameterType.GetType(out elementType); if (hr != S_OK) return "?"; bool ignore; return elementType.ToTypeStringWorker(session, recursionLevel, out ignore) + "[]"; } else if (symTag == SymTagEnum.SymTagUDT || symTag == SymTagEnum.SymTagEnum) { // Need to figure out whether this is a value type as our recursive caller needs to know whether the "byref pointer" that wrapped this // is a true managed byref or just the "byref pointer" that wraps all non-valuetypes. if (symTag == SymTagEnum.SymTagEnum) { isValueTypeOrByRef = true; } else { IDiaEnumSymbols baseClasses; hr = session.FindChildren(parameterType, SymTagEnum.SymTagBaseClass, null, 0, out baseClasses); if (hr != S_OK) return "?"; int count; hr = baseClasses.Count(out count); if (hr != S_OK) return "?"; for (int i = 0; i < count; i++) { IDiaSymbol baseClass; if (S_OK == baseClasses.Item(i, out baseClass)) { String baseClassName; if (S_OK == baseClass.GetName(out baseClassName)) { if (baseClassName == "System::ValueType") isValueTypeOrByRef = true; } } } } String name; hr = parameterType.GetName(out name); if (hr != S_OK) return "?"; return name.RemoveNamespaces().Demanglify(); } else if (symTag == SymTagEnum.SymTagBaseType) { // Certain "primitive" types are encoded specially. BasicType basicType; hr = parameterType.GetBaseType(out basicType); if (hr != S_OK) return "?"; long length; hr = parameterType.GetLength(out length); if (hr != S_OK) return "?"; return ConvertBasicTypeToTypeString(basicType, length, out isValueTypeOrByRef); } else { return "?"; } }
private static String ToTypeString(this IDiaSymbol parameterType, IDiaSession session) { bool ignore; return parameterType.ToTypeStringWorker(session, 0, out ignore); }
// // Generate the " in <filename>:line <line#>" section. // private static String CreateSourceInfoString(IDiaSession session, int rva) { StringBuilder sb = new StringBuilder(); string fileName; int lineNumber, columnNumber; TryGetSourceLineInfo(session, rva, out fileName, out lineNumber, out columnNumber); if(!string.IsNullOrEmpty(fileName)) { sb.Append(" in ").Append(fileName); if(lineNumber >= 0) { sb.Append(":line ").Append(lineNumber); } } return sb.ToString(); }
// // Create the method parameter list. // private static String CreateParameterListString(IDiaSession session, IDiaSymbol symbol) { StringBuilder sb = new StringBuilder("("); // find the parameters IDiaEnumSymbols dataSymbols; int hr = session.FindChildren(symbol, SymTagEnum.SymTagData, null, NameSearchOptions.nsNone, out dataSymbols); if (hr == S_OK) { int count; hr = dataSymbols.Count(out count); if (hr == S_OK) { for (int i = 0, iParam = 0; i < count; i++) { IDiaSymbol dataSym; hr = dataSymbols.Item(i, out dataSym); if (hr != S_OK) continue; DataKind dataKind; hr = dataSym.GetDataKind(out dataKind); if (hr != S_OK || dataKind != DataKind.DataIsParam) continue; string paramName; hr = dataSym.GetName(out paramName); if (hr != S_OK) { continue; } //this approximates the way C# displays methods by not including these hidden arguments if (paramName == "InstParam" || paramName == "this") { continue; } IDiaSymbol parameterType; hr = dataSym.GetType(out parameterType); if (hr != S_OK) { continue; } if (iParam++ != 0) sb.Append(", "); sb.Append(parameterType.ToTypeString(session)); sb.Append(' '); sb.Append(paramName); } } } sb.Append(')'); return sb.ToString(); }
/// <summary> /// Locate and lazily load debug info for the native app module overlapping given /// virtual address. /// </summary> /// <param name="ip">Instruction pointer address (code address for the lookup)</param> /// <param name="rva">Output VA relative to module base</param> private static IDiaSession GetDiaSession(IntPtr ip, out int rva) { if (ip == IntPtr.Zero) { rva = -1; return null; } IntPtr moduleBase = RuntimeAugments.GetModuleFromPointer(ip); if (moduleBase == IntPtr.Zero) { rva = -1; return null; } rva = (int)(ip.ToInt64() - moduleBase.ToInt64()); if (s_loadedModules == null) { // Lazily create the parallel arrays s_loadedModules and s_perModuleDebugInfo int moduleCount = RuntimeAugments.GetLoadedModules(null); s_loadedModules = new IntPtr[moduleCount]; s_perModuleDebugInfo = new IDiaSession[moduleCount]; // Actually read the module addresses into the array RuntimeAugments.GetLoadedModules(s_loadedModules); } // Locate module index based on base address int moduleIndex = s_loadedModules.Length; do { if (--moduleIndex < 0) { return null; } } while(s_loadedModules[moduleIndex] != moduleBase); IDiaSession diaSession = s_perModuleDebugInfo[moduleIndex]; if (diaSession != null) { return diaSession; } string modulePath = RuntimeAugments.TryGetFullPathToApplicationModule(moduleBase); if (modulePath == null) { return null; } int indexOfLastDot = modulePath.LastIndexOf('.'); if (indexOfLastDot == -1) { return null; } IDiaDataSource diaDataSource = GetDiaDataSource(); if (diaDataSource == null) { return null; } // Look for .pdb next to .exe / dll - if it's not there, bail. String pdbPath = modulePath.Substring(0, indexOfLastDot) + ".pdb"; int hr = diaDataSource.LoadDataFromPdb(pdbPath); if (hr != S_OK) { return null; } hr = diaDataSource.OpenSession(out diaSession); if (hr != S_OK) { return null; } s_perModuleDebugInfo[moduleIndex] = diaSession; return diaSession; }