summaryrefslogtreecommitdiff
path: root/plugins/rtti/rtti.cpp
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-03-01 00:34:12 -0500
committerMason Reed <mason@vector35.com>2025-03-19 21:17:34 -0400
commitf719d1d5565f7b7b1237b8e183c2985f006fa3e4 (patch)
tree0fbb2c1af1254add49049abdec3f935669d658de /plugins/rtti/rtti.cpp
parent93e92844d77b72f07bd7563211d60dc3595cc2e0 (diff)
Refactor and fixup MSVC and Itanium RTTI
Bunch of misc fixes and performance improvements
Diffstat (limited to 'plugins/rtti/rtti.cpp')
-rw-r--r--plugins/rtti/rtti.cpp102
1 files changed, 63 insertions, 39 deletions
diff --git a/plugins/rtti/rtti.cpp b/plugins/rtti/rtti.cpp
index d212edbc..91d3481c 100644
--- a/plugins/rtti/rtti.cpp
+++ b/plugins/rtti/rtti.cpp
@@ -14,19 +14,12 @@ std::optional<std::string> RTTI::DemangleNameMS(BinaryView* view, bool allowMang
}
-std::string RemoveItaniumPrefix(const std::string& name) {
- // Remove class prefixes.
- // 1 and 7 is class_type
- // 9 is si_class_type
- // 1..4 is vmi_class_type
- if (name.rfind('1', 0) == 0)
- return name.substr(1);
- if (name.rfind('7', 0) == 0)
- return name.substr(1);
- if (name.rfind('9', 0) == 0)
- return name.substr(1);
- if (name.rfind("4", 0) == 0)
- return name.substr(2);
+std::string RemoveItaniumPrefix(std::string &name)
+{
+ // Remove numerical prefixes.
+ // TODO: We might want to use the numbers for figuring out the class info.
+ while (!name.empty() && std::isdigit(name[0]))
+ name = name.substr(1);
return name;
}
@@ -56,54 +49,85 @@ std::optional<std::string> RTTI::DemangleNameLLVM(bool allowMangled, const std::
}
-Ref<Metadata> ClassInfo::SerializedMetadata()
+Ref<Metadata> BaseClassInfo::SerializedMetadata() const
+{
+ std::map<std::string, Ref<Metadata>> baseClassMeta;
+ baseClassMeta["className"] = new Metadata(className);
+ baseClassMeta["classOffset"] = new Metadata(offset);
+ // NOTE: We omit base vft functions as it can be resolved manually and just bloats the size.
+ if (vft.has_value())
+ baseClassMeta["vft"] = vft->SerializedMetadata(false);
+ return new Metadata(baseClassMeta);
+}
+
+BaseClassInfo BaseClassInfo::DeserializedMetadata(const Ref<Metadata> &metadata)
{
- std::map<std::string, Ref<Metadata> > classInfoMeta;
+ std::map<std::string, Ref<Metadata>> baseClassMeta = metadata->GetKeyValueStore();
+ std::string className = baseClassMeta["className"]->GetString();
+ uint64_t offset = baseClassMeta["classOffset"]->GetUnsignedInteger();
+ BaseClassInfo baseClassInfo = {className, offset};
+ if (baseClassMeta.find("vft") != baseClassMeta.end())
+ baseClassInfo.vft = VirtualFunctionTableInfo::DeserializedMetadata(baseClassMeta["vft"]);
+ return baseClassInfo;
+}
+
+
+Ref<Metadata> ClassInfo::SerializedMetadata() const
+{
+ std::map<std::string, Ref<Metadata>> classInfoMeta;
classInfoMeta["processor"] = new Metadata(static_cast<uint64_t>(processor));
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 (!baseClasses.empty())
+ {
+ std::vector<Ref<Metadata> > basesMeta;
+ basesMeta.reserve(baseClasses.size());
+ for (const auto& baseClass : baseClasses)
+ basesMeta.emplace_back(baseClass.SerializedMetadata());
+ classInfoMeta["bases"] = new Metadata(basesMeta);
+ }
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();
+ std::map<std::string, Ref<Metadata>> classInfoMeta = metadata->GetKeyValueStore();
std::string className = classInfoMeta["className"]->GetString();
RTTIProcessorType processor = static_cast<RTTIProcessorType>(classInfoMeta["processor"]->GetUnsignedInteger());
ClassInfo info = {processor, className};
- 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("bases") != classInfoMeta.end())
+ {
+ for (auto &entry: classInfoMeta["bases"]->GetArray())
+ info.baseClasses.emplace_back(BaseClassInfo::DeserializedMetadata(entry));
+ }
if (classInfoMeta.find("vft") != classInfoMeta.end())
info.vft = VirtualFunctionTableInfo::DeserializedMetadata(classInfoMeta["vft"]);
return info;
}
-Ref<Metadata> VirtualFunctionTableInfo::SerializedMetadata()
+Ref<Metadata> VirtualFunctionTableInfo::SerializedMetadata(const bool serializeFunctions) const
{
- 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;
+ std::map<std::string, Ref<Metadata>> vftMeta;
vftMeta["address"] = new Metadata(address);
- vftMeta["functions"] = new Metadata(funcsMeta);
+ // NOTE: We allow omitting baseVft functions as it can be resolved manually and just bloats the size.
+ if (serializeFunctions && !virtualFunctions.empty())
+ {
+ std::vector<Ref<Metadata> > funcsMeta;
+ funcsMeta.reserve(virtualFunctions.size());
+ for (auto &vFunc: virtualFunctions)
+ funcsMeta.emplace_back(vFunc.SerializedMetadata());
+ 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();
+ std::map<std::string, Ref<Metadata>> vftMeta = metadata->GetKeyValueStore();
VirtualFunctionTableInfo vftInfo = {vftMeta["address"]->GetUnsignedInteger()};
if (vftMeta.find("functions") != vftMeta.end())
{
@@ -114,9 +138,9 @@ VirtualFunctionTableInfo VirtualFunctionTableInfo::DeserializedMetadata(const Re
}
-Ref<Metadata> VirtualFunctionInfo::SerializedMetadata()
+Ref<Metadata> VirtualFunctionInfo::SerializedMetadata() const
{
- std::map<std::string, Ref<Metadata> > vFuncMeta;
+ std::map<std::string, Ref<Metadata>> vFuncMeta;
vFuncMeta["address"] = new Metadata(funcAddr);
return new Metadata(vFuncMeta);
}
@@ -124,7 +148,7 @@ Ref<Metadata> VirtualFunctionInfo::SerializedMetadata()
VirtualFunctionInfo VirtualFunctionInfo::DeserializedMetadata(const Ref<Metadata> &metadata)
{
- std::map<std::string, Ref<Metadata> > vFuncMeta = metadata->GetKeyValueStore();
+ std::map<std::string, Ref<Metadata>> vFuncMeta = metadata->GetKeyValueStore();
VirtualFunctionInfo vFuncInfo = {vFuncMeta["address"]->GetUnsignedInteger()};
return vFuncInfo;
}
@@ -132,7 +156,7 @@ VirtualFunctionInfo VirtualFunctionInfo::DeserializedMetadata(const Ref<Metadata
Ref<Metadata> RTTIProcessor::SerializedMetadata()
{
- std::map<std::string, Ref<Metadata> > classesMeta;
+ std::map<std::string, Ref<Metadata>> classesMeta;
for (auto &[objectAddr, classInfo]: m_classInfo)
{
auto addrStr = std::to_string(objectAddr);
@@ -147,7 +171,7 @@ Ref<Metadata> RTTIProcessor::SerializedMetadata()
classesMeta[addrStr] = classInfo.SerializedMetadata();
}
- std::map<std::string, Ref<Metadata> > itaniumMeta;
+ std::map<std::string, Ref<Metadata>> itaniumMeta;
itaniumMeta["classes"] = new Metadata(classesMeta);
return new Metadata(itaniumMeta);
}
@@ -155,7 +179,7 @@ Ref<Metadata> RTTIProcessor::SerializedMetadata()
void RTTIProcessor::DeserializedMetadata(RTTIProcessorType type, const Ref<Metadata> &metadata)
{
- std::map<std::string, Ref<Metadata> > msvcMeta = metadata->GetKeyValueStore();
+ std::map<std::string, Ref<Metadata>> msvcMeta = metadata->GetKeyValueStore();
if (msvcMeta.find("classes") != msvcMeta.end())
{
for (auto &[objectAddrStr, classInfoMeta]: msvcMeta["classes"]->GetKeyValueStore())