@@ -695,9 +695,9 @@ void MicrosoftRTTIProcessor::ProcessRTTI()
695695
696696void MicrosoftRTTIProcessor::ProcessVFT ()
697697{
698- auto bgTask = new BackgroundTask (" Scanning for Microsoft RTTI ..." , true );
698+ auto bgTask = new BackgroundTask (" Scanning for Microsoft VFT ..." , true );
699699 std::map<uint64_t , uint64_t > vftMap = {};
700- std::map <uint64_t , std::optional<VirtualFunctionTableInfo>> vftFinishedMap = {};
700+ std::unordered_set <uint64_t > vftFinished = {};
701701 auto start_time = std::chrono::high_resolution_clock::now ();
702702 for (auto &[coLocatorAddr, classInfo]: m_classInfo)
703703 {
@@ -749,20 +749,34 @@ void MicrosoftRTTIProcessor::ProcessVFT()
749749 }
750750 }
751751
752- auto GetCachedVFTInfo = [&](uint64_t vftAddr, ClassInfo& classInfo) -> std::optional<VirtualFunctionTableInfo> {
753- // Check in the cache so that we don't process vfts more than once.
754- auto cachedVftInfo = vftFinishedMap.find (vftAddr);
755- if (cachedVftInfo != vftFinishedMap.end ())
756- return cachedVftInfo->second ;
752+ std::function<void (uint64_t )> processClassAndBases = [&](uint64_t coLocatorAddr) -> void {
753+ auto & classInfo = m_classInfo[coLocatorAddr];
754+ uint64_t vftAddr = vftMap[coLocatorAddr];
755+ if (vftFinished.find (vftAddr) != vftFinished.end () || classInfo.vft .has_value ())
756+ return ;
757+
758+ // Process all relevant base classes first.
759+ // Otherwise, when we process this class we won't have the base vft available if needed.
760+ for (auto & baseInfo : classInfo.baseClasses )
761+ {
762+ for (auto & [baseCoLocAddr, baseClassInfo] : m_classInfo)
763+ {
764+ if (baseClassInfo.className != baseInfo.className )
765+ continue ;
766+ processClassAndBases (baseCoLocAddr);
767+ // TODO: We might want to return the vft from processClassAndBases instead of doing this.
768+ baseInfo.vft = m_classInfo[baseCoLocAddr].vft ;
769+ }
770+ }
771+
772+ // Process the vtable for the current class.
773+ // By this point all base classes should already exist, along with their type.
757774
758775 // Get the appropriate base class if there is one by reading the colocator.
759- BinaryReader reader = BinaryReader (m_view);
760- reader.Seek (vftAddr - m_view->GetAddressSize ());
761- auto coLocatorAddr = reader.ReadPointer ();
762776 auto coLocator = ReadCompleteObjectorLocator (m_view, coLocatorAddr);
763777 // TODO: This should always be valid!
764778 if (!coLocator.has_value ())
765- return std:: nullopt ;
779+ return ;
766780
767781 std::optional<BaseClassInfo> baseClassInfo;
768782 for (const auto & base: classInfo.baseClasses )
@@ -775,45 +789,20 @@ void MicrosoftRTTIProcessor::ProcessVFT()
775789 }
776790 }
777791
792+ vftFinished.insert (vftAddr);
778793 auto vftInfo = ProcessVFT (vftAddr, classInfo, baseClassInfo);
779- vftFinishedMap[vftAddr] = vftInfo;
780- return vftInfo;
794+ classInfo.vft = vftInfo.value ();
781795 };
782796
783- std::function<void (uint64_t )> ProcessClassAndBases = [&](uint64_t coLocatorAddr) -> void {
784- auto & classInfo = m_classInfo[coLocatorAddr];
785-
786- // Process all relevant base classes first.
787- // Otherwise, when we process this class we won't have the base vft available if needed.
788- for (auto & baseInfo : classInfo.baseClasses )
789- {
790- for (auto & [baseCoLocAddr, baseClassInfo] : m_classInfo)
791- {
792- if (baseClassInfo.className == baseInfo.className )
793- {
794- uint64_t baseVftAddr = vftMap[baseCoLocAddr];
795- // Recurse into the bases bases.
796- ProcessClassAndBases (baseCoLocAddr);
797-
798- // Fetch the VFT info for the base class and store it.
799- if (auto baseVftInfo = GetCachedVFTInfo (baseVftAddr, baseClassInfo))
800- {
801- baseInfo.vft = baseVftInfo.value ();
802- break ;
803- }
804- }
805- }
806- }
807-
808- // Process the vtable for the current class.
809- // By this point all base classes should already exist, along with their type.
810- uint64_t vftAddr = vftMap[coLocatorAddr];
811- if (auto vftInfo = GetCachedVFTInfo (vftAddr, classInfo))
812- classInfo.vft = vftInfo.value ();
813- };
814-
797+ size_t processedNum = 0 ;
815798 for (const auto &[coLocatorAddr, _]: vftMap)
816- ProcessClassAndBases (coLocatorAddr);
799+ {
800+ if (bgTask->IsCancelled ())
801+ break ;
802+ processClassAndBases (coLocatorAddr);
803+ std::string progress = fmt::format (" Processing Microsoft VFTs... {}/{}" , processedNum++, vftMap.size ());
804+ bgTask->SetProgressText (progress);
805+ }
817806
818807 bgTask->Finish ();
819808 auto end_time = std::chrono::high_resolution_clock::now ();
0 commit comments