diff options
| author | Peter LaFosse <peter@vector35.com> | 2026-03-10 12:27:34 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2026-03-26 17:56:23 -0400 |
| commit | 260ca61d94134b6743807e29f64b5ce4f6918d73 (patch) | |
| tree | 9b77dc9990873549f096c5eae00a2b924215946b /demangler/gnu3/demangle_gnu3.cpp | |
| parent | 0789f70c4a7496cf23672011cdb5bf5b8a5738c6 (diff) | |
Rewrite GNU3 demangler for performance using DemangledTypeNode
Replace the TypeBuilder-based demangling path with a lightweight
DemangledTypeNode representation that defers type object construction
until the symbol is fully parsed. This avoids repeated heap allocation
and ref-count churn during recursive descent.
Key changes:
- Add DemangledTypeNode / demangled_type_node.{h,cpp}: a compact IR
that mirrors the type grammar without allocating BN Type objects
- Use a thread_local demangler instance to amortize vector allocations
across calls
- Also commonize some of the demangled string length calculations.
Result: ~3x throughput improvement on a 180K-symbol corpus with
97.7% success rate (matching the previous implementation).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'demangler/gnu3/demangle_gnu3.cpp')
| -rw-r--r-- | demangler/gnu3/demangle_gnu3.cpp | 821 |
1 files changed, 428 insertions, 393 deletions
diff --git a/demangler/gnu3/demangle_gnu3.cpp b/demangler/gnu3/demangle_gnu3.cpp index d36fcedf..c8fec64f 100644 --- a/demangler/gnu3/demangle_gnu3.cpp +++ b/demangler/gnu3/demangle_gnu3.cpp @@ -49,8 +49,7 @@ void MyLogDebug(string fmt, ...) #else #define indent() #define dedent() -void MyLogDebug(string fmt, ...) -{ (void)fmt; } +#define MyLogDebug(...) do {} while(0) #endif static inline void rtrim(string &s) @@ -59,78 +58,218 @@ static inline void rtrim(string &s) } -static string GetTemplateString(vector<FunctionParameter> args) +static size_t TotalStringSize(const _STD_VECTOR<_STD_STRING>& v) +{ + size_t n = 0; + for (const auto& s : v) + n += s.size(); + return n; +} + + +static string GetTemplateString(const vector<string>& args) { - string name = "<"; + // Pre-calculate total length to avoid reallocations + size_t total = 2; // "<" + ">" for (size_t i = 0; i < args.size(); i++) { if (i != 0) - { - name += ", "; - } + total += 2; // ", " + total += args[i].size(); + } + total += 1; // possible " " before ">" - name += args[i].name; + string name; + name.reserve(total); + name += '<'; + for (size_t i = 0; i < args.size(); i++) + { + if (i != 0) + name += ", "; + name += args[i]; } rtrim(name); if (name.back() == '>') name += " "; //Be c++03 compliant where we can - name += ">"; + name += '>'; return name; } -static void ExtendTypeName(TypeBuilder& type, const string& extend) +static string GetOperator(char elm1, char elm2) { - QualifiedName qn = type.GetTypeName(); - if (qn.StringSize() + extend.size() > MAX_DEMANGLE_LENGTH) - throw DemangleException("Detected adversarial mangled string"); - if (qn.size() > 0) - qn.back() += extend; - else - qn.push_back(extend); - - // This type might not be an NTR (Vector35/binaryninja-api#6261) - if (type.GetClass() == NamedTypeReferenceClass) + switch (hash(elm1, elm2)) { - type.SetNamedTypeReference( - NamedTypeReference::GenerateAutoDemangledTypeReference(type.GetNamedTypeReference()->GetTypeReferenceClass(), qn) - ); + case hash('d','c'): return "dynamic_cast"; + case hash('s','c'): return "static_cast"; + case hash('c','c'): return "const_cast"; + case hash('r','c'): return "reinterpret_cast"; + case hash('t','i'): return "typeid"; + case hash('t','e'): return "typeid"; + case hash('s','t'): return "sizeof"; + case hash('s','z'): return "sizeof"; + case hash('a','t'): return "alignof"; + case hash('a','z'): return "alignof"; + case hash('n','x'): return "noexcept"; + case hash('s','Z'): return "sizeof..."; + case hash('s','P'): return "sizeof..."; + case hash('s','p'): return ""; + case hash('t','w'): return "throw"; + case hash('t','r'): return "throw"; + case hash('l','s'): return "<<"; // << + case hash('r','s'): return ">>"; // >> + case hash('a','S'): return "="; // = + case hash('n','t'): return "!"; // ! + case hash('e','q'): return "=="; // == + case hash('n','e'): return "!="; // != + case hash('i','x'): return "[]"; // [] + case hash('d','t'): return "."; // . + case hash('p','t'): return "->"; // -> + case hash('m','l'): return "*"; // * + case hash('p','p'): return "++"; // ++ (postfix in <expression> context) + case hash('m','m'): return "--"; // -- (postfix in <expression> context) + case hash('n','g'): return "-"; // - (unary) + case hash('m','i'): return "-"; // - + case hash('p','s'): return "+"; // + (unary) + case hash('p','l'): return "+"; // + + case hash('a','d'): return "&"; // & (unary) + case hash('a','n'): return "&"; // & + case hash('p','m'): return "->*"; // ->* + case hash('d','v'): return "/"; // / + case hash('r','m'): return "%"; // % + case hash('l','t'): return "<"; // < + case hash('l','e'): return "<="; // <= + case hash('g','t'): return ">"; // > + case hash('g','e'): return ">="; // >= + case hash('c','m'): return ","; // , + case hash('c','l'): return "()"; // () + case hash('c','o'): return "~"; // ~ + case hash('e','o'): return "^"; // ^ + case hash('o','r'): return "|"; // | + case hash('a','a'): return "&&"; // && + case hash('o','o'): return "||"; // || + case hash('d','e'): return "*"; // * (unary) + case hash('m','L'): return "*="; // *= + case hash('p','L'): return "+="; // += + case hash('m','I'): return "-="; // -= + case hash('d','V'): return "/="; // /= + case hash('r','M'): return "%="; // %= + case hash('r','S'): return ">>="; // >>= + case hash('l','S'): return "<<="; // <<= + case hash('a','N'): return "&="; // &= + case hash('o','R'): return "|="; // |= + case hash('e','O'): return "^="; // ^= + case hash('d','l'): return "delete"; // delete + case hash('d','a'): return "delete[]"; // delete[] + case hash('n','w'): return "new"; // new + case hash('n','a'): return "new[]"; // new [] + default: return ""; } } - -static TypeBuilder CreateUnknownType(const QualifiedName& s) +static BNNameType GetNameType(char elm1, char elm2) { - return TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference(UnknownNamedTypeClass, s)); + switch (hash(elm1, elm2)) + { + case hash('n','t'): return OperatorNotNameType; // ! + case hash('n','g'): return OperatorMinusNameType; // - (unary) + case hash('p','s'): return OperatorPlusNameType; // + (unary) + case hash('a','d'): return OperatorBitAndNameType; // & (unary) + case hash('d','e'): return OperatorStarNameType; // * (unary) + case hash('i','x'): return OperatorArrayNameType; // [] + case hash('p','p'): return OperatorIncrementNameType; // ++ (postfix in <expression> context) + case hash('m','m'): return OperatorDecrementNameType; // -- (postfix in <expression> context) + case hash('l','s'): return OperatorLeftShiftNameType; // << + case hash('r','s'): return OperatorRightShiftNameType; // >> + case hash('a','S'): return OperatorAssignNameType; // = + case hash('e','q'): return OperatorEqualNameType; // == + case hash('n','e'): return OperatorNotEqualNameType; // != + case hash('p','t'): return OperatorArrowNameType; // -> + case hash('m','l'): return OperatorStarNameType; // * + case hash('m','i'): return OperatorMinusNameType; // - + case hash('p','l'): return OperatorPlusNameType; // + + case hash('a','n'): return OperatorBitAndNameType; // & + case hash('p','m'): return OperatorArrowStarNameType; // ->* + case hash('d','v'): return OperatorDivideNameType; // / + case hash('r','m'): return OperatorModulusNameType; // % + case hash('l','t'): return OperatorLessThanNameType; // < + case hash('l','e'): return OperatorLessThanEqualNameType; // <= + case hash('g','t'): return OperatorGreaterThanNameType; // > + case hash('g','e'): return OperatorGreaterThanEqualNameType; // >= + case hash('c','m'): return OperatorCommaNameType; // , + case hash('c','l'): return OperatorParenthesesNameType; // () + case hash('c','o'): return OperatorTildeNameType; // ~ + case hash('e','o'): return OperatorXorNameType; // ^ + case hash('o','r'): return OperatorBitOrNameType; // | + case hash('a','a'): return OperatorLogicalAndNameType; // && + case hash('o','o'): return OperatorLogicalOrNameType; // || + case hash('m','L'): return OperatorStarEqualNameType; // *= + case hash('p','L'): return OperatorPlusEqualNameType; // += + case hash('m','I'): return OperatorMinusEqualNameType; // -= + case hash('d','V'): return OperatorDivideEqualNameType; // /= + case hash('r','M'): return OperatorModulusEqualNameType; // %= + case hash('r','S'): return OperatorRightShiftEqualNameType; // >>= + case hash('l','S'): return OperatorLeftShiftEqualNameType; // <<= + case hash('a','N'): return OperatorAndEqualNameType; // &= + case hash('o','R'): return OperatorOrEqualNameType; // |= + case hash('e','O'): return OperatorXorEqualNameType; // ^= + case hash('d','l'): return OperatorDeleteNameType; // delete + case hash('d','a'): return OperatorDeleteArrayNameType; // delete[] + case hash('n','w'): return OperatorNewNameType; // new + case hash('n','a'): return OperatorNewArrayNameType; // new [] + case hash('C','1'): return ConstructorNameType; + case hash('C','2'): return ConstructorNameType; + case hash('C','3'): return ConstructorNameType; + case hash('C','4'): return ConstructorNameType; + case hash('C','5'): return ConstructorNameType; + case hash('D','0'): return DestructorNameType; + case hash('D','1'): return DestructorNameType; + case hash('D','2'): return DestructorNameType; + case hash('D','3'): return DestructorNameType; + case hash('D','4'): return DestructorNameType; + case hash('D','5'): return DestructorNameType; + default: + return NoNameType; + } } - -static TypeBuilder CreateUnknownType(const string& s) +static int8_t HexToDec(char c) { - return TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference(UnknownNamedTypeClass, {s})); + if (isdigit(c)) + { + return c - '0'; + } + else if(islower(c) && c <= 'f') + { + return c - 'a' + 10; + } + return -1; } -DemangleGNU3::Reader::Reader(const string& data): m_data(data), m_offset(0) + +// ===== Reader implementation (non-templated) ===== + +DemangleGNU3Reader::DemangleGNU3Reader(const string& data): m_data(data), m_offset(0) {} -string DemangleGNU3::Reader::PeekString(size_t count) +void DemangleGNU3Reader::Reset(const string& data) { - if (count > Length()) - return "\0"; - return m_data.substr(m_offset, count); + m_data = data; + m_offset = 0; } -char DemangleGNU3::Reader::Peek() +string DemangleGNU3Reader::PeekString(size_t count) { - if (1 > Length()) - return '\0'; - return (char)m_data[m_offset]; + if (count > Length()) + return "\0"; + return m_data.substr(m_offset, count); } -bool DemangleGNU3::Reader::NextIsOneOf(const string& list) + +bool DemangleGNU3Reader::NextIsOneOf(const string& list) { char elm = Peek(); for (auto a : list) @@ -142,21 +281,14 @@ bool DemangleGNU3::Reader::NextIsOneOf(const string& list) } -string DemangleGNU3::Reader::GetRaw() +string DemangleGNU3Reader::GetRaw() { return m_data.substr(m_offset); } -char DemangleGNU3::Reader::Read() -{ - if (1 > Length()) - throw DemangleException(); - return m_data[m_offset++]; -} - -string DemangleGNU3::Reader::ReadString(size_t count) +string DemangleGNU3Reader::ReadString(size_t count) { if (count > Length()) throw DemangleException(); @@ -167,7 +299,7 @@ string DemangleGNU3::Reader::ReadString(size_t count) } -string DemangleGNU3::Reader::ReadUntil(char sentinal) +string DemangleGNU3Reader::ReadUntil(char sentinal) { size_t pos = m_data.find_first_of(sentinal, m_offset); if (pos == string::npos) @@ -176,46 +308,74 @@ string DemangleGNU3::Reader::ReadUntil(char sentinal) } -void DemangleGNU3::Reader::UnRead(size_t count) + +// ===== DemangleGNU3 implementation ===== + +DemangleGNU3::DemangleGNU3(Architecture* arch, const string& mangledName) : + m_reader(mangledName), + m_arch(arch), + m_isParameter(false), + m_shouldDeleteReader(true), + m_topLevel(true), + m_isOperatorOverload(false) { - if (count <= m_offset) - m_offset -= count; + MyLogDebug("%s : %s\n", __FUNCTION__, m_reader.GetRaw().c_str()); } -void DemangleGNU3::Reader::Consume(size_t count) +void DemangleGNU3::Reset(Architecture* arch, const string& mangledName) { - if (count > Length()) - throw DemangleException(); - m_offset += count; + m_reader.Reset(mangledName); + m_arch = arch; + m_varName.clear(); + m_substitute.clear(); + m_templateSubstitute.clear(); + m_functionSubstitute.clear(); + m_lastName.clear(); + m_nameType = {}; + m_localType = {}; + m_hasReturnType = {}; + m_isParameter = false; + m_shouldDeleteReader = true; + m_topLevel = true; + m_isOperatorOverload = false; } -size_t DemangleGNU3::Reader::Length() const +DemangledTypeNode DemangleGNU3::CreateUnknownType(const QualifiedName& s) { - return m_data.length() - m_offset; + return DemangledTypeNode::NamedType(UnknownNamedTypeClass, s); } -DemangleGNU3::DemangleGNU3(Architecture* arch, const string& mangledName) : - m_reader(mangledName), - m_arch(arch), - m_isParameter(false), - m_shouldDeleteReader(true), - m_topLevel(true), - m_isOperatorOverload(false) +DemangledTypeNode DemangleGNU3::CreateUnknownType(const string& s) { - MyLogDebug("%s : %s\n", __FUNCTION__, m_reader.GetRaw().c_str()); + return DemangledTypeNode::NamedType(UnknownNamedTypeClass, _STD_VECTOR<_STD_STRING>{s}); +} + + +void DemangleGNU3::ExtendTypeName(DemangledTypeNode& type, const string& extend) +{ + if (type.NameStringSize() + extend.size() > MAX_DEMANGLE_LENGTH) + throw DemangleException("Detected adversarial mangled string"); + + { + auto& qn = type.GetMutableTypeName(); + if (qn.size() > 0) + qn.back() += extend; + else + qn.push_back(extend); + } } -void DemangleGNU3::PushTemplateType(TypeBuilder type) +void DemangleGNU3::PushTemplateType(const DemangledTypeNode& type) { m_templateSubstitute.push_back(type); } -const TypeBuilder& DemangleGNU3::GetTemplateType(size_t ref) +const DemangledTypeNode& DemangleGNU3::GetTemplateType(size_t ref) { if (ref >= m_templateSubstitute.size()) { @@ -226,13 +386,13 @@ const TypeBuilder& DemangleGNU3::GetTemplateType(size_t ref) } -void DemangleGNU3::PushType(TypeBuilder type) +void DemangleGNU3::PushType(const DemangledTypeNode& type) { m_substitute.push_back(type); } -const TypeBuilder& DemangleGNU3::GetType(size_t ref) +const DemangledTypeNode& DemangleGNU3::GetType(size_t ref) { if (ref >= m_substitute.size()) { @@ -287,7 +447,7 @@ string DemangleGNU3::DemangleSourceName() } -TypeBuilder DemangleGNU3::DemangleFunction(bool cnst, bool vltl) +DemangledTypeNode DemangleGNU3::DemangleFunction(bool cnst, bool vltl) { indent(); MyLogDebug("%s : %s\n", __FUNCTION__, m_reader.GetRaw().c_str()); @@ -298,26 +458,26 @@ TypeBuilder DemangleGNU3::DemangleFunction(bool cnst, bool vltl) m_reader.Consume(); } - TypeBuilder retType = DemangleType(); + DemangledTypeNode retType = DemangleType(); - vector<FunctionParameter> params; + ParamList params; old_isparam = m_isParameter; m_isParameter = true; m_functionSubstitute.push_back({}); int i = 0; while (m_reader.Peek() != 'E') { - TypeBuilder param = DemangleType(); + DemangledTypeNode param = DemangleType(); if (param.GetClass() == VoidTypeClass) continue; MyLogDebug("Var_%d - %s\n", i++, param.GetString().c_str()); m_functionSubstitute.back().push_back(param); - params.push_back({"", param.Finalize(), true, Variable()}); + params.push_back({"", std::make_shared<DemangledTypeNode>(std::move(param))}); } m_reader.Consume(); m_functionSubstitute.pop_back(); m_isParameter = old_isparam; - TypeBuilder newType = TypeBuilder::FunctionType(retType.Finalize(), nullptr, params); + DemangledTypeNode newType = DemangledTypeNode::FunctionType(std::move(retType), nullptr, std::move(params)); PushType(newType); newType.SetConst(cnst); @@ -331,7 +491,7 @@ TypeBuilder DemangleGNU3::DemangleFunction(bool cnst, bool vltl) } -const TypeBuilder& DemangleGNU3::DemangleTemplateSubstitution() +const DemangledTypeNode& DemangleGNU3::DemangleTemplateSubstitution() { indent(); MyLogDebug("%s : %s\n", __FUNCTION__, m_reader.GetRaw().c_str()); @@ -365,11 +525,11 @@ const TypeBuilder& DemangleGNU3::DemangleTemplateSubstitution() } -TypeBuilder DemangleGNU3::DemangleType() +DemangledTypeNode DemangleGNU3::DemangleType() { indent(); MyLogDebug("%s : %s\n", __FUNCTION__, m_reader.GetRaw().c_str()); - TypeBuilder type; + DemangledTypeNode type; bool cnst = false, vltl = false, rstrct = false; bool substitute = false; QualifiedName name; @@ -399,7 +559,7 @@ TypeBuilder DemangleGNU3::DemangleType() if (m_reader.Peek() == 'I') { m_reader.Consume(); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); ExtendTypeName(type, GetTemplateString(args)); type.SetHasTemplateArguments(true); @@ -412,9 +572,9 @@ TypeBuilder DemangleGNU3::DemangleType() { m_reader.Consume(1); type = DemangleUnqualifiedName(); - QualifiedName qn = type.GetTypeName(); + auto qn = type.GetTypeName(); qn.insert(qn.begin(), "std"); - type.SetTypeName(qn); + type.SetTypeName(std::move(qn)); substitute = true; } else @@ -426,7 +586,7 @@ TypeBuilder DemangleGNU3::DemangleType() m_reader.Consume(); if (substitute) PushType(type); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); ExtendTypeName(type, GetTemplateString(args)); type.SetHasTemplateArguments(true); @@ -445,22 +605,19 @@ TypeBuilder DemangleGNU3::DemangleType() if (m_reader.Peek() == 's') { m_reader.Consume(); - type = TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference( - StructNamedTypeClass, {DemangleSourceName()})); + type = DemangledTypeNode::NamedType(StructNamedTypeClass, _STD_VECTOR<_STD_STRING>{DemangleSourceName()}); break; } else if (m_reader.Peek() == 'u') { m_reader.Consume(); - type = TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference( - UnionNamedTypeClass, {DemangleSourceName()})); + type = DemangledTypeNode::NamedType(UnionNamedTypeClass, _STD_VECTOR<_STD_STRING>{DemangleSourceName()}); break; } else if (m_reader.Peek() == 'e') { m_reader.Consume(); - type = TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference( - EnumNamedTypeClass, {DemangleSourceName()}), + type = DemangledTypeNode::NamedType(EnumNamedTypeClass, QualifiedName({DemangleSourceName()}), m_arch->GetDefaultIntegerSize(), m_arch->GetDefaultIntegerSize()); break; } @@ -473,7 +630,7 @@ TypeBuilder DemangleGNU3::DemangleType() m_reader.Consume(); if (substitute) PushType(type); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); ExtendTypeName(type, GetTemplateString(args)); type.SetHasTemplateArguments(true); @@ -481,50 +638,59 @@ TypeBuilder DemangleGNU3::DemangleType() break; } case 'P': - type = TypeBuilder::PointerType(m_arch, DemangleType().Finalize(), cnst, vltl, PointerReferenceType); + { + DemangledTypeNode child = DemangleType(); + type = DemangledTypeNode::PointerType(m_arch, std::move(child), cnst, vltl, PointerReferenceType); substitute = true; break; + } case 'R': - type = TypeBuilder::PointerType(m_arch, DemangleType().Finalize(), cnst, vltl, ReferenceReferenceType); + { + DemangledTypeNode child = DemangleType(); + type = DemangledTypeNode::PointerType(m_arch, std::move(child), cnst, vltl, ReferenceReferenceType); substitute = true; break; + } case 'O': - type = TypeBuilder::PointerType(m_arch, DemangleType().Finalize(), cnst, vltl, RValueReferenceType); + { + DemangledTypeNode child = DemangleType(); + type = DemangledTypeNode::PointerType(m_arch, std::move(child), cnst, vltl, RValueReferenceType); substitute = true; break; + } case 'C': //TODO:complex case 'G': //TODO:imaginary case 'U': //TODO:vendor extended type throw DemangleException(); - case 'v': type = TypeBuilder::VoidType(); break; - case 'w': type = TypeBuilder::IntegerType(4, false, "wchar_t"); break; //TODO: verify - case 'b': type = TypeBuilder::BoolType(); break; - case 'c': type = TypeBuilder::IntegerType(1, true); break; - case 'a': type = TypeBuilder::IntegerType(1, true); break; - case 'h': type = TypeBuilder::IntegerType(1, false); break; - case 's': type = TypeBuilder::IntegerType(2, true); break; - case 't': type = TypeBuilder::IntegerType(2, false); break; - case 'i': type = TypeBuilder::IntegerType(4, true); break; - case 'j': type = TypeBuilder::IntegerType(4, false); break; - case 'l': type = TypeBuilder::IntegerType(m_arch->GetAddressSize(), true); break; //long - case 'm': type = TypeBuilder::IntegerType(m_arch->GetAddressSize(), false); break; //ulong - case 'x': type = TypeBuilder::IntegerType(8, true); break; - case 'y': type = TypeBuilder::IntegerType(8, false); break; - case 'n': type = TypeBuilder::IntegerType(16, true); break; - case 'o': type = TypeBuilder::IntegerType(16, false); break; - case 'f': type = TypeBuilder::FloatType(4); break; - case 'd': type = TypeBuilder::FloatType(8); break; - case 'e': type = TypeBuilder::FloatType(10); break; - case 'g': type = TypeBuilder::FloatType(16); break; - case 'z': type = TypeBuilder::VarArgsType(); break; + case 'v': type = DemangledTypeNode::VoidType(); break; + case 'w': type = DemangledTypeNode::IntegerType(4, false, "wchar_t"); break; //TODO: verify + case 'b': type = DemangledTypeNode::BoolType(); break; + case 'c': type = DemangledTypeNode::IntegerType(1, true); break; + case 'a': type = DemangledTypeNode::IntegerType(1, true); break; + case 'h': type = DemangledTypeNode::IntegerType(1, false); break; + case 's': type = DemangledTypeNode::IntegerType(2, true); break; + case 't': type = DemangledTypeNode::IntegerType(2, false); break; + case 'i': type = DemangledTypeNode::IntegerType(4, true); break; + case 'j': type = DemangledTypeNode::IntegerType(4, false); break; + case 'l': type = DemangledTypeNode::IntegerType(m_arch->GetAddressSize(), true); break; //long + case 'm': type = DemangledTypeNode::IntegerType(m_arch->GetAddressSize(), false); break; //ulong + case 'x': type = DemangledTypeNode::IntegerType(8, true); break; + case 'y': type = DemangledTypeNode::IntegerType(8, false); break; + case 'n': type = DemangledTypeNode::IntegerType(16, true); break; + case 'o': type = DemangledTypeNode::IntegerType(16, false); break; + case 'f': type = DemangledTypeNode::FloatType(4); break; + case 'd': type = DemangledTypeNode::FloatType(8); break; + case 'e': type = DemangledTypeNode::FloatType(10); break; + case 'g': type = DemangledTypeNode::FloatType(16); break; + case 'z': type = DemangledTypeNode::VarArgsType(); break; case 'M': // TODO: Make into pointer to function member { - TypeBuilder name = DemangleType(); - TypeBuilder member = DemangleType(); - string fullName = member.GetStringBeforeName() + "(" + name.GetString() + "::*)" + member.GetStringAfterName(); + DemangledTypeNode memberName = DemangleType(); + DemangledTypeNode member = DemangleType(); + string fullName = member.GetStringBeforeName() + "(" + memberName.GetString() + "::*)" + member.GetStringAfterName(); //member.SetScope(NonStaticScope); - //TypeBuilder ptr = TypeBuilder::PointerType(m_arch, member, cnst, vltl); - //QualifiedName qn({name.GetString(), "*"}); + //DemangledTypeNode ptr = DemangledTypeNode::PointerType(m_arch, member, cnst, vltl); + //QualifiedName qn({memberName.GetString(), "*"}); type = CreateUnknownType(fullName); break; } @@ -532,12 +698,12 @@ TypeBuilder DemangleGNU3::DemangleType() case 'D': switch (m_reader.Read()) { - case 'd': type = TypeBuilder::FloatType(8); break; - case 'e': type = TypeBuilder::FloatType(16); break; - case 'f': type = TypeBuilder::FloatType(4); break; - case 'h': type = TypeBuilder::FloatType(2); break; - case 'i': type = TypeBuilder::IntegerType(4, true, "char32_t"); break; - case 's': type = TypeBuilder::IntegerType(2, true, "char16_t"); break; + case 'd': type = DemangledTypeNode::FloatType(8); break; + case 'e': type = DemangledTypeNode::FloatType(16); break; + case 'f': type = DemangledTypeNode::FloatType(4); break; + case 'h': type = DemangledTypeNode::FloatType(2); break; + case 'i': type = DemangledTypeNode::IntegerType(4, true, "char32_t"); break; + case 's': type = DemangledTypeNode::IntegerType(2, true, "char16_t"); break; case 'a': type = CreateUnknownType("auto"); break; //auto type case 'c': type = CreateUnknownType("decltype(auto)"); break; //decltype(auto) case 'n': @@ -559,7 +725,8 @@ TypeBuilder DemangleGNU3::DemangleType() uint64_t size = DemangleNumber(); if (m_reader.Read() != '_') throw DemangleException(); - type = TypeBuilder::ArrayType(DemangleType().Finalize(), size); + DemangledTypeNode child = DemangleType(); + type = DemangledTypeNode::ArrayType(std::move(child), size); break; } default: @@ -580,7 +747,8 @@ TypeBuilder DemangleGNU3::DemangleType() uint64_t size = DemangleNumber(); if (m_reader.Read() != '_') throw DemangleException(); - type = TypeBuilder::ArrayType(DemangleType().Finalize(), size); + DemangledTypeNode child = DemangleType(); + type = DemangledTypeNode::ArrayType(std::move(child), size); } else { @@ -616,7 +784,7 @@ TypeBuilder DemangleGNU3::DemangleType() substitute = false; m_reader.Consume(); PushType(type); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); ExtendTypeName(type, GetTemplateString(args)); type.SetHasTemplateArguments(true); @@ -633,7 +801,7 @@ TypeBuilder DemangleGNU3::DemangleType() } -TypeBuilder DemangleGNU3::DemangleSubstitution() +DemangledTypeNode DemangleGNU3::DemangleSubstitution() { static const QualifiedName stdAllocatorName(vector<string>{"std", "allocator"}); static const QualifiedName stdBasicStringName(vector<string>{"std", "basic_string"}); @@ -694,7 +862,7 @@ TypeBuilder DemangleGNU3::DemangleSubstitution() string DemangleGNU3::DemangleNumberAsString() { bool negativeFactor = false; - if ( m_reader.Peek() == 'n') + if (m_reader.Peek() == 'n') { negativeFactor = true; m_reader.Consume(); @@ -703,15 +871,32 @@ string DemangleGNU3::DemangleNumberAsString() string number; while (isdigit(m_reader.Peek())) { - number += m_reader.ReadString(1); + number += m_reader.Read(); } - return (negativeFactor?"-":"") + number; + if (negativeFactor) + return "-" + number; + return number; } // number ::= [n] <decimal> int64_t DemangleGNU3::DemangleNumber() { - return std::stol(DemangleNumberAsString().c_str()); + bool negative = false; + if (m_reader.Peek() == 'n') + { + negative = true; + m_reader.Consume(); + } + + if (!isdigit(m_reader.Peek())) + throw DemangleException(); + + int64_t result = 0; + do + { + result = result * 10 + (m_reader.Read() - '0'); + } while (isdigit(m_reader.Peek())); + return negative ? -result : result; } @@ -728,18 +913,6 @@ string DemangleGNU3::DemangleInitializer() return out; } -static int8_t HexToDec(char c) -{ - if (isdigit(c)) - { - return c - '0'; - } - else if(islower(c) && c <= 'f') - { - return c - 'a' + 10; - } - return -1; -} string DemangleGNU3::DemanglePrimaryExpression() { @@ -757,7 +930,7 @@ string DemangleGNU3::DemanglePrimaryExpression() m_reader.Consume(2); oldTopLevel = m_topLevel; m_topLevel = false; - TypeBuilder t = DemangleSymbol(tmpList); + DemangledTypeNode t = DemangleSymbol(tmpList); m_topLevel = oldTopLevel; out += t.GetStringBeforeName(); out += tmpList.GetString(); @@ -894,149 +1067,13 @@ string DemangleGNU3::DemangleExpressionList() return expr; } -static string GetOperator(char elm1, char elm2) -{ - switch (hash(elm1, elm2)) - { - case hash('d','c'): return "dynamic_cast"; - case hash('s','c'): return "static_cast"; - case hash('c','c'): return "const_cast"; - case hash('r','c'): return "reinterpret_cast"; - case hash('t','i'): return "typeid"; - case hash('t','e'): return "typeid"; - case hash('s','t'): return "sizeof"; - case hash('s','z'): return "sizeof"; - case hash('a','t'): return "alignof"; - case hash('a','z'): return "alignof"; - case hash('n','x'): return "noexcept"; - case hash('s','Z'): return "sizeof..."; - case hash('s','P'): return "sizeof..."; - case hash('s','p'): return ""; - case hash('t','w'): return "throw"; - case hash('t','r'): return "throw"; - case hash('l','s'): return "<<"; // << - case hash('r','s'): return ">>"; // >> - case hash('a','S'): return "="; // = - case hash('n','t'): return "!"; // ! - case hash('e','q'): return "=="; // == - case hash('n','e'): return "!="; // != - case hash('i','x'): return "[]"; // [] - case hash('d','t'): return "."; // . - case hash('p','t'): return "->"; // -> - case hash('m','l'): return "*"; // * - case hash('p','p'): return "++"; // ++ (postfix in <expression> context) - case hash('m','m'): return "--"; // -- (postfix in <expression> context) - case hash('n','g'): return "-"; // - (unary) - case hash('m','i'): return "-"; // - - case hash('p','s'): return "+"; // + (unary) - case hash('p','l'): return "+"; // + - case hash('a','d'): return "&"; // & (unary) - case hash('a','n'): return "&"; // & - case hash('p','m'): return "->*"; // ->* - case hash('d','v'): return "/"; // / - case hash('r','m'): return "%"; // % - case hash('l','t'): return "<"; // < - case hash('l','e'): return "<="; // <= - case hash('g','t'): return ">"; // > - case hash('g','e'): return ">="; // >= - case hash('c','m'): return ","; // , - case hash('c','l'): return "()"; // () - case hash('c','o'): return "~"; // ~ - case hash('e','o'): return "^"; // ^ - case hash('o','r'): return "|"; // | - case hash('a','a'): return "&&"; // && - case hash('o','o'): return "||"; // || - case hash('d','e'): return "*"; // * (unary) - case hash('m','L'): return "*="; // *= - case hash('p','L'): return "+="; // += - case hash('m','I'): return "-="; // -= - case hash('d','V'): return "/="; // /= - case hash('r','M'): return "%="; // %= - case hash('r','S'): return ">>="; // >>= - case hash('l','S'): return "<<="; // <<= - case hash('a','N'): return "&="; // &= - case hash('o','R'): return "|="; // |= - case hash('e','O'): return "^="; // ^= - case hash('d','l'): return "delete"; // delete - case hash('d','a'): return "delete[]"; // delete[] - case hash('n','w'): return "new"; // new - case hash('n','a'): return "new[]"; // new [] - default: return ""; - } -} -static BNNameType GetNameType(char elm1, char elm2) -{ - switch (hash(elm1, elm2)) - { - case hash('n','t'): return OperatorNotNameType; // ! - case hash('n','g'): return OperatorMinusNameType; // - (unary) - case hash('p','s'): return OperatorPlusNameType; // + (unary) - case hash('a','d'): return OperatorBitAndNameType; // & (unary) - case hash('d','e'): return OperatorStarNameType; // * (unary) - case hash('i','x'): return OperatorArrayNameType; // [] - case hash('p','p'): return OperatorIncrementNameType; // ++ (postfix in <expression> context) - case hash('m','m'): return OperatorDecrementNameType; // -- (postfix in <expression> context) - case hash('l','s'): return OperatorLeftShiftNameType; // << - case hash('r','s'): return OperatorRightShiftNameType; // >> - case hash('a','S'): return OperatorAssignNameType; // = - case hash('e','q'): return OperatorEqualNameType; // == - case hash('n','e'): return OperatorNotEqualNameType; // != - case hash('p','t'): return OperatorArrowNameType; // -> - case hash('m','l'): return OperatorStarNameType; // * - case hash('m','i'): return OperatorMinusNameType; // - - case hash('p','l'): return OperatorPlusNameType; // + - case hash('a','n'): return OperatorBitAndNameType; // & - case hash('p','m'): return OperatorArrowStarNameType; // ->* - case hash('d','v'): return OperatorDivideNameType; // / - case hash('r','m'): return OperatorModulusNameType; // % - case hash('l','t'): return OperatorLessThanNameType; // < - case hash('l','e'): return OperatorLessThanEqualNameType; // <= - case hash('g','t'): return OperatorGreaterThanNameType; // > - case hash('g','e'): return OperatorGreaterThanEqualNameType; // >= - case hash('c','m'): return OperatorCommaNameType; // , - case hash('c','l'): return OperatorParenthesesNameType; // () - case hash('c','o'): return OperatorTildeNameType; // ~ - case hash('e','o'): return OperatorXorNameType; // ^ - case hash('o','r'): return OperatorBitOrNameType; // | - case hash('a','a'): return OperatorLogicalAndNameType; // && - case hash('o','o'): return OperatorLogicalOrNameType; // || - case hash('m','L'): return OperatorStarEqualNameType; // *= - case hash('p','L'): return OperatorPlusEqualNameType; // += - case hash('m','I'): return OperatorMinusEqualNameType; // -= - case hash('d','V'): return OperatorDivideEqualNameType; // /= - case hash('r','M'): return OperatorModulusEqualNameType; // %= - case hash('r','S'): return OperatorRightShiftEqualNameType; // >>= - case hash('l','S'): return OperatorLeftShiftEqualNameType; // <<= - case hash('a','N'): return OperatorAndEqualNameType; // &= - case hash('o','R'): return OperatorOrEqualNameType; // |= - case hash('e','O'): return OperatorXorEqualNameType; // ^= - case hash('d','l'): return OperatorDeleteNameType; // delete - case hash('d','a'): return OperatorDeleteArrayNameType; // delete[] - case hash('n','w'): return OperatorNewNameType; // new - case hash('n','a'): return OperatorNewArrayNameType; // new [] - case hash('C','1'): return ConstructorNameType; - case hash('C','2'): return ConstructorNameType; - case hash('C','3'): return ConstructorNameType; - case hash('C','4'): return ConstructorNameType; - case hash('C','5'): return ConstructorNameType; - case hash('D','0'): return DestructorNameType; - case hash('D','1'): return DestructorNameType; - case hash('D','2'): return DestructorNameType; - case hash('D','3'): return DestructorNameType; - case hash('D','4'): return DestructorNameType; - case hash('D','5'): return DestructorNameType; - default: - return NoNameType; - } -} - -TypeBuilder DemangleGNU3::DemangleUnqualifiedName() +DemangledTypeNode DemangleGNU3::DemangleUnqualifiedName() { indent() MyLogDebug("%s: '%s'\n", __FUNCTION__, m_reader.GetRaw().c_str()); - TypeBuilder outType; + DemangledTypeNode outType; char elm1 = m_reader.Read(); char elm2 = m_reader.Read(); switch (hash(elm1, elm2)) @@ -1143,13 +1180,13 @@ TypeBuilder DemangleGNU3::DemangleUnqualifiedName() { string name; name = "'lambda"; - vector<TypeBuilder> params; + vector<DemangledTypeNode> lambdaParams; do { - TypeBuilder param = DemangleType(); + DemangledTypeNode param = DemangleType(); if (param.GetClass() == VoidTypeClass) break; - params.push_back(std::move(param)); + lambdaParams.push_back(std::move(param)); }while (m_reader.Peek() != 'E'); m_reader.Consume(); @@ -1161,11 +1198,11 @@ TypeBuilder DemangleGNU3::DemangleUnqualifiedName() throw DemangleException(); name += "'("; - for (size_t i = 0; i < params.size(); i++) + for (size_t i = 0; i < lambdaParams.size(); i++) { if (i != 0) name += ", "; - name += params[i].GetString(); + name += lambdaParams[i].GetString(); } name += ")"; m_lastName = name; @@ -1232,7 +1269,7 @@ QualifiedName DemangleGNU3::DemangleBaseUnresolvedName() if (m_reader.Peek() == 'I') { m_reader.Consume(); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); out.back() += GetTemplateString(args); PushType(CreateUnknownType(out)); @@ -1253,7 +1290,7 @@ QualifiedName DemangleGNU3::DemangleBaseUnresolvedName() if (m_reader.Peek() == 'I') { m_reader.Consume(); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); out.back() += GetTemplateString(args); } @@ -1264,14 +1301,14 @@ QualifiedName DemangleGNU3::DemangleBaseUnresolvedName() } -TypeBuilder DemangleGNU3::DemangleUnresolvedType() +DemangledTypeNode DemangleGNU3::DemangleUnresolvedType() { indent(); MyLogDebug("%s: '%s'\n", __FUNCTION__, m_reader.GetRaw().c_str()); //<unresolved-type> ::= <template-param> [ <template-args> ] # T:: or T<X,Y>:: // ::= <decltype> # decltype(p):: // ::= <substitution> - TypeBuilder type; + DemangledTypeNode type; if (m_reader.Peek() == 'T') { m_reader.Consume(); @@ -1280,7 +1317,7 @@ TypeBuilder DemangleGNU3::DemangleUnresolvedType() { PushType(type); m_reader.Consume(); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); ExtendTypeName(type, GetTemplateString(args)); type.SetHasTemplateArguments(true); @@ -1403,7 +1440,7 @@ string DemangleGNU3::DemangleExpression() return GetOperator(elm1, elm2) + "(" + DemangleTypeString() + ")"; case hash('s','P'): { - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); return "sizeof...(" + GetTemplateString(args) + ")..."; } @@ -1471,7 +1508,7 @@ string DemangleGNU3::DemangleExpression() return "(" + DemangleExpressionList() + ")"; case hash('c','v'): //type (expression) { - TypeBuilder type = DemangleType(); + DemangledTypeNode type = DemangleType(); out = type.GetString(); if (m_reader.Peek() == '_') out += " (" + DemangleExpressionList() + ")"; @@ -1495,7 +1532,7 @@ string DemangleGNU3::DemangleExpression() // ::= fL <L-1 num> p <CV> <prm-2 num> _ # L > 0, second and later parameters bool cnst = false, vltl = false, rstrct = false; - TypeBuilder type; + DemangledTypeNode type; int64_t listNumber = 0; int64_t elementNum = 0; char elm; @@ -1566,11 +1603,10 @@ string DemangleGNU3::DemangleExpression() do { out += DemangleSourceName(); - PushType(TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference( - UnknownNamedTypeClass, out))); + PushType(DemangledTypeNode::NamedType(UnknownNamedTypeClass, _STD_VECTOR<_STD_STRING>{out})); if (m_reader.Peek() == 'I') { - vector<FunctionParameter> args; + vector<string> args; m_reader.Consume(); //<tmplate-args> DemangleTemplateArgs(args); @@ -1590,7 +1626,7 @@ string DemangleGNU3::DemangleExpression() out += DemangleSourceName(); if (m_reader.Peek() == 'I') { - vector<FunctionParameter> args; + vector<string> args; m_reader.Consume(); //<tmplate-args> DemangleTemplateArgs(args); @@ -1613,7 +1649,7 @@ string DemangleGNU3::DemangleExpression() out = DemangleSourceName(); if (m_reader.Peek() == 'I') { - vector<FunctionParameter> args; + vector<string> args; m_reader.Consume(); //<tmplate-args> DemangleTemplateArgs(args); @@ -1625,11 +1661,11 @@ string DemangleGNU3::DemangleExpression() } -void DemangleGNU3::DemangleTemplateArgs(vector<FunctionParameter>& args) +void DemangleGNU3::DemangleTemplateArgs(vector<string>& args) { indent(); MyLogDebug("%s:: '%s'\n", __FUNCTION__, m_reader.GetRaw().c_str()); - TypeBuilder tmp; + DemangledTypeNode tmp; bool tmpValid = false; string expr; bool topLevel; @@ -1640,12 +1676,12 @@ void DemangleGNU3::DemangleTemplateArgs(vector<FunctionParameter>& args) { case 'L': expr = DemanglePrimaryExpression(); - args.push_back({expr, nullptr, true, Variable()}); + args.push_back(expr); tmp = CreateUnknownType(expr); tmpValid = true; break; case 'X': - args.push_back({DemangleExpression(), nullptr, true, Variable()}); + args.push_back(DemangleExpression()); if (m_reader.Read() != 'E') throw DemangleException(); break; @@ -1658,7 +1694,7 @@ void DemangleGNU3::DemangleTemplateArgs(vector<FunctionParameter>& args) m_topLevel = false; tmp = DemangleType(); m_topLevel = topLevel; - args.push_back({tmp.GetString(), nullptr, true, Variable()}); + args.push_back(tmp.GetString()); tmpValid = true; } if (m_topLevel && tmpValid) @@ -1674,7 +1710,7 @@ void DemangleGNU3::DemangleTemplateArgs(vector<FunctionParameter>& args) } -TypeBuilder DemangleGNU3::DemangleNestedName() +DemangledTypeNode DemangleGNU3::DemangleNestedName() { /* This can be either a qualified name like: "foo::bar::bas" @@ -1708,13 +1744,12 @@ TypeBuilder DemangleGNU3::DemangleNestedName() indent(); MyLogDebug("%s:: '%s'\n", __FUNCTION__, m_reader.GetRaw().c_str()); - TypeBuilder type = TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference( - UnknownNamedTypeClass, QualifiedName())); + DemangledTypeNode type = DemangledTypeNode::NamedType(UnknownNamedTypeClass, QualifiedName()); bool cnst = false, vltl = false, rstrct = false; bool ref = false; bool rvalueRef = false; bool substitute = true; - TypeBuilder newType; + DemangledTypeNode newType; bool base = false; bool isTemplate = false; bool hasB = false; @@ -1757,7 +1792,7 @@ TypeBuilder DemangleGNU3::DemangleNestedName() { if (!base) throw DemangleException(); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); ExtendTypeName(type, GetTemplateString(args)); type.SetHasTemplateArguments(true); @@ -1774,12 +1809,15 @@ TypeBuilder DemangleGNU3::DemangleNestedName() if (!isTemplate) { type.SetNameType(newType.GetNameType()); - QualifiedName newName = type.GetTypeName() + newType.GetTypeName(); - if (newName.StringSize() > MAX_DEMANGLE_LENGTH) + auto aNames = type.GetTypeName(); + auto bNames = newType.GetTypeName(); + _STD_VECTOR<_STD_STRING> newName; + newName.reserve(aNames.size() + bNames.size()); + newName.insert(newName.end(), aNames.begin(), aNames.end()); + newName.insert(newName.end(), bNames.begin(), bNames.end()); + if (TotalStringSize(newName) > MAX_DEMANGLE_LENGTH) throw DemangleException("Detected adversarial mangled string"); - type.SetNamedTypeReference( - NamedTypeReference::GenerateAutoDemangledTypeReference(type.GetNamedTypeReference()->GetTypeReferenceClass(), newName) - ); + type.SetNTR(type.GetNTRClass(), newName); type.SetHasTemplateArguments(false); } if (substitute && m_reader.Peek() != 'E') @@ -1814,11 +1852,11 @@ TypeBuilder DemangleGNU3::DemangleNestedName() } -TypeBuilder DemangleGNU3::DemangleLocalName() +DemangledTypeNode DemangleGNU3::DemangleLocalName() { indent(); MyLogDebug("%s '%s'\n", __FUNCTION__, m_reader.GetRaw().c_str()); - TypeBuilder type; + DemangledTypeNode type; QualifiedName varName; bool oldTopLevel = m_topLevel; m_topLevel = false; @@ -1833,12 +1871,17 @@ TypeBuilder DemangleGNU3::DemangleLocalName() if (m_reader.Peek() != 's') { //<entity name> - TypeBuilder tmpType = DemangleName(); - type = TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference(UnknownNamedTypeClass, varName)); - QualifiedName newName = type.GetTypeName() + tmpType.GetTypeName(); - if (newName.StringSize() > MAX_DEMANGLE_LENGTH) + DemangledTypeNode tmpType = DemangleName(); + type = DemangledTypeNode::NamedType(UnknownNamedTypeClass, varName); + auto aNames = type.GetTypeName(); + auto bNames = tmpType.GetTypeName(); + _STD_VECTOR<_STD_STRING> newName; + newName.reserve(aNames.size() + bNames.size()); + newName.insert(newName.end(), aNames.begin(), aNames.end()); + newName.insert(newName.end(), bNames.begin(), bNames.end()); + if (TotalStringSize(newName) > MAX_DEMANGLE_LENGTH) throw DemangleException("Detected adversarial mangled string"); - type.SetTypeName(newName); + type.SetTypeName(std::move(newName)); type.SetConst(tmpType.IsConst()); type.SetVolatile(tmpType.IsVolatile()); type.SetPointerSuffix(tmpType.GetPointerSuffix()); @@ -1846,7 +1889,7 @@ TypeBuilder DemangleGNU3::DemangleLocalName() else { m_reader.Consume(); - type = TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference(UnknownNamedTypeClass, varName)); + type = DemangledTypeNode::NamedType(UnknownNamedTypeClass, varName); } // [<discriminator>] //TODO: What do we do with discriminators? @@ -1870,7 +1913,7 @@ TypeBuilder DemangleGNU3::DemangleLocalName() } -TypeBuilder DemangleGNU3::DemangleName() +DemangledTypeNode DemangleGNU3::DemangleName() { indent(); MyLogDebug("%s '%s'\n", __FUNCTION__, m_reader.GetRaw().c_str()); @@ -1886,7 +1929,7 @@ TypeBuilder DemangleGNU3::DemangleName() <unscoped-template-name> ::= <unscoped-name> ::= <substitution> */ - TypeBuilder type; + DemangledTypeNode type; bool substitute = false; switch (m_reader.Read()) { @@ -1895,9 +1938,9 @@ TypeBuilder DemangleGNU3::DemangleName() { m_reader.Consume(1); type = DemangleUnqualifiedName(); - QualifiedName qn = type.GetTypeName(); + auto qn = type.GetTypeName(); qn.insert(qn.begin(), "std"); - type.SetTypeName(qn); + type.SetTypeName(std::move(qn)); substitute = true; } else @@ -1910,7 +1953,7 @@ TypeBuilder DemangleGNU3::DemangleName() m_reader.Consume(); if (substitute) PushType(type); - vector<FunctionParameter> args; + vector<string> args; DemangleTemplateArgs(args); ExtendTypeName(type, GetTemplateString(args)); type.SetHasTemplateArguments(true); @@ -1937,7 +1980,7 @@ TypeBuilder DemangleGNU3::DemangleName() { PushType(type); //<unscoped-template-name> - vector<FunctionParameter> args; + vector<string> args; m_reader.Consume(); //<tmplate-args> DemangleTemplateArgs(args); @@ -1952,15 +1995,15 @@ TypeBuilder DemangleGNU3::DemangleName() } -TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) +DemangledTypeNode DemangleGNU3::DemangleSymbol(QualifiedName& varName) { indent(); MyLogDebug("%s: %s\n", __FUNCTION__, m_reader.GetRaw().c_str()); - TypeBuilder returnType; + DemangledTypeNode returnType; bool isReturnTypeUnknown = false; - TypeBuilder type; - vector<FunctionParameter> params; - Confidence<bool> cnst = false, vltl = false, rstrct = false; + DemangledTypeNode type; + ParamList params; + bool cnst = false, vltl = false, rstrct = false; bool oldTopLevel; QualifiedName name; @@ -1987,9 +2030,9 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) throw DemangleException(); case 'V': { - TypeBuilder t = DemangleSymbol(name); + DemangledTypeNode t = DemangleSymbol(name); varName.push_back("guard_variable_for_" + t.GetTypeAndName(name)); - type = TypeBuilder::IntegerType(1, false); + type = DemangledTypeNode::IntegerType(1, false); if (m_reader.Length() == 0) return type; //function parameters @@ -2037,13 +2080,13 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) throw DemangleException(); case 'C': { - TypeBuilder t = DemangleType(); + DemangledTypeNode t = DemangleType(); DemangleNumberAsString(); if (m_reader.Read() != '_') throw DemangleException(); - return TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference(UnknownNamedTypeClass, - {"construction_vtable_for_" + DemangleTypeString() + "-in-" + t.GetString()})); + return DemangledTypeNode::NamedType(UnknownNamedTypeClass, + _STD_VECTOR<_STD_STRING>{"construction_vtable_for_" + DemangleTypeString() + "-in-" + t.GetString()}); } case 'D': LogWarn("Unsupported: 'typeinfo common proxy'\n"); @@ -2058,32 +2101,32 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) throw DemangleException(); oldTopLevel = m_topLevel; m_topLevel = false; - TypeBuilder t = DemangleSymbol(name); + DemangledTypeNode t = DemangleSymbol(name); m_topLevel = oldTopLevel; - return TypeBuilder::NamedType( - NamedTypeReference::GenerateAutoDemangledTypeReference(UnknownNamedTypeClass, - {"non-virtual_thunk_to_" + name.GetString() + t.GetStringAfterName()})); + return DemangledTypeNode::NamedType(UnknownNamedTypeClass, + _STD_VECTOR<_STD_STRING>{"non-virtual_thunk_to_" + name.GetString() + t.GetStringAfterName()}); } case 'H': LogWarn("Unsupported: 'TLS init function'\n"); throw DemangleException(); case 'I': - return TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference(StructNamedTypeClass, - {"typeinfo_for_" + DemangleTypeString()})); + return DemangledTypeNode::NamedType(StructNamedTypeClass, + _STD_VECTOR<_STD_STRING>{"typeinfo_for_" + DemangleTypeString()}); case 'J': LogWarn("Unsupported: 'java class'\n"); throw DemangleException(); case 'S': { - TypeBuilder t = DemangleType(); + DemangledTypeNode t = DemangleType(); varName = vector<string>{"typeinfo_name_for_" + t.GetString()}; - return TypeBuilder::ArrayType(Type::IntegerType(1, true), 0); + DemangledTypeNode elemType = DemangledTypeNode::IntegerType(1, true); + return DemangledTypeNode::ArrayType(std::move(elemType), 0); } case 'T': //VTT { - TypeBuilder t = DemangleType(); - return TypeBuilder::NamedType(NamedTypeReference::GenerateAutoDemangledTypeReference(StructNamedTypeClass, - {"VTT_for_" + t.GetString()})); + DemangledTypeNode t = DemangleType(); + return DemangledTypeNode::NamedType(StructNamedTypeClass, + _STD_VECTOR<_STD_STRING>{"VTT_for_" + t.GetString()}); } case 'v': //TODO: Convert to whatever the actual type is! { @@ -2095,16 +2138,14 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) throw DemangleException(); oldTopLevel = m_topLevel; m_topLevel = false; - TypeBuilder t = DemangleSymbol(name); + DemangledTypeNode t = DemangleSymbol(name); m_topLevel = oldTopLevel; - return TypeBuilder::NamedType( - NamedTypeReference::GenerateAutoDemangledTypeReference(UnknownNamedTypeClass, - {"virtual_thunk_to_" + name.GetString() + t.GetStringAfterName()})); + return DemangledTypeNode::NamedType(UnknownNamedTypeClass, + _STD_VECTOR<_STD_STRING>{"virtual_thunk_to_" + name.GetString() + t.GetStringAfterName()}); } case 'V': //Vtable - return TypeBuilder::NamedType( - NamedTypeReference::GenerateAutoDemangledTypeReference(StructNamedTypeClass, - {"vtable_for_" + DemangleTypeString()})); + return DemangledTypeNode::NamedType(StructNamedTypeClass, + _STD_VECTOR<_STD_STRING>{"vtable_for_" + DemangleTypeString()}); case 'W': MyLogDebug("Unsupported: 'TLS wrapper function'\n"); throw DemangleException(); @@ -2130,7 +2171,7 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) varName = type.GetTypeName(); cnst = type.IsConst(); vltl = type.IsVolatile(); - set<BNPointerSuffix> suffix = type.GetPointerSuffix(); + auto suffix = type.GetPointerSuffix(); if (m_reader.Peek() == 'J') { m_reader.Consume(); @@ -2139,7 +2180,7 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) if (m_reader.Peek() == 'B') { m_reader.Consume(); - TypeBuilder t = DemangleUnqualifiedName(); + DemangledTypeNode t = DemangleUnqualifiedName(); if (t.GetString() == "cxx11") { @@ -2151,7 +2192,7 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) type.GetNameType() == ConstructorNameType || type.GetNameType() == DestructorNameType) { - returnType = TypeBuilder::VoidType(); + returnType = DemangledTypeNode::VoidType(); } else if (m_isParameter || type.HasTemplateArguments()) { @@ -2160,11 +2201,11 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) else { isReturnTypeUnknown = true; - returnType = TypeBuilder::IntegerType(m_arch->GetAddressSize(), true); + returnType = DemangledTypeNode::IntegerType(m_arch->GetAddressSize(), true); } m_functionSubstitute.push_back({}); - for (size_t i = 0; m_reader.Length() > 0; i++) + while (m_reader.Length() > 0) { if (m_reader.Peek() == 'E') { @@ -2191,7 +2232,7 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) MyLogDebug("Var_%d: %s\n", i, m_reader.GetRaw().c_str()); if (m_reader.PeekString(2) == "@@") break; - TypeBuilder param = DemangleType(); + DemangledTypeNode param = DemangleType(); if (param.GetClass() == VoidTypeClass) { if (m_reader.Peek() == 'E') @@ -2202,8 +2243,9 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) break; } m_functionSubstitute.back().push_back(param); - params.push_back({"", param.Finalize(), true, Variable()}); - if (param.GetClass() == VarArgsTypeClass) + bool isVarArgs = param.GetClass() == VarArgsTypeClass; + params.push_back({"", std::make_shared<DemangledTypeNode>(std::move(param))}); + if (isVarArgs) { if (m_reader.Peek() == 'E') { @@ -2216,13 +2258,14 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) m_functionSubstitute.pop_back(); m_isParameter = false; - type = TypeBuilder::FunctionType(returnType.Finalize()-> - WithConfidence(isReturnTypeUnknown ? BN_MINIMUM_CONFIDENCE : BN_DEFAULT_CONFIDENCE), nullptr, params); + type = DemangledTypeNode::FunctionType(std::move(returnType), nullptr, std::move(params)); + if (isReturnTypeUnknown) + type.SetReturnTypeConfidence(BN_MINIMUM_CONFIDENCE); type.SetPointerSuffix(suffix); type.SetConst(cnst); type.SetVolatile(vltl); - if (rstrct.GetValue()) + if (rstrct) type.SetPointerSuffix({RestrictSuffix}); // PrintTables(); @@ -2234,7 +2277,9 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName) } -bool DemangleGNU3::IsGNU3MangledString(const string& name) +// ===== Non-templated static methods ===== + +bool DemangleGNU3Static::IsGNU3MangledString(const string& name) { string headerless = name; string header; @@ -2248,7 +2293,7 @@ bool DemangleGNU3::IsGNU3MangledString(const string& name) } -bool DemangleGNU3::DemangleGlobalHeader(string& name, string& header) +bool DemangleGNU3Static::DemangleGlobalHeader(string& name, string& header) { size_t strippedCount = 0; string encoded = name; @@ -2281,19 +2326,7 @@ bool DemangleGNU3::DemangleGlobalHeader(string& name, string& header) } -bool DemangleGNU3::DemangleStringGNU3(Architecture* arch, const string& name, Ref<Type>& outType, QualifiedName& outVarName, const Ref<BinaryView>& view) -{ - return DemangleStringGNU3(arch, name, outType, outVarName); -} - - -bool DemangleGNU3::DemangleStringGNU3(Architecture* arch, const string& name, Ref<Type>& outType, QualifiedName& outVarName, BinaryView* view) -{ - return DemangleStringGNU3(arch, name, outType, outVarName); -} - - -bool DemangleGNU3::DemangleStringGNU3(Architecture* arch, const string& name, Ref<Type>& outType, QualifiedName& outVarName) +bool DemangleGNU3Static::DemangleStringGNU3(Architecture* arch, const string& name, Ref<Type>& outType, QualifiedName& outVarName) { string encoding = name; string header; @@ -2305,18 +2338,17 @@ bool DemangleGNU3::DemangleStringGNU3(Architecture* arch, const string& name, Re encoding = encoding.substr(3); else if (foundHeader && !header.empty()) { - // Some variable constructors/destructors are __GLOBAL__I_name - // And there are even __GLOBAL__sub_I_file_name.cpp outVarName.clear(); outVarName.push_back(header); outVarName.push_back(encoding); - outType = CreateUnknownType(outVarName).Finalize(); + outType = DemangledTypeNode::NamedType(UnknownNamedTypeClass, outVarName).Finalize(); return true; } else return false; - DemangleGNU3 demangle(arch, encoding); + thread_local DemangleGNU3 demangle(arch, encoding); + demangle.Reset(arch, encoding); try { outType = demangle.DemangleSymbol(outVarName).Finalize(); @@ -2349,6 +2381,11 @@ bool DemangleGNU3::DemangleStringGNU3(Architecture* arch, const string& name, Re } +// ===== Explicit template instantiation ===== + + +// ===== Demangler plugin registration ===== + class GNU3Demangler: public Demangler { public: @@ -2359,7 +2396,7 @@ public: virtual bool IsMangledString(const string& name) override { - return DemangleGNU3::IsGNU3MangledString(name); + return DemangleGNU3Static::IsGNU3MangledString(name); } #ifdef BINARYNINJACORE_LIBRARY @@ -2370,9 +2407,7 @@ public: Ref<BinaryView> view) override #endif { - if (view) - return DemangleGNU3::DemangleStringGNU3(arch, name, outType, outVarName, view); - return DemangleGNU3::DemangleStringGNU3(arch, name, outType, outVarName); + return DemangleGNU3Static::DemangleStringGNU3(arch, name, outType, outVarName); } }; |
