void close() { if ( pGlobal != NULL ) { pGlobal->Release(); pGlobal = NULL; } if ( pSession != NULL ) { pSession->Release(); pSession = NULL; } if ( pSource != NULL ) { pSource->Release(); pSource = NULL; } if ( dia_hmod != NULL ) { FreeLibrary(dia_hmod); dia_hmod = NULL; } }
sBool PDBFileReader::ReadDebugInfo(sChar *fileName,DebugInfo &to) { sBool readOk = sFALSE; if(FAILED(CoInitialize(0))) return sFALSE; IDiaDataSource *source = 0; CoCreateInstance(__uuidof(DiaSource),0,CLSCTX_INPROC_SERVER, __uuidof(IDiaDataSource),(void**) &source); if(source) { wchar_t wideFileName[260]; mbstowcs(wideFileName,fileName,260); if(SUCCEEDED(source->loadDataForExe(wideFileName,0,0))) { if(SUCCEEDED(source->openSession(&Session))) { ReadEverything(to); readOk = sTRUE; Session->Release(); } } source->Release(); } CoUninitialize(); return readOk; }
sBool PDBFileReader::ReadDebugInfo(sChar *fileName,DebugInfo &to) { static const struct DLLDesc { const char *Filename; IID UseCLSID; } DLLs[] = { "msdia71.dll", __uuidof(DiaSource71), "msdia80.dll", __uuidof(DiaSource80), "msdia90.dll", __uuidof(DiaSource90), // add more here as new versions appear (as long as they're backwards-compatible) 0 }; sBool readOk = false; if(FAILED(CoInitialize(0))) { fprintf(stderr, " failed to initialize COM\n"); return false; } IDiaDataSource *source = 0; HRESULT hr = E_FAIL; // Try creating things "the official way" for(sInt i=0;DLLs[i].Filename;i++) { hr = CoCreateInstance(DLLs[i].UseCLSID,0,CLSCTX_INPROC_SERVER, __uuidof(IDiaDataSource),(void**) &source); if(SUCCEEDED(hr)) break; } if(FAILED(hr)) { // None of the classes are registered, but most programmers will have the // DLLs on their system anyway and can copy it over; try loading it directly. for(sInt i=0;DLLs[i].Filename;i++) { HMODULE hDIADll = LoadLibrary(DLLs[i].Filename); if(hDIADll) { typedef HRESULT (__stdcall *PDllGetClassObject)(REFCLSID rclsid,REFIID riid,void** ppvObj); PDllGetClassObject DllGetClassObject = (PDllGetClassObject) GetProcAddress(hDIADll,"DllGetClassObject"); if(DllGetClassObject) { // first create a class factory IClassFactory *classFactory; hr = DllGetClassObject(DLLs[i].UseCLSID,IID_IClassFactory,(void**) &classFactory); if(SUCCEEDED(hr)) { hr = classFactory->CreateInstance(0,__uuidof(IDiaDataSource),(void**) &source); classFactory->Release(); } } if(SUCCEEDED(hr)) break; else FreeLibrary(hDIADll); } } } if(source) { wchar_t wideFileName[260]; mbstowcs(wideFileName,fileName,260); if(SUCCEEDED(source->loadDataForExe(wideFileName,0,0))) { if(SUCCEEDED(source->openSession(&Session))) { ReadEverything(to); readOk = true; Session->Release(); } else fprintf(stderr," failed to open DIA session\n"); } else fprintf(stderr," failed to load debug symbols (PDB not found)\n"); source->Release(); } else fprintf(stderr," couldn't find (or properly initialize) any DIA dll, copying msdia*.dll to app dir might help.\n"); CoUninitialize(); return readOk; }
DDR_RC PdbScanner::startScan(OMRPortLibrary *portLibrary, Symbol_IR *ir, vector<string> *debugFiles, const char *blacklistPath) { DDR_RC rc = DDR_RC_OK; IDiaDataSource *diaDataSource = NULL; IDiaSession *diaSession = NULL; IDiaSymbol *diaSymbol = NULL; _ir = ir; initBaseTypeList(); if (FAILED(CoInitialize(NULL))) { rc = DDR_RC_ERROR; } if (DDR_RC_OK == rc) { rc = loadBlacklist(blacklistPath); } if (DDR_RC_OK == rc) { /* For each input Pdb file, load the file, then add the UDTs and Enums. * If findChildren(SymTagNull, ...) were to be used instead of finding * the UDTs and enums separately, duplicate types are returned with * undecorated names. The IR would contain inner classes twice, once as * an inner class, and once with no parent link and an undecorated name. * Finding UDT and enum children separately seems to work around this * quirk in the PDB API. */ for (vector<string>::iterator it = debugFiles->begin(); it != debugFiles->end(); ++it) { const string &file = *it; const size_t len = file.length(); wchar_t *filename = new wchar_t[len + 1]; mbstowcs(filename, file.c_str(), len + 1); rc = loadDataFromPdb(filename, &diaDataSource, &diaSession, &diaSymbol); if (DDR_RC_OK == rc) { rc = addChildrenSymbols(diaSymbol, SymTagUDT, NULL); } if (DDR_RC_OK == rc) { rc = addChildrenSymbols(diaSymbol, SymTagEnum, NULL); } if (DDR_RC_OK == rc) { rc = addChildrenSymbols(diaSymbol, SymTagTypedef, NULL); } if (NULL != diaDataSource) { diaDataSource->Release(); diaDataSource = NULL; } if (NULL != diaSession) { diaSession->Release(); diaSession = NULL; } if (NULL != diaSymbol) { diaSymbol->Release(); diaSymbol = NULL; } delete[] filename; if (DDR_RC_OK != rc) { break; } } } /* Field and superclass types which are needed before the type is found * are added to a postponed list. After all types are found, process the * postponed list to add these missing references. */ if (DDR_RC_OK == rc) { rc = updatePostponedFieldNames(); } CoUninitialize(); return rc; }
bool LoadDIASymbols(const wxString &strPDBFile, wxInt32 modulenum, std::list<CFunctionDescription> & llFuncs, stdext::hash_map<BasedAddress,int> & addressmap ) { // Create DIA80 Data Source Object IDiaDataSource *pDataSource; HRESULT hr = NoRegCoCreate( L"msdia80.dll", _uuidof( DiaSource ), _uuidof( IDiaDataSource ), (void **) &(pDataSource)); if(!SUCCEEDED(hr)) { return false; } /* HMODULE mod=LoadLibrary(L"msdia80.dll"); if(!mod) { return false; } TYPEOF_DllGetClassObject *pGetClassObject=(TYPEOF_DllGetClassObject *)GetProcAddress(mod,"DllGetClassObject"); if(!pGetClassObject) { FreeLibrary(mod); return false; } IClassFactory *pcf; HRESULT hr=(*pGetClassObject)(CLSID_DiaSource,IID_IClassFactory,(void **)&pcf); if(!SUCCEEDED(hr)) { FreeLibrary(mod); return false; } IDiaDataSource *pDataSource; hr=pcf->CreateInstance(NULL,_uuidof(IDiaDataSource),(void **)&pDataSource); if(!SUCCEEDED(hr)) { pcf->Release(); FreeLibrary(mod); return false; } pcf->Release(); */ // Load the executable's debug symbols hr=pDataSource->loadDataFromPdb(strPDBFile); if(!SUCCEEDED(hr)) { pDataSource->Release(); return false; } // Open a symbol session IDiaSession *pDIASession; hr=pDataSource->openSession(&pDIASession); if(!SUCCEEDED(hr)) { pDataSource->Release(); return false; } // Set the UNBASED address on the session, for resolving BasedAddress addrs hr=pDIASession->put_loadAddress(0); if(!SUCCEEDED(hr)) { pDIASession->Release(); pDataSource->Release(); return false; } // Get addresses for this module std::list<BasedAddress> addresses; for(stdext::hash_map<BasedAddress,int>::iterator iter=addressmap.begin();iter!=addressmap.end();iter++) { if(iter->first.nModule==modulenum) { addresses.push_back(iter->first); } } stdext::hash_map<DWORD,wxInt32> functions; int curidx=(int)llFuncs.size(); for(std::list<BasedAddress>::iterator itera=addresses.begin();itera!=addresses.end();itera++) { // Get the symbol for this thing IDiaSymbol* pFunc; if(FAILED(pDIASession->findSymbolByVA(itera->nAddr, SymTagFunction, &pFunc)) || pFunc==NULL) { continue; } // Get the unique symbol index id DWORD indexId; if(FAILED(pFunc->get_symIndexId(&indexId))) { pFunc->Release(); continue; } // See if we have this function already stdext::hash_map<DWORD,int>::iterator iterf=functions.find(indexId); if(iterf!=functions.end()) { addressmap[*itera]=iterf->second; } else { CFunctionDescription func; ////// ULONGLONG addr; if(FAILED(pFunc->get_virtualAddress(&addr))) { pFunc->Release(); continue; } ////// ULONGLONG length; if(FAILED(pFunc->get_length(&length))) { pFunc->Release(); continue; } ///////// BSTR pName; if(FAILED(pFunc->get_name(&pName))) { pFunc->Release(); continue; } func.strMangledName=(const LPWSTR)pName; LocalFree(pName); char mangled[512]; WideCharToMultiByte(CP_UTF8,0,func.strMangledName,-1,mangled,512,NULL,NULL); ///////// char outbase[512]; __unDName(outbase,mangled,512,&malloc,&free,0x1000); wchar_t outbasew[512]; MultiByteToWideChar(CP_UTF8,0,outbase,-1,outbasew,512); func.strBaseName=(const wchar_t *)(outbasew); ///////// char outfull[512]; __unDName(outfull,mangled,512,&malloc,&free,0); wchar_t outfullw[512]; MultiByteToWideChar(CP_UTF8,0,outfull,-1,outfullw,512); func.strFullName=(const wchar_t *)(outfullw); ////////// func.nAddress=BasedAddress(addr,modulenum); func.nByteLength=length; ///////// IDiaEnumLineNumbers *pdeln; func.strSourceFile=wxT("<unknown>"); func.nFirstSourceLine=0; func.nLastSourceLine=0; bool bGotFile=false; if(SUCCEEDED(pDIASession->findLinesByVA(addr,length,&pdeln))) { IDiaLineNumber *pdln; int nLineItem=0; while(SUCCEEDED(pdeln->Item(nLineItem,&pdln))) { DWORD dwLineNumber; IDiaSourceFile *pdsf; if(SUCCEEDED(pdln->get_lineNumber(&dwLineNumber)) && SUCCEEDED(pdln->get_sourceFile(&pdsf))) { BSTR filename; if(SUCCEEDED(pdsf->get_fileName(&filename))) { if(bGotFile) { if(filename==func.strSourceFile) { if(dwLineNumber<func.nFirstSourceLine) { func.nFirstSourceLine=dwLineNumber; } if(dwLineNumber>func.nLastSourceLine) { func.nLastSourceLine=dwLineNumber; } } } else { bGotFile=true; func.strSourceFile=filename; func.nFirstSourceLine=dwLineNumber; func.nLastSourceLine=dwLineNumber; } LocalFree(filename); } pdsf->Release(); } pdln->Release(); nLineItem++; } pdeln->Release(); } llFuncs.push_back(func); functions[indexId]=curidx; addressmap[*itera]=curidx; curidx++; } } pDIASession->Release(); pDataSource->Release(); // FreeLibrary(mod); return true; }