//---------------------------------------------------------------------- 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; }
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? } }
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::addChildrenSymbols(IDiaSymbol *symbol, enum SymTagEnum symTag, NamespaceUDT *outerNamespace) { DDR_RC rc = DDR_RC_OK; IDiaEnumSymbols *classSymbols = NULL; /* Find children symbols. SymTagUDT covers struct, union, and class symbols. */ HRESULT hr = symbol->findChildren(symTag, NULL, nsNone, &classSymbols); if (FAILED(hr)) { ERRMSG("findChildren() failed with HRESULT = %08lX", hr); rc = DDR_RC_ERROR; } /* Allocate space for the children symbols. */ LONG count = 0; if (DDR_RC_OK == rc) { hr = classSymbols->get_Count(&count); if (FAILED(hr)) { ERRMSG("Failed to get count of children symbols with HRESULT = %08lX", hr); rc = DDR_RC_ERROR; } } IDiaSymbol **childSymbols = NULL; ULONG celt = 0; if ((DDR_RC_OK == rc) && (0 != count)) { childSymbols = new IDiaSymbol*[count]; hr = classSymbols->Next(count, childSymbols, &celt); if (FAILED(hr)) { ERRMSG("Failed to get children symbols with HRESULT = %08lX", hr); rc = DDR_RC_ERROR; } } /* Iterate the children symbols, adding them to the IR. * Inner symbols are first found with a decorated name and no * parent reference. Ignore these for now and add the outer * types first. */ vector<ULONG> innerTypeSymbols; if (DDR_RC_OK == rc) { bool alreadyHadFields = false; bool alreadyCheckedFields = false; bool alreadyHadSubtypes = false; if (NULL != outerNamespace) { alreadyHadSubtypes = !outerNamespace->_subUDTs.empty(); } for (ULONG index = 0; index < celt; ++index) { string udtName = ""; DWORD childTag = 0; hr = childSymbols[index]->get_symTag(&childTag); if (FAILED(hr)) { ERRMSG("Failed to get child symbol SymTag with HRESULT = %08lX", hr); rc = DDR_RC_ERROR; } if ((DDR_RC_OK == rc) && ((SymTagEnum == childTag) || (SymTagUDT == childTag))) { rc = getName(childSymbols[index], &udtName); } if (DDR_RC_OK == rc) { if ((NULL == outerNamespace) || (string::npos == udtName.find("::"))) { /* When adding fields/subtypes to a type, only add fields to a type with no fields * and only add subtypes to a type with no subtypes. This avoids adding duplicates * fields/subtypes when scanning multiple files. Children symbols must be processed * for already existing symbols because fields and subtypes can appear separately. */ if (!alreadyCheckedFields && (SymTagData == childTag)) { alreadyCheckedFields = true; alreadyHadFields = !((ClassType *)outerNamespace)->_fieldMembers.empty(); } if (!((SymTagData == childTag) ? alreadyHadFields : alreadyHadSubtypes)) { rc = addSymbol(childSymbols[index], outerNamespace); } childSymbols[index]->Release(); } else { innerTypeSymbols.push_back(index); } } if (DDR_RC_OK != rc) { break; } } } /* Iterate the inner types. Only namespaces will be added to the IR * here, since they have no associated symbol. */ if (DDR_RC_OK == rc) { for (vector<ULONG>::iterator it = innerTypeSymbols.begin(); it != innerTypeSymbols.end() && DDR_RC_OK == rc; ++it) { rc = addSymbol(childSymbols[*it], outerNamespace); childSymbols[*it]->Release(); } } if (NULL != childSymbols) { delete childSymbols; } if (NULL != classSymbols) { classSymbols->Release(); } return rc; }
//----------------------------------------------------------------------------- // 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; }