demangler/gcc3+: handle vendor-specific suffix

fix bug #13720

Change-Id: I3363572b88aaa674f5ee7cf69866b9f2bbb4e84c
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4084
Reviewed-by: Rene Gollent <[email protected]>
Reviewed-by: Alex von Gluck IV <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Jérôme Duval
2021-06-11 01:42:54 +00:00
committed by Alex von Gluck IV
parent 8c232f164a
commit 1b0f948ea2
2 changed files with 93 additions and 6 deletions
+90 -6
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2009-2011, Ingo Weinhold, [email protected].
* Copyright 2021, Jerome Duval, [email protected].
* 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));
// <mangled-name> ::= _Z <encoding>
// <mangled-name> ::= _Z <encoding> [<clone-suffix>]*
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<ClonedNode>(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('.')) {
// <data name>
return NodeCreator<ObjectNode>(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 <function-type>
} while (fInput.CharsRemaining() > 0 && fInput[0] != 'E'
&& fInput[0] != '.');
// 'E' und '.' delimit <function-type>
return true;
}
@@ -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<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(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