以下以自己的控件库skinhgy为例,windbg启动
1.dv(display Local variable)
dv 命令显示当前作用域的所有局部变量的名字和值。
0:000> x Simple1Demo!CSimple1DemoApp::InitInstance 00640080 Simple1Demo!CSimple1DemoApp::InitInstance (void) 0:000> bp 00640080 0:000> bl 0 e 00640080 0001 (0001) 0:**** Simple1Demo!CSimple1DemoApp::InitInstance 0:000> g ModLoad: 62c20000 62c29000 C:\WINDOWS\system32\LPK.DLL ModLoad: 73fa0000 7400b000 C:\WINDOWS\system32\USP10.dll ModLoad: 5adc0000 5adf7000 C:\WINDOWS\system32\uxtheme.dll Breakpoint 0 hit eax=0062c312 ebx=7ffdd000 ecx=00b24d28 edx=00a765dc esi=0342f76e edi=0342f6f2 eip=00640080 esp=0012fedc ebp=0012fefc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 Simple1Demo!CSimple1DemoApp::InitInstance: 00640080 55 push ebp 0:000> dv this = 0x0012fecc dlg = class CSimple1DemoDlg InitCtrls = struct tagINITCOMMONCONTROLSEX nResponse = -16843010
我的代码是这样的:
BOOL CSimple1DemoApp::InitInstance() { INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinAppEx::InitInstance(); AfxEnableControlContainer(); SetRegistryKey(_T("应用程序向导生成的本地应用程序")); m_hDll = LoadLibrary(TEXT("SkinHgy.dll")); if (m_hDll) { #ifdef UNICODE SkinLoadFileSkin = (fun_SkinLoadFileSkin)GetProcAddress(m_hDll, "SkinLoadFileSkinW"); #else SkinLoadFileSkin = (fun_SkinLoadFileSkin)GetProcAddress(m_hDll, "SkinLoadFileSkinA"); #endif if (SkinLoadFileSkin) { TCHAR wcPath[MAX_PATH] = {0}; ::GetModuleFileName(NULL, wcPath, MAX_PATH); CString szSkinPath = wcPath; szSkinPath = szSkinPath.Left(szSkinPath.ReverseFind('\\')); szSkinPath += TEXT("\\skin\\skin.xml"); SkinLoadFileSkin(szSkinPath); } } m_bDragFull = IsDragFullWindows(); if (m_bDragFull) { ::SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, FALSE, NULL, 0); } CSimple1DemoDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { } else if (nResponse == IDCANCEL) { } return FALSE; }
我们可以看到,的确显示的四个局部变量,当然,出现的顺序可能并不一致,
- /i 使得输出中显示变量的类型:局部、全局、参数、函数或未知:
0:000> dv /i prv local this = 0x0012fecc prv local dlg = class CSimple1DemoDlg prv local InitCtrls = struct tagINITCOMMONCONTROLSEX prv local nResponse = -16843010
数据结构和陌生的数据类型不会完整显示,而只显示他们的类型名。要显示整个结构或结构中的特定成员,使用dt (Display Type)命令。
0:000> dt InitCtrls Local var @ 0x12feb0 Type tagINITCOMMONCONTROLSEX +0x000 dwSize : 0xb1c238 +0x004 dwICC : 4
贴一下tagINITCOMMONCONTROLSEX的定义:
typedef struct tagINITCOMMONCONTROLSEX { DWORD dwSize; // size of this structure DWORD dwICC; // flags indicating which classes to be initialized } INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
我们继续F10单步调试,到了系统函数COMCTL32!InitCommonControlsEx中,F11进入,这时再dv
0:000> t eax=0012feb0 ebx=7ffdd000 ecx=00b24d28 edx=00a765dc esi=0012f7c0 edi=0012fecc eip=77184088 esp=0012f7b8 ebp=0012fed8 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 COMCTL32!InitCommonControlsEx: 77184088 8bff mov edi,edi 0:000> dv Unable to enumerate locals, HRESULT 0x80004005 Private symbols (symbols.pri) are required for locals. Type ".hh dbgerr005" for details.
显示不了local,这是因为dv命令是显示当前函数的局部变量,而当前函数是系统的函数(比如ntdll!DbgBreakPoint),那么因为没有系统模块的私有符号,所以会出错。
建议你切换到0号线程(~0s),然后使用单步或者gu命令执行到CSimple1Demo模块中的函数,然后再用dv命令
我们dt this看看:
0:000> dt this Local var @ 0x12fec0 Type CSimple1DemoApp* 0x0012fecc +0x000 __VFN_table : 0x0012fed8 =00a85844 CObject::classCObject : CRuntimeClass =00a78d54 CCmdTarget::classCCmdTarget : CRuntimeClass =00a78d18 CCmdTarget::_commandEntries : [1] AFX_OLECMDMAP_ENTRY =00a78d24 CCmdTarget::commandMap : AFX_OLECMDMAP =00a78c8c CCmdTarget::_dispatchEntries : [1] AFX_DISPMAP_ENTRY =00b1c484 CCmdTarget::_dispatchEntryCount : 0xffffffff =00b1c488 CCmdTarget::_dwStockPropMask : 0xffffffff ......................未完
我们可以看到,第一个就是指向虚表的指针:__VFN_table
补充点小细节,用dt /f <addr>可以用它来查看任何地方的任何代码处有些什么参数和局部变量。它会关闭对值得显示并隐含/V。/f 必须是最后一个标志
0:000> dv /i /v /f VerifyTxSignDemo!WinMain prv param @ebp+0x08 hInstance prv param @ebp+0x0c hPrevInstance prv param @ebp+0x10 lpCmdLine prv param @ebp+0x14 nCmdShow
也可以使用通配符,注意用双引号
0:000> dv /f VerifyTxSignDemo!WinMain "*cmd*" @ebp+0x10 lpCmdLine @ebp+0x14 nCmdShow