https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/137763
>From 7e690c523128f6e18e1baa3e26fdaf1c694dcf67 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Tue, 29 Apr 2025 08:11:13 +0100 Subject: [PATCH 1/2] This patch adds another frame-format variable (currently only implemented in the CPlusPlus language plugin) that represents the "suffix" of a function. The name is derived from the `DotSuffix` node of LLVM's Itanium demangler. For a function name such as `int foo() (.cold)`, the suffix would be `(.cold)`. --- lldb/docs/use/formatting.rst | 11 ++++--- lldb/include/lldb/Core/FormatEntity.h | 1 + lldb/source/Core/FormatEntity.cpp | 3 ++ .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 32 +++++++++++++++++++ .../CPlusPlus/LanguageCPlusPlusProperties.td | 2 +- .../TestFrameFormatFunctionSuffix.test | 23 +++++++++++++ 6 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 lldb/test/Shell/Settings/TestFrameFormatFunctionSuffix.test diff --git a/lldb/docs/use/formatting.rst b/lldb/docs/use/formatting.rst index a21165a3ecae3..61f51812d2ea9 100644 --- a/lldb/docs/use/formatting.rst +++ b/lldb/docs/use/formatting.rst @@ -106,6 +106,8 @@ A complete list of currently supported format string variables is listed below: | ``function.return-right`` | The return type to the right of the demangled function name of the current function. This depends on the frame's language. In ``void ns::foo(int)`` there is no ``function.return-right`` so this would correspond to an empty string. However, in some cases, particularly for functions | | | returning function pointers, part of the return type is to the right of the function name. E.g., for ``void (*ns::func(float))(int)`` the ``function.return-left`` would be ``void (*`` and the ``function.return-right`` would be ``)(int)``. | +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``function.suffix`` | Any suffix added to the demangled function name of the current function. This depends on the frame's language. E.g., for C++ the suffix for ``void ns::foo(int) (.cold)`` is '(.cold). | ++---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``function.mangled-name`` | The mangled name of the current function or symbol. | +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``function.pc-offset`` | The program counter offset within the current function or symbol | @@ -329,6 +331,7 @@ The function names displayed in backtraces/``frame info``/``thread info`` are th - ``${function.formatted-arguments}`` - ``${function.qualifiers}`` - ``${function.return-right}`` +- ``${function.suffix}`` Each language plugin decides how to handle these variables. For C++, LLDB uses these variables to dictate how function names are formatted. This can be customized using the ``plugin.cplusplus.display.function-name-format`` LLDB setting. @@ -336,19 +339,19 @@ E.g., the following setting would reconstruct the entire function name (and is L :: - (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.return-left}${function.scope}${function.basename}${function.template-arguments}${function.formatted-arguments}${function.qualifiers}${function.return-right}" + (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.return-left}${function.scope}${function.basename}${function.template-arguments}${function.formatted-arguments}${function.qualifiers}${function.return-right}${function.suffix}" -If a user wanted to omit the return type and template arguments of C++ function names one could do: +If a user wanted to only print the name and arguments of a C++ function one could do: :: - (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.scope}${function.basename}${function.formatted-arguments}${function.qualifiers}" + (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.scope}${function.basename}${function.formatted-arguments}" Then the following would highlight just the basename in green: :: - (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.formatted-arguments}${function.qualifiers}" + (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.formatted-arguments}" The ``${function.name-with-args}`` by default asks the language plugin whether it supports a language-specific ``function-name-format`` (e.g., the ``plugin.cplusplus.display.function-name-format`` for C++), and if it does, uses it. Otherwise it will display the demangled function name. diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h index e62c82d080d5f..97065afe19bfe 100644 --- a/lldb/include/lldb/Core/FormatEntity.h +++ b/lldb/include/lldb/Core/FormatEntity.h @@ -95,6 +95,7 @@ struct Entry { FunctionReturnLeft, FunctionReturnRight, FunctionQualifiers, + FunctionSuffix, FunctionAddrOffset, FunctionAddrOffsetConcrete, FunctionLineOffset, diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp index 6cdfcfedf8be5..468203ac73a42 100644 --- a/lldb/source/Core/FormatEntity.cpp +++ b/lldb/source/Core/FormatEntity.cpp @@ -130,6 +130,7 @@ constexpr Definition g_function_child_entries[] = { Definition("return-left", EntryType::FunctionReturnLeft), Definition("return-right", EntryType::FunctionReturnRight), Definition("qualifiers", EntryType::FunctionQualifiers), + Definition("suffix", EntryType::FunctionSuffix), }; constexpr Definition g_line_child_entries[] = { @@ -368,6 +369,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) { ENUM_TO_CSTR(FunctionReturnLeft); ENUM_TO_CSTR(FunctionReturnRight); ENUM_TO_CSTR(FunctionQualifiers); + ENUM_TO_CSTR(FunctionSuffix); ENUM_TO_CSTR(FunctionAddrOffset); ENUM_TO_CSTR(FunctionAddrOffsetConcrete); ENUM_TO_CSTR(FunctionLineOffset); @@ -1808,6 +1810,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, case Entry::Type::FunctionFormattedArguments: case Entry::Type::FunctionReturnRight: case Entry::Type::FunctionReturnLeft: + case Entry::Type::FunctionSuffix: case Entry::Type::FunctionQualifiers: { if (!sc->function) return false; diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 283e867d53bb7..90db03c45700e 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -381,6 +381,29 @@ GetDemangledScope(const SymbolContext &sc) { return demangled_name.slice(info->ScopeRange.first, info->ScopeRange.second); } +/// Handles anything printed after the FunctionEncoding ItaniumDemangle +/// node. Most notably the DotSUffix node. +static std::optional<llvm::StringRef> +GetDemangledFunctionSuffix(const SymbolContext &sc) { + Mangled mangled = sc.GetPossiblyInlinedFunctionName(); + if (!mangled) + return std::nullopt; + + auto demangled_name = mangled.GetDemangledName().GetStringRef(); + if (demangled_name.empty()) + return std::nullopt; + + const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo(); + if (!info) + return std::nullopt; + + // Function without a basename is nonsense. + if (!info->hasBasename()) + return std::nullopt; + + return demangled_name.slice(info->QualifiersRange.second, llvm::StringRef::npos); +} + bool CPlusPlusLanguage::CxxMethodName::TrySimplifiedParse() { // This method tries to parse simple method definitions which are presumably // most comman in user programs. Definitions that can be parsed by this @@ -1966,6 +1989,15 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable( return true; } + case FormatEntity::Entry::Type::FunctionSuffix: { + std::optional<llvm::StringRef> suffix = GetDemangledFunctionSuffix(sc); + if (!suffix) + return false; + + s << *suffix; + + return true; + } default: return false; } diff --git a/lldb/source/Plugins/Language/CPlusPlus/LanguageCPlusPlusProperties.td b/lldb/source/Plugins/Language/CPlusPlus/LanguageCPlusPlusProperties.td index 348de256b154a..4d74a040f4de4 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LanguageCPlusPlusProperties.td +++ b/lldb/source/Plugins/Language/CPlusPlus/LanguageCPlusPlusProperties.td @@ -3,6 +3,6 @@ include "../../../../include/lldb/Core/PropertiesBase.td" let Definition = "language_cplusplus" in { def FunctionNameFormat: Property<"function-name-format", "FormatEntity">, Global, - DefaultStringValue<"${function.return-left}${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.template-arguments}${function.formatted-arguments}${function.return-right}${function.qualifiers}">, + DefaultStringValue<"${function.return-left}${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.template-arguments}${function.formatted-arguments}${function.return-right}${function.qualifiers}${function.suffix}">, Desc<"C++ specific frame format string to use when displaying stack frame information for threads.">; } diff --git a/lldb/test/Shell/Settings/TestFrameFormatFunctionSuffix.test b/lldb/test/Shell/Settings/TestFrameFormatFunctionSuffix.test new file mode 100644 index 0000000000000..ce7fa22b00b5a --- /dev/null +++ b/lldb/test/Shell/Settings/TestFrameFormatFunctionSuffix.test @@ -0,0 +1,23 @@ +# XFAIL: target-windows + +# Test the ${function.suffix} frame-format variable. + +# RUN: split-file %s %t +# RUN: %clang_host -g -gdwarf %t/main.cpp -o %t.out +# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \ +# RUN: | FileCheck %s + +#--- main.cpp +void bar() asm("_Z3barv.cold"); +void bar() {} + +int main() { bar(); } + +#--- commands.input +settings set -f frame-format "custom-frame '${function.suffix}'\n" +break set -n "_Z3barv.cold" + +run +bt + +# CHECK: custom-frame ' (.cold)' >From 74d156276346777c49888fb5883f3469f6f42164 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Tue, 29 Apr 2025 08:11:49 +0100 Subject: [PATCH 2/2] fixup! clang-format --- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 90db03c45700e..6491fb761de52 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -401,7 +401,8 @@ GetDemangledFunctionSuffix(const SymbolContext &sc) { if (!info->hasBasename()) return std::nullopt; - return demangled_name.slice(info->QualifiersRange.second, llvm::StringRef::npos); + return demangled_name.slice(info->QualifiersRange.second, + llvm::StringRef::npos); } bool CPlusPlusLanguage::CxxMethodName::TrySimplifiedParse() { _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits