在调查转储时,我偶然发现了一个CMap
对象。这在Visual Studio中很容易调试,如下所示:
pThread->p<Class>->m_mapParameters.m_pHashTable,2741
其中2741是m_mapParameters CMap对象的m_nHashTableSize。
现在我已经尝试在Windbg中做同样的事情,但这不起作用。我唯一能做的就是:
dt pThread
然后,我开始点击,结果如下(只是自动生成的命令):
dx -r1 ((<application>!<Class> *)0x7f8e820)
dx -r1 (*((<application>!<Class> *)0x7f8e820)),nd
dx -r1 -n (*((<application>!<Class> *)0x7f8e820)),nd
然而,我陷入困境:没有办法(我发现)使用元素数量来获得CMap条目的完整列表。
有人知道是否有办法在Windbg(或Windbg预览)会话中获取CMap条目的完整列表?
提前致谢
多米尼克
答案 0 :(得分:0)
当你说m_mapParameters是CMap对象时,你为什么要看pThread?
你可以使用dx m_mapParameters
下面是一个小示例代码,它在vs2017社区开发提示中编译的MFC最低应用程序中实现CMap,并在windbg中查看CMap
#define WINVER 0x501 // compiler warning for _WINNT_WINVER so adding winxp
#define _CRT_SECURE_NO_WARNINGS // using sprintf which is deprecated
#include <afxwin.h>
class CMainFrame : public CFrameWnd {
public: CMainFrame();
protected:
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
DECLARE_MESSAGE_MAP()
};
CMainFrame::CMainFrame() {
Create(NULL, "MFC Test", WS_OVERLAPPEDWINDOW, CRect(120, 100, 700, 480), NULL);
}
class CMessagesApp : public CWinApp {
public: BOOL InitInstance();
};
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
BOOL CMessagesApp::InitInstance() {
m_pMainWnd = new CMainFrame;
m_pMainWnd->ShowWindow(SW_SHOW);m_pMainWnd->UpdateWindow();
return TRUE;
}
CMessagesApp theApp;
CMap<UINT, UINT, CStringA, CStringA> myMap; // global CMap Declaration
void CMainFrame::OnKeyDown(UINT nChar, UINT, UINT) {
char buff[0x100] = { 0 }; char buffy[0x100] = { 0 };
sprintf(buff, "you pressed %c \n", nChar);
myMap[nChar] = CStringA(buff);
sprintf(buffy, "total number of keys is %d\n", myMap.GetSize());
MessageBox(buffy);
}
编译执行按几个键盘键并将其附加到windbg
:\>cl /Zi /W4 /Ox /nologo /EHsc mfctest.cpp /link /nologo /subsystem:windows
mfctest.cpp
:\>mfctest.exe
:\>windbg -pn mfctest.exe
:\>
结果
0:001> dx mfctest!myMap
mfctest!myMap [Type: CMap<unsigned int,unsigned int,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > >]
[=0x5c79bc] classCObject : {"CObject"} [Type: CRuntimeClass]
[+0x004] m_pHashTable : 0x8d32b8 [Type: CMap<unsigned int,unsigned int,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > >::CAssoc * *]
[+0x008] m_nHashTableSize : 0x11 [Type: unsigned int]
[+0x00c] m_nCount : 9 [Type: int]
[+0x010] m_pFreeList : 0x8dd958 [Type: CMap<unsigned int,unsigned int,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > >::CAssoc *]
[+0x014] m_pBlocks : 0x8dd8c0 [Type: CPlex *]
[+0x018] m_nBlockSize : 10 [Type: int]
0:001> dx mfctest!myMap.m_pHashTable[0]->value.m_pszData
mfctest!myMap.m_pHashTable[0]->value.m_pszData : 0x8cf808 : "you pressed U ." [Type: char *]
0:001> dx mfctest!myMap.m_nCount
mfctest!myMap.m_nCount : 9 [Type: int]
修改强> 这里是你如何转储CMap-&gt; pHashTable.values
此地图有26个键值对(a,b..z)
hashtablesize是默认的0x11(推荐的素数)
0:001> dt myMap
mfctest!myMap
+0x000 __VFN_table : 0x0161b96c
=0161bba8 classCObject : CRuntimeClass
+0x004 m_pHashTable : 0x002e0858 -> 0x002e0d30 CMap<cut>::CAssoc
+0x008 m_nHashTableSize : 0x11
+0x00c m_nCount : 0n26
+0x010 m_pFreeList : 0x002e0d90 CMap<cut>::CAssoc
+0x014 m_pBlocks : 0x002e0d28 CPlex
+0x018 m_nBlockSize : 0n10
转储默认的pHashTables数组
下面的每个0x11 DWORD都是指向CMap :: CAssoc类型的pHashTable的指针
每个都可以有一个有效的pNext成员或null表示没有更多的条目
0:001> dd @@c++(myMap.m_pHashTable) L @@c++(myMap.m_nHashTableSize)
002e0858 002e0d30 002e0600 002e05d0 002e05a0
002e0868 002e0d80 002e0d50 002e0620 002e05f0
002e0878 002e05c0 002e0590 002e0d70 002e0d40
002e0888 002e0610 002e05e0 002e05b0 002e0950
002e0898 002e0d60
准备使用c ++表达式求值程序转储
0:001> $$ each of 0x11 dword are pointers to pHashTable and can have a valid pNext
0:001> $$ lets c++ expressify the first array member
0:001> r? @$t0 = myMap.m_pHashTable[0]
0:001> ? @$t0
Evaluate expression: 3018032 = 002e0d30 <<<<< see the dump above
0:001> r? @$t0 = myMap.m_pHashTable[1]
0:001> ? @$t0
Evaluate expression: 3016192 = 002e0600 <<<<< see the dump above
0:001> $$ @$t0 represents the pHashTables and if you have sufficiently
0:001> $$ big data m_nHashTableSize would be modified
0:001> ?? myMap.m_nHashTableSize
unsigned int 0x11
0:001> $$ now that we have an expression that points to the first pHashTable
0:001> we can iterate over the pNext and dump the keys
0:001> ? @$t0
Evaluate expression: 3016192 = 002e0600
转储实际条目
0:001> $$ we are going to iterate the second HashTable entries
0:001> .printf "%ma\n" , @@c++(@$t0->value.m_pszData)
you pressed R
0:001> $$ choose the pNext if it exists
0:001> .printf "%ma\n" , @@c++(@$t0->pNext->value.m_pszData)
you pressed A
0:001> .printf "%ma\n" , @@c++(@$t0->pNext->pNext->value.m_pszData)
Memory access error at 'm_pszData)'
0:001> ? @@c++(@$t0->pNext->pNext)
Evaluate expression: 0 = 00000000
0:001> $$ we reached the end so choose the next pHashTable and repeat the process
0:001> r? @$t0 = myMap.m_pHashTable[0]
0:001> ? @$t0
Evaluate expression: 3018032 = 002e0d30
0:001> $$ we are going to iterate the first HashTable entries
0:001> .printf "%ma\n" , @@c++(@$t0->value.m_pszData)
you pressed U
0:001> .printf "%ma\n" , @@c++(@$t0->pNext->value.m_pszData)
you pressed D
0:001> .printf "%ma\n" , @@c++(@$t0->pNext->pNext->value.m_pszData)
Memory access error at 'm_pszData)'
一个示例javascript代码,用于使用来自dt / v / t mfctest的类描述转储CMap条目以实例化CMap(int,int.CString,CString)!myMap
"use strict";
// usage !dumpcmap address
// typeDescription is copied from windbg dt /v /t myMap for this instantiation
// of CMap (int,int,CString,Cstring) myMap and pointerised
function initializeScript() {
return [new host.functionAlias(dump_CMap, "dumpcmap")];
}
function log(instr) {
host.diagnostics.debugLog(instr + "\n")
}
function dump_CMap(input ) {
var typeDescription = "(CMap<unsigned int,unsigned int,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > > *)"
var foo = host.evaluateExpression( typeDescription + input.toString() )
for(var i =0; i< foo.m_nHashTableSize ; i ++) {
log (foo.m_pHashTable[i].value)
if(foo.m_pHashTable[i].pNext != 0) {
log (foo.m_pHashTable[i].pNext.value)
}
}
}
执行js的结果
0:001> ? myMap
Evaluate expression: 17889164 = 0110f78c
0:001> ?? myMap
class CMap<unsigned int,unsigned int,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > >
+0x000 __VFN_table : 0x0108b96c
=0108bba8 classCObject : CRuntimeClass
+0x004 m_pHashTable : 0x00325660 -> 0x00331460 CMap<unsigned int,unsigned int,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > >::CAssoc
+0x008 m_nHashTableSize : 0x11
+0x00c m_nCount : 0n26
+0x010 m_pFreeList : 0x003314c0 CMap<unsigned int,unsigned int,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >,ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > >::CAssoc
+0x014 m_pBlocks : 0x00331458 CPlex
+0x018 m_nBlockSize : 0n10
0:001> .scriptload c:\wdscr\dump_cmap.js
JavaScript script successfully loaded from 'c:\wdscr\dump_cmap.js'
0:001> !dumpcmap 0x0110f78c
"you pressed U"
"you pressed D"
"you pressed R"
"you pressed A"
"you pressed O"
[object Object]
"you pressed L"
[object Object]
"you pressed Z"
"you pressed I"
"you pressed W"
"you pressed F"
"you pressed T"
"you pressed C"
"you pressed Q"
[object Object]
"you pressed N"
[object Object]
"you pressed K"
[object Object]
"you pressed Y"
"you pressed H"
"you pressed V"
"you pressed E"
"you pressed S"
"you pressed B"
"you pressed P"
[object Object]
"you pressed M"
[object Object]
"you pressed J"
[object Object]
"you pressed X"
"you pressed G"
@$dumpcmap(0x0110f78c)
答案 1 :(得分:0)
糟糕,这似乎是Windbg dt
命令的标准功能:
Option Description
====== ===========
-a[quantity] Show each array element on a new line, with its index.
A total of quantity elements will be displayed.
There must be no space between the a and the quantity.
If -a is not followed by a digit, all items in the array are shown.
The -a[quantity] switch should appear immediately before each type name or
field name that you want displayed in this manner.
然而,虽然这个解释提到不需要元素的数量,但我已经看到过没有将数量导致显示元素太多的情况。
因此:
dt -a2741 pThread->p<Class>->m_mapParameters.m_pHashTable