Skip to content

Commit 5842d95

Browse files
Merge pull request #10579 from swiftlang/lldb/suffix-frame-format-to-6.2
🍒[lldb][Format] Add function.suffix frame-format variable
2 parents ab2d282 + 8ad8457 commit 5842d95

File tree

6 files changed

+117
-2
lines changed

6 files changed

+117
-2
lines changed

lldb/docs/use/formatting.rst

+56-1
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,29 @@ A complete list of currently supported format string variables is listed below:
8585
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
8686
| ``function.name`` | The name of the current function or symbol. |
8787
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
88-
| ``function.name-with-args`` | The name of the current function with arguments and values or the symbol name. |
88+
| ``function.name-with-args`` | The name of the current function with arguments and values or the symbol name. The name will be displayed according to the current frame's language if possible. |
8989
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
9090
| ``function.name-without-args`` | The name of the current function without arguments and values (used to include a function name in-line in the ``disassembly-format``) |
9191
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
92+
| ``function.basename`` | The basename of the current function depending on the frame's language. E.g., for C++ the basename for ``void ns::foo<float>::bar<int>(int) const`` is ``bar``. |
93+
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
94+
| ``function.scope`` | The scope qualifiers of the current function depending on the frame's language. E.g., for C++ the scope for ``void ns::foo<float>::bar<int>(int) const`` is ``ns::foo<float>``. |
95+
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
96+
| ``function.template-arguments`` | The template arguments of the current function depending on the frame's language. E.g., for C++ the template arguments for ``void ns::foo<float>::bar<int>(int) const`` are ``<float>``. |
97+
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
98+
| ``function.formatted-arguments`` | Arguments of the current function, formatted according to the frame's language. When debug-info is available, will apply data-formatters to each argument and include it's name if available. Otherwise prints the type of each argument according to the mangling. E.g., for C++ the |
99+
| | pretty-printed arguments for ``func(int x, const char *str)`` are ``(x=10, str="Hello")``. Without debug-info it would be ``(int, const char*)``. |
100+
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
101+
| ``function.qualifiers`` | The function CV and reference qualifiers of the current function depending on the frame's language. E.g., for C++ the qualifiers for ``void ns::foo<float>::bar<int>(int) const &`` are ``const &``. |
102+
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
103+
| ``function.return-left`` | The return type to the left of the demangled function name of the current function. This depends on the frame's language. E.g., for C++ the ``function.return-left`` is in most-cases the entirety of the return type. In ``void ns::foo(int)`` that would be ``void``. However, in some |
104+
| | 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)``. |
105+
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
106+
| ``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 |
107+
| | 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)``. |
108+
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
109+
| ``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). |
110+
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
92111
| ``function.mangled-name`` | The mangled name of the current function or symbol. |
93112
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
94113
| ``function.pc-offset`` | The program counter offset within the current function or symbol |
@@ -300,3 +319,39 @@ you would see output like:
300319

301320
* Thread main has 21 frames
302321

322+
Function Name Formats
323+
_____________________
324+
325+
The function names displayed in backtraces/``frame info``/``thread info`` are the demangled names of functions. On some platforms (like ones using Itanium the mangling scheme), LLDB supports decomposing these names into fine-grained components. These are currently:
326+
327+
- ``${function.return-left}``
328+
- ``${function.scope}``
329+
- ``${function.basename}``
330+
- ``${function.template-arguments}``
331+
- ``${function.formatted-arguments}``
332+
- ``${function.qualifiers}``
333+
- ``${function.return-right}``
334+
- ``${function.suffix}``
335+
336+
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.
337+
338+
E.g., the following setting would reconstruct the entire function name (and is LLDB's default):
339+
340+
::
341+
342+
(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}"
343+
344+
If a user wanted to only print the name and arguments of a C++ function one could do:
345+
346+
::
347+
348+
(lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.scope}${function.basename}${function.formatted-arguments}"
349+
350+
351+
Then the following would highlight just the basename in green:
352+
353+
::
354+
355+
(lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.formatted-arguments}"
356+
357+
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.

lldb/include/lldb/Core/FormatEntity.h

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ struct Entry {
9595
FunctionReturnLeft,
9696
FunctionReturnRight,
9797
FunctionQualifiers,
98+
FunctionSuffix,
9899
FunctionAddrOffset,
99100
FunctionAddrOffsetConcrete,
100101
FunctionLineOffset,

lldb/source/Core/FormatEntity.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ constexpr Definition g_function_child_entries[] = {
130130
Definition("return-left", EntryType::FunctionReturnLeft),
131131
Definition("return-right", EntryType::FunctionReturnRight),
132132
Definition("qualifiers", EntryType::FunctionQualifiers),
133+
Definition("suffix", EntryType::FunctionSuffix),
133134
};
134135

135136
constexpr Definition g_line_child_entries[] = {
@@ -368,6 +369,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
368369
ENUM_TO_CSTR(FunctionReturnLeft);
369370
ENUM_TO_CSTR(FunctionReturnRight);
370371
ENUM_TO_CSTR(FunctionQualifiers);
372+
ENUM_TO_CSTR(FunctionSuffix);
371373
ENUM_TO_CSTR(FunctionAddrOffset);
372374
ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
373375
ENUM_TO_CSTR(FunctionLineOffset);
@@ -1816,6 +1818,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
18161818
case Entry::Type::FunctionFormattedArguments:
18171819
case Entry::Type::FunctionReturnRight:
18181820
case Entry::Type::FunctionReturnLeft:
1821+
case Entry::Type::FunctionSuffix:
18191822
case Entry::Type::FunctionQualifiers: {
18201823
Language *language_plugin = nullptr;
18211824
if (sc->function)

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,30 @@ GetDemangledScope(const SymbolContext &sc) {
354354
return demangled_name.slice(info->ScopeRange.first, info->ScopeRange.second);
355355
}
356356

357+
/// Handles anything printed after the FunctionEncoding ItaniumDemangle
358+
/// node. Most notably the DotSUffix node.
359+
static std::optional<llvm::StringRef>
360+
GetDemangledFunctionSuffix(const SymbolContext &sc) {
361+
Mangled mangled = sc.GetPossiblyInlinedFunctionName();
362+
if (!mangled)
363+
return std::nullopt;
364+
365+
auto demangled_name = mangled.GetDemangledName().GetStringRef();
366+
if (demangled_name.empty())
367+
return std::nullopt;
368+
369+
const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo();
370+
if (!info)
371+
return std::nullopt;
372+
373+
// Function without a basename is nonsense.
374+
if (!info->hasBasename())
375+
return std::nullopt;
376+
377+
return demangled_name.slice(info->QualifiersRange.second,
378+
llvm::StringRef::npos);
379+
}
380+
357381
static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) {
358382
assert(sc.symbol);
359383

@@ -2023,6 +2047,15 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
20232047

20242048
return true;
20252049
}
2050+
case FormatEntity::Entry::Type::FunctionSuffix: {
2051+
std::optional<llvm::StringRef> suffix = GetDemangledFunctionSuffix(sc);
2052+
if (!suffix)
2053+
return false;
2054+
2055+
s << *suffix;
2056+
2057+
return true;
2058+
}
20262059
default:
20272060
return false;
20282061
}

lldb/source/Plugins/Language/CPlusPlus/LanguageCPlusPlusProperties.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ include "../../../../include/lldb/Core/PropertiesBase.td"
33
let Definition = "language_cplusplus" in {
44
def FunctionNameFormat: Property<"function-name-format", "FormatEntity">,
55
Global,
6-
DefaultStringValue<"${function.return-left}${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.template-arguments}${function.formatted-arguments}${function.return-right}${function.qualifiers}">,
6+
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}">,
77
Desc<"C++ specific frame format string to use when displaying stack frame information for threads.">;
88
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# UNSUPPORTED: system-windows
2+
3+
# Test the ${function.suffix} frame-format variable.
4+
5+
# RUN: split-file %s %t
6+
# RUN: %clang_host -g -gdwarf %t/main.cpp -o %t.out
7+
# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
8+
# RUN: | FileCheck %s
9+
10+
#--- main.cpp
11+
void bar() asm("_Z3barv.cold");
12+
void bar() {}
13+
14+
int main() { bar(); }
15+
16+
#--- commands.input
17+
settings set -f frame-format "custom-frame '${function.suffix}'\n"
18+
break set -n "_Z3barv.cold"
19+
20+
run
21+
bt
22+
23+
# CHECK: custom-frame ' (.cold)'

0 commit comments

Comments
 (0)