MCPcopy Create free account
hub / github.com/Vector35/binaryninja-api / ProcessVFT

Method ProcessVFT

plugins/rtti/itanium.cpp:555–708  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

553
554
555std::optional<VirtualFunctionTableInfo> ItaniumRTTIProcessor::ProcessVFT(uint64_t vftAddr, ClassInfo &classInfo, std::optional<BaseClassInfo> baseClassInfo)
556{
557 VirtualFunctionTableInfo vftInfo = {vftAddr};
558 BinaryReader reader = BinaryReader(m_view);
559 reader.Seek(vftAddr);
560 // Gather all virtual functions
561 std::vector<VirtualFunctionInfo> virtualFunctions = {};
562 while (true)
563 {
564 uint64_t vFuncAddr = reader.ReadPointer();
565 auto funcs = m_view->GetAnalysisFunctionsForAddress(vFuncAddr);
566 if (funcs.empty())
567 {
568 Ref<Segment> segment = m_view->GetSegmentAt(vFuncAddr);
569 if (segment == nullptr || !(segment->GetFlags() & (SegmentExecutable | SegmentDenyWrite)))
570 {
571 // TODO: Sometimes vFunc idx will be zeroed iirc.
572 // We allow vfuncs to point to extern functions.
573 // TODO: Until https://github.com/Vector35/binaryninja-api/issues/5982 is fixed we need to check extern sym relocs instead of the symbol directly
574 auto vFuncSym = GetRealSymbol(m_view, reader.GetOffset(), vFuncAddr);
575 if (!vFuncSym)
576 break;
577 DataVariable dv;
578 bool foundDv = m_view->GetDataVariableAtAddress(vFuncAddr, dv);
579 // Last virtual function, or hit the next vtable.
580 if (!foundDv || !dv.type->m_object)
581 break;
582 // Void externs are very likely to be a func.
583 // TODO: Add some sanity checks for this!
584 if (!dv.type->IsFunction() && !(dv.type->IsVoid() && vFuncSym->GetType() == ExternalSymbol))
585 break;
586 }
587 else
588 {
589 // TODO: Is likely a function check here?
590 m_logger->LogDebug("Discovered function from virtual function table... %llx", vFuncAddr);
591 m_view->AddFunctionForAnalysis(m_view->GetDefaultPlatform(), vFuncAddr, true);
592 }
593 }
594 // Only ever add one function.
595 virtualFunctions.emplace_back(VirtualFunctionInfo{vFuncAddr});
596 }
597
598 if (virtualFunctions.empty())
599 {
600 m_logger->LogDebug("Skipping empty virtual function table... %llx", vftAddr);
601 return std::nullopt;
602 }
603
604 // Create virtual function table type
605 auto vftTypeName = fmt::format("{}::VTable", classInfo.className);
606 if (baseClassInfo.has_value())
607 {
608 // TODO: What is the correct form for the name?
609 vftTypeName = fmt::format("{}::{}", baseClassInfo->className, vftTypeName);
610 }
611 // TODO: Hack the debug type id is used here to allow the PDB type (debug info) to overwrite the RTTI vtable type.
612 auto typeId = Type::GenerateAutoDebugTypeId(vftTypeName);

Callers 1

VFTAnalysisFunction · 0.45

Calls 15

GetRealSymbolFunction · 0.85
PointerTypeClass · 0.85
ConfidenceClass · 0.85
StructureTypeClass · 0.85
ArchFieldSizeFunction · 0.85
GetSegmentAtMethod · 0.80
LogDebugMethod · 0.80
GetDefaultPlatformMethod · 0.80
eraseMethod · 0.80

Tested by

no test coverage detected