diff --git a/src/add-ons/kernel/debugger/demangle/gcc3+.cpp b/src/add-ons/kernel/debugger/demangle/gcc3+.cpp index bfa3a2edf2..65b02fab4a 100644 --- a/src/add-ons/kernel/debugger/demangle/gcc3+.cpp +++ b/src/add-ons/kernel/debugger/demangle/gcc3+.cpp @@ -1,5 +1,6 @@ /* * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2021, Jerome Duval, jerome.duval@gmail.com. * Distributed under the terms of the MIT License. */ @@ -20,7 +21,7 @@ #include "demangle.h" -// C++ ABI: http://www.codesourcery.com/public/cxx-abi/abi.html +// C++ ABI: https://itanium-cxx-abi.github.io/cxx-abi/abi.html //#define TRACE_GCC3_DEMANGLER @@ -1297,6 +1298,58 @@ private: }; +class ClonedNode : public ObjectNode { +public: + ClonedNode(Node* clone, Node* node) + : + ObjectNode(NULL), + fNode(node), + fCloneNode(clone) + { + fNode->SetParent(this); + fCloneNode->SetParent(this); + } + + virtual bool GetName(NameBuffer& buffer) const + { + if (!fNode->GetName(buffer)) + return false; + + buffer.Append(" [clone "); + if (!fCloneNode->GetName(buffer)) + return false; + buffer.Append("]"); + return true; + } + + virtual Node* GetUnqualifiedNode(Node* beforeNode) + { + return beforeNode == fCloneNode + ? fNode->GetUnqualifiedNode(beforeNode) + : fCloneNode->GetUnqualifiedNode(beforeNode); + } + + virtual bool IsNoReturnValueFunction() const + { + return fNode->IsNoReturnValueFunction(); + } + + virtual object_type ObjectType() const + { + return fNode->ObjectType(); + } + + virtual prefix_type PrefixType() const + { + return PREFIX_UNKNOWN; + } + +private: + Node* fNode; + Node* fCloneNode; +}; + + typedef PrefixedNode DependentNameNode; @@ -1843,6 +1896,7 @@ private: const char*& versionSuffix, ObjectNode*& _node); + bool _ParseClone(ObjectNode*& _node); bool _ParseEncoding(ObjectNode*& _node); bool _ParseSpecialName(Node*& _node); bool _ParseCallOffset(bool& nonVirtual, @@ -2135,12 +2189,12 @@ Demangler::_Parse(const char* mangledName, const char*& versionSuffix, versionSuffix != NULL ? versionSuffix - mangledName : strlen(mangledName)); - // ::= _Z + // ::= _Z []* if (!fInput.SkipPrefix("_Z")) return ERROR_NOT_MANGLED; - if (!_ParseEncoding(_node)) + if (!_ParseEncoding(_node) || !_ParseClone(_node)) return fError; if (fInput.CharsRemaining() != 0) { @@ -2152,6 +2206,34 @@ Demangler::_Parse(const char* mangledName, const char*& versionSuffix, } +bool +Demangler::_ParseClone(ObjectNode*& _node) +{ + DEBUG_SCOPE("_ParseClone"); + + while (fInput.HasPrefix('.')) { + int count = fInput.CharsRemaining(); + int i = 1; + while (true) { + for (; i < count && fInput[i] != '.'; i++) + ; + if (i + 1 >= count || fInput[i + 1] < '0' || fInput[i + 1] > '9') + break; + i++; + } + if (i == 1) + break; + Node* clone; + if (!_CreateNodeAndSkip(fInput.String(), i, i, clone)) + return false; + + if (!NodeCreator(this)(clone, _node, _node)) + return false; + } + return true; +} + + bool Demangler::_ParseEncoding(ObjectNode*& _node) { @@ -2176,7 +2258,8 @@ Demangler::_ParseEncoding(ObjectNode*& _node) if (!_ParseName(name)) return false; - if (fInput.CharsRemaining() == 0 || fInput.HasPrefix('E')) { + if (fInput.CharsRemaining() == 0 || fInput.HasPrefix('E') + || fInput.HasPrefix('.')) { // return NodeCreator(this)(name, _node); } @@ -3225,8 +3308,9 @@ Demangler::_ParseBareFunctionType(FunctionNode* node) return false; node->AddType(typeNode); - } while (fInput.CharsRemaining() > 0 && fInput[0] != 'E'); - // 'E' delimits + } while (fInput.CharsRemaining() > 0 && fInput[0] != 'E' + && fInput[0] != '.'); + // 'E' und '.' delimit return true; } diff --git a/src/tests/add-ons/kernel/debugger/DemangleTest.cpp b/src/tests/add-ons/kernel/debugger/DemangleTest.cpp index c485490ca9..e3eb5aa27c 100644 --- a/src/tests/add-ons/kernel/debugger/DemangleTest.cpp +++ b/src/tests/add-ons/kernel/debugger/DemangleTest.cpp @@ -51,6 +51,9 @@ DemangleTest::RunGCC3PTests() "_ZN8BPrivate16BContainerWindow10UpdateMenuEP5BMenuNS0_17UpdateMenuContextE"); TEST("icu_57::BreakIterator::registerInstance(icu_57::BreakIterator*, icu_57::Locale const&, UBreakIteratorType, UErrorCode&)", "_ZN6icu_5713BreakIterator16registerInstanceEPS0_RKNS_6LocaleE18UBreakIteratorTypeR10UErrorCode"); + TEST("void std::__cxx11::basic_string, std::allocator >::_M_construct(char*, char*, std::forward_iterator_tag) [clone .isra.25]", + "_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPcEEvT_S7_St20forward_iterator_tag.isra.25"); + TEST("foo(int) [clone .part.1.123456] [clone .constprop.777.54321]", "_Z3fooi.part.1.123456.constprop.777.54321"); } #undef TEST