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

Method ProcessVFT

plugins/rtti/microsoft.cpp:470–606  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

468
469
470std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint64_t vftAddr, ClassInfo &classInfo, std::optional<BaseClassInfo> baseClassInfo)
471{
472 VirtualFunctionTableInfo vftInfo = {vftAddr};
473 // Gather all virtual functions
474 BinaryReader reader = BinaryReader(m_view);
475 reader.Seek(vftAddr);
476 // Virtual functions and the analysis object of it, if it exists.
477 std::vector<std::pair<uint64_t, std::optional<Ref<Function>>>> virtualFunctions = {};
478 while (true)
479 {
480 uint64_t vFuncAddr = reader.ReadPointer();
481 auto funcs = m_view->GetAnalysisFunctionsForAddress(vFuncAddr);
482 if (funcs.empty())
483 {
484 Ref<Segment> segment = m_view->GetSegmentAt(vFuncAddr);
485 if (segment == nullptr || !(segment->GetFlags() & (SegmentExecutable | SegmentDenyWrite)))
486 {
487 // Last CompleteObjectLocator or hit the next CompleteObjectLocator
488 break;
489 }
490 // TODO: Is likely a function check here?
491 m_logger->LogDebug("Discovered function from virtual function table... %llx", vFuncAddr);
492 auto vFunc = m_view->AddFunctionForAnalysis(m_view->GetDefaultPlatform(), vFuncAddr, true);
493 virtualFunctions.emplace_back(vFuncAddr, vFunc ? std::optional(vFunc) : std::nullopt);
494 }
495 else
496 {
497 // Only ever add one function.
498 virtualFunctions.emplace_back(vFuncAddr, funcs.front());
499 }
500 }
501
502 if (virtualFunctions.empty())
503 {
504 m_logger->LogDebug("Skipping empty virtual function table... %llx", vftAddr);
505 return std::nullopt;
506 }
507
508 for (auto &[vFuncAddr, _]: virtualFunctions)
509 vftInfo.virtualFunctions.emplace_back(VirtualFunctionInfo{vFuncAddr});
510
511 // Create virtual function table type
512 auto vftTypeName = fmt::format("{}::VTable", classInfo.className);
513 if (baseClassInfo.has_value())
514 {
515 // TODO: What is the correct form for the name?
516 vftTypeName = fmt::format("{}::{}", baseClassInfo->className, vftTypeName);
517 }
518 // TODO: Hack the debug type id is used here to allow the PDB type (debug info) to overwrite the RTTI vtable type.
519 auto typeId = Type::GenerateAutoDebugTypeId(vftTypeName);
520 Ref<Type> vftType = m_view->GetTypeById(typeId);
521
522 if (vftType == nullptr)
523 {
524 size_t addrSize = m_view->GetAddressSize();
525 StructureBuilder vftBuilder = {};
526 vftBuilder.SetPropagateDataVariableReferences(true);
527 size_t vFuncIdx = 0;

Callers

nothing calls this directly

Calls 15

VoidTypeClass · 0.85
PointerTypeClass · 0.85
ConfidenceClass · 0.85
StructureTypeClass · 0.85
GetSegmentAtMethod · 0.80
LogDebugMethod · 0.80
GetDefaultPlatformMethod · 0.80
eraseMethod · 0.80
GetShortNameMethod · 0.80

Tested by

no test coverage detected