summaryrefslogtreecommitdiff
path: root/plugins/rtti/itanium.cpp
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2026-01-12 10:58:59 -0800
committerMason Reed <35282038+emesare@users.noreply.github.com>2026-01-13 19:37:46 -0800
commite299a6c1bf74f0ca6d2c3d79135e8c23e6b9fbba (patch)
tree132683a047f4a97c0dc18a1f01df8f46b79105b1 /plugins/rtti/itanium.cpp
parent0893694568345908163262785097878460604855 (diff)
[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
Diffstat (limited to 'plugins/rtti/itanium.cpp')
-rw-r--r--plugins/rtti/itanium.cpp58
1 files changed, 5 insertions, 53 deletions
diff --git a/plugins/rtti/itanium.cpp b/plugins/rtti/itanium.cpp
index 6f4c7158..145969c0 100644
--- a/plugins/rtti/itanium.cpp
+++ b/plugins/rtti/itanium.cpp
@@ -14,22 +14,6 @@ constexpr const char *TYPE_SOURCE_ITANIUM = "rtti_itanium";
constexpr int MAX_FAILED_SCAN_ATTEMPTS = 10;
-Ref<Symbol> GetRealSymbol(BinaryView *view, uint64_t relocAddr, uint64_t symAddr)
-{
- if (view->IsOffsetExternSemantics(symAddr))
- {
- // Because bases in the extern section are not 8 byte width only they will
- // overlap with other externs, until https://github.com/Vector35/binaryninja-api/issues/6387 is fixed.
- // Check relocation at objectAddr for symbol
- for (const auto& r : view->GetRelocationsAt(relocAddr))
- if (auto relocSym = r->GetSymbol())
- return relocSym;
- }
-
- return view->GetSymbolByAddress(symAddr);
-}
-
-
// Some fields are not always u32, use this if it goes from u32 -> u16 on 32bit
uint64_t ArchFieldSize(BinaryView *view)
{
@@ -37,7 +21,6 @@ uint64_t ArchFieldSize(BinaryView *view)
}
-
uint64_t TypeInfoSize(BinaryView *view)
{
return view->GetAddressSize() * 2;
@@ -558,47 +541,16 @@ std::optional<ClassInfo> ItaniumRTTIProcessor::ProcessRTTI(uint64_t objectAddr)
std::optional<VirtualFunctionTableInfo> ItaniumRTTIProcessor::ProcessVFT(uint64_t vftAddr, ClassInfo &classInfo, std::optional<BaseClassInfo> baseClassInfo)
{
VirtualFunctionTableInfo vftInfo = {vftAddr};
- BinaryReader reader = BinaryReader(m_view);
- reader.Seek(vftAddr);
// Gather all virtual functions
std::vector<VirtualFunctionInfo> 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> segment = m_view->GetSegmentAt(vFuncAddr);
- if (segment == nullptr || !(segment->GetFlags() & (SegmentExecutable | SegmentDenyWrite)))
- {
- // TODO: Sometimes vFunc idx will be zeroed iirc.
- // We allow vfuncs to point to extern functions.
- // TODO: Until https://github.com/Vector35/binaryninja-api/issues/5982 is fixed we need to check extern sym relocs instead of the symbol directly
- auto vFuncSym = GetRealSymbol(m_view, reader.GetOffset(), vFuncAddr);
- if (!vFuncSym)
- break;
- DataVariable dv;
- bool foundDv = m_view->GetDataVariableAtAddress(vFuncAddr, dv);
- // Last virtual function, or hit the next vtable.
- if (!foundDv || !dv.type->m_object)
- break;
- // Void externs are very likely to be a func.
- // TODO: Add some sanity checks for this!
- if (!dv.type->IsFunction() && !(dv.type->IsVoid() && vFuncSym->GetType() == ExternalSymbol))
- break;
- }
- else
- {
- // 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);
- m_view->AddFunctionForAnalysis(vftPlatform, vFuncAddr, true);
- }
- }
- // Only ever add one function.
+ currentVftEntry += m_view->GetAddressSize();
virtualFunctions.emplace_back(VirtualFunctionInfo{vFuncAddr});
}