[ItaniumDemangle] Strip __alloc_token_ to transparently demangle allocation functions (#191048)
Update the Itanium demangler to recognize and strip `__alloc_token_` prefixes introduced by AllocToken instrumentation [1]. This ensures that instrumented allocation functions (e.g., `__alloc_token__Znwm`) demangle back to their original source-level names (e.g., `operator new(unsigned long)`) with a suffix `(.alloc_token)` indicating their non-standard origin. Since AllocToken is intended to be transparent to users who continue to use `operator new` as before, the demangled name should reflect this reality instead of confusing users with internal instrumentation names in stack traces or symbolization output. Synchronize changes across llvm and libcxxabi copies. [1] https://clang.llvm.org/docs/AllocToken.html Original RFC: https://discourse.llvm.org/t/rfc-a-framework-for-allocator-partitioning-hints/87434
This commit is contained in:
parent
42ef1321e6
commit
fb6f1bde00
6 changed files with 70 additions and 0 deletions
|
|
@ -6157,8 +6157,17 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
|
|||
// extension ::= ___Z <encoding> _block_invoke
|
||||
// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
|
||||
// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
|
||||
// extension ::= __alloc_token__Z <encoding>
|
||||
// extension ::= __alloc_token_<decimal-digit>+__Z <encoding>
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
|
||||
bool AllocToken = consumeIf("__alloc_token_");
|
||||
if (AllocToken) {
|
||||
const char *Saved = First;
|
||||
if (parseNumber().empty() || !consumeIf('_'))
|
||||
First = Saved;
|
||||
}
|
||||
|
||||
if (consumeIf("_Z") || consumeIf("__Z")) {
|
||||
Node *Encoding = getDerived().parseEncoding(ParseParams);
|
||||
if (Encoding == nullptr)
|
||||
|
|
@ -6168,6 +6177,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
|
|||
make<DotSuffix>(Encoding, std::string_view(First, Last - First));
|
||||
First = Last;
|
||||
}
|
||||
if (AllocToken)
|
||||
Encoding = make<DotSuffix>(Encoding, ".alloc_token");
|
||||
if (numLeft() != 0)
|
||||
return nullptr;
|
||||
return Encoding;
|
||||
|
|
|
|||
|
|
@ -30219,4 +30219,15 @@
|
|||
{"_Z3fooIPU9__ptrauthILj1ELb0ELj64EEPiEvT_", "void foo<int* __ptrauth<1u, false, 64u>*>(int* __ptrauth<1u, false, 64u>*)"},
|
||||
|
||||
{"_ZN1CpmEi", "C::operator->*(int)"},
|
||||
|
||||
// AllocToken instrumentation
|
||||
{"__alloc_token__Znwm", "operator new(unsigned long) (.alloc_token)"},
|
||||
{"__alloc_token__Znam", "operator new[](unsigned long) (.alloc_token)"},
|
||||
{"__alloc_token__ZnwmRKSt9nothrow_t", "operator new(unsigned long, std::nothrow_t const&) (.alloc_token)"},
|
||||
{"__alloc_token__ZnamRKSt9nothrow_t", "operator new[](unsigned long, std::nothrow_t const&) (.alloc_token)"},
|
||||
{"__alloc_token_0__Znwm", "operator new(unsigned long) (.alloc_token)"},
|
||||
{"__alloc_token_1__Znam", "operator new[](unsigned long) (.alloc_token)"},
|
||||
{"__alloc_token_123__ZnwmRKSt9nothrow_t", "operator new(unsigned long, std::nothrow_t const&) (.alloc_token)"},
|
||||
{"__alloc_token__Znwm.llvm.1234", "operator new(unsigned long) (.llvm.1234) (.alloc_token)"},
|
||||
{"__alloc_token_123__Z3foov", "foo() (.alloc_token)"},
|
||||
// clang-format on
|
||||
|
|
|
|||
|
|
@ -6157,8 +6157,17 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
|
|||
// extension ::= ___Z <encoding> _block_invoke
|
||||
// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
|
||||
// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
|
||||
// extension ::= __alloc_token__Z <encoding>
|
||||
// extension ::= __alloc_token_<decimal-digit>+__Z <encoding>
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
|
||||
bool AllocToken = consumeIf("__alloc_token_");
|
||||
if (AllocToken) {
|
||||
const char *Saved = First;
|
||||
if (parseNumber().empty() || !consumeIf('_'))
|
||||
First = Saved;
|
||||
}
|
||||
|
||||
if (consumeIf("_Z") || consumeIf("__Z")) {
|
||||
Node *Encoding = getDerived().parseEncoding(ParseParams);
|
||||
if (Encoding == nullptr)
|
||||
|
|
@ -6168,6 +6177,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
|
|||
make<DotSuffix>(Encoding, std::string_view(First, Last - First));
|
||||
First = Last;
|
||||
}
|
||||
if (AllocToken)
|
||||
Encoding = make<DotSuffix>(Encoding, ".alloc_token");
|
||||
if (numLeft() != 0)
|
||||
return nullptr;
|
||||
return Encoding;
|
||||
|
|
|
|||
|
|
@ -30219,4 +30219,15 @@
|
|||
{"_Z3fooIPU9__ptrauthILj1ELb0ELj64EEPiEvT_", "void foo<int* __ptrauth<1u, false, 64u>*>(int* __ptrauth<1u, false, 64u>*)"},
|
||||
|
||||
{"_ZN1CpmEi", "C::operator->*(int)"},
|
||||
|
||||
// AllocToken instrumentation
|
||||
{"__alloc_token__Znwm", "operator new(unsigned long) (.alloc_token)"},
|
||||
{"__alloc_token__Znam", "operator new[](unsigned long) (.alloc_token)"},
|
||||
{"__alloc_token__ZnwmRKSt9nothrow_t", "operator new(unsigned long, std::nothrow_t const&) (.alloc_token)"},
|
||||
{"__alloc_token__ZnamRKSt9nothrow_t", "operator new[](unsigned long, std::nothrow_t const&) (.alloc_token)"},
|
||||
{"__alloc_token_0__Znwm", "operator new(unsigned long) (.alloc_token)"},
|
||||
{"__alloc_token_1__Znam", "operator new[](unsigned long) (.alloc_token)"},
|
||||
{"__alloc_token_123__ZnwmRKSt9nothrow_t", "operator new(unsigned long, std::nothrow_t const&) (.alloc_token)"},
|
||||
{"__alloc_token__Znwm.llvm.1234", "operator new(unsigned long) (.llvm.1234) (.alloc_token)"},
|
||||
{"__alloc_token_123__Z3foov", "foo() (.alloc_token)"},
|
||||
// clang-format on
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "llvm/Demangle/Demangle.h"
|
||||
#include "llvm/Demangle/StringViewExtras.h"
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <string_view>
|
||||
|
||||
|
|
@ -38,6 +39,15 @@ std::string llvm::demangle(std::string_view MangledName) {
|
|||
}
|
||||
|
||||
static bool isItaniumEncoding(std::string_view S) {
|
||||
if (starts_with(S, "__alloc_token_")) {
|
||||
S.remove_prefix(sizeof("__alloc_token_") - 1);
|
||||
if (!S.empty() && std::isdigit(S[0])) {
|
||||
while (!S.empty() && std::isdigit(S[0]))
|
||||
S.remove_prefix(1);
|
||||
if (starts_with(S, "_"))
|
||||
S.remove_prefix(1);
|
||||
}
|
||||
}
|
||||
// Itanium demangler supports prefixes with 1-4 underscores.
|
||||
const size_t Pos = S.find_first_not_of('_');
|
||||
return Pos > 0 && Pos <= 4 && S[Pos] == 'Z';
|
||||
|
|
|
|||
16
llvm/test/tools/llvm-cxxfilt/alloc-token.test
Normal file
16
llvm/test/tools/llvm-cxxfilt/alloc-token.test
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
## Show that llvm-cxxfilt can handle __alloc_token_ prefixed demangling.
|
||||
|
||||
RUN: llvm-cxxfilt __alloc_token__Znwm \
|
||||
RUN: __alloc_token__Znam \
|
||||
RUN: __alloc_token_0__Znwm \
|
||||
RUN: __alloc_token_1__Znam \
|
||||
RUN: __alloc_token_123__Z3foov \
|
||||
RUN: __alloc_token_malloc \
|
||||
RUN: | FileCheck %s
|
||||
|
||||
CHECK: operator new(unsigned long) (.alloc_token)
|
||||
CHECK-NEXT: operator new[](unsigned long) (.alloc_token)
|
||||
CHECK-NEXT: operator new(unsigned long) (.alloc_token)
|
||||
CHECK-NEXT: operator new[](unsigned long) (.alloc_token)
|
||||
CHECK-NEXT: foo() (.alloc_token)
|
||||
CHECK-NEXT: __alloc_token_malloc
|
||||
Loading…
Reference in a new issue