@@ -441,6 +441,17 @@ std::optional<ClassInfo> MicrosoftRTTIProcessor::ProcessRTTI(uint64_t coLocatorA
441441 if (!className.has_value ())
442442 return std::nullopt ;
443443
444+ // If the className is empty we will change it to the address, this is to fix type clobbering.
445+ if (className->empty ())
446+ {
447+ if (!allowAnonymousClassNames)
448+ {
449+ m_logger->LogDebug (" Skipping CompleteObjectorLocator with anonymous name %llx" , coLocatorAddr);
450+ return std::nullopt ;
451+ }
452+ className = fmt::format (" ANONYMOUS_{:#x}" , coLocatorAddr);
453+ }
454+
444455 auto classInfo = ClassInfo{className.value ()};
445456 if (coLocator->offset > 0 )
446457 classInfo.classOffset = coLocator->offset ;
@@ -509,7 +520,8 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
509520 // Gather all virtual functions
510521 BinaryReader reader = BinaryReader (m_view);
511522 reader.Seek (vftAddr);
512- std::vector<Ref<Function> > virtualFunctions = {};
523+ // Virtual functions and the analysis object of it, if it exists.
524+ std::vector<std::pair<uint64_t , std::optional<Ref<Function>>>> virtualFunctions = {};
513525 while (true )
514526 {
515527 uint64_t vFuncAddr = reader.ReadPointer ();
@@ -525,10 +537,13 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
525537 // TODO: Is likely a function check here?
526538 m_logger->LogDebug (" Discovered function from virtual function table... %llx" , vFuncAddr);
527539 auto vFunc = m_view->AddFunctionForAnalysis (m_view->GetDefaultPlatform (), vFuncAddr, true );
528- funcs.emplace_back (vFunc);
540+ virtualFunctions.emplace_back (vFuncAddr, vFunc ? std::optional (vFunc) : std::nullopt );
541+ }
542+ else
543+ {
544+ // Only ever add one function.
545+ virtualFunctions.emplace_back (vFuncAddr, funcs.front ());
529546 }
530- // Only ever add one function.
531- virtualFunctions.emplace_back (funcs.front ());
532547 }
533548
534549 if (virtualFunctions.empty ())
@@ -537,8 +552,8 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
537552 return std::nullopt ;
538553 }
539554
540- for (auto &func : virtualFunctions)
541- vftInfo.virtualFunctions .emplace_back (VirtualFunctionInfo{func-> GetStart () });
555+ for (auto &[vFuncAddr, _] : virtualFunctions)
556+ vftInfo.virtualFunctions .emplace_back (VirtualFunctionInfo{vFuncAddr });
542557
543558 // Create virtual function table type
544559 auto vftTypeName = fmt::format (" {}::VTable" , classInfo.className );
@@ -585,22 +600,27 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
585600 }
586601 }
587602
588- for (auto &&vFunc: virtualFunctions)
603+ for (auto &&[_, vFunc] : virtualFunctions)
589604 {
590605 auto vFuncName = fmt::format (" vFunc_{}" , vFuncIdx);
591- // If we have a better name, use it.
592- auto vFuncSymName = vFunc->GetSymbol ()->GetShortName ();
593- if (vFuncSymName.compare (0 , 4 , " sub_" ) != 0 )
594- vFuncName = vFunc->GetSymbol ()->GetShortName ();
595- // MyClass::func -> func
596- std::size_t pos = vFuncName.rfind (" ::" );
597- if (pos != std::string::npos)
598- vFuncName = vFuncName.substr (pos + 2 );
606+ if (vFunc.has_value ())
607+ {
608+ // If we have a better name, use it.
609+ auto vFuncObj = vFunc.value ();
610+ auto vFuncSymName = vFuncObj->GetSymbol ()->GetShortName ();
611+ if (vFuncSymName.compare (0 , 4 , " sub_" ) != 0 )
612+ vFuncName = vFuncObj->GetSymbol ()->GetShortName ();
613+ // MyClass::func -> func
614+ std::size_t pos = vFuncName.rfind (" ::" );
615+ if (pos != std::string::npos)
616+ vFuncName = vFuncName.substr (pos + 2 );
617+ }
599618
600619 // NOTE: The analyzed function type might not be available here.
601620 auto vFuncOffset = vFuncIdx * addrSize;
621+ // We have access to a backing function type, use it, otherwise void!
602622 vftBuilder.AddMemberAtOffset (
603- Type::PointerType (addrSize, vFunc->GetType (), true ), vFuncName, vFuncOffset);
623+ Type::PointerType (addrSize, vFunc. has_value () ? vFunc. value () ->GetType () : Type::VoidType (), true ), vFuncName, vFuncOffset);
604624 vFuncIdx++;
605625 }
606626 m_view->DefineType (typeId, vftTypeName,
@@ -616,10 +636,11 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
616636}
617637
618638
619- MicrosoftRTTIProcessor::MicrosoftRTTIProcessor (const Ref<BinaryView> &view, bool useMangled, bool checkRData, bool vftSweep) : m_view(view)
639+ MicrosoftRTTIProcessor::MicrosoftRTTIProcessor (const Ref<BinaryView> &view, bool useMangled, bool checkRData, bool vftSweep, bool allowAnonymous ) : m_view(view)
620640{
621641 m_logger = new Logger (" Microsoft RTTI" );
622642 allowMangledClassNames = useMangled;
643+ allowAnonymousClassNames = allowAnonymous;
623644 checkWritableRData = checkRData;
624645 m_classInfo = {};
625646 virtualFunctionTableSweep = vftSweep;
0 commit comments