23.windbg-dv(显示局部变量)


以下以自己的控件库skinhgy为例,windbg启动

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


 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值