mirror of
https://github.com/reactos/reactosdbg.git
synced 2024-11-26 21:20:22 +00:00
af9999e73d
* Use modern output directory name in DbgHelp * Use modern outut directory name in settings dialog * Use CMake file to detect source directory * Use modern symbol file format to detect output directory Co-authored-by: William Kent <wjk@users.noreply.github.com>
477 lines
16 KiB
C#
477 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace DbgHelpAPI
|
|
{
|
|
public enum SymOptionsFlags
|
|
{
|
|
SYMOPT_ALLOW_ABSOLUTE_SYMBOLS = 0x80,
|
|
SYMOPT_ALLOW_ZERO_ADDRESS = 0x1000000,
|
|
SYMOPT_AUTO_PUBLICS = 0x10000,
|
|
SYMOPT_CASE_INSENSITIVE = 1,
|
|
SYMOPT_DEBUG = -2147483648,
|
|
SYMOPT_DEFERRED_LOADS = 4,
|
|
SYMOPT_DISABLE_SYMSRV_AUTODETECT = 0x2000000,
|
|
SYMOPT_EXACT_SYMBOLS = 0x400,
|
|
SYMOPT_FAIL_CRITICAL_ERRORS = 0x200,
|
|
SYMOPT_FAVOR_COMPRESSED = 0x800000,
|
|
SYMOPT_FLAT_DIRECTORY = 0x400000,
|
|
SYMOPT_IGNORE_CVREC = 0x80,
|
|
SYMOPT_IGNORE_IMAGEDIR = 0x200000,
|
|
SYMOPT_IGNORE_NT_SYMPATH = 0x1000,
|
|
SYMOPT_INCLUDE_32BIT_MODULES = 0x2000,
|
|
SYMOPT_LOAD_ANYTHING = 0x40,
|
|
SYMOPT_LOAD_LINES = 0x10,
|
|
SYMOPT_NO_CPP = 8,
|
|
SYMOPT_NO_IMAGE_SEARCH = 0x20000,
|
|
SYMOPT_NO_PROMPTS = 0x80000,
|
|
SYMOPT_NO_PUBLICS = 0x8000,
|
|
SYMOPT_NO_UNQUALIFIED_LOADS = 0x100,
|
|
SYMOPT_OVERWRITE = 0x100000,
|
|
SYMOPT_PUBLICS_ONLY = 0x4000,
|
|
SYMOPT_SECURE = 0x40000,
|
|
SYMOPT_UNDNAME = 2
|
|
}
|
|
|
|
public enum SsigType
|
|
{
|
|
DBHHEADER_DEBUGDIRS = 1,
|
|
DBHHEADER_CVMISC = 2
|
|
}
|
|
|
|
public struct MODLOAD_DATA
|
|
{
|
|
public UInt32 ssize;
|
|
public SsigType ssig;
|
|
public IntPtr data;
|
|
public UInt32 size;
|
|
public UInt32 flags;
|
|
}
|
|
|
|
public enum SymLoadModuleFlags
|
|
{
|
|
SLMFLAG_NO_SYMBOLS = 4,
|
|
SLMFLAG_VIRTUAL = 1
|
|
}
|
|
|
|
public struct IMAGEHLP_STACK_FRAME
|
|
{
|
|
public ulong InstructionOffset;
|
|
ulong ReturnOffset;
|
|
ulong FrameOffset;
|
|
ulong StackOffset;
|
|
ulong BackingStoreOffset;
|
|
ulong FuncTableEntry;
|
|
[MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
|
|
ulong[] Params;
|
|
[MarshalAs(UnmanagedType.ByValArray,SizeConst=5)]
|
|
ulong[] Reserved;
|
|
[MarshalAs(UnmanagedType.I1)]
|
|
bool Virtual;
|
|
uint Reserved2;
|
|
}
|
|
|
|
public enum SymInfoFlags
|
|
{
|
|
SYMFLAG_NONE = 0,
|
|
SYMFLAG_CLR_TOKEN = 0x40000,
|
|
SYMFLAG_CONSTANT = 0x100,
|
|
SYMFLAG_EXPORT = 0x200,
|
|
SYMFLAG_FORWARDER = 0x400,
|
|
SYMFLAG_FRAMEREL = 0x20,
|
|
SYMFLAG_FUNCTION = 0x800,
|
|
SYMFLAG_ILREL = 0x10000,
|
|
SYMFLAG_LOCAL = 0x80,
|
|
SYMFLAG_METADATA = 0x20000,
|
|
SYMFLAG_PARAMETER = 0x40,
|
|
SYMFLAG_REGISTER = 8,
|
|
SYMFLAG_REGREL = 0x10,
|
|
SYMFLAG_SLOT = 0x8000,
|
|
SYMFLAG_THUNK = 0x2000,
|
|
SYMFLAG_TLSREL = 0x4000,
|
|
SYMFLAG_VALUEPRESENT = 1,
|
|
SYMFLAG_VIRTUAL = 0x1000
|
|
}
|
|
|
|
public struct SYMBOL_INFO
|
|
{
|
|
public uint SizeOfStruct;
|
|
public uint TypeIndex;
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
|
|
public ulong []Reserved;
|
|
public uint Index;
|
|
public uint Size;
|
|
public ulong ModBase;
|
|
public SymInfoFlags Flags;
|
|
public ulong Value;
|
|
public ulong Address;
|
|
public uint Register;
|
|
public uint Scope;
|
|
public uint Tag;
|
|
public uint NameLen;
|
|
public uint MaxNameLen;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
|
|
public string Name;
|
|
|
|
public void Initialize()
|
|
{
|
|
SizeOfStruct = (uint)Marshal.SizeOf(this);
|
|
MaxNameLen = 256;
|
|
}
|
|
}
|
|
|
|
public enum IMAGEHLP_SYMBOL_TYPE_INFO
|
|
{
|
|
TI_GET_SYMTAG,
|
|
TI_GET_SYMNAME,
|
|
TI_GET_LENGTH,
|
|
TI_GET_TYPE,
|
|
TI_GET_TYPEID,
|
|
TI_GET_BASETYPE,
|
|
TI_GET_ARRAYINDEXTYPEID,
|
|
TI_FINDCHILDREN,
|
|
TI_GET_DATAKIND,
|
|
TI_GET_ADDRESSOFFSET,
|
|
TI_GET_OFFSET,
|
|
TI_GET_VALUE,
|
|
TI_GET_COUNT,
|
|
TI_GET_CHILDRENCOUNT,
|
|
TI_GET_BITPOSITION,
|
|
TI_GET_VIRTUALBASECLASS,
|
|
TI_GET_VIRTUALTABLESHAPEID,
|
|
TI_GET_VIRTUALBASEPOINTEROFFSET,
|
|
TI_GET_CLASSPARENTID,
|
|
TI_GET_NESTED,
|
|
TI_GET_SYMINDEX,
|
|
TI_GET_LEXICALPARENT,
|
|
TI_GET_ADDRESS,
|
|
TI_GET_THISADJUST,
|
|
TI_GET_UDTKIND,
|
|
TI_IS_EQUIV_TO,
|
|
TI_GET_CALLING_CONVENTION,
|
|
TI_IS_CLOSE_EQUIV_TO,
|
|
TI_GTIEX_REQS_VALID,
|
|
TI_GET_VIRTUALBASEOFFSET,
|
|
TI_GET_VIRTUALBASEDISPINDEX,
|
|
TI_GET_IS_REFERENCE,
|
|
TI_GET_INDIRECTVIRTUALBASECLASS
|
|
}
|
|
|
|
public struct IMAGEHLP_LINE64
|
|
{
|
|
public uint SizeOfStruct;
|
|
public IntPtr Key;
|
|
public uint LineNumber;
|
|
[MarshalAs(UnmanagedType.LPStr)]
|
|
public string FileName;
|
|
public ulong Address;
|
|
public void Initialize() { SizeOfStruct = (uint)Marshal.SizeOf(this); }
|
|
}
|
|
|
|
public delegate bool SymEnumSymbolsProc(ref SYMBOL_INFO symInfo, uint SymbolSize, IntPtr contextZero);
|
|
|
|
public enum DesiredAccess
|
|
{
|
|
GENERIC_READ = -2147483648
|
|
}
|
|
|
|
public enum ShareMode
|
|
{
|
|
FILE_SHARE_READ = 1
|
|
}
|
|
|
|
public enum CreateDisposition
|
|
{
|
|
OPEN_EXISTING = 3
|
|
}
|
|
|
|
public enum FlagsAndAttributes
|
|
{
|
|
FILE_ATTRIBUTE_NORMAL = 0x80
|
|
}
|
|
|
|
class Kernel32
|
|
{
|
|
public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
|
|
[DllImport("kernel32")]
|
|
public extern static IntPtr CreateFile(string FileName, DesiredAccess da, ShareMode sm, IntPtr SecurityAttributesZero, CreateDisposition cd, FlagsAndAttributes fa, IntPtr TemplateFileZero);
|
|
[DllImport("kernel32")]
|
|
public extern static void CloseHandle(IntPtr handle);
|
|
}
|
|
|
|
class DbgHelp
|
|
{
|
|
[DllImport("dbghelp")]
|
|
public extern static SymOptionsFlags SymSetOptions(SymOptionsFlags flags);
|
|
[DllImport("dbghelp")]
|
|
public extern static SymOptionsFlags SymGetOptions();
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymInitialize(IntPtr hProcess, string UserSearchPath, bool fInvadeProcess);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymSetSearchPath(IntPtr hProcess, string SearchPath);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymGetSearchPath(IntPtr hProcess, StringBuilder SearchPathResult, int SearchPathLength);
|
|
[DllImport("dbghelp")]
|
|
public extern static long SymLoadModuleEx(IntPtr hProcess, IntPtr hFile, string ImageName, string ModuleName, ulong BaseOfDll, uint DllSize, IntPtr DataZero, SymLoadModuleFlags Flags);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymUnloadModule64(IntPtr hProcess, ulong BaseOfDll);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymSetContext(IntPtr hProcess, ref IMAGEHLP_STACK_FRAME StackFrame, IntPtr ContextIgnored);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymSetScopeFromAddr(IntPtr hProcess, ulong Address);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymFromAddr(IntPtr hProcess, ulong Address, IntPtr DisplacementUnused, ref SYMBOL_INFO Symbol);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymFromName(IntPtr hProcess, string Name, ref SYMBOL_INFO Symbol);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymGetScope(IntPtr hProcess, ulong BaseOfDll, uint Index, ref SYMBOL_INFO Symbol);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymGetTypeInfo(IntPtr hProcess, ulong ModBase, uint TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType, ref byte[] Data);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymGetTypeFromName(IntPtr hProcess, ulong BaseOfDll, string Name, ref SYMBOL_INFO Symbol);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymGetLineFromAddr64(IntPtr hProcess, ulong Addr, out IntPtr Displacement, ref IMAGEHLP_LINE64 Line);
|
|
[DllImport("dbghelp")]
|
|
public extern static bool SymEnumSymbols(IntPtr hProcess, ulong BaseOfDll, string Mask, SymEnumSymbolsProc Callback, IntPtr ContextZero);
|
|
}
|
|
|
|
public class Variable
|
|
{
|
|
public enum Register
|
|
{
|
|
CV_REG_NONE = 0,
|
|
CV_REG_AL = 1,
|
|
CV_REG_CL = 2,
|
|
CV_REG_DL = 3,
|
|
CV_REG_BL = 4,
|
|
CV_REG_AH = 5,
|
|
CV_REG_CH = 6,
|
|
CV_REG_DH = 7,
|
|
CV_REG_BH = 8,
|
|
CV_REG_AX = 9,
|
|
CV_REG_CX = 10,
|
|
CV_REG_DX = 11,
|
|
CV_REG_BX = 12,
|
|
CV_REG_SP = 13,
|
|
CV_REG_BP = 14,
|
|
CV_REG_SI = 15,
|
|
CV_REG_DI = 16,
|
|
CV_REG_EAX = 17,
|
|
CV_REG_ECX = 18,
|
|
CV_REG_EDX = 19,
|
|
CV_REG_EBX = 20,
|
|
CV_REG_ESP = 21,
|
|
CV_REG_EBP = 22,
|
|
CV_REG_ESI = 23,
|
|
CV_REG_EDI = 24,
|
|
CV_REG_ES = 25,
|
|
CV_REG_CS = 26,
|
|
CV_REG_SS = 27,
|
|
CV_REG_DS = 28,
|
|
CV_REG_FS = 29,
|
|
CV_REG_GS = 30,
|
|
CV_REG_IP = 31,
|
|
CV_REG_FLAGS = 32,
|
|
CV_REG_EIP = 33,
|
|
CV_REG_EFLAGS = 34,
|
|
|
|
/* <pcode> */
|
|
CV_REG_TEMP = 40,
|
|
CV_REG_TEMPH = 41,
|
|
CV_REG_QUOTE = 42,
|
|
CV_REG_PCDR3 = 43, /* this includes PCDR4 to PCDR7 */
|
|
CV_REG_CR0 = 80, /* this includes CR1 to CR4 */
|
|
CV_REG_DR0 = 90, /* this includes DR1 to DR7 */
|
|
/* </pcode> */
|
|
|
|
CV_REG_GDTR = 110,
|
|
CV_REG_GDTL = 111,
|
|
CV_REG_IDTR = 112,
|
|
CV_REG_IDTL = 113,
|
|
CV_REG_LDTR = 114,
|
|
CV_REG_TR = 115,
|
|
|
|
CV_REG_PSEUDO1 = 116, /* this includes Pseudo02 to Pseuso09 */
|
|
CV_REG_ST0 = 128, /* this includes ST1 to ST7 */
|
|
CV_REG_CTRL = 136,
|
|
CV_REG_STAT = 137,
|
|
CV_REG_TAG = 138,
|
|
CV_REG_FPIP = 139,
|
|
CV_REG_FPCS = 140,
|
|
CV_REG_FPDO = 141,
|
|
CV_REG_FPDS = 142,
|
|
CV_REG_ISEM = 143,
|
|
CV_REG_FPEIP = 144,
|
|
CV_REG_FPEDO = 145,
|
|
CV_REG_MM0 = 146, /* this includes MM1 to MM7 */
|
|
CV_REG_XMM0 = 154, /* this includes XMM1 to XMM7 */
|
|
CV_REG_XMM00 = 162,
|
|
CV_REG_XMM0L = 194, /* this includes XMM1L to XMM7L */
|
|
CV_REG_XMM0H = 202, /* this includes XMM1H to XMM7H */
|
|
CV_REG_MXCSR = 211,
|
|
CV_REG_EDXEAX = 212,
|
|
CV_REG_EMM0L = 220,
|
|
CV_REG_EMM0H = 228,
|
|
CV_REG_MM00 = 236,
|
|
CV_REG_MM01 = 237,
|
|
CV_REG_MM10 = 238,
|
|
CV_REG_MM11 = 239,
|
|
CV_REG_MM20 = 240,
|
|
CV_REG_MM21 = 241,
|
|
CV_REG_MM30 = 242,
|
|
CV_REG_MM31 = 243,
|
|
CV_REG_MM40 = 244,
|
|
CV_REG_MM41 = 245,
|
|
CV_REG_MM50 = 246,
|
|
CV_REG_MM51 = 247,
|
|
CV_REG_MM60 = 248,
|
|
CV_REG_MM61 = 249,
|
|
CV_REG_MM70 = 250,
|
|
CV_REG_MM71 = 251
|
|
};
|
|
public string Name;
|
|
public Register Reg;
|
|
public int Offset, Size;
|
|
public bool Local, Parameter, Regval, Regrel;
|
|
}
|
|
|
|
public class SymbolContext
|
|
{
|
|
IntPtr hProcess;
|
|
static Random mRandom = new Random();
|
|
static FileMap mFileMap = new FileMap();
|
|
string mReactosOutputPath = "output-MinGW-i386", mReactosSourcePath = ".";
|
|
|
|
public string ReactosOutputPath
|
|
{
|
|
get { return mReactosOutputPath; }
|
|
set
|
|
{
|
|
mReactosOutputPath = value;
|
|
mFileMap.Directories = new string[] { mReactosOutputPath };
|
|
mFileMap.Scan();
|
|
LoadModules();
|
|
}
|
|
}
|
|
public string ReactosSourcePath
|
|
{
|
|
get { return mReactosSourcePath; }
|
|
set
|
|
{
|
|
mReactosSourcePath = value;
|
|
}
|
|
}
|
|
Dictionary<string, ulong> mLoadedModules = new Dictionary<string,ulong>();
|
|
|
|
static SymbolContext()
|
|
{
|
|
DbgHelp.SymSetOptions(SymOptionsFlags.SYMOPT_LOAD_LINES);
|
|
}
|
|
|
|
public SymbolContext()
|
|
{
|
|
hProcess = new IntPtr(mRandom.Next() + 1);
|
|
}
|
|
public void Initialize()
|
|
{
|
|
DbgHelp.SymInitialize(hProcess, null, false);
|
|
mFileMap.Directories = new string[] { mReactosOutputPath };
|
|
}
|
|
public void SetModuleAddress(string module, ulong addr)
|
|
{
|
|
if (mLoadedModules.ContainsKey(module))
|
|
{
|
|
DbgHelp.SymUnloadModule64(hProcess, mLoadedModules[module]);
|
|
}
|
|
mLoadedModules[module] = addr;
|
|
LoadModule(module, addr);
|
|
}
|
|
public void LoadModule(string module, ulong addr)
|
|
{
|
|
string realPath = mFileMap.GetFilePathFromShortName((Path.GetFileNameWithoutExtension(module) + ".nostrip").ToUpper());
|
|
if (realPath != null)
|
|
{
|
|
long loadResult = DbgHelp.SymLoadModuleEx
|
|
(hProcess,
|
|
IntPtr.Zero,
|
|
realPath,
|
|
null,
|
|
addr,
|
|
0,
|
|
IntPtr.Zero,
|
|
0);
|
|
}
|
|
}
|
|
public void LoadModules()
|
|
{
|
|
foreach (string module in mLoadedModules.Keys)
|
|
DbgHelp.SymUnloadModule64(hProcess, mLoadedModules[module]);
|
|
}
|
|
|
|
public KeyValuePair<string, int> GetFileAndLine(ulong addr)
|
|
{
|
|
IntPtr displacement = new IntPtr();
|
|
IMAGEHLP_LINE64 lineNumberIdent = new IMAGEHLP_LINE64();
|
|
lineNumberIdent.Initialize();
|
|
if (DbgHelp.SymGetLineFromAddr64
|
|
(hProcess, addr, out displacement, ref lineNumberIdent))
|
|
{
|
|
Console.Out.WriteLine("Got File and Line for addr " + addr + ": " + lineNumberIdent.FileName.ToString() + ":" + lineNumberIdent.LineNumber);
|
|
return new KeyValuePair<string, int>(lineNumberIdent.FileName.ToString(), (int)lineNumberIdent.LineNumber);
|
|
}
|
|
return new KeyValuePair<string, int>("unknown", 0);
|
|
}
|
|
|
|
Variable MakeVarFromSym(SYMBOL_INFO symInfo)
|
|
{
|
|
Variable v = new Variable();
|
|
v.Local = (symInfo.Flags & SymInfoFlags.SYMFLAG_LOCAL) != SymInfoFlags.SYMFLAG_NONE;
|
|
v.Parameter = (symInfo.Flags & SymInfoFlags.SYMFLAG_PARAMETER) != SymInfoFlags.SYMFLAG_NONE;
|
|
v.Regval = (symInfo.Flags & SymInfoFlags.SYMFLAG_REGISTER) != SymInfoFlags.SYMFLAG_NONE;
|
|
v.Regrel = (symInfo.Flags & SymInfoFlags.SYMFLAG_REGREL) != SymInfoFlags.SYMFLAG_NONE;
|
|
v.Reg = (Variable.Register)symInfo.Register;
|
|
v.Offset = (int)symInfo.Address;
|
|
v.Size = (int)symInfo.Size;
|
|
v.Name = symInfo.Name;
|
|
return v;
|
|
}
|
|
|
|
List<Variable> mVariables = new List<Variable>();
|
|
bool EnumLocals(ref SYMBOL_INFO symInfo, uint symSize, IntPtr contextZero)
|
|
{
|
|
Variable var = MakeVarFromSym(symInfo);
|
|
if (var != null)
|
|
mVariables.Add(var);
|
|
return true;
|
|
}
|
|
|
|
public List<Variable> GetLocals(ulong addr)
|
|
{
|
|
lock (mVariables)
|
|
{
|
|
mVariables.Clear();
|
|
IMAGEHLP_STACK_FRAME stackFrame = new IMAGEHLP_STACK_FRAME();
|
|
stackFrame.InstructionOffset = addr;
|
|
// Always succeeds
|
|
DbgHelp.SymSetContext(hProcess, ref stackFrame, IntPtr.Zero);
|
|
DbgHelp.SymEnumSymbols(hProcess, 0, null, EnumLocals, IntPtr.Zero);
|
|
return new List<Variable>(mVariables);
|
|
}
|
|
}
|
|
|
|
public Variable GetNamedVar(string name, ulong addr)
|
|
{
|
|
SYMBOL_INFO symInfo = new SYMBOL_INFO();
|
|
symInfo.Initialize();
|
|
if (DbgHelp.SymFromName(hProcess, name, ref symInfo))
|
|
return MakeVarFromSym(symInfo);
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
}
|