/// <summary> /// Gets the symbol tag of the specified type. /// </summary> /// <param name="module">The module.</param> /// <param name="typeId">The type identifier.</param> public SymTag GetTypeTag(Module module, uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { return(typedData[Tuple.Create(module.Address, typeId, module.Process.PebAddress)].Tag); } }
/// <summary> /// Gets the runtime code type and offset to original code type. /// </summary> /// <param name="vtableAddress">The vtable address.</param> public Tuple <CodeType, int> GetRuntimeCodeTypeAndOffset(uint vtableAddress) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { uint nameSize; ulong displacement; StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); DbgEngDll.Symbols.GetNameByOffset(vtableAddress + Module.Address, sb, (uint)sb.Capacity, out nameSize, out displacement); // Fully undecorated name should be in form: "DerivedClass::`vftable'" string fullyUndecoratedName = sb.ToString(); const string vftableString = "::`vftable'"; if (string.IsNullOrEmpty(fullyUndecoratedName) || !fullyUndecoratedName.EndsWith(vftableString)) { // Pointer is not vtable. return(null); } string codeTypeName = fullyUndecoratedName.Substring(0, fullyUndecoratedName.Length - vftableString.Length); CodeType codeType = CodeType.Create(Module.Process, codeTypeName); // TODO: We need to be able to get partially undecorated name in order to find offset (See DiaModule.cs for more info) return(Tuple.Create(codeType, 0)); } }
/// <summary> /// Gets the size of the specified type. /// </summary> /// <param name="typeId">The type identifier.</param> public uint GetTypeSize(uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { return(DbgEngDll.Symbols.GetTypeSize(Module.Address, typeId)); } }
/// <summary> /// Gets the type identifier. /// </summary> /// <param name="typeName">Name of the type.</param> public uint GetTypeId(string typeName) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { return(DbgEngDll.Symbols.GetTypeIdWide(Module.Address, Module.Name + "!" + typeName)); } }
/// <summary> /// Gets the global variable address. /// </summary> /// <param name="globalVariableName">Name of the global variable.</param> public ulong GetGlobalVariableAddress(string globalVariableName) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { string name = Module.Name + "!" + globalVariableName; return(DbgEngDll.Symbols.GetOffsetByNameWide(name)); } }
/// <summary> /// Gets the code type tag of the specified type. /// </summary> /// <param name="typeId">The type identifier.</param> public CodeTypeTag GetTypeTag(uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { SymTagEnum symTag = DbgEngSymbolProvider.typedData[Tuple.Create(Module.Address, typeId, Module.Process.PebAddress)].Tag; return(symTag.ToCodeTypeTag()); } }
/// <summary> /// Gets the name of the enumeration value. /// </summary> /// <param name="enumTypeId">The enumeration type identifier.</param> /// <param name="enumValue">The enumeration value.</param> public string GetEnumName(uint enumTypeId, ulong enumValue) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { uint enumNameSize; StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); DbgEngDll.Symbols.GetConstantNameWide(Module.Offset, enumTypeId, enumValue, sb, (uint)sb.Capacity, out enumNameSize); return(sb.ToString()); } }
/// <summary> /// Determines whether the specified process address is function type public symbol. /// </summary> /// <param name="address">The address.</param> /// <returns> /// <c>true</c> if the specified process address is function type public symbol; otherwise, <c>false</c>. /// </returns> public bool IsFunctionAddressPublicSymbol(uint address) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { ulong moduleAddress; uint typeId; DbgEngDll.Symbols.GetOffsetTypeId(address + Module.Address, out typeId, out moduleAddress); return(typeId == 0); } }
/// <summary> /// Gets the name of the specified type. /// </summary> /// <param name="typeId">The type identifier.</param> public string GetTypeName(uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { uint nameSize; StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); DbgEngDll.Symbols.GetTypeName(Module.Address, typeId, sb, (uint)sb.Capacity, out nameSize); return(sb.ToString()); } }
/// <summary> /// Gets the name of the function for the specified stack frame. /// </summary> /// <param name="address">The address.</param> /// <param name="functionName">Name of the function.</param> /// <param name="displacement">The displacement.</param> public void GetFunctionNameAndDisplacement(uint address, out string functionName, out ulong displacement) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { uint functionNameSize; StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); DbgEngDll.Symbols.GetNameByOffset(address + Module.Address, sb, (uint)sb.Capacity, out functionNameSize, out displacement); functionName = sb.ToString(); } }
/// <summary> /// Gets the name of the enumeration value. /// </summary> /// <param name="module">The module.</param> /// <param name="enumTypeId">The enumeration type identifier.</param> /// <param name="enumValue">The enumeration value.</param> public string GetEnumName(Module module, uint enumTypeId, ulong enumValue) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { uint enumNameSize; StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); dbgEngDll.Symbols.GetConstantNameWide(module.Offset, enumTypeId, enumValue, sb, (uint)sb.Capacity, out enumNameSize); return sb.ToString(); } }
/// <summary> /// Gets the source file name and line for the specified stack frame. /// </summary> /// <param name="address">The address.</param> /// <param name="sourceFileName">Name of the source file.</param> /// <param name="sourceFileLine">The source file line.</param> /// <param name="displacement">The displacement.</param> public void GetSourceFileNameAndLine(uint address, out string sourceFileName, out uint sourceFileLine, out ulong displacement) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { uint fileNameLength; StringBuilder sb = new StringBuilder(Constants.MaxFileName); DbgEngDll.Symbols.GetLineByOffset(address + Module.Address, out sourceFileLine, sb, (uint)sb.Capacity, out fileNameLength, out displacement); sourceFileName = sb.ToString(); } }
/// <summary> /// Gets the global variable type identifier. /// </summary> /// <param name="globalVariableName">Name of the global variable.</param> public uint GetGlobalVariableTypeId(string globalVariableName) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { string name = Module.Name + "!" + globalVariableName.Replace("::", "."); uint typeId; ulong moduleId; DbgEngDll.Symbols.GetSymbolTypeIdWide(name, out typeId, out moduleId); return(typeId); } }
/// <summary> /// Gets the symbol name by address. /// </summary> /// <param name="address">The address.</param> public Tuple <string, ulong> GetSymbolNameByAddress(uint address) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); ulong displacement; uint nameSize; DbgEngDll.Symbols.GetNameByOffsetWide(address + Module.Address, sb, (uint)sb.Capacity, out nameSize, out displacement); return(Tuple.Create(sb.ToString(), displacement)); } }
/// <summary> /// Gets the type pointer to type of the specified type. /// </summary> /// <param name="typeId">The type identifier.</param> public uint GetTypePointerToTypeId(uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { var typedData = DbgEngSymbolProvider.typedData[Tuple.Create(Module.Address, typeId, Module.Process.PebAddress)]; typedData.Data = Module.Process.PebAddress; var result = DbgEngDll.Advanced.Request(DebugRequest.ExtTypedDataAnsi, new EXT_TYPED_DATA() { Operation = ExtTdop.GetPointerTo, InData = typedData, }).OutData.TypeId; return(result); } }
/// <summary> /// Gets the element type of the specified type. /// </summary> /// <param name="module">The module.</param> /// <param name="typeId">The type identifier.</param> public uint GetTypeElementTypeId(Module module, uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { var typedData = DbgEngSymbolProvider.typedData[Tuple.Create(module.Address, typeId, module.Process.PEB)]; typedData.Data = module.Process.PEB; var result = dbgEngDll.Advanced.Request(DebugRequest.ExtTypedDataAnsi, new EXT_TYPED_DATA() { Operation = ExtTdop.GetDereference, InData = typedData, }).OutData.TypeId; return(result); } }
/// <summary> /// Reads the simple data (1 to 8 bytes) for specified type and address to read from. /// </summary> /// <param name="codeType">Type of the code.</param> /// <param name="address">The address.</param> public ulong ReadSimpleData(CodeType codeType, ulong address) { NativeCodeType nativeCodeType = codeType as NativeCodeType; if (nativeCodeType == null) { return(Debugger.ReadSimpleData(codeType, address)); } Module module = codeType.Module; using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { return(DbgEngSymbolProvider.typedData[Tuple.Create(module.Address, nativeCodeType.TypeId, address)].Data); } }
/// <summary> /// Reads the simple data (1 to 8 bytes) for specified type and address to read from. /// </summary> /// <param name="codeType">Type of the code.</param> /// <param name="address">The address.</param> public ulong ReadSimpleData(CodeType codeType, ulong address) { NativeCodeType nativeCodeType = codeType as NativeCodeType; if (nativeCodeType == null) { throw new ArgumentOutOfRangeException(nameof(codeType), "This is only supported for NativeCodeType"); } Module module = codeType.Module; using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { return(typedData[Tuple.Create(module.Address, nativeCodeType.TypeId, address)].Data); } }
/// <summary> /// Gets the field type id and offset of the specified type. /// </summary> /// <param name="typeId">The type identifier.</param> /// <param name="fieldName">Name of the field.</param> public Tuple <uint, int> GetTypeAllFieldTypeAndOffset(uint typeId, string fieldName) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { try { uint fieldTypeId, fieldOffset; DbgEngDll.Symbols.GetFieldTypeAndOffsetWide(Module.Address, typeId, fieldName, out fieldTypeId, out fieldOffset); return(Tuple.Create(fieldTypeId, (int)fieldOffset)); } catch (Exception) { return(Tuple.Create <uint, int>(0, -1)); } } }
/// <summary> /// Gets the names of all fields of the specified type. /// </summary> /// <param name="typeId">The type identifier.</param> public string[] GetTypeAllFieldNames(uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, Module.Process)) { List <string> fields = new List <string>(); uint nameSize; try { for (uint fieldIndex = 0; ; fieldIndex++) { StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); DbgEngDll.Symbols.GetFieldName(Module.Address, typeId, fieldIndex, sb, (uint)sb.Capacity, out nameSize); fields.Add(sb.ToString()); } } catch (Exception) { } return(fields.ToArray()); } }
/// <summary> /// Gets the name of the function for the specified address. /// </summary> /// <param name="process">The process.</param> /// <param name="address">The address.</param> /// <param name="functionName">Name of the function.</param> /// <param name="displacement">The displacement.</param> public void GetProcessAddressFunctionName(Process process, ulong address, out string functionName, out ulong displacement) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, process)) { uint functionNameSize; StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); dbgEngDll.Symbols.GetNameByOffset(address, sb, (uint)sb.Capacity, out functionNameSize, out displacement); functionName = sb.ToString(); } }
/// <summary> /// Gets the symbol name by address. /// </summary> /// <param name="process">The process.</param> /// <param name="address">The address.</param> public Tuple<string, ulong> GetSymbolNameByAddress(Process process, ulong address) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, process)) { StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); ulong displacement; uint nameSize; dbgEngDll.Symbols.GetNameByOffsetWide(address, sb, (uint)sb.Capacity, out nameSize, out displacement); return Tuple.Create(sb.ToString(), displacement); } }
/// <summary> /// Gets the field type id and offset of the specified type. /// </summary> /// <param name="module">The module.</param> /// <param name="typeId">The type identifier.</param> /// <param name="fieldName">Name of the field.</param> public Tuple<uint, int> GetTypeAllFieldTypeAndOffset(Module module, uint typeId, string fieldName) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { try { uint fieldTypeId, fieldOffset; dbgEngDll.Symbols.GetFieldTypeAndOffsetWide(module.Address, typeId, fieldName, out fieldTypeId, out fieldOffset); return Tuple.Create(fieldTypeId, (int)fieldOffset); } catch (Exception) { return Tuple.Create<uint, int>(0, -1); } } }
/// <summary> /// Gets the name of the specified type. /// </summary> /// <param name="module">The module.</param> /// <param name="typeId">The type identifier.</param> public string GetTypeName(Module module, uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { uint nameSize; StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); dbgEngDll.Symbols.GetTypeName(module.Address, typeId, sb, (uint)sb.Capacity, out nameSize); return sb.ToString(); } }
/// <summary> /// Gets the size of the specified type. /// </summary> /// <param name="module">The module.</param> /// <param name="typeId">The type identifier.</param> public uint GetTypeSize(Module module, uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { return dbgEngDll.Symbols.GetTypeSize(module.Address, typeId); } }
/// <summary> /// Reads the simple data (1 to 8 bytes) for specified type and address to read from. /// </summary> /// <param name="codeType">Type of the code.</param> /// <param name="address">The address.</param> public ulong ReadSimpleData(CodeType codeType, ulong address) { NativeCodeType nativeCodeType = codeType as NativeCodeType; if (nativeCodeType == null) { return Debugger.ReadSimpleData(codeType, address); } Module module = codeType.Module; using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { return typedData[Tuple.Create(module.Address, nativeCodeType.TypeId, address)].Data; } }
/// <summary> /// Gets the effective processor type of the specified process. /// </summary> /// <param name="process">The process.</param> public ImageFileMachine GetProcessEffectiveProcessorType(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { return (ImageFileMachine)Control.GetEffectiveProcessorType(); } }
/// <summary> /// Gets the name of the module. /// </summary> /// <param name="module">The module.</param> /// <param name="modname">The type of module name.</param> /// <returns>Read name</returns> private string GetModuleName(Module module, DebugModname modname) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, module.Process)) { uint nameSize; StringBuilder sb = new StringBuilder(Constants.MaxFileName); Symbols.GetModuleNameStringWide((uint)modname, 0xffffffff, module.Address, sb, (uint)sb.Capacity, out nameSize); return sb.ToString(); } }
/// <summary> /// Gets the module version. /// </summary> /// <param name="module">The module.</param> /// <param name="major">The version major number.</param> /// <param name="minor">The version minor number.</param> /// <param name="revision">The version revision number.</param> /// <param name="patch">The version patch number.</param> public void GetModuleVersion(Module module, out int major, out int minor, out int revision, out int patch) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, module.Process)) { uint index, bufferSize; ulong baseAddress; Symbols.GetModuleByOffset(module.Address, 0, out index, out baseAddress); Symbols.GetModuleVersionInformation(index, module.Address, "\\", IntPtr.Zero, 0, out bufferSize); IntPtr buffer = Marshal.AllocHGlobal((int)bufferSize); try { Symbols.GetModuleVersionInformation(index, module.Address, "\\", buffer, bufferSize, out bufferSize); minor = (ushort)Marshal.ReadInt16(buffer, 8); major = (ushort)Marshal.ReadInt16(buffer, 10); patch = (ushort)Marshal.ReadInt16(buffer, 12); revision = (ushort)Marshal.ReadInt16(buffer, 14); } finally { Marshal.FreeHGlobal(buffer); } } }
/// <summary> /// Gets the address of the module loaded into specified process. /// </summary> /// <param name="process">The process.</param> /// <param name="moduleName">Name of the module.</param> public ulong GetModuleAddress(Process process, string moduleName) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { uint index; ulong moduleAddress; Symbols.GetModuleByModuleName2Wide(moduleName, 0, 0, out index, out moduleAddress); return moduleAddress; } }
/// <summary> /// Gets the all memory regions available in the specified process. /// </summary> /// <param name="process">The process.</param> /// <returns>Array of <see cref="MemoryRegion"/> objects available in the specified process</returns> public MemoryRegion[] GetMemoryRegions(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { List<MemoryRegion> regionsList = new List<MemoryRegion>(); ulong currentAddress = 0, baseAddress, regionSize; try { while (true) { currentAddress = DataSpaces.GetNextDifferentlyValidOffsetVirtual(currentAddress); if (currentAddress == 0) { break; } QueryVirtual(process, currentAddress, out baseAddress, out regionSize); // Merge consecutive regions if (regionsList.Count > 0 && regionsList[regionsList.Count - 1].MemoryEnd == baseAddress) regionsList[regionsList.Count - 1] = new MemoryRegion { BaseAddress = regionsList[regionsList.Count - 1].BaseAddress, MemoryEnd = baseAddress + regionSize }; else regionsList.Add(new MemoryRegion { BaseAddress = baseAddress, RegionSize = regionSize }); currentAddress = baseAddress + regionSize - 1; } } catch { } return regionsList.ToArray(); } }
/// <summary> /// Finds the pattern in memory of the specified process. /// </summary> /// <param name="process">The process.</param> /// <param name="memoryStart">The memory start.</param> /// <param name="memoryEnd">The memory end.</param> /// <param name="pattern">The pattern.</param> /// <param name="patternStart">The pattern start.</param> /// <param name="patternEnd">The pattern end.</param> /// <param name="searchAlignment">The search alignment in number of bytes. For a successful match, the difference between the location of the found pattern and memoryStart must be a multiple of searchAlignment.</param> /// <param name="searchWritableMemoryOnly">if set to <c>true</c> search through writable memory only.</param> /// <returns>Address of the successful match or 0 if patterns wasn't found.</returns> public ulong FindPatternInMemory(Process process, ulong memoryStart, ulong memoryEnd, byte[] pattern, int patternStart, int patternEnd, uint searchAlignment = 1, bool searchWritableMemoryOnly = false) { if (memoryEnd <= memoryStart) { throw new ArgumentOutOfRangeException("memoryEnd", "less than memoryStart"); } int patternSize = patternEnd - patternStart; IntPtr pointer = Marshal.AllocHGlobal(patternSize); try { Marshal.Copy(pattern, patternStart, pointer, patternSize); using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { return DataSpaces.SearchVirtual2(memoryStart, memoryEnd - memoryStart, searchWritableMemoryOnly ? 1U : 0U, pointer, (uint)patternSize, searchAlignment); } } catch (COMException ex) { if ((uint)ex.HResult == 0x9000001A) { return 0; } throw; } finally { Marshal.FreeHGlobal(pointer); } }
/// <summary> /// Releases the process that is being debugged. /// </summary> public void ContinueExecution(Process process) { using (var processSwitcher = new ProcessSwitcher(StateCache, process)) { DebuggeeFlowController flowControler = debugeeFlowControlers[process.Id]; flowControler.DebugStatusBreak.WaitOne(); Control.Execute(0, "g", 0); } }
/// <summary> /// Reads the memory from the specified process. /// </summary> /// <param name="process">The process.</param> /// <param name="address">The memory address.</param> /// <param name="size">The buffer size.</param> /// <returns> /// Buffer containing read memory /// </returns> public MemoryBuffer ReadMemory(Process process, ulong address, uint size) { try { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { IntPtr buffer = Marshal.AllocHGlobal((int)size); uint read; try { DataSpaces.ReadVirtual(address, buffer, size, out read); byte[] bytes = new byte[size]; Marshal.Copy(buffer, bytes, 0, (int)size); return new MemoryBuffer(bytes); } finally { Marshal.FreeHGlobal(buffer); } } } catch (Exception) { throw new InvalidMemoryAddressException(address); } }
/// <summary> /// Gets the process environment block address of the specified process. /// </summary> /// <param name="process">The process.</param> public ulong GetProcessEnvironmentBlockAddress(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { return SystemObjects.GetCurrentProcessPeb(); } }
/// <summary> /// Gets the symbol tag of the specified type. /// </summary> /// <param name="module">The module.</param> /// <param name="typeId">The type identifier.</param> public SymTag GetTypeTag(Module module, uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { return typedData[Tuple.Create(module.Address, typeId, module.Process.PebAddress)].Tag; } }
/// <summary> /// Gets the executable name of the specified process. /// </summary> /// <param name="process">The process.</param> public string GetProcessExecutableName(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { return SystemObjects.GetCurrentProcessExecutableName(); } }
/// <summary> /// Gets the type pointer to type of the specified type. /// </summary> /// <param name="module">The module.</param> /// <param name="typeId">The type identifier.</param> public uint GetTypePointerToTypeId(Module module, uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { var typedData = DbgEngSymbolProvider.typedData[Tuple.Create(module.Address, typeId, module.Process.PebAddress)]; typedData.Data = module.Process.PebAddress; var result = dbgEngDll.Advanced.Request(DebugRequest.ExtTypedDataAnsi, new EXT_TYPED_DATA() { Operation = ExtTdop.GetPointerTo, InData = typedData, }).OutData.TypeId; return result; } }
/// <summary> /// Gets all modules of the specified process. /// </summary> /// <param name="process">The process.</param> public Module[] GetProcessModules(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { uint loaded, unloaded; Symbols.GetNumberModules(out loaded, out unloaded); Module[] modules = new Module[loaded + unloaded]; for (int i = 0; i < modules.Length; i++) { ulong moduleId = Symbols.GetModuleByIndex((uint)i); modules[i] = process.ModulesById[moduleId]; } return modules; } }
/// <summary> /// Gets all threads of the specified process. /// </summary> /// <param name="process">The process.</param> public Thread[] GetProcessThreads(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { uint threadCount = SystemObjects.GetNumberThreads(); Thread[] threads = new Thread[threadCount]; uint[] threadIds = new uint[threadCount]; uint[] threadSytemIds = new uint[threadCount]; unsafe { fixed (uint* ids = &threadIds[0]) fixed (uint* systemIds = &threadSytemIds[0]) { SystemObjects.GetThreadIdsByIndex(0, threadCount, out *ids, out *systemIds); } } for (uint i = 0; i < threadCount; i++) { threads[i] = new Thread(threadIds[i], threadSytemIds[i], process); } return threads; } }
/// <summary> /// Gets the up time of the specified process. /// </summary> /// <param name="process">The process.</param> public uint GetProcessUpTime(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { return SystemObjects.GetCurrentProcessUpTime(); } }
/// <summary> /// Gets the type identifier. /// </summary> /// <param name="module">The module.</param> /// <param name="typeName">Name of the type.</param> public uint GetTypeId(Module module, string typeName) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { return dbgEngDll.Symbols.GetTypeIdWide(module.Address, module.Name + "!" + typeName); } }
/// <summary> /// Determines whether the specified process is being debugged as minidump without heap. /// </summary> /// <param name="process">The process.</param> public bool IsMinidump(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { uint cls, qual; Control.GetDebuggeeType(out cls, out qual); if (qual == (uint)Defines.DebugDumpSmall) { uint flags = Control.GetDumpFormatFlags(); return (flags & (uint)Defines.DebugFormatUserSmallFullMemory) == 0; } } return false; }
/// <summary> /// Gets the names of all fields of the specified type. /// </summary> /// <param name="module">The module.</param> /// <param name="typeId">The type identifier.</param> public string[] GetTypeAllFieldNames(Module module, uint typeId) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, module.Process)) { List<string> fields = new List<string>(); uint nameSize; try { for (uint fieldIndex = 0; ; fieldIndex++) { StringBuilder sb = new StringBuilder(Constants.MaxSymbolName); dbgEngDll.Symbols.GetFieldName(module.Address, typeId, fieldIndex, sb, (uint)sb.Capacity, out nameSize); fields.Add(sb.ToString()); } } catch (Exception) { } return fields.ToArray(); } }
/// <summary> /// Finds memory range where the specified address belongs to. /// </summary> /// <param name="process">The process.</param> /// <param name="address">The address.</param> /// <param name="baseAddress">The base address.</param> /// <param name="regionSize">Size of the region.</param> public void QueryVirtual(Process process, ulong address, out ulong baseAddress, out ulong regionSize) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { var memoryInfo = DataSpaces.QueryVirtual(address); baseAddress = memoryInfo.BaseAddress; regionSize = memoryInfo.RegionSize; } }
/// <summary> /// Gets the source file name and line for the specified address. /// </summary> /// <param name="process">The process.</param> /// <param name="address">The address.</param> /// <param name="sourceFileName">Name of the source file.</param> /// <param name="sourceFileLine">The source file line.</param> /// <param name="displacement">The displacement.</param> public void GetProcessAddressSourceFileNameAndLine(Process process, ulong address, out string sourceFileName, out uint sourceFileLine, out ulong displacement) { using (ProcessSwitcher switcher = new ProcessSwitcher(DbgEngDll.StateCache, process)) { uint fileNameLength; StringBuilder sb = new StringBuilder(Constants.MaxFileName); dbgEngDll.Symbols.GetLineByOffset(address, out sourceFileLine, sb, (uint)sb.Capacity, out fileNameLength, out displacement); sourceFileName = sb.ToString(); } }
/// <summary> /// Reads the unicode string. /// </summary> /// <param name="process">The process.</param> /// <param name="address">The address.</param> /// <param name="length">The length. If length is -1, string is null terminated</param> public string ReadUnicodeString(Process process, ulong address, int length = -1) { try { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { bool readAll = true; if (length < 0) { readAll = false; length = (int)Constants.MaxStringReadLength; } uint byteLength = 0; StringBuilder sb = new StringBuilder(length); if (readAll) { while (length > 0) { StringBuilder temp = new StringBuilder(length); DataSpaces.ReadUnicodeStringVirtualWide(address, (uint)temp.Capacity * 2, temp, (uint)temp.Capacity, out byteLength); sb.Append(temp); length -= (int)byteLength / 2; if (length > 0) { address += byteLength; sb.Append('\0'); } } } else { DataSpaces.ReadUnicodeStringVirtualWide(address, (uint)sb.Capacity * 2, sb, (uint)sb.Capacity, out byteLength); } return sb.ToString(); } } catch (Exception) { throw new InvalidMemoryAddressException(address); } }
/// <summary> /// Gets the dump file name of the specified process. /// </summary> /// <param name="process">The process.</param> public string GetProcessDumpFileName(Process process) { using (ProcessSwitcher switcher = new ProcessSwitcher(StateCache, process)) { uint dumpsFiles = Client.GetNumberDumpFiles(); if (dumpsFiles > 1) { throw new Exception("Unexpected number of dump files"); } if (dumpsFiles == 1) { StringBuilder sb = new StringBuilder(Constants.MaxFileName); uint nameSize, type; ulong handle; Client.GetDumpFileWide(0, sb, (uint)sb.Capacity, out nameSize, out handle, out type); return sb.ToString(); } return ""; } }
/// <summary> /// Breaks the process that is being debugged. /// </summary> public void BreakExecution(Process process) { using (var processSwitcher = new ProcessSwitcher(StateCache, process)) { DebuggeeFlowController flowControler = debugeeFlowControlers[process.Id]; flowControler.DebugStatusBreak.Reset(); Control.SetInterrupt(0); flowControler.DebugStatusBreak.WaitOne(); // Drop the cache. // TODO: When support for debugging multiple processes is added. // this needs to clear the cache of all the processes. // process.InvalidateProcessCache(); } }