Debug Interface Access SDK介绍

Debug Interface Access SDK也叫做DIA库,是用来访问调试符号文件pdb里面的数据的。代码编译成二进制文件,很多信息都储存在pdb文件中,比如类型,变量、参数、函数等等,远比我们想象的要多。利用好这个库会对我们调试和开发有很多的帮助。

pdb里面每个的信息都被称之为一个符号symbol。这些符号有不同的类别,不同类别也有不同的属性。符号的类别就被称之为Symbol Tag,可以从这里看到详细的类别信息:https://msdn.microsoft.com/en-us/library/bkedss5f.aspx

一般我们定义的结构体、类 都是SymTagUDT类型,也就是user-defined type。Symbol Tag没有什么好说的,基本上看名字就知道它指代的是什么。

所有的符号都有两个属性,一个是get_symIndexId,一个是get_symTag。symIndexId就是这个符号在pdb里面唯一的id值。

一般来说,安装好visual studio,dia库就会随之安装好了,C:\Program Files (x86)\Microsoft Visual Studio 12.0\DIA SDK就是dia库所在的目录。

使用DIA库也很简单,首先是初始化:

bool DiaWrapper::Init() {
  HRESULT hr;
  hr = CoInitialize(NULL);
  if (FAILED(hr)) {
    cout << "CoInitialize failed" << endl;
    return false;
  }

  hr = CoCreateInstance(CLSID_DiaSource, NULL, CLSCTX_INPROC_SERVER,
                        __uuidof(IDiaDataSource), (void **)&pSource_);

  if (FAILED(hr)) {
    cout << "Could not CoCreate CLSID_DiaSource. Register msdia80.dll." << endl;
    return false;
  }

  return true;
}

可以看到DIA其实就是com接口。然后加载pdb信息。

bool DiaWrapper::LoadDataFromPdb(const std::wstring &pdb_path) {
  HRESULT hr = pSource_->loadDataFromPdb(pdb_path.c_str());
  if (FAILED(hr)) {
    wcout << L"loadDataFromPdb " << pdb_path << L" failed" << endl;
    return false;
  }

  hr = pSource_->openSession(&pSession_);
  if (FAILED(hr)) {
    cout << "openSession failed" << endl;
    return false;
  }

  hr = pSession_->get_globalScope(&pGlobalSymbol_);
  if (FAILED(hr)) {
    cout << "get_globalScope failed" << endl;
    return false;
  }

  return true;
}

下面是遍历symbol,我们可以从globalScope开始遍历:

void DiaWrapper::PrintAllSymbols() {
  CComPtr<IDiaEnumSymbols> pEnum;
  CComPtr<IDiaSymbol> pSymbol;
  HRESULT hr = pGlobalSymbol_->findChildren(
    SymTagNull, NULL, nsfCaseInsensitive | nsfUndecoratedName, &pEnum);
  if (S_OK == hr) {
    DWORD celt = 0;
    while (SUCCEEDED(hr = pEnum->Next(1, &pSymbol, &celt)) && celt == 1) {
      BSTR name;
      if (pSymbol->get_name(&name) != S_OK) {
        continue;
      }
      PrintSymbolDetail(pSymbol);
      pSymbol = 0;
    }
  }
}