From e299a6c1bf74f0ca6d2c3d79135e8c23e6b9fbba Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Mon, 12 Jan 2026 10:58:59 -0800 Subject: [RTTI] Improve virtual function discovery - Allow extern functions to show up in a MSVC vtable - Fix https://github.com/Vector35/binaryninja-api/issues/7871 - Share code between itanium and msvc vft analysis, it is the same logic basically --- plugins/rtti/microsoft.cpp | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) (limited to 'plugins/rtti/microsoft.cpp') diff --git a/plugins/rtti/microsoft.cpp b/plugins/rtti/microsoft.cpp index 684a68cd..b57b15f6 100644 --- a/plugins/rtti/microsoft.cpp +++ b/plugins/rtti/microsoft.cpp @@ -482,37 +482,19 @@ std::optional MicrosoftRTTIProcessor::ProcessRTTI(uint64_t coLocatorA std::optional MicrosoftRTTIProcessor::ProcessVFT(uint64_t vftAddr, ClassInfo &classInfo, std::optional baseClassInfo) { VirtualFunctionTableInfo vftInfo = {vftAddr}; - // Gather all virtual functions - BinaryReader reader = BinaryReader(m_view); - reader.Seek(vftAddr); // Virtual functions and the analysis object of it, if it exists. std::vector>>> virtualFunctions = {}; + uint64_t currentVftEntry = vftAddr; while (true) { - uint64_t readOffset = reader.GetOffset(); - if (!m_view->IsValidOffset(readOffset)) + uint64_t vFuncAddr = 0; + const FunctionDiscoverState state = DiscoverVirtualFunction(currentVftEntry, vFuncAddr); + if (state == FunctionDiscoverState::Failed) break; - uint64_t vFuncAddr = reader.ReadPointer(); - auto funcs = m_view->GetAnalysisFunctionsForAddress(vFuncAddr); - if (funcs.empty()) - { - Ref segment = m_view->GetSegmentAt(vFuncAddr); - if (segment == nullptr || !(segment->GetFlags() & (SegmentExecutable | SegmentDenyWrite))) - { - // Last CompleteObjectLocator or hit the next CompleteObjectLocator - break; - } - // TODO: Is likely a function check here? - m_logger->LogDebugF("Discovered function from virtual function table... {:#x}", vFuncAddr); - auto vftPlatform = m_view->GetDefaultPlatform()->GetAssociatedPlatformByAddress(vFuncAddr); - auto vFunc = m_view->AddFunctionForAnalysis(vftPlatform, vFuncAddr, true); - virtualFunctions.emplace_back(vFuncAddr, vFunc ? std::optional(vFunc) : std::nullopt); - } - else - { - // Only ever add one function. - virtualFunctions.emplace_back(vFuncAddr, funcs.front()); - } + currentVftEntry += m_view->GetAddressSize(); + Ref vftPlatform = m_view->GetDefaultPlatform()->GetAssociatedPlatformByAddress(vFuncAddr); + Ref vFunc = m_view->GetAnalysisFunction(vftPlatform, vFuncAddr); + virtualFunctions.emplace_back(vFuncAddr, vFunc ? std::optional(vFunc) : std::nullopt); } if (virtualFunctions.empty()) -- cgit v1.3.1