Debug Interface Access SDK介绍
发布于 2016-07-02
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;
}
}
}