DbgHelp教程1——初始化


发布于 2016-05-07


以下是初始化DbgHelp最简单的代码:

#include <windows.h>
#include <dbghelp.h>
#include <iostream>
#include <string>
#include <tchar.h>

using namespace std;

#pragma comment(lib, "dbghelp.lib")

int _tmain(int argc, _TCHAR *argv[]) {

  DWORD options = SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES;
  SymSetOptions(options);

  std::string path =
      R"(SRV*E:\symbols*https://msdl.microsoft.com/download/symbols)";
  BOOL result = SymInitialize(GetCurrentProcess(), path.c_str(), TRUE);
  if (!result) {
    DWORD error = GetLastError();
    cout << "SymInitialize returned error : " << error << endl;
  }

  result = ::SymCleanup(GetCurrentProcess());

  system("pause");
  return 0;
}

SymSetOptions函数是设置DbgHelper的功能选项,具体用法见https://msdn.microsoft.com/en-us/library/windows/desktop/ms681366(v=vs.85).aspx。

SymSetOptions参数为0的时候,表示所有的选项都关闭,一下是常见的选项解释:

  • SYMOPT_ALLOW_ZERO_ADDRESS。允许符号没有地址。默认的DbgHelp会过滤掉没有地址的符号。
  • SYMOPT_CASE_INSENSITIVE。所有的搜索符号不区分大小写。
  • SYMOPT_DEBUG。通过OutputDebugString或者SymRegisterCallbackProc64 输出调试信息。
  • SYMOPT_DEFERRED_LOADS。延迟加载符号。就是知道某个模块被加载了,才会加载对应的符号。这样会提高调速速度。
  • SYMOPT_EXACT_SYMBOLS。不加载不匹配的pdb文件。
  • SYMOPT_IGNORE_CVREC。忽略CodeView里面的pdb路径
  • SYMOPT_LOAD_LINES。加载行信息
  • SYMOPT_UNDNAME。所有符号都是未修饰的形式。

可以在运行的时候多次调用SymSetOptions来修改选项,也可以用SymGetOptions来获取当前选项。

注意:所有的DbgHelp函数都是单线程的,因此不能在多个线程中调用,否则会导致不可预知的异常。

SymInitialize函数是正在的初始化DbgHelp库,它的原型如下:

BOOL WINAPI SymInitialize(
  _In_     HANDLE hProcess,
  _In_opt_ PCTSTR UserSearchPath,
  _In_     BOOL   fInvadeProcess
);
  • hProcess是调用者的进程句柄。如果当局进程是调试器,要调试其它进程,那么个hProcess就是那个被调试进程的句柄。当前去进程作为调试器去调试其它进程的时候,不要用GetCurrentProcess返回的句柄。
  • UserSearchPath,符号路径,规则跟windbg一样。如果值为NULL,则读取默认位置 。
  • fInvadeProcess,如果为TRUE,枚举进程已经加载的模块,类似调用SymLoadModule64