之前我曾提供了导出stl map和set内容的windbg扩展指令库,并给出了使用方法。授人以鱼不如授人以渔,下面的文章将以开发一个导出CMap容器内容的windbg扩展指令cmap为例,介绍如果开发一个windbg的扩展指令库。
//---------------------------------------------------------------------------- // // extcpp.cpp // // EngExtCpp-style extension sample. // // Copyright (C) Microsoft Corporation, 2005. // //---------------------------------------------------------------------------- #include #include #include using std::string; //---------------------------------------------------------------------------- // // Base extension class. // Extensions derive from the provided ExtExtension class. // // The standard class name is "Extension". It can be // overridden by providing an alternate definition of // EXT_CLASS before including engextcpp.hpp. // //---------------------------------------------------------------------------- class EXT_CLASS : public ExtExtension { public: EXT_COMMAND_METHOD(cmap); // private: void OutUnfold( ExtRemoteTyped& node, int nRecur, int nOrgRecur); void DumpCmap(ExtRemoteTyped& hashTable, INT_PTR hashTableSize); }; // EXT_DECLARE_GLOBALS must be used to instantiate // the framework's assumed globals. EXT_DECLARE_GLOBALS(); void EXT_CLASS::DumpCmap(ExtRemoteTyped& hashTable, INT_PTR hashTableSize) { for (LONG i=0; i ExtRemoteTyped tableElement = hashTable[i]; while (tableElement.GetPtr() != 0) { ExtRemoteTyped key = tableElement.Field("key"); ExtRemoteTyped value = tableElement.Field("value"); Warn("== key======>\n"); OutUnfold(key, 5, 5); Warn("\n== value=====>\n"); OutUnfold(value, 5, 5); Out("\n"); tableElement = tableElement.Field("pNext"); } } } void EXT_CLASS::OutUnfold( ExtRemoteTyped& node, int nRecur, int nOrgRecur) { CHAR Name[MAX_PATH]; if (nRecur <= 0) { return; } if (nRecur == nOrgRecur) { string strType = node.GetTypeName(); if (strType.find("class") != string::npos && strType.find("*") != string::npos) { dprintf("%s : %s\n", node.GetTypeName(), node.GetSimpleValue()); } else { dprintf("%s :\n", node.GetTypeName()); } } for (int i=0; ;i++) { HRESULT Hr; ULONG Offset=0; Hr = m_Symbols2->GetFieldName(node.m_Typed.ModBase, node.m_Typed.TypeId, i, Name, MAX_PATH, NULL); if (Hr == S_OK) { m_Symbols2->GetFieldOffset(node.m_Typed.ModBase, node.m_Typed.TypeId, Name, &Offset); ExtRemoteTyped nodefield; try { nodefield = node.Field(Name); for(int i=0; i dprintf(" "); } dprintf("+%03lx %s %10s %s\n", Offset, Name, ":", nodefield.GetSimpleValue()); OutUnfold(nodefield, nRecur-1, nOrgRecur); } catch (.../*ExtException e*/) { //dprintf("excp :%s\n", e.GetMessage()); //dprintf("Exception OutUnfold \n"); } } else if (Hr == E_INVALIDARG) { if (i == 0 && nRecur == nOrgRecur) { node.OutSimpleValue(); } // All Fields done break; } else { dprintf("GetFieldName Failed %lx\n", Hr); break; } } } EXT_COMMAND(cmap, "\n-Description: \n" "- Dump the content of a specific CMap (VC9).\n" "-Usage:" " Directly use the name of a map variate, eg." " !cmap NameOfMapVar", "{;x;arg;argument}") { ExtRemoteTyped mtlmap; //dprintf("raw:%s\n",GetRawArgStr()); string strRawArgs = GetRawArgStr(); mtlmap.Set(strRawArgs.c_str()); mtlmap.OutFullValue(); Out("\n"); ExtRemoteTyped mapsize = mtlmap.Field("m_nCount"); ExtRemoteTyped hashTable = mtlmap.Field("m_pHashTable"); ExtRemoteTyped hashTableSize = mtlmap.Field("m_nHashTableSize"); Out("\n----------------------------------\n"); Warn("Map size: %s", mapsize.GetSimpleValue()); Out("\n----------------------------------\n"); Out("%s , %s", mtlmap.Field("m_pFreeList.key").GetTypeName(), mtlmap.Field("m_pFreeList.value").GetTypeName()); Out("\n----------------------------------\n"); // DumpCmap(hashTable, hashTableSize.GetLongPtr()); } |
;-------------------------------------------------------------------- ; Copyright (c) 2005 Microsoft Corporation ; ;Module: ; extcpp.def ;-------------------------------------------------------------------- EXPORTS ;-------------------------------------------------------------------- ; Core exports provided by the ExtCpp framework. ;-------------------------------------------------------------------- DebugExtensionInitialize DebugExtensionUninitialize DebugExtensionNotify help ;-------------------------------------------------------------------- ; Extension commands. ;-------------------------------------------------------------------- cmap |
#include |
class EXT_CLASS : public ExtExtension { public: EXT_COMMAND_METHOD(cmap); // private: void OutUnfold( ExtRemoteTyped& node, int nRecur, int nOrgRecur); void DumpCmap(ExtRemoteTyped& hashTable, INT_PTR hashTableSize); }; // EXT_DECLARE_GLOBALS must be used to instantiate // the framework's assumed globals. EXT_DECLARE_GLOBALS(); |
#ifndef EXT_CLASS #define EXT_CLASS Extension #endif |
public: EXT_COMMAND_METHOD(cmap); |
EXT_COMMAND(cmap, "\n-Description: \n" "- Dump the content of a specific CMap (VC9).\n" "-Usage:" " Directly use the name of a map variate, eg." " !cmap NameOfMapVar", "{;x;arg;argument}") { ExtRemoteTyped mtlmap; //dprintf("raw:%s\n",GetRawArgStr()); string strRawArgs = GetRawArgStr(); mtlmap.Set(strRawArgs.c_str()); mtlmap.OutFullValue(); Out("\n"); ExtRemoteTyped mapsize = mtlmap.Field("m_nCount"); ExtRemoteTyped hashTable = mtlmap.Field("m_pHashTable"); ExtRemoteTyped hashTableSize = mtlmap.Field("m_nHashTableSize"); Out("\n----------------------------------\n"); Warn("Map size: %s", mapsize.GetSimpleValue()); Out("\n----------------------------------\n"); Out("%s , %s", mtlmap.Field("m_pFreeList.key").GetTypeName(), mtlmap.Field("m_pFreeList.value").GetTypeName()); Out("\n----------------------------------\n"); // DumpCmap(hashTable, hashTableSize.GetLongPtr()); } |
EXT_COMMAND( _Name, _Desc, _Args ); |
_Name:指令的名称 |
_Desc:指令的描述信息 |
_Args:指令参数的描述信息 (指定windbg指令后面参数的属性,如参数是数字还是字符串等等,可以参考windbg帮助文档中的主题 Parsing Extension Arguments) |