//------------------------------------------------------------------------ // pSymbol 타입의 정보를 srcPtr 주소에서 가져온다. // pSymbol 은 srcPtr 에 저장된 심볼의 타입을 가르킨다. // pSymbol 은 SymTagData 이거나 SymTagBaseType 타입이어야 한다. // isApplyOffset : false 이면 변수의 offset을 적용하지 않는다. // 이미 계산된 상태라면 할필요 없음 //------------------------------------------------------------------------ _variant_t dia::GetValueFromSymbol(void *srcPtr, IDiaSymbol *pSymbol ) { _variant_t value; void *ptr = (BYTE*)srcPtr; enum SymTagEnum symTag; HRESULT hr = pSymbol->get_symTag((DWORD*)&symTag); ASSERT_RETV((S_OK == hr), value); bool isReleaseBaseType=false; IDiaSymbol *pBaseType; if (SymTagData == symTag) { hr = pSymbol->get_type(&pBaseType); ASSERT_RETV((S_OK == hr), value); pSymbol = pBaseType; isReleaseBaseType = true; } else { pBaseType = pSymbol; } enum SymTagEnum baseSymTag; hr = pBaseType->get_symTag((DWORD*)&baseSymTag); ASSERT_RETV(S_OK==hr, value); BasicType btype; switch (baseSymTag) { case SymTagBaseType: hr = pBaseType->get_baseType((DWORD*)&btype); ASSERT_RETV((S_OK == hr), value ); break; case SymTagPointerType: btype = btULong; break; default: if (isReleaseBaseType) pBaseType->Release(); return value; } ULONGLONG length = 0; hr = pBaseType->get_length(&length); ASSERT_RETV((S_OK == hr), value ); value = dia::GetValueFromAddress(ptr, btype, length); if (isReleaseBaseType) pBaseType->Release(); return value; }
//---------------------------------------------------------------------- static HRESULT for_all_children( IDiaSymbol *sym, enum SymTagEnum type, children_visitor_t &cv) { IDiaEnumSymbols *pEnumSymbols; HRESULT hr = sym->findChildren(type, NULL, nsNone, &pEnumSymbols); if ( SUCCEEDED(hr) ) { while ( true ) { ULONG celt = 0; IDiaSymbol *pChild; hr = pEnumSymbols->Next(1, &pChild, &celt); if ( FAILED(hr) || celt != 1 ) { hr = S_OK; // end of enumeration break; } hr = cv.visit_child(pChild); pChild->Release(); if ( FAILED(hr) ) break; } pEnumSymbols->Release(); } return hr; }
IDiaSymbol* CSym::Enum( __in IDiaSymbol* symParent, __in enum SymTagEnum enTag, __in EnumProc cbEnum, __in_opt PVOID param) { if (NULL == symParent) return NULL; CComPtr<IDiaEnumSymbols> pEnum = NULL; HRESULT hr = symParent->findChildren(enTag, NULL, nsNone, &pEnum); if (SUCCEEDED(hr) && pEnum) { ULONG count = 1; IDiaSymbol* curItem = NULL; pEnum->Next(1, &curItem, &count); do { if (NULL != curItem) { if (cbEnum(curItem, param)) return curItem; curItem->Release(); } pEnum->Next(1, &curItem, &count); } while (0 != count); } return NULL; }
static void DumpTypes(IDiaSession *session) { IDiaSymbol * globalScope = NULL; IDiaEnumSymbols * enumSymbols = NULL; IDiaSymbol * symbol = NULL; HRESULT hr = session->get_globalScope(&globalScope); if (FAILED(hr)) return; AddReportSepLine(); g_report.Append("Types:\n"); DWORD flags = nsfCaseInsensitive|nsfUndecoratedName; // nsNone ? hr = globalScope->findChildren(SymTagUDT, 0, flags, &enumSymbols); if (FAILED(hr)) goto Exit; ULONG celt = 0; for (;;) { hr = enumSymbols->Next(1, &symbol, &celt); if (FAILED(hr) || (celt != 1)) break; DumpType(symbol, 0); symbol->Release(); } Exit: UnkReleaseSafe(enumSymbols); UnkReleaseSafe(globalScope); }
static void DumpType(IDiaSymbol *symbol, int deep) { IDiaEnumSymbols * enumChilds = NULL; HRESULT hr; const char * nameStr = NULL; const char * type; LONG offset; ULONGLONG length; ULONG celt = 0; ULONG symtag; DWORD locType; bool typeSeen; #if 0 if (deep > 2) return; #endif if (symbol->get_symTag(&symtag) != S_OK) return; nameStr = GetTypeName(symbol); g_typesSeen.Intern(nameStr, &typeSeen); if (typeSeen) return; symbol->get_length(&length); symbol->get_offset(&offset); if (SymTagData == symtag) { if (symbol->get_locationType(&locType) != S_OK) return; // must be a symbol in optimized code // TODO: use get_offsetInUdt (http://msdn.microsoft.com/en-us/library/dd997149.aspx) ? // TODO: use get_type (http://msdn.microsoft.com/en-US/library/cwx3656b(v=vs.80).aspx) ? // TODO: see what else we can get http://msdn.microsoft.com/en-US/library/w8ae4k32(v=vs.80).aspx if (LocIsThisRel == locType) { g_report.AppendFmt("%s%s|%d\n", spaces(deep), nameStr, (int)offset); } } else if (SymTagUDT == symtag) { // TODO: why is it always "struct" even for classes? type = GetUdtType(symbol); g_report.AppendFmt("%s%s|%s|%d\n", spaces(deep), type, nameStr, (int)length); hr = symbol->findChildren(SymTagNull, NULL, nsNone, &enumChilds); if (!SUCCEEDED(hr)) return; IDiaSymbol* child; while (SUCCEEDED(enumChilds->Next(1, &child, &celt)) && (celt == 1)) { DumpType(child, deep+1); child->Release(); } enumChilds->Release(); } else { if (symbol->get_locationType(&locType) != S_OK) return; // must be a symbol in optimized code // TODO: assert? } }
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; } }
static void DumpSymbols(IDiaSession *session) { HRESULT hr; IDiaEnumSymbolsByAddr * enumByAddr = NULL; IDiaSymbol * symbol = NULL; hr = session->getSymbolsByAddr(&enumByAddr); if (!SUCCEEDED(hr)) goto Exit; // get first symbol to get first RVA (argh) hr = enumByAddr->symbolByAddr(1, 0, &symbol); if (!SUCCEEDED(hr)) goto Exit; DWORD rva; hr = symbol->get_relativeVirtualAddress(&rva); if (S_OK != hr) goto Exit; symbol->Release(); symbol = NULL; // enumerate by rva hr = enumByAddr->symbolByRVA(rva, &symbol); if (!SUCCEEDED(hr)) goto Exit; AddReportSepLine(); g_report.Append("Symbols:\n"); ULONG numFetched; for (;;) { DumpSymbol(symbol); symbol->Release(); symbol = NULL; hr = enumByAddr->Next(1, &symbol, &numFetched); if (FAILED(hr) || (numFetched != 1)) break; } Exit: UnkReleaseSafe(symbol); UnkReleaseSafe(enumByAddr); }
static void DumpSymbol(IDiaSymbol *symbol) { DWORD section, offset, rva; DWORD dwTag; enum SymTagEnum tag; ULONGLONG length = 0; const char * typeName = NULL; char * dataTypeName = NULL; const char * thunkTypeName = NULL; symbol->get_symTag(&dwTag); tag = (enum SymTagEnum)dwTag; typeName = GetSymTypeName(tag); symbol->get_relativeVirtualAddress(&rva); symbol->get_addressSection(§ion); symbol->get_addressOffset(&offset); // for data, get length from type if (SymTagData == tag) { IDiaSymbol *type = NULL; if (symbol->get_type(&type) == S_OK) // no SUCCEEDED test as may return S_FALSE! { type->get_length(&length); const char *s = GetUndecoratedSymbolName(type, ""); if (s && *s) dataTypeName = str::Dup(s); type->Release(); } } if (SymTagThunk == tag) { DWORD dwThunkKind; if (S_OK == symbol->get_thunkOrdinal(&dwThunkKind)) thunkTypeName = GetThunkTypeName(dwThunkKind); } else { symbol->get_length(&length); } const char *nameStr = GetUndecoratedSymbolName(symbol); if (SymTagData == tag) { // type | section | length | offset | rva | name | dataTypeName char *tmp = dataTypeName ? dataTypeName : ""; g_report.AppendFmt("%s|%d|%d|%d|%d|%s|%s\n", typeName, (int)section, (int)length, (int)offset, (int)rva, nameStr, tmp); free(dataTypeName); } else if (SymTagThunk == tag) { const char *tmp = thunkTypeName ? thunkTypeName : ""; // type | section | length | offset | rva | name | thunkTypeName g_report.AppendFmt("%s|%d|%d|%d|%d|%s|%s\n", typeName, (int)section, (int)length, (int)offset, (int)rva, nameStr, tmp); } else { // type | section | length | offset | rva | name g_report.AppendFmt("%s|%d|%d|%d|%d|%s\n", typeName, (int)section, (int)length, (int)offset, (int)rva, nameStr); } }
// the result doesn't have to be free()d but is only valid until the next call to this function static const char *GetObjFileName(IDiaSectionContrib *item) { static str::Str<char> strTmp; BSTR name = 0; IDiaSymbol * compiland = 0; item->get_compiland(&compiland); if (compiland) { compiland->get_name(&name); compiland->Release(); } BStrToString(strTmp, name, "<noobjfile>"); SysFreeStringSafe(name); return strTmp.Get(); }
//---------------------------------------------------------------------- size_t get_symbol_length(IDiaSymbol *sym) { DWORD64 size = 0; DWORD tag = 0; sym->get_symTag(&tag); if ( tag == SymTagData ) { IDiaSymbol *pType; if ( sym->get_type(&pType) == S_OK ) { pType->get_length(&size); pType->Release(); } } else { sym->get_length(&size); } return size_t(size); }
/** @brief pSymbol 의 타입 심볼을 리턴한다. UDT, BaseClass, Data, TypeDef 타입일 경우 타입심볼을 리턴한다. 그 밖에 타입은 option에 따라 결정된다. option = 0: pointer, array 타입 등은 NULL 을 리턴한다. option = 1: pointer, array 타입을 리턴한다. option = 2: pointer, array 타입이라면, 실제 한번 더 baseType을 구해 포인터가 가르키는 데이타를 리턴하게 한다. pSymbol 자신일 경우 result = PARAM_SYMBOL 새 심볼을 생성해서 리턴할 경우 result = NEW_SYMBOL 찾지 못했을 경우 NULL을 리턴한다. */ IDiaSymbol* dia::GetBaseTypeSymbol( IDiaSymbol *pSymbol, DWORD option, OUT SymbolState &result ) { RETV(!pSymbol, NULL); enum SymTagEnum tag; HRESULT hr = pSymbol->get_symTag((DWORD*)&tag); ASSERT_RETV(S_OK == hr, NULL); IDiaSymbol *pRet = NULL; switch (tag) { case SymTagUDT: case SymTagBaseClass: case SymTagBaseType: pRet = pSymbol; result = PARAM_SYMBOL; break; case SymTagPointerType: case SymTagArrayType: if (0 == option) { // nothing } else if (1 == option) { pRet = pSymbol; result = PARAM_SYMBOL; } else if (2 == option) { IDiaSymbol *pBaseType; hr = pSymbol->get_type(&pBaseType); ASSERT_RETV(S_OK == hr, NULL); SymbolState rs; pRet = GetBaseTypeSymbol(pBaseType, 1, rs); if (!pRet) break; if (PARAM_SYMBOL != rs) pBaseType->Release(); result = NEW_SYMBOL; } break; case SymTagTypedef: case SymTagData: { IDiaSymbol *pBaseType; hr = pSymbol->get_type(&pBaseType); ASSERT_RETV(S_OK == hr, NULL); SymbolState rs; pRet = GetBaseTypeSymbol(pBaseType, option, rs); if (!pRet) break; if (PARAM_SYMBOL != rs) pBaseType->Release(); result = NEW_SYMBOL; } break; default: break; } return pRet; }
void PDBFileReader::ProcessSymbol(IDiaSymbol *symbol,DebugInfo &to) { DWORD section,offset,rva; enum SymTagEnum tag; ULONGLONG length = 0; sU32 compilandId; IDiaSymbol *compiland = 0; BSTR name = 0, sourceName = 0; sBool codeFlag; symbol->get_symTag((DWORD *) &tag); symbol->get_relativeVirtualAddress(&rva); symbol->get_length(&length); symbol->get_addressSection(§ion); symbol->get_addressOffset(&offset); // is the previous symbol desperately looking for a length? we can help! if(DanglingLengthStart) { to.Symbols[to.Symbols.Count - 1].Size = rva - DanglingLengthStart; DanglingLengthStart = 0; } // get length from type for data if(tag == SymTagData) { IDiaSymbol *type; if(symbol->get_type(&type) == S_OK) { type->get_length(&length); type->Release(); } // if length still zero, just guess and take number of bytes between // this symbol and the next one. if(!length) DanglingLengthStart = rva; } compilandId = CompilandFromSectionOffset(section,offset,codeFlag); Session->symbolById(compilandId,&compiland); if(compiland) compiland->get_name(&sourceName); symbol->get_name(&name); // fill out structure sChar *nameStr = BStrToString(name,"<no name>"); sChar *sourceStr = BStrToString(sourceName,"<no source>"); if(tag == SymTagPublicSymbol) { length = 0; DanglingLengthStart = rva; } DISymbol *outSym = to.Symbols.Add(); outSym->Name.Index = outSym->MangledName.Index = to.MakeString(nameStr); outSym->FileNum = to.GetFileByName(sourceStr); outSym->VA = rva; outSym->Size = (sU32) length; outSym->Class = codeFlag ? DIC_CODE : DIC_DATA; outSym->NameSpNum = to.GetNameSpaceByName(nameStr); // clean up delete[] nameStr; delete[] sourceStr; if(compiland) compiland->Release(); if(sourceName) SysFreeString(sourceName); if(name) SysFreeString(name); }
AddrInfo GetAddr(wstring req) { uint32_t module; uint64_t addr; int charsRead = swscanf_s(req.c_str(), L"%d %llu", &module, &addr); AddrInfo ret; ZeroMemory(&ret, sizeof(ret)); if(module > 0 && module < modules.size()) { SymTagEnum tag = SymTagFunction; IDiaSymbol *pFunc = NULL; HRESULT hr = modules[module].pSession->findSymbolByVA(addr, tag, &pFunc); if(hr != S_OK) { if(pFunc) pFunc->Release(); // try again looking for public symbols tag = SymTagPublicSymbol; hr = modules[module].pSession->findSymbolByVA(addr, tag, &pFunc); if(hr != S_OK) { if(pFunc) pFunc->Release(); return ret; } } DWORD opts = 0; opts |= UNDNAME_NO_LEADING_UNDERSCORES; opts |= UNDNAME_NO_MS_KEYWORDS; opts |= UNDNAME_NO_FUNCTION_RETURNS; opts |= UNDNAME_NO_ALLOCATION_MODEL; opts |= UNDNAME_NO_ALLOCATION_LANGUAGE; opts |= UNDNAME_NO_THISTYPE; opts |= UNDNAME_NO_ACCESS_SPECIFIERS; opts |= UNDNAME_NO_THROW_SIGNATURES; opts |= UNDNAME_NO_MEMBER_TYPE; opts |= UNDNAME_NO_RETURN_UDT_MODEL; opts |= UNDNAME_32_BIT_DECODE; opts |= UNDNAME_NO_LEADING_UNDERSCORES; // first try undecorated name BSTR file; hr = pFunc->get_undecoratedNameEx(opts, &file); // if not, just try name if(hr != S_OK) { hr = pFunc->get_name(&file); if(hr != S_OK) { pFunc->Release(); SysFreeString(file); return ret; } wcsncpy_s(ret.funcName, file, 126); } else { wcsncpy_s(ret.funcName, file, 126); wchar_t *voidparam = wcsstr(ret.funcName, L"(void)"); // remove stupid (void) for empty parameters if(voidparam != NULL) { *(voidparam + 1) = L')'; *(voidparam + 2) = 0; } } pFunc->Release(); pFunc = NULL; SysFreeString(file); // find the line numbers touched by this address. IDiaEnumLineNumbers *lines = NULL; hr = modules[module].pSession->findLinesByVA(addr, DWORD(4), &lines); if(FAILED(hr)) { if(lines) lines->Release(); return ret; } IDiaLineNumber *line = NULL; ULONG count = 0; // just take the first one if(SUCCEEDED(lines->Next(1, &line, &count)) && count == 1) { IDiaSourceFile *dia_source = NULL; hr = line->get_sourceFile(&dia_source); if(FAILED(hr)) { line->Release(); lines->Release(); if(dia_source) dia_source->Release(); return ret; } hr = dia_source->get_fileName(&file); if(FAILED(hr)) { line->Release(); lines->Release(); dia_source->Release(); return ret; } wcsncpy_s(ret.fileName, file, 126); SysFreeString(file); dia_source->Release(); dia_source = NULL; DWORD line_num = 0; hr = line->get_lineNumber(&line_num); if(FAILED(hr)) { line->Release(); lines->Release(); return ret; } ret.lineNum = line_num; line->Release(); } lines->Release(); } return ret; }
void PDBFileReader::ProcessSymbol(IDiaSymbol *symbol,DebugInfo &to) { // print a dot for each 1000 symbols processed static int counter = 0; ++counter; if( counter == 1000 ) { fputc( '.', stderr ); counter = 0; } DWORD section,offset,rva; enum SymTagEnum tag; ULONGLONG length = 0; BSTR name = 0, srcFileName = 0; symbol->get_symTag((DWORD *) &tag); symbol->get_relativeVirtualAddress(&rva); symbol->get_length(&length); symbol->get_addressSection(§ion); symbol->get_addressOffset(&offset); // get length from type for data if( tag == SymTagData ) { IDiaSymbol *type = NULL; if( symbol->get_type(&type) == S_OK ) // no SUCCEEDED test as may return S_FALSE! { if( FAILED(type->get_length(&length)) ) length = 0; type->Release(); } else length = 0; } const SectionContrib *contrib = ContribFromSectionOffset(section,offset); sInt objFile = 0; sInt sectionType = DIC_UNKNOWN; if(contrib) { objFile = contrib->ObjFile; sectionType = contrib->Type; } symbol->get_name(&name); // fill out structure sChar *nameStr = BStrToString( name, "<noname>", true); to.Symbols.push_back( DISymbol() ); DISymbol *outSym = &to.Symbols.back(); outSym->name = outSym->mangledName = to.MakeString(nameStr); outSym->objFileNum = objFile; outSym->VA = rva; outSym->Size = (sU32) length; outSym->Class = sectionType; outSym->NameSpNum = to.GetNameSpaceByName(nameStr); // clean up delete[] nameStr; if(name) SysFreeString(name); }
void PDBFileReader::ReadEverything(DebugInfo &to) { ULONG celt; Contribs = 0; nContribs = 0; DanglingLengthStart = 0; // read section table IDiaEnumTables *enumTables; if(Session->getEnumTables(&enumTables) == S_OK) { VARIANT vIndex; vIndex.vt = VT_BSTR; vIndex.bstrVal = SysAllocString(L"Sections"); IDiaTable *secTable; if(enumTables->Item(vIndex,&secTable) == S_OK) { LONG count; secTable->get_Count(&count); Contribs = new SectionContrib[count]; nContribs = 0; IDiaSectionContrib *item; while(SUCCEEDED(secTable->Next(1,(IUnknown **)&item,&celt)) && celt == 1) { SectionContrib &contrib = Contribs[nContribs++]; item->get_addressOffset(&contrib.Offset); item->get_addressSection(&contrib.Section); item->get_length(&contrib.Length); item->get_compilandId(&contrib.Compiland); item->get_execute(&contrib.CodeFlag); item->Release(); } secTable->Release(); } SysFreeString(vIndex.bstrVal); enumTables->Release(); } // enumerate symbols by (virtual) address IDiaEnumSymbolsByAddr *enumByAddr; if(SUCCEEDED(Session->getSymbolsByAddr(&enumByAddr))) { IDiaSymbol *symbol; // get first symbol to get first RVA (argh) if(SUCCEEDED(enumByAddr->symbolByAddr(1,0,&symbol))) { DWORD rva; if(symbol->get_relativeVirtualAddress(&rva) == S_OK) { symbol->Release(); // now, enumerate by rva. if(SUCCEEDED(enumByAddr->symbolByRVA(rva,&symbol))) { do { ProcessSymbol(symbol,to); symbol->Release(); if(FAILED(enumByAddr->Next(1,&symbol,&celt))) break; } while(celt == 1); } } else symbol->Release(); } enumByAddr->Release(); } // clean up delete[] Contribs; }
DDR_RC PdbScanner::addEnumMembers(IDiaSymbol *symbol, EnumUDT *enumUDT) { DDR_RC rc = DDR_RC_OK; /* All children symbols of a symbol for an Enum type should be * enum members. */ IDiaEnumSymbols *enumSymbols = NULL; HRESULT hr = symbol->findChildren(SymTagNull, NULL, nsNone, &enumSymbols); if (FAILED(hr)) { ERRMSG("findChildren() failed with HRESULT = %08lX", hr); rc = DDR_RC_ERROR; } if (DDR_RC_OK == rc) { vector<EnumMember *> *members = NULL; NamespaceUDT *outerUDT = enumUDT->_outerNamespace; /* literals of a nested anonymous enum are collected in the enclosing namespace */ if ((NULL != outerUDT) && enumUDT->isAnonymousType()) { members = &outerUDT->_enumMembers; } else { members = &enumUDT->_enumMembers; } set<string> memberNames; for (vector<EnumMember *>::iterator m = members->begin(); m != members->end(); ++m) { memberNames.insert((*m)->_name); } IDiaSymbol *childSymbol = NULL; ULONG celt = 0; LONG count = 0; enumSymbols->get_Count(&count); members->reserve(count); while (SUCCEEDED(enumSymbols->Next(1, &childSymbol, &celt)) && (1 == celt) && (DDR_RC_OK == rc) ) { string name = ""; int value = 0; rc = getName(childSymbol, &name); if (DDR_RC_OK == rc) { VARIANT variantValue; variantValue.vt = VT_EMPTY; hr = childSymbol->get_value(&variantValue); if (FAILED(hr)) { ERRMSG("get_value() failed with HRESULT = %08lX", hr); rc = DDR_RC_ERROR; } else { switch (variantValue.vt) { case VT_I1: value = variantValue.cVal; break; case VT_I2: value = variantValue.iVal; break; case VT_I4: value = (int)variantValue.lVal; break; case VT_UI1: value = variantValue.bVal; break; case VT_UI2: value = variantValue.uiVal; break; case VT_UI4: value = (int)variantValue.ulVal; break; case VT_INT: value = variantValue.intVal; break; case VT_UINT: value = (int)variantValue.uintVal; break; default: ERRMSG("get_value() unexpected variant: 0x%02X", variantValue.vt); rc = DDR_RC_ERROR; break; } } } if (DDR_RC_OK == rc) { if (memberNames.end() == memberNames.find(name)) { EnumMember *enumMember = new EnumMember; enumMember->_name = name; enumMember->_value = value; members->push_back(enumMember); memberNames.insert(name); } } childSymbol->Release(); } enumSymbols->Release(); } return rc; }
DDR_RC PdbScanner::setType(IDiaSymbol *symbol, Type **type, Modifiers *modifiers, NamespaceUDT *outerUDT) { DDR_RC rc = DDR_RC_OK; /* Get all type information, such as type and modifiers, for abort * field symbol. */ IDiaSymbol *typeSymbol = NULL; HRESULT hr = symbol->get_type(&typeSymbol); if (FAILED(hr)) { ERRMSG("get_type failed with HRESULT = %08lX", hr); rc = DDR_RC_ERROR; } if (DDR_RC_OK == rc) { rc = setTypeModifier(typeSymbol, modifiers); } DWORD symTag = 0; if (DDR_RC_OK == rc) { hr = typeSymbol->get_symTag(&symTag); if (FAILED(hr)) { ERRMSG("get_symTag failed with HRESULT = %08lX", hr); rc = DDR_RC_ERROR; } } if (DDR_RC_OK == rc) { switch (symTag) { case SymTagEnum: case SymTagUDT: rc = setTypeUDT(typeSymbol, type, outerUDT); break; case SymTagArrayType: { DWORD size = 0; if (FAILED(typeSymbol->get_count(&size))) { ERRMSG("Failed to get array dimensions."); rc = DDR_RC_ERROR; } else { modifiers->addArrayDimension(size); rc = setType(typeSymbol, type, modifiers, outerUDT); } break; } case SymTagPointerType: rc = setPointerType(symbol, modifiers); if (DDR_RC_OK == rc) { rc = setType(typeSymbol, type, modifiers, outerUDT); } break; case SymTagBaseType: rc = setBaseType(typeSymbol, type); break; case SymTagFunctionType: *type = getType("void"); break; default: ERRMSG("unknown symtag: %lu", symTag); rc = DDR_RC_ERROR; break; } } if (NULL != typeSymbol) { typeSymbol->Release(); } return rc; }
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 CTypeInfos::GetType(IDiaSymbol* pSymbol, BOOL bBaseType ) { BOOL bRet; HRESULT hResult; IDiaSymbol* pBaseType; DWORD dwTag=SymTagNull; // until a name is found try to get name if (!this->Name) { BSTR Name=NULL; pSymbol->get_name(&Name); if (Name) { #if (defined(UNICODE)||defined(_UNICODE)) this->Name=_tcsdup(Name); #else CAnsiUnicodeConvert::UnicodeToAnsi(Name,&this->Name); #endif SysFreeString(Name); } } else { if ( bBaseType && (!this->TypeName) ) { BSTR TypeName=NULL; pSymbol->get_name(&TypeName); if (TypeName) { #if (defined(UNICODE)||defined(_UNICODE)) this->TypeName=_tcsdup(TypeName); #else CAnsiUnicodeConvert::UnicodeToAnsi(TypeName,&this->TypeName); #endif SysFreeString(TypeName); } } } pSymbol->get_length(&this->Size); pSymbol->get_constType(&this->bConst); pSymbol->get_volatileType(&this->bVolatile); pSymbol->get_unalignedType(&this->bUnaligned); hResult=pSymbol->get_symTag(&dwTag); if(FAILED(hResult) || (dwTag==SymTagNull)) return FALSE; if (this->DataKind==SymTagNull) this->DataKind=dwTag; switch(dwTag) { case SymTagUDT: { BSTR UDTName; if (FAILED(pSymbol->get_udtKind(&this->UserDefineTypeKind))) return FALSE; pSymbol->get_name(&UDTName); WCHAR* wName; // don't put struct / enum / class keyword info to this->TypeName // keep only type name // wName =(WCHAR*) _alloca((wcslen(rgUdtKind[this->UserDefineTypeKind])+wcslen(UDTName)+2)*sizeof(WCHAR)); //swprintf(wName,L"%s %s",rgUdtKind[this->UserDefineTypeKind],UDTName); wName =(WCHAR*) _alloca((wcslen(UDTName)+1)*sizeof(WCHAR)); wcscpy(wName,UDTName); this->bUserDefineType=TRUE; #if (defined(UNICODE)||defined(_UNICODE)) this->TypeName=_tcsdup(wName); #else CAnsiUnicodeConvert::UnicodeToAnsi(wName,&this->TypeName); #endif SysFreeString(UDTName); } break; case SymTagEnum: this->bEnum=TRUE; break; case SymTagFunctionType: this->bFunction=TRUE; break; case SymTagPointerType: pBaseType=0; pSymbol->get_reference(&this->bRefPointer); hResult=pSymbol->get_type(&pBaseType); if(FAILED(hResult) || (pBaseType==0)) return FALSE; bRet=this->GetType(pBaseType,TRUE); this->PointerLevel++; pBaseType->Release(); if (!bRet) return FALSE; break; case SymTagArrayType: pBaseType=0; hResult=pSymbol->get_type(&pBaseType); if(FAILED(hResult) || (pBaseType==0)) return FALSE; // simplify , don't get array length (sized provided for local vars) this->PointerLevel++; bRet=this->GetType(pBaseType,TRUE); pBaseType->Release(); if (!bRet) return FALSE; break; case SymTagBaseType: { WCHAR wsType[MAX_PATH]; ULONGLONG ulLen; pSymbol->get_length(&ulLen); // ukLen may differ from this->Size (if pointer or other type) *wsType=0; if(FAILED(pSymbol->get_baseType(&this->BaseType))) return FALSE; switch(this->BaseType) { case btUInt : wcscpy(wsType,L"unsigned "); // don't break btUInt to Fall through btInt case btInt : switch(ulLen) { case 1: wcscat(wsType,L"char"); break; case 2: wcscat(wsType,L"short"); break; case 4: wcscat(wsType,L"int"); break; case 8: wcscat(wsType,L"int64"); break; } break; case btFloat : switch(ulLen) { case 4: wcscpy(wsType,L"float"); break; case 8: wcscpy(wsType,L"double"); break; } break; } // if type not filled if(*wsType==0) // get the one defined by array wcscpy(wsType,rgBaseType[this->BaseType]); #if (defined(UNICODE)||defined(_UNICODE)) this->TypeName=_tcsdup(wsType); #else CAnsiUnicodeConvert::UnicodeToAnsi(wsType,&this->TypeName); #endif } break; case SymTagCustomType: break; case SymTagData: pBaseType=0; hResult=pSymbol->get_type(&pBaseType); if(FAILED(hResult) || (pBaseType==0)) return FALSE; // no information : can appear for local type (static can be name of local vars. Debug infos ???) bRet=this->GetType(pBaseType,TRUE); pBaseType->Release(); if (!bRet) return FALSE; break; case SymTagUsingNamespace: break; case SymTagTypedef: // should not appear break; default: #ifdef _DEBUG if (IsDebuggerPresent()) DebugBreak(); #endif break; } return TRUE; }
void PDBFileReader::ReadEverything(DebugInfo &to) { ULONG celt; Contribs = 0; nContribs = 0; // read section table IDiaEnumTables *enumTables; if(Session->getEnumTables(&enumTables) == S_OK) { VARIANT vIndex; vIndex.vt = VT_BSTR; vIndex.bstrVal = SysAllocString(L"Sections"); IDiaTable *secTable; if(enumTables->Item(vIndex,&secTable) == S_OK) { LONG count; secTable->get_Count(&count); Contribs = new SectionContrib[count]; nContribs = 0; IDiaSectionContrib *item; while(SUCCEEDED(secTable->Next(1,(IUnknown **)&item,&celt)) && celt == 1) { SectionContrib &contrib = Contribs[nContribs++]; item->get_addressOffset(&contrib.Offset); item->get_addressSection(&contrib.Section); item->get_length(&contrib.Length); item->get_compilandId(&contrib.Compiland); BOOL code=FALSE,initData=FALSE,uninitData=FALSE; item->get_code(&code); item->get_initializedData(&initData); item->get_uninitializedData(&uninitData); if(code && !initData && !uninitData) contrib.Type = DIC_CODE; else if(!code && initData && !uninitData) contrib.Type = DIC_DATA; else if(!code && !initData && uninitData) contrib.Type = DIC_BSS; else contrib.Type = DIC_UNKNOWN; BSTR objFileName = 0; IDiaSymbol *compiland = 0; item->get_compiland(&compiland); if(compiland) { compiland->get_name(&objFileName); compiland->Release(); } sChar *objFileStr = BStrToString(objFileName,"<noobjfile>"); contrib.ObjFile = to.GetFileByName(objFileStr); delete[] objFileStr; if(objFileName) SysFreeString(objFileName); item->Release(); } secTable->Release(); } SysFreeString(vIndex.bstrVal); enumTables->Release(); } // enumerate symbols by (virtual) address IDiaEnumSymbolsByAddr *enumByAddr; if(SUCCEEDED(Session->getSymbolsByAddr(&enumByAddr))) { IDiaSymbol *symbol; // get first symbol to get first RVA (argh) if(SUCCEEDED(enumByAddr->symbolByAddr(1,0,&symbol))) { DWORD rva; if(symbol->get_relativeVirtualAddress(&rva) == S_OK) { symbol->Release(); // now, enumerate by rva. if(SUCCEEDED(enumByAddr->symbolByRVA(rva,&symbol))) { do { ProcessSymbol(symbol,to); symbol->Release(); if(FAILED(enumByAddr->Next(1,&symbol,&celt))) break; } while(celt == 1); } } else symbol->Release(); } enumByAddr->Release(); } // clean up delete[] Contribs; }
HRESULT SymBase::GetInfoTable( SymbolInfoTable &InfoTable ) { HRESULT hr; ULONG SymULONG; LPCWSTR SymStr; BSTR SymBStr; BOOL SymBOOL; IDiaSymbol *SymSymbol; IDiaEnumSymbols *SymEnum; BOOL TableRet; CString Tmp; // // Children // hr = Self()->findChildren(SymTagNull, NULL, nsNone, &SymEnum); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_CHILDREN, BOOL_STR(SymEnum != NULL)); VERIFY_EXP(TableRet); SymEnum->Release(); } // // access // hr = Self()->get_access(&SymULONG); if (HR_OK(hr)) { SymStr = GetAccessStr(SymULONG); TableRet = InfoTable.Add(SYMBOL_ACCESS, SymStr); VERIFY_EXP(TableRet); } // // addressOffset // hr = Self()->get_addressOffset(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_ADDRESSOFFSET, Tmp); VERIFY_EXP(TableRet); } // // addressSection // hr = Self()->get_addressSection(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_ADDRESSSECTION, Tmp); VERIFY_EXP(TableRet); } // // addressTaken // hr = Self()->get_addressTaken(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ADDRESSTAKEN, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // age // hr = Self()->get_age(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_AGE, Tmp); VERIFY_EXP(TableRet); } // // arrayIndexType // hr = Self()->get_arrayIndexType(&SymSymbol); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ARRAYINDEXTYPE, BOOL_STR(SymSymbol != NULL)); VERIFY_EXP(TableRet); SymSymbol->Release(); } // // arrayIndexTypeId // hr = Self()->get_arrayIndexTypeId(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_ARRAYINDEXTYPEID, Tmp); VERIFY_EXP(TableRet); } // // backEndMajor (Not implement) // // // backEndMinor (Not implement) // // // backEndBuild (Not implement) // // // baseType // hr = Self()->get_baseType(&SymULONG); if (HR_OK(hr)) { SymStr = GetBaseTypeStr(SymULONG, 0); TableRet = InfoTable.Add(SYMBOL_BASETYPE, SymStr); VERIFY_EXP(TableRet); } // // bitPosition // hr = Self()->get_bitPosition(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_BITPOSITION, Tmp); VERIFY_EXP(TableRet); } // // callingConvention // hr = Self()->get_callingConvention(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_CALLINGCONVENTION, GetCallingConventionStr(SymULONG)); VERIFY_EXP(TableRet); } // // classParent // hr = Self()->get_classParent(&SymSymbol); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_CLASSPARENT, BOOL_STR(SymSymbol != NULL)); VERIFY_EXP(TableRet); SymSymbol->Release(); } // // classParentId // hr = Self()->get_classParentId(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_CLASSPARENTID, Tmp); VERIFY_EXP(TableRet); } // // code // hr = Self()->get_code(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_CODE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // compilerGenerated // hr = Self()->get_compilerGenerated(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_COMPILERGENERATED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // compilerName // hr = Self()->get_compilerName(&SymBStr); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_COMPILERNAME, SymBStr); VERIFY_EXP(TableRet); } // // constructor // hr = Self()->get_constructor(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_CONSTRUCTOR, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // container // hr = Self()->get_container(&SymSymbol); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_CONTAINER, BOOL_STR(SymSymbol != NULL)); VERIFY_EXP(TableRet); SymSymbol->Release(); } // // constType // hr = Self()->get_constType(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_CONSTTYPE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // count // hr = Self()->get_count(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_COUNT, Tmp); VERIFY_EXP(TableRet); } // // customCallingConvention // hr = Self()->get_customCallingConvention(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_CUSTOMCALLINGCONVENTION, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // dataBytes (Not implement) // // // dataKind // hr = Self()->get_dataKind(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_DATAKIND, GetDataKindStr(SymULONG)); VERIFY_EXP(TableRet); } // // editAndContinueEnabled // hr = Self()->get_editAndContinueEnabled(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_EDITANDCONTINUEENABLED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // farReturn // hr = Self()->get_farReturn(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_FARRETURN, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // frontEndMajor (Not implement) // // // frontEndMinor (Not implement) // // // frontEndBuild (Not implement) // // // function // hr = Self()->get_function(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_FARRETURN, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // guid // GUID SymGuid; hr = Self()->get_guid(&SymGuid); if (HR_OK(hr)) { Tmp.Format(L"{%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X} ", SymGuid.Data1, SymGuid.Data2, SymGuid.Data3, SymGuid.Data4[0], SymGuid.Data4[1], SymGuid.Data4[2], SymGuid.Data4[3], SymGuid.Data4[4], SymGuid.Data4[5], SymGuid.Data4[6], SymGuid.Data4[7]); TableRet = InfoTable.Add(SYMBOL_GUID, Tmp); VERIFY_EXP(TableRet); } // // hasAlloca // hr = Self()->get_hasAlloca(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASALLOCA, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasAssignmentOperator // hr = Self()->get_hasAssignmentOperator(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASASSIGNMENTOPERATOR, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasCastOperator // hr = Self()->get_hasCastOperator(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASCASTOPERATOR, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasDebugInfo // hr = Self()->get_hasDebugInfo(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASDEBUGINFO, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasEH // hr = Self()->get_hasEH(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASEH, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasEHa // hr = Self()->get_hasEHa(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASEHA, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasInlAsm // hr = Self()->get_hasInlAsm(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASINLASM, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasLongJump // hr = Self()->get_hasLongJump(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASLONGJUMP, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasManagedCode // hr = Self()->get_hasManagedCode(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASMANAGEDCODE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasNestedTypes // hr = Self()->get_hasNestedTypes(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASNESTEDTYPES, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasSecurityChecks // hr = Self()->get_hasSecurityChecks(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASSECURITYCHECKS, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasSEH // hr = Self()->get_hasSEH(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASSEH, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // hasSetJump // hr = Self()->get_hasSetJump(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_HASSETJUMP, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // indirectVirtualBaseClass // hr = Self()->get_indirectVirtualBaseClass(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_INDIRECTVIRTUALBASECLASS, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // inlSpec // hr = Self()->get_inlSpec(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_INLSPEC, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // interruptReturn // hr = Self()->get_interruptReturn(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_INTERRUPTRETURN, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // intro // hr = Self()->get_intro(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_INTRO, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isAggregated // hr = Self()->get_isAggregated(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISAGGREGATED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isCTypes // hr = Self()->get_isCTypes(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISCTYPES, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isCVTCIL // hr = Self()->get_isCVTCIL(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISCVTCIL, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isDataAligned // hr = Self()->get_isDataAligned(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISDATAALIGNED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isHotpatchable // hr = Self()->get_isHotpatchable(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISHOTPATCHABLE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isLTCG // hr = Self()->get_isLTCG(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISLTCG, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isMSILNetmodule // hr = Self()->get_isMSILNetmodule(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISMSILNETMODULE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isNaked // hr = Self()->get_isNaked(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISNAKED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isSplitted // hr = Self()->get_isSplitted(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISSPLITTED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isStatic // hr = Self()->get_isStatic(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISSTATIC, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // isStripped // hr = Self()->get_isStripped(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_ISSTRIPPED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // language // hr = Self()->get_language(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_LANGUAGE, GetLanguageStr(SymULONG)); VERIFY_EXP(TableRet); } // // length // ULONGLONG SymULONGLONG; hr = Self()->get_length(&SymULONGLONG); if (HR_OK(hr)) { Tmp.Format(L"%0.16I64X", SymULONGLONG); TableRet = InfoTable.Add(SYMBOL_LENGTH, Tmp); VERIFY_EXP(TableRet); } // // lexicalParent // hr = Self()->get_lexicalParent(&SymSymbol); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_LEXICALPARENT, BOOL_STR(SymSymbol != NULL)); VERIFY_EXP(TableRet); SymSymbol->Release(); } // // lexicalParentId // hr = Self()->get_lexicalParentId(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_LEXICALPARENTID, Tmp); VERIFY_EXP(TableRet); } // // libraryName // hr = Self()->get_libraryName(&SymBStr); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_LIBRARYNAME, SymBStr); VERIFY_EXP(TableRet); } // // liveLVarInstances (Not implement) // // // locationType // hr = Self()->get_locationType(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_LOCATIONTYPE, GetLocationTypeStr(SymULONG)); VERIFY_EXP(TableRet); } // // lowerBound (Not implement) // // // lowerBoundId (Not implement) // // // machineType // hr = Self()->get_machineType(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_MACHINETYPE, GetMachineTypeStr(SymULONG)); VERIFY_EXP(TableRet); } // // managed // hr = Self()->get_managed(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_MANAGED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // msil // hr = Self()->get_msil(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_MSIL, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // name // hr = Self()->get_name(&SymBStr); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_NAME, SymBStr); VERIFY_EXP(TableRet); } // // nested // hr = Self()->get_nested(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_NESTED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // noInline // hr = Self()->get_noInline(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_NOINLINE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // noReturn // hr = Self()->get_noReturn(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_NORETURN, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // noStackOrdering // hr = Self()->get_noStackOrdering(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_NOSTACKORDERING, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // notReached // hr = Self()->get_notReached(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_NOTREACHED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // objectPointerType // hr = Self()->get_objectPointerType(&SymSymbol); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_OBJECTPOINTERTYPE, BOOL_STR(SymSymbol != NULL)); VERIFY_EXP(TableRet); SymSymbol->Release(); } // // oemId // hr = Self()->get_oemId(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_OEMID, Tmp); VERIFY_EXP(TableRet); } // // oemSymbolId // hr = Self()->get_oemSymbolId(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_OEMSYMBOLID, Tmp); VERIFY_EXP(TableRet); } // // offset // LONG SymLONG; hr = Self()->get_offset(&SymLONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymLONG); TableRet = InfoTable.Add(SYMBOL_OFFSET, Tmp); VERIFY_EXP(TableRet); } // // optimizedCodeDebugInfo // hr = Self()->get_optimizedCodeDebugInfo(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_OPTIMIZEDCODEDEBUGINFO, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // overloadedOperator // hr = Self()->get_overloadedOperator(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_OVERLOADEDOPERATOR, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // packed // hr = Self()->get_packed(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_PACKED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // platform // hr = Self()->get_platform(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_OEMSYMBOLID, GetMachineTypeStr(SymULONG)); VERIFY_EXP(TableRet); } // // pure // hr = Self()->get_pure(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_PURE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // rank (Not implement) // // // reference // hr = Self()->get_reference(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_REFERENCE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // registerId // hr = Self()->get_platform(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_REGISTERID, GetMachineTypeStr(SymULONG)); VERIFY_EXP(TableRet); } // // relativeVirtualAddress // hr = Self()->get_platform(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_RELATIVEVIRTUALADDRESS, GetMachineTypeStr(SymULONG)); VERIFY_EXP(TableRet); } // // scoped // hr = Self()->get_scoped(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_SCOPED, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // signature // hr = Self()->get_signature(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_SIGNATURE, Tmp); VERIFY_EXP(TableRet); } // // slot // hr = Self()->get_slot(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_SLOT, Tmp); VERIFY_EXP(TableRet); } // // sourceFileName // hr = Self()->get_sourceFileName(&SymBStr); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_SOURCEFILENAME, SymBStr); VERIFY_EXP(TableRet); } // // symbolsFileName // hr = Self()->get_symbolsFileName(&SymBStr); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_SYMBOLSFILENAME, SymBStr); VERIFY_EXP(TableRet); } // // symIndexId // hr = Self()->get_symIndexId(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_SYMINDEXID, Tmp); VERIFY_EXP(TableRet); } // // symTag // hr = Self()->get_symTag(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_SYMTAG, GetSymTagStr(SymULONG)); VERIFY_EXP(TableRet); } // // targetOffset // hr = Self()->get_targetOffset(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_SYMINDEXID, Tmp); VERIFY_EXP(TableRet); } // // targetRelativeVirtualAddress // hr = Self()->get_targetRelativeVirtualAddress(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_TARGETRELATIVEVIRTUALADDRESS, Tmp); VERIFY_EXP(TableRet); } // // targetSection // hr = Self()->get_targetSection(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_TARGETSECTION, Tmp); VERIFY_EXP(TableRet); } // // targetVirtualAddress // hr = Self()->get_targetVirtualAddress(&SymULONGLONG); if (HR_OK(hr)) { Tmp.Format(L"%0.16I64X", SymULONGLONG); TableRet = InfoTable.Add(SYMBOL_TARGETVIRTUALADDRESS, Tmp); VERIFY_EXP(TableRet); } // // thisAdjust // hr = Self()->get_thisAdjust(&SymLONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymLONG); TableRet = InfoTable.Add(SYMBOL_THISADJUST, Tmp); VERIFY_EXP(TableRet); } // // thunkOrdinal // hr = Self()->get_thunkOrdinal(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_THISADJUST, Tmp); VERIFY_EXP(TableRet); } // // timeStamp // hr = Self()->get_timeStamp(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_TIMESTAMP, Tmp); VERIFY_EXP(TableRet); } // // token // hr = Self()->get_token(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_TOKEN, Tmp); VERIFY_EXP(TableRet); } // // type // hr = Self()->get_type(&SymSymbol); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_TYPE, BOOL_STR(SymSymbol != NULL)); VERIFY_EXP(TableRet); SymSymbol->Release(); } // // typeId // hr = Self()->get_typeId(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_TYPEID, Tmp); VERIFY_EXP(TableRet); } // // types (Not implement) // // // typeIds (Not implement) // // // udtKind // hr = Self()->get_udtKind(&SymULONG); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_UDTKIND, GetUdtKindStr(SymULONG)); VERIFY_EXP(TableRet); } // // unalignedType // hr = Self()->get_unalignedType(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_UNALIGNEDTYPE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // undecoratedName // hr = Self()->get_undecoratedName(&SymBStr); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_UNDECORATEDNAME, SymBStr); VERIFY_EXP(TableRet); } // // undecoratedNameEx (Not implement) // // // upperBound (Not implement) // // // upperBoundId (Not implement) // // // value // VARIANT SymVar; SymVar.vt = VT_EMPTY; hr = Self()->get_value(&SymVar); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_VALUE, L"TRUE"); VERIFY_EXP(TableRet); } // // virtual // hr = Self()->get_virtual(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_VIRTUAL, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // virtualAddress // hr = Self()->get_virtualAddress(&SymULONGLONG); if (HR_OK(hr)) { Tmp.Format(L"%0.16I64X", SymULONGLONG); TableRet = InfoTable.Add(SYMBOL_VIRTUALADDRESS, Tmp); VERIFY_EXP(TableRet); } // // virtualBaseClass // hr = Self()->get_virtualBaseClass(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_VIRTUALBASECLASS, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } // // virtualBaseDispIndex // hr = Self()->get_virtualBaseDispIndex(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_VIRTUALBASEDISPINDEX, Tmp); VERIFY_EXP(TableRet); } // // virtualBaseOffset // hr = Self()->get_virtualBaseOffset(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_VIRTUALBASEOFFSET, Tmp); VERIFY_EXP(TableRet); } // // virtualBasePointerOffset // hr = Self()->get_virtualBasePointerOffset(&SymLONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymLONG); TableRet = InfoTable.Add(SYMBOL_VIRTUALBASEPOINTEROFFSET, Tmp); VERIFY_EXP(TableRet); } // // virtualBaseTableType // hr = Self()->get_virtualBaseTableType(&SymSymbol); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_VIRTUALBASETABLETYPE, BOOL_STR(SymSymbol != NULL)); VERIFY_EXP(TableRet); SymSymbol->Release(); } // // virtualTableShape // hr = Self()->get_virtualTableShape(&SymSymbol); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_VIRTUALTABLESHAPE, BOOL_STR(SymSymbol != NULL)); VERIFY_EXP(TableRet); SymSymbol->Release(); } // // virtualTableShapeId // hr = Self()->get_virtualTableShapeId(&SymULONG); if (HR_OK(hr)) { Tmp.Format(L"%08X", SymULONG); TableRet = InfoTable.Add(SYMBOL_VIRTUALTABLESHAPEID, Tmp); VERIFY_EXP(TableRet); } // // volatileType // hr = Self()->get_volatileType(&SymBOOL); if (HR_OK(hr)) { TableRet = InfoTable.Add(SYMBOL_VOLATILETYPE, BOOL_STR(SymBOOL)); VERIFY_EXP(TableRet); } #ifdef DEBUG_PRINT DisplayInfo(InfoTable); #endif return S_OK; }
//------------------------------------------------------------------------ // pParentSymbol 에서 자식중에 symbolName 인 심볼을 리턴한다. // 찾은 심볼의 Offset값을 리턴한다. // pParentSymbol 은 Data, UDT, TypeDef 타입이어야 한다. //------------------------------------------------------------------------ IDiaSymbol* dia::FindChildSymbol( const std::string &symbolName, IDiaSymbol *pParentSymbol, OUT LONG *pOffset ) // pOffset =NULL { RETV( !pParentSymbol, NULL ); const string name = GetSymbolName(pParentSymbol); //debug용 const wstring searchSymbolName = memmonitor::str2wstr(symbolName).c_str(); // 데이타 심볼이면, 타입 심볼로 교체한다. enum SymTagEnum symTag; HRESULT hr = pParentSymbol->get_symTag((DWORD*)&symTag); bool isNewTypeSymbol = false; IDiaSymbol* pTypeSymbol = NULL; switch (symTag) { case SymTagData: isNewTypeSymbol = true; hr = pParentSymbol->get_type(&pTypeSymbol); break; case SymTagTypedef: { hr = pParentSymbol->get_type(&pTypeSymbol); IDiaSymbol *reval = FindChildSymbol(symbolName, pTypeSymbol, pOffset); if (pTypeSymbol) pTypeSymbol->Release(); return reval; } break; default: { pTypeSymbol = pParentSymbol; } break; } // Enumeration CComPtr<IDiaEnumSymbols> pEnumSymbols; if (FAILED(pTypeSymbol->findChildren(SymTagNull, searchSymbolName.c_str(), nsRegularExpression, &pEnumSymbols))) { if (isNewTypeSymbol) pTypeSymbol->Release(); return NULL; } IDiaSymbol *pFindSymbol; ULONG celt = 0; pEnumSymbols->Next(1, &pFindSymbol, &celt); // 찾았다면 리턴 if (1 == celt) { if (isNewTypeSymbol) pTypeSymbol->Release(); if (pOffset) hr = pFindSymbol->get_offset(pOffset); return pFindSymbol; } // 못찾았다면, 자식 중에서 찾아본다. enum 으로 선언된 값은 이렇게 찾아야함 CComPtr<IDiaEnumSymbols> pAnotherEnumSymbols; if (FAILED(pTypeSymbol->findChildren(SymTagNull, NULL, nsNone, &pAnotherEnumSymbols))) { if (isNewTypeSymbol) pTypeSymbol->Release(); return NULL; } pFindSymbol = NULL; IDiaSymbol* pChildSymbol; celt = 0; while (SUCCEEDED(pAnotherEnumSymbols->Next(1, &pChildSymbol, &celt)) && (celt == 1)) { enum SymTagEnum symTag; pChildSymbol->get_symTag((DWORD*)&symTag); if (SymTagBaseClass == symTag) { LONG childOffset = 0; pFindSymbol = FindChildSymbol( symbolName, pChildSymbol, &childOffset ); if (pFindSymbol) { LONG baseClassOffset = 0; hr = pChildSymbol->get_offset(&baseClassOffset); if (pOffset) *pOffset = baseClassOffset + childOffset; break; } } if (SymTagEnum != symTag) { pChildSymbol->Release(); continue; } CComPtr<IDiaEnumSymbols> pSubEnumSymbols; if (FAILED(pChildSymbol->findChildren(SymTagNull, searchSymbolName.c_str(), nsRegularExpression, &pSubEnumSymbols))) { pChildSymbol->Release(); continue; } celt = 0; pSubEnumSymbols->Next( 1, &pFindSymbol, &celt ); if (1 == celt) { pChildSymbol->Release(); const string name = GetSymbolName(pFindSymbol); //debug용 if (pOffset) *pOffset = 0; // 상수값은 offset이 없다. break; // 찾았으니 종료 } } if (isNewTypeSymbol) pTypeSymbol->Release(); return pFindSymbol; }
//----------------------------------------------------------------------------- // Name: ParseModules // Object: parse all compilands // Parameters : // in : // out : // return : TRUE on success //----------------------------------------------------------------------------- BOOL CDebugInfos::ParseModules() { HRESULT hr; IDiaEnumSymbols* pEnumSymbols; IDiaEnumSymbols* pEnumChildren; IDiaSymbol* pCompiland; IDiaSymbol* pSymbol; ULONG celt = 0; CModuleInfos* pModuleInfo; BSTR Name; // Retrieve the compilands first if(FAILED(this->pDiaGlobalSymbol->findChildren(SymTagCompiland, NULL, nsNone, &pEnumSymbols))) return FALSE; // for each compiland while(pEnumSymbols->Next(1, &pCompiland, &celt) == S_OK && celt == 1) { // Retrieve the name of the module Name=NULL; pCompiland->get_name(&Name); #if (REMOVE_LINKER_COMPILAND==1) // avoid to display "* Linker *" infos if (Name) { if (wcsicmp(Name,LINKER_COMPILAND_NAME)==0) { SysFreeString(Name); pCompiland->Release(); continue; } } #endif // create module info pModuleInfo=new CModuleInfos(); // add it to modules list this->pLinkListModules->AddItem(pModuleInfo); // assume module name is set if (Name) { #if (defined(UNICODE)||defined(_UNICODE)) pModuleInfo->Name=_tcsdup(Name); #else CAnsiUnicodeConvert::UnicodeToAnsi(Name,&pModuleInfo->Name); #endif SysFreeString(Name); } else pModuleInfo->Name=_tcsdup(_T("")); // Find all the symbols defined in this compiland and get their info if(SUCCEEDED(pCompiland->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) { ULONG celt_ = 0; while (pEnumChildren->Next(1, &pSymbol, &celt_) == S_OK && celt_ == 1) { hr=pModuleInfo->Parse(pSymbol); if (FAILED(hr)) this->ReportError(_T("Error parsing module information"),hr); pSymbol->Release(); } pEnumChildren->Release(); } pCompiland->Release(); } pEnumSymbols->Release(); return TRUE; }
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; }