From 9ff2b8d804a34941a6085af85b6749c20549240e Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Fri, 22 Nov 2024 18:16:32 -0500 Subject: Itanium RTTI scaffolding --- plugins/rtti/rtti.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 plugins/rtti/rtti.cpp (limited to 'plugins/rtti/rtti.cpp') diff --git a/plugins/rtti/rtti.cpp b/plugins/rtti/rtti.cpp new file mode 100644 index 00000000..d99983ee --- /dev/null +++ b/plugins/rtti/rtti.cpp @@ -0,0 +1,112 @@ +#include "rtti.h" + +using namespace BinaryNinja; +using namespace BinaryNinja::RTTI; + + +std::optional RTTI::DemangleNameMS(BinaryView* view, bool allowMangled, const std::string &mangledName) +{ + QualifiedName demangledName = {}; + Ref outType = {}; + if (!DemangleMS(view->GetDefaultArchitecture(), mangledName, outType, demangledName, true)) + return DemangleNameLLVM(allowMangled, mangledName); + return demangledName.GetString(); +} + + +std::optional RTTI::DemangleNameGNU3(BinaryView* view, bool allowMangled, const std::string &mangledName) +{ + QualifiedName demangledName = {}; + Ref outType = {}; + if (!DemangleGNU3(view->GetDefaultArchitecture(), mangledName, outType, demangledName, true)) + return DemangleNameLLVM(allowMangled, mangledName); + return demangledName.GetString(); +} + + +std::optional RTTI::DemangleNameLLVM(bool allowMangled, const std::string &mangledName) +{ + QualifiedName demangledName = {}; + Ref outType = {}; + if (!DemangleLLVM(mangledName, demangledName, true)) + return allowMangled ? std::optional(mangledName) : std::nullopt; + auto demangledNameStr = demangledName.GetString(); + size_t beginFind = demangledNameStr.find_first_of(' '); + if (beginFind != std::string::npos) + demangledNameStr.erase(0, beginFind + 1); + size_t endFind = demangledNameStr.find(" `RTTI Type Descriptor Name'"); + if (endFind != std::string::npos) + demangledNameStr.erase(endFind, demangledNameStr.length()); + return demangledNameStr; +} + + +Ref ClassInfo::SerializedMetadata() +{ + std::map > classInfoMeta; + classInfoMeta["className"] = new Metadata(className); + if (baseClassName.has_value()) + classInfoMeta["baseClassName"] = new Metadata(baseClassName.value()); + if (classOffset.has_value()) + classInfoMeta["classOffset"] = new Metadata(classOffset.value()); + if (vft.has_value()) + classInfoMeta["vft"] = vft->SerializedMetadata(); + // NOTE: We omit baseVft as it can be resolved manually and just bloats the size. + return new Metadata(classInfoMeta); +} + + +ClassInfo ClassInfo::DeserializedMetadata(const Ref &metadata) +{ + std::map > classInfoMeta = metadata->GetKeyValueStore(); + ClassInfo info = {classInfoMeta["className"]->GetString()}; + if (classInfoMeta.find("baseClassName") != classInfoMeta.end()) + info.baseClassName = classInfoMeta["baseClassName"]->GetString(); + if (classInfoMeta.find("classOffset") != classInfoMeta.end()) + info.classOffset = classInfoMeta["classOffset"]->GetUnsignedInteger(); + if (classInfoMeta.find("vft") != classInfoMeta.end()) + info.vft = VirtualFunctionTableInfo::DeserializedMetadata(classInfoMeta["vft"]); + return info; +} + + +Ref VirtualFunctionTableInfo::SerializedMetadata() +{ + std::vector > funcsMeta; + funcsMeta.reserve(virtualFunctions.size()); + for (auto &vFunc: virtualFunctions) + funcsMeta.emplace_back(vFunc.SerializedMetadata()); + std::map > vftMeta; + vftMeta["address"] = new Metadata(address); + vftMeta["functions"] = new Metadata(funcsMeta); + return new Metadata(vftMeta); +} + + +VirtualFunctionTableInfo VirtualFunctionTableInfo::DeserializedMetadata(const Ref &metadata) +{ + std::map > vftMeta = metadata->GetKeyValueStore(); + VirtualFunctionTableInfo vftInfo = {vftMeta["address"]->GetUnsignedInteger()}; + if (vftMeta.find("functions") != vftMeta.end()) + { + for (auto &entry: vftMeta["functions"]->GetArray()) + vftInfo.virtualFunctions.emplace_back(VirtualFunctionInfo::DeserializedMetadata(entry)); + } + return vftInfo; +} + + +Ref VirtualFunctionInfo::SerializedMetadata() +{ + std::map > vFuncMeta; + vFuncMeta["address"] = new Metadata(funcAddr); + return new Metadata(vFuncMeta); +} + + +VirtualFunctionInfo VirtualFunctionInfo::DeserializedMetadata(const Ref &metadata) +{ + std::map > vFuncMeta = metadata->GetKeyValueStore(); + VirtualFunctionInfo vFuncInfo = {vFuncMeta["address"]->GetUnsignedInteger()}; + return vFuncInfo; +} \ No newline at end of file -- cgit v1.3.1