[Lldb-commits] [lldb] [llvm] [lldb][Format] Add function.suffix frame-format variable (PR #137763)
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Tue Apr 29 00:09:04 PDT 2025
https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/137763
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)`.
>From 4d102853c77456873b8360de32789f1c15416bc6 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 29 Apr 2025 08:04:34 +0100
Subject: [PATCH] [lldb][Format] Add function.suffix frame-format variable
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)`.
---
.../utils/yaml-bench/cmake_install.cmake | 39 +++++++++++++++++++
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 +++++++++++
7 files changed, 106 insertions(+), 5 deletions(-)
create mode 100644 lldb-builds/release/utils/yaml-bench/cmake_install.cmake
create mode 100644 lldb/test/Shell/Settings/TestFrameFormatFunctionSuffix.test
diff --git a/lldb-builds/release/utils/yaml-bench/cmake_install.cmake b/lldb-builds/release/utils/yaml-bench/cmake_install.cmake
new file mode 100644
index 0000000000000..fa0d8ddfac037
--- /dev/null
+++ b/lldb-builds/release/utils/yaml-bench/cmake_install.cmake
@@ -0,0 +1,39 @@
+# Install script for directory: /Users/jonas/Git/llvm-worktrees/frame-format/llvm/utils/yaml-bench
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "/usr/local")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
+# Set path to fallback-tool for dependency-resolution.
+if(NOT DEFINED CMAKE_OBJDUMP)
+ set(CMAKE_OBJDUMP "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/objdump")
+endif()
+
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)'
More information about the lldb-commits
mailing list