@@ -441,6 +441,17 @@ std::optional<ClassInfo> MicrosoftRTTIProcessor::ProcessRTTI(uint64_t coLocatorA
441
441
if (!className.has_value ())
442
442
return std::nullopt;
443
443
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
+
444
455
auto classInfo = ClassInfo{className.value ()};
445
456
if (coLocator->offset > 0 )
446
457
classInfo.classOffset = coLocator->offset ;
@@ -509,7 +520,8 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
509
520
// Gather all virtual functions
510
521
BinaryReader reader = BinaryReader (m_view);
511
522
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 = {};
513
525
while (true )
514
526
{
515
527
uint64_t vFuncAddr = reader.ReadPointer ();
@@ -525,10 +537,13 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
525
537
// TODO: Is likely a function check here?
526
538
m_logger->LogDebug (" Discovered function from virtual function table... %llx" , vFuncAddr);
527
539
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 ());
529
546
}
530
- // Only ever add one function.
531
- virtualFunctions.emplace_back (funcs.front ());
532
547
}
533
548
534
549
if (virtualFunctions.empty ())
@@ -537,8 +552,8 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
537
552
return std::nullopt;
538
553
}
539
554
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 });
542
557
543
558
// Create virtual function table type
544
559
auto vftTypeName = fmt::format (" {}::VTable" , classInfo.className );
@@ -585,22 +600,27 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
585
600
}
586
601
}
587
602
588
- for (auto &&vFunc: virtualFunctions)
603
+ for (auto &&[_, vFunc] : virtualFunctions)
589
604
{
590
605
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
+ }
599
618
600
619
// NOTE: The analyzed function type might not be available here.
601
620
auto vFuncOffset = vFuncIdx * addrSize;
621
+ // We have access to a backing function type, use it, otherwise void!
602
622
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);
604
624
vFuncIdx++;
605
625
}
606
626
m_view->DefineType (typeId, vftTypeName,
@@ -616,10 +636,11 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
616
636
}
617
637
618
638
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)
620
640
{
621
641
m_logger = new Logger (" Microsoft RTTI" );
622
642
allowMangledClassNames = useMangled;
643
+ allowAnonymousClassNames = allowAnonymous;
623
644
checkWritableRData = checkRData;
624
645
m_classInfo = {};
625
646
virtualFunctionTableSweep = vftSweep;
0 commit comments