//------------------------------------------------------------------------ // pSymbol의 데이타 길이를 리턴한다. //------------------------------------------------------------------------ ULONGLONG dia::GetSymbolLength(IDiaSymbol *pSymbol) { ULONGLONG len = 0; SymbolState state; IDiaSymbol *pTypeSymbol = GetBaseTypeSymbol(pSymbol, 1, state); if (!pTypeSymbol) return 0; enum SymTagEnum symTag; HRESULT hr = pTypeSymbol->get_symTag((DWORD*)&symTag); switch (symTag) { case SymTagPointerType: case SymTagArrayType: { IDiaSymbol *pBaseType; hr = pTypeSymbol->get_type(&pBaseType); if (NEW_SYMBOL == state) SAFE_RELEASE(pTypeSymbol); pTypeSymbol = pBaseType; } break; } hr = pTypeSymbol->get_length(&len); if (NEW_SYMBOL == state) SAFE_RELEASE(pTypeSymbol); return len; }
//------------------------------------------------------------------------ // 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; }
//------------------------------------------------------------------------ // //------------------------------------------------------------------------ IDiaSymbol* dia::FindType(const std::string &typeName) { RETV(!m_pGlobalSymbol, NULL); CComPtr<IDiaEnumSymbols> pEnumSymbols; if (FAILED(m_pGlobalSymbol->findChildren(SymTagNull, memmonitor::str2wstr(typeName).c_str(), nsRegularExpression, &pEnumSymbols))) return NULL; std::list<IDiaSymbol *> childSymbols; IDiaSymbol *pSymbol = NULL; ULONG celt = 0; // 첫번째로 발견되는 정보만 찾아서 리턴한다. while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { childSymbols.push_back(pSymbol); enum SymTagEnum symTag; HRESULT hr = pSymbol->get_symTag((DWORD*)&symTag); if (SymTagData == symTag || SymTagUDT == symTag) break; } if (childSymbols.empty()) return NULL; // SymTagEnum 값이 SymTagData 이거나 SymTagUDT 을 먼저 선택하도록 한다. // 가장 나중에 추가된 것을 제외하고 나머지는 제거한다. while (childSymbols.size() > 1) { childSymbols.front()->Release(); childSymbols.pop_front(); } return childSymbols.back(); }
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; }
//------------------------------------------------------------------------ // 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; }