Skip to content

Commit 1e153b7

Browse files
authored
[lldb][Format] Display only the inlined frame name in backtraces if available (llvm#135343)
When a frame is inlined, LLDB will display its name in backtraces as follows: ``` * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3 * frame #0: 0x0000000100000398 a.out`func() [inlined] baz(x=10) at inline.cpp:1:42 frame #1: 0x0000000100000398 a.out`func() [inlined] bar() at inline.cpp:2:37 frame #2: 0x0000000100000398 a.out`func() at inline.cpp:4:15 frame #3: 0x00000001000003c0 a.out`main at inline.cpp:7:5 frame #4: 0x000000026eb29ab8 dyld`start + 6812 ``` The longer the names get the more confusing this gets because the first function name that appears is the parent frame. My assumption (which may need some more surveying) is that for the majority of cases we only care about the actual frame name (not the parent). So this patch removes all the special logic that prints the parent frame. Another quirk of the current format is that the inlined frame name does not abide by the `${function.name-XXX}` format variables. We always just print the raw demangled name. With this patch, we would format the inlined frame name according to the `frame-format` setting (see the test-cases). If we really want to have the `parentFrame [inlined] inlinedFrame` format, we could expose it through a new `frame-format` variable (e..g., `${function.inlined-at-name}` and let the user decide where to place things.
1 parent 5710759 commit 1e153b7

File tree

8 files changed

+76
-105
lines changed

8 files changed

+76
-105
lines changed

lldb/include/lldb/Symbol/SymbolContext.h

+7
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,13 @@ class SymbolContext {
307307
SymbolContext &next_frame_sc,
308308
Address &inlined_frame_addr) const;
309309

310+
/// If available, will return the function name according to the specified
311+
/// mangling preference. If this object represents an inlined function,
312+
/// returns the name of the inlined function. Returns nullptr if no function
313+
/// name could be determined.
314+
const char *GetPossiblyInlinedFunctionName(
315+
Mangled::NamePreference mangling_preference) const;
316+
310317
// Member variables
311318
lldb::TargetSP target_sp; ///< The Target for a given query
312319
lldb::ModuleSP module_sp; ///< The Module for a given query

lldb/source/Core/FormatEntity.cpp

+24-71
Original file line numberDiff line numberDiff line change
@@ -1147,19 +1147,6 @@ static void PrettyPrintFunctionNameWithArgs(Stream &out_stream,
11471147
out_stream.PutChar(')');
11481148
}
11491149

1150-
static void FormatInlinedBlock(Stream &out_stream, Block *block) {
1151-
if (!block)
1152-
return;
1153-
Block *inline_block = block->GetContainingInlinedBlock();
1154-
if (inline_block) {
1155-
if (const InlineFunctionInfo *inline_info =
1156-
inline_block->GetInlinedFunctionInfo()) {
1157-
out_stream.PutCString(" [inlined] ");
1158-
inline_info->GetName().Dump(&out_stream);
1159-
}
1160-
}
1161-
}
1162-
11631150
static VariableListSP GetFunctionVariableList(const SymbolContext &sc) {
11641151
assert(sc.function);
11651152

@@ -1170,22 +1157,6 @@ static VariableListSP GetFunctionVariableList(const SymbolContext &sc) {
11701157
return sc.function->GetBlock(true).GetBlockVariableList(true);
11711158
}
11721159

1173-
static char const *GetInlinedFunctionName(const SymbolContext &sc) {
1174-
if (!sc.block)
1175-
return nullptr;
1176-
1177-
const Block *inline_block = sc.block->GetContainingInlinedBlock();
1178-
if (!inline_block)
1179-
return nullptr;
1180-
1181-
const InlineFunctionInfo *inline_info =
1182-
inline_block->GetInlinedFunctionInfo();
1183-
if (!inline_info)
1184-
return nullptr;
1185-
1186-
return inline_info->GetName().AsCString(nullptr);
1187-
}
1188-
11891160
static bool PrintFunctionNameWithArgs(Stream &s,
11901161
const ExecutionContext *exe_ctx,
11911162
const SymbolContext &sc) {
@@ -1194,16 +1165,11 @@ static bool PrintFunctionNameWithArgs(Stream &s,
11941165
ExecutionContextScope *exe_scope =
11951166
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
11961167

1197-
const char *cstr = sc.function->GetName().AsCString(nullptr);
1168+
const char *cstr =
1169+
sc.GetPossiblyInlinedFunctionName(Mangled::ePreferDemangled);
11981170
if (!cstr)
11991171
return false;
12001172

1201-
if (const char *inlined_name = GetInlinedFunctionName(sc)) {
1202-
s.PutCString(cstr);
1203-
s.PutCString(" [inlined] ");
1204-
cstr = inlined_name;
1205-
}
1206-
12071173
VariableList args;
12081174
if (auto variable_list_sp = GetFunctionVariableList(sc))
12091175
variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
@@ -1724,21 +1690,17 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
17241690
if (language_plugin_handled) {
17251691
s << ss.GetString();
17261692
return true;
1727-
} else {
1728-
const char *name = nullptr;
1729-
if (sc->function)
1730-
name = sc->function->GetName().AsCString(nullptr);
1731-
else if (sc->symbol)
1732-
name = sc->symbol->GetName().AsCString(nullptr);
1733-
1734-
if (name) {
1735-
s.PutCString(name);
1736-
FormatInlinedBlock(s, sc->block);
1737-
return true;
1738-
}
17391693
}
1694+
1695+
const char *name = sc->GetPossiblyInlinedFunctionName(
1696+
Mangled::NamePreference::ePreferDemangled);
1697+
if (!name)
1698+
return false;
1699+
1700+
s.PutCString(name);
1701+
1702+
return true;
17401703
}
1741-
return false;
17421704

17431705
case Entry::Type::FunctionNameNoArgs: {
17441706
if (!sc)
@@ -1760,20 +1722,17 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
17601722
if (language_plugin_handled) {
17611723
s << ss.GetString();
17621724
return true;
1763-
} else {
1764-
ConstString name;
1765-
if (sc->function)
1766-
name = sc->function->GetNameNoArguments();
1767-
else if (sc->symbol)
1768-
name = sc->symbol->GetNameNoArguments();
1769-
if (name) {
1770-
s.PutCString(name.GetCString());
1771-
FormatInlinedBlock(s, sc->block);
1772-
return true;
1773-
}
17741725
}
1726+
1727+
const char *name = sc->GetPossiblyInlinedFunctionName(
1728+
Mangled::NamePreference::ePreferDemangledWithoutArguments);
1729+
if (!name)
1730+
return false;
1731+
1732+
s.PutCString(name);
1733+
1734+
return true;
17751735
}
1776-
return false;
17771736

17781737
case Entry::Type::FunctionNameWithArgs: {
17791738
if (!sc)
@@ -1815,19 +1774,13 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
18151774
if (!sc)
18161775
return false;
18171776

1818-
const char *name = nullptr;
1819-
if (sc->symbol)
1820-
name =
1821-
sc->symbol->GetMangled().GetName(Mangled::ePreferMangled).AsCString();
1822-
else if (sc->function)
1823-
name = sc->function->GetMangled()
1824-
.GetName(Mangled::ePreferMangled)
1825-
.AsCString();
1826-
1777+
const char *name = sc->GetPossiblyInlinedFunctionName(
1778+
Mangled::NamePreference::ePreferMangled);
18271779
if (!name)
18281780
return false;
1781+
18291782
s.PutCString(name);
1830-
FormatInlinedBlock(s, sc->block);
1783+
18311784
return true;
18321785
}
18331786
case Entry::Type::FunctionAddrOffset:

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

+2-23
Original file line numberDiff line numberDiff line change
@@ -1707,22 +1707,6 @@ static VariableListSP GetFunctionVariableList(const SymbolContext &sc) {
17071707
return sc.function->GetBlock(true).GetBlockVariableList(true);
17081708
}
17091709

1710-
static char const *GetInlinedFunctionName(const SymbolContext &sc) {
1711-
if (!sc.block)
1712-
return nullptr;
1713-
1714-
const Block *inline_block = sc.block->GetContainingInlinedBlock();
1715-
if (!inline_block)
1716-
return nullptr;
1717-
1718-
const InlineFunctionInfo *inline_info =
1719-
inline_block->GetInlinedFunctionInfo();
1720-
if (!inline_info)
1721-
return nullptr;
1722-
1723-
return inline_info->GetName().AsCString(nullptr);
1724-
}
1725-
17261710
static bool PrintFunctionNameWithArgs(Stream &s,
17271711
const ExecutionContext *exe_ctx,
17281712
const SymbolContext &sc) {
@@ -1731,16 +1715,11 @@ static bool PrintFunctionNameWithArgs(Stream &s,
17311715
ExecutionContextScope *exe_scope =
17321716
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
17331717

1734-
const char *cstr = sc.function->GetName().AsCString(nullptr);
1718+
const char *cstr = sc.GetPossiblyInlinedFunctionName(
1719+
Mangled::NamePreference::ePreferDemangled);
17351720
if (!cstr)
17361721
return false;
17371722

1738-
if (const char *inlined_name = GetInlinedFunctionName(sc)) {
1739-
s.PutCString(cstr);
1740-
s.PutCString(" [inlined] ");
1741-
cstr = inlined_name;
1742-
}
1743-
17441723
VariableList args;
17451724
if (auto variable_list_sp = GetFunctionVariableList(sc))
17461725
variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,

lldb/source/Symbol/SymbolContext.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,36 @@ const Symbol *SymbolContext::FindBestGlobalDataSymbol(ConstString name,
872872
return nullptr; // no error; we just didn't find anything
873873
}
874874

875+
char const *SymbolContext::GetPossiblyInlinedFunctionName(
876+
Mangled::NamePreference mangling_preference) const {
877+
const char *name = nullptr;
878+
if (function)
879+
name = function->GetMangled().GetName(mangling_preference).AsCString();
880+
else if (symbol)
881+
name = symbol->GetMangled().GetName(mangling_preference).AsCString();
882+
883+
if (!block)
884+
return name;
885+
886+
const Block *inline_block = block->GetContainingInlinedBlock();
887+
if (!inline_block)
888+
return name;
889+
890+
const InlineFunctionInfo *inline_info =
891+
inline_block->GetInlinedFunctionInfo();
892+
if (!inline_info)
893+
return name;
894+
895+
// If we do have an inlined frame name, return that.
896+
if (char const *inline_name =
897+
inline_info->GetMangled().GetName(mangling_preference).AsCString())
898+
return inline_name;
899+
900+
// Sometimes an inline frame may not have mangling information,
901+
// but does have a valid name.
902+
return inline_info->GetName().AsCString();
903+
}
904+
875905
//
876906
// SymbolContextSpecifier
877907
//

lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ __attribute__((noinline)) void func6(int &sink, int x) {
7070
__attribute__((noinline)) void func7(int &sink, int x) {
7171
//% self.filecheck("bt", "main.cpp", "-check-prefix=FUNC7-BT")
7272
// FUNC7-BT: func7
73-
// FUNC7-BT-NEXT: [inlined] func8_inlined
74-
// FUNC7-BT-NEXT: [inlined] func9_inlined
73+
// FUNC7-BT-NEXT: func8_inlined
74+
// FUNC7-BT-NEXT: func9_inlined
7575
// FUNC7-BT-NEXT: func10
7676
use<int &, int>(sink, x);
7777
use<int &, int>(dummy, 0);

lldb/test/API/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
volatile int x;
22

3+
// clang-format off
34
void __attribute__((noinline)) tail_call_sink() {
45
x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=TAIL-CALL-SINK")
56
// TAIL-CALL-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`tail_call_sink() at main.cpp:[[@LINE-1]]:4
6-
// TAIL-CALL-SINK-NEXT: func3{{.*}} [artificial]
7+
// TAIL-CALL-SINK-NEXT: inlinable_function_which_tail_calls() at main.cpp{{.*}} [artificial]
78
// TAIL-CALL-SINK-NEXT: main{{.*}}
8-
9-
// TODO: The backtrace should include inlinable_function_which_tail_calls.
109
}
10+
// clang-format on
1111

1212
void __attribute__((always_inline)) inlinable_function_which_tail_calls() {
1313
tail_call_sink();
@@ -17,13 +17,15 @@ void __attribute__((noinline)) func3() {
1717
inlinable_function_which_tail_calls();
1818
}
1919

20+
// clang-format off
2021
void __attribute__((always_inline)) inline_sink() {
2122
x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=INLINE-SINK")
22-
// INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`func2() [inlined] inline_sink() at main.cpp:[[@LINE-1]]:4
23+
// INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`inline_sink() at main.cpp:[[@LINE-1]]:4
2324
// INLINE-SINK-NEXT: func2{{.*}}
2425
// INLINE-SINK-NEXT: func1{{.*}} [artificial]
2526
// INLINE-SINK-NEXT: main{{.*}}
2627
}
28+
// clang-format on
2729

2830
void __attribute__((noinline)) func2() { inline_sink(); /* inlined */ }
2931

lldb/test/Shell/Recognizer/verbose_trap-in-stl-max-depth.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ run
1212
frame recognizer info 0
1313
# CHECK: frame 0 is recognized by Verbose Trap StackFrame Recognizer
1414
frame info
15-
# CHECK: frame #0: {{.*}}`std::recursively_aborts(int) {{.*}} at verbose_trap-in-stl-max-depth.cpp
15+
# CHECK: frame #0: {{.*}}`__clang_trap_msg$Error$max depth at verbose_trap-in-stl-max-depth.cpp
1616
q

lldb/test/Shell/Settings/TestFrameFormatName.test

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,26 @@ c
3030
c
3131
# NAME_WITH_ARGS: frame Foo::returns_func_ptr<int>(this={{.*}}, (null)={{.*}})
3232
c
33-
# NAME_WITH_ARGS: frame main [inlined] inlined_foo(str="bar")
33+
# NAME_WITH_ARGS: frame inlined_foo(str="bar")
3434
q
3535

3636
#--- name.input
3737
# RUN: %lldb -b -s %t/name.input %t.out | FileCheck %s --check-prefix=NAME
3838
settings set -f frame-format "frame ${function.name}\n"
3939
break set -n inlined_foo
4040
run
41-
# NAME: frame main [inlined] inlined_foo(char const*)
41+
# NAME: frame inlined_foo(char const*)
4242

4343
#--- name_without_args.input
4444
# RUN: %lldb -b -s %t/name_without_args.input %t.out | FileCheck %s --check-prefix=NAME_WITHOUT_ARGS
4545
settings set -f frame-format "frame ${function.name-without-args}\n"
4646
break set -n inlined_foo
4747
run
48-
# NAME_WITHOUT_ARGS: frame main [inlined] inlined_foo(char const*)
48+
# NAME_WITHOUT_ARGS: frame inlined_foo
4949

5050
#--- mangled_name.input
5151
# RUN: %lldb -b -s %t/mangled_name.input %t.out | FileCheck %s --check-prefix=MANGLED_NAME
5252
settings set -f frame-format "frame ${function.mangled-name}\n"
5353
break set -n inlined_foo
5454
run
55-
# MANGLED_NAME: frame main [inlined] inlined_foo(char const*)
55+
# MANGLED_NAME: frame _Z11inlined_fooPKc

0 commit comments

Comments
 (0)