summaryrefslogtreecommitdiff
path: root/plugins/rtti/rtti.cpp
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2024-11-22 18:16:32 -0500
committerMason Reed <mason@vector35.com>2025-03-19 21:17:34 -0400
commit9ff2b8d804a34941a6085af85b6749c20549240e (patch)
tree9b78b478476cfb66fc68828087ad9ff99cdfacb5 /plugins/rtti/rtti.cpp
parent7d66d87a4600c8954c585c3c690546fc56903d44 (diff)
Itanium RTTI scaffolding
Diffstat (limited to 'plugins/rtti/rtti.cpp')
-rw-r--r--plugins/rtti/rtti.cpp112
1 files changed, 112 insertions, 0 deletions
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<std::string> RTTI::DemangleNameMS(BinaryView* view, bool allowMangled, const std::string &mangledName)
+{
+ QualifiedName demangledName = {};
+ Ref<Type> outType = {};
+ if (!DemangleMS(view->GetDefaultArchitecture(), mangledName, outType, demangledName, true))
+ return DemangleNameLLVM(allowMangled, mangledName);
+ return demangledName.GetString();
+}
+
+
+std::optional<std::string> RTTI::DemangleNameGNU3(BinaryView* view, bool allowMangled, const std::string &mangledName)
+{
+ QualifiedName demangledName = {};
+ Ref<Type> outType = {};
+ if (!DemangleGNU3(view->GetDefaultArchitecture(), mangledName, outType, demangledName, true))
+ return DemangleNameLLVM(allowMangled, mangledName);
+ return demangledName.GetString();
+}
+
+
+std::optional<std::string> RTTI::DemangleNameLLVM(bool allowMangled, const std::string &mangledName)
+{
+ QualifiedName demangledName = {};
+ Ref<Type> 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<Metadata> ClassInfo::SerializedMetadata()
+{
+ std::map<std::string, Ref<Metadata> > 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> &metadata)
+{
+ std::map<std::string, Ref<Metadata> > 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<Metadata> VirtualFunctionTableInfo::SerializedMetadata()
+{
+ std::vector<Ref<Metadata> > funcsMeta;
+ funcsMeta.reserve(virtualFunctions.size());
+ for (auto &vFunc: virtualFunctions)
+ funcsMeta.emplace_back(vFunc.SerializedMetadata());
+ std::map<std::string, Ref<Metadata> > vftMeta;
+ vftMeta["address"] = new Metadata(address);
+ vftMeta["functions"] = new Metadata(funcsMeta);
+ return new Metadata(vftMeta);
+}
+
+
+VirtualFunctionTableInfo VirtualFunctionTableInfo::DeserializedMetadata(const Ref<Metadata> &metadata)
+{
+ std::map<std::string, Ref<Metadata> > 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<Metadata> VirtualFunctionInfo::SerializedMetadata()
+{
+ std::map<std::string, Ref<Metadata> > vFuncMeta;
+ vFuncMeta["address"] = new Metadata(funcAddr);
+ return new Metadata(vFuncMeta);
+}
+
+
+VirtualFunctionInfo VirtualFunctionInfo::DeserializedMetadata(const Ref<Metadata> &metadata)
+{
+ std::map<std::string, Ref<Metadata> > vFuncMeta = metadata->GetKeyValueStore();
+ VirtualFunctionInfo vFuncInfo = {vFuncMeta["address"]->GetUnsignedInteger()};
+ return vFuncInfo;
+} \ No newline at end of file