dmp文件的分析,可以借助各种工具,比如WinDbg, CDB , NTSD,KD等。Windbg提供了窗口接口,而CDB , NTSD是基于命令行的工具,它们都使用了同样的调试引擎Dbgeng.dll,该调试引擎就是 “Windows 调试程序”。
dbgeng.dll 可以在基于x86,x64 或ARM的处理器上运行,并且可以调试在那些相同体系结构上运行的代码。
dbgeng.dll 的使用:
out.hpp
#ifndef __OUT_HPP__
#define __OUT_HPP__
#include
class StdioOutputCallbacks : public IDebugOutputCallbacks
{
public:
// IUnknown.
STDMETHOD(QueryInterface)(
THIS_
_In_ REFIID InterfaceId,
_Out_ PVOID* Interface
);
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
// IDebugOutputCallbacks.
STDMETHOD(Output)(
THIS\_
\_In\_ ULONG Mask,
\_In\_ PCSTR Text
);
};
extern StdioOutputCallbacks g_OutputCb;
#endif // #ifndef __OUT_HPP__
out.cpp
#include
#include
#include
#include "out.hpp"
StdioOutputCallbacks g_OutputCb;
FILE *fp = NULL;
STDMETHODIMP
StdioOutputCallbacks::QueryInterface(
THIS_
_In_ REFIID InterfaceId,
_Out_ PVOID* Interface
)
{
if (!fp) {
fp = fopen("D:/ZZZ/analyze.txt", "w+");
}
\*Interface = NULL;
if (IsEqualIID(InterfaceId, \_\_uuidof(IUnknown)) ||
IsEqualIID(InterfaceId, \_\_uuidof(IDebugOutputCallbacks)))
{
\*Interface = (IDebugOutputCallbacks \*)this;
AddRef();
return S\_OK;
}
else
{
return E\_NOINTERFACE;
}
}
STDMETHODIMP_(ULONG)
StdioOutputCallbacks::AddRef(
THIS
)
{
// This class is designed to be static so
// there's no true refcount.
return 1;
}
STDMETHODIMP_(ULONG)
StdioOutputCallbacks::Release(
THIS
)
{
// This class is designed to be static so
// there's no true refcount.
//fclose(fp);
return 0;
}
STDMETHODIMP
StdioOutputCallbacks::Output(
THIS_
_In_ ULONG Mask,
_In_ PCSTR Text
)
{
UNREFERENCED_PARAMETER(Mask);
//fputs(Text, fp);
fputs(Text, stdout);
return S_OK;
}
main.cpp
#include "out.hpp"
#include
#include
#include
#include
#include
PSTR g_DumpFile;
IDebugClient* g_Client;
IDebugControl* g_Control;
IDebugSymbols3* g_Symbols3;
void Exit(int Code, _In_ _Printf_format_string_ PCSTR Format, …)
{
// Clean up any resources.
if (g_Symbols3 != NULL)
{
g_Symbols3->Release();
}
if (g\_Control != NULL) {
g\_Control->Release();
}
if (g\_Client != NULL)
{
g\_Client->SetOutputCallbacks(NULL);
g\_Client->EndSession(DEBUG\_END\_PASSIVE);
g\_Client->Release();
}
// Output an error message if given.
if (Format != NULL)
{
va\_list Args;
va\_start(Args, Format);
vfprintf(stderr, Format, Args);
va\_end(Args);
}
exit(Code);
}
void CreateInterfaces(void)
{
HRESULT Status;
// Start things off by getting an initial interface from
// the engine. This can be any engine interface but is
// generally IDebugClient as the client interface is
// where sessions are started.
if ((Status = DebugCreate(\_\_uuidof(IDebugClient),
(void\*\*)&g\_Client)) != S\_OK)
{
Exit(1, "DebugCreate failed, 0x%X\\n", Status);
}
// Query for some other interfaces that we'll need.
if ((Status = g\_Client->QueryInterface(\_\_uuidof(IDebugControl),
(void\*\*)&g\_Control)) != S\_OK ||
(Status = g\_Client->QueryInterface(\_\_uuidof(IDebugSymbols3),
(void\*\*)&g\_Symbols3)) != S\_OK)
{
Exit(1, "QueryInterface failed, 0x%X\\n", Status);
}
}
//typedef _Null_terminated_ CHAR *TTPSTR;
void ParseCommandLine(int Argc, _In_reads_(Argc) PSTR* Argv)
{
int i;
while (--Argc > 0)
{
Argv++;
if (!strcmp(Argv[0], "-z"))
{
Argv++;
Argc--;
if (Argc > 0)
{
g_DumpFile = Argv[0];
}
else
{
Exit(1, "-z missing argument\n");
}
}
else
{
//Exit(1, "Unknown command line argument '%s'\n", Argv[0]);
}
}
if (g\_DumpFile == NULL)
{
Exit(1, "No dump file specified, use -z <file>\\n");
}
}
void ApplyCommandLineArguments(void)
{
HRESULT Status;
// Install output callbacks so we get any output that the
// later calls produce.
if ((Status = g\_Client->SetOutputCallbacks(&g\_OutputCb)) != S\_OK)
{
Exit(1, "SetOutputCallbacks failed, 0x%X\\n", Status);
}
// Everything's set up so open the dump file.
if ((Status = g\_Client->OpenDumpFile(g\_DumpFile)) != S\_OK)
{
Exit(1, "OpenDumpFile failed, 0x%X\\n", Status);
}
// Finish initialization by waiting for the event that
// caused the dump. This will return immediately as the
// dump file is considered to be at its event.
if ((Status = g\_Control->WaitForEvent(DEBUG\_WAIT\_DEFAULT,
INFINITE)) != S\_OK)
{
Exit(1, "WaitForEvent failed, 0x%X\\n", Status);
}
// Everything is now initialized and we can make any
// queries we want.
}
void DumpStack(void)
{
HRESULT Status;
DEBUG_STACK_FRAME Frames[3] = { 0 };
ULONG Filled;
g\_Symbols3->SetScopeFromStoredEvent();
if (Frames == NULL)
{
Exit(1, "Unable to allocate stack frames\\n");
}
if ((Status = g\_Control->
GetStackTrace(0, 0, 0,
Frames, 3, &Filled)) != S\_OK)
{
Exit(1, "GetStackTrace failed, 0x%X\\n", Status);
}
printf("\\nFirst %d frames of the call stack:\\n", Filled);
//// Print the call stack.
if ((Status = g\_Control->
OutputStackTrace(DEBUG\_OUTCTL\_ALL\_CLIENTS, Frames,
Filled, DEBUG\_STACK\_ARGUMENTS | DEBUG\_STACK\_SOURCE\_LINE |
DEBUG\_STACK\_FRAME\_ADDRESSES |
DEBUG\_STACK\_COLUMN\_NAMES |
DEBUG\_STACK\_FRAME\_NUMBERS)) != S\_OK)
{
Exit(1, "OutputStackTrace failed, 0x%X\\n", Status);
}
}
int main(int argc, char *argv[])
{
CreateInterfaces();
ParseCommandLine(argc, argv);
ApplyCommandLineArguments();
DumpStack();
return 0;
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章