Пример #1
0
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;
}
Пример #2
0
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;
}