Author: Michael Buch
Date: 2025-04-13T23:21:52+01:00
New Revision: 1e153b782ea3054c02dd0016314fca11a5d781da

URL: 
https://github.com/llvm/llvm-project/commit/1e153b782ea3054c02dd0016314fca11a5d781da
DIFF: 
https://github.com/llvm/llvm-project/commit/1e153b782ea3054c02dd0016314fca11a5d781da.diff

LOG: [lldb][Format] Display only the inlined frame name in backtraces if 
available (#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.

Added: 
    

Modified: 
    lldb/include/lldb/Symbol/SymbolContext.h
    lldb/source/Core/FormatEntity.cpp
    lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
    lldb/source/Symbol/SymbolContext.cpp
    lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp
    
lldb/test/API/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp
    lldb/test/Shell/Recognizer/verbose_trap-in-stl-max-depth.test
    lldb/test/Shell/Settings/TestFrameFormatName.test

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Symbol/SymbolContext.h 
b/lldb/include/lldb/Symbol/SymbolContext.h
index 8b6317c6f33c2..4f8405f1f0db5 100644
--- a/lldb/include/lldb/Symbol/SymbolContext.h
+++ b/lldb/include/lldb/Symbol/SymbolContext.h
@@ -307,6 +307,13 @@ class SymbolContext {
                                SymbolContext &next_frame_sc,
                                Address &inlined_frame_addr) const;
 
+  /// If available, will return the function name according to the specified
+  /// mangling preference. If this object represents an inlined function,
+  /// returns the name of the inlined function. Returns nullptr if no function
+  /// name could be determined.
+  const char *GetPossiblyInlinedFunctionName(
+      Mangled::NamePreference mangling_preference) const;
+
   // Member variables
   lldb::TargetSP target_sp; ///< The Target for a given query
   lldb::ModuleSP module_sp; ///< The Module for a given query

diff  --git a/lldb/source/Core/FormatEntity.cpp 
b/lldb/source/Core/FormatEntity.cpp
index 7130248100c6f..2392edb78d2ce 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -1147,19 +1147,6 @@ static void PrettyPrintFunctionNameWithArgs(Stream 
&out_stream,
     out_stream.PutChar(')');
 }
 
-static void FormatInlinedBlock(Stream &out_stream, Block *block) {
-  if (!block)
-    return;
-  Block *inline_block = block->GetContainingInlinedBlock();
-  if (inline_block) {
-    if (const InlineFunctionInfo *inline_info =
-            inline_block->GetInlinedFunctionInfo()) {
-      out_stream.PutCString(" [inlined] ");
-      inline_info->GetName().Dump(&out_stream);
-    }
-  }
-}
-
 static VariableListSP GetFunctionVariableList(const SymbolContext &sc) {
   assert(sc.function);
 
@@ -1170,22 +1157,6 @@ static VariableListSP GetFunctionVariableList(const 
SymbolContext &sc) {
   return sc.function->GetBlock(true).GetBlockVariableList(true);
 }
 
-static char const *GetInlinedFunctionName(const SymbolContext &sc) {
-  if (!sc.block)
-    return nullptr;
-
-  const Block *inline_block = sc.block->GetContainingInlinedBlock();
-  if (!inline_block)
-    return nullptr;
-
-  const InlineFunctionInfo *inline_info =
-      inline_block->GetInlinedFunctionInfo();
-  if (!inline_info)
-    return nullptr;
-
-  return inline_info->GetName().AsCString(nullptr);
-}
-
 static bool PrintFunctionNameWithArgs(Stream &s,
                                       const ExecutionContext *exe_ctx,
                                       const SymbolContext &sc) {
@@ -1194,16 +1165,11 @@ static bool PrintFunctionNameWithArgs(Stream &s,
   ExecutionContextScope *exe_scope =
       exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
 
-  const char *cstr = sc.function->GetName().AsCString(nullptr);
+  const char *cstr =
+      sc.GetPossiblyInlinedFunctionName(Mangled::ePreferDemangled);
   if (!cstr)
     return false;
 
-  if (const char *inlined_name = GetInlinedFunctionName(sc)) {
-    s.PutCString(cstr);
-    s.PutCString(" [inlined] ");
-    cstr = inlined_name;
-  }
-
   VariableList args;
   if (auto variable_list_sp = GetFunctionVariableList(sc))
     variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
@@ -1724,21 +1690,17 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
     if (language_plugin_handled) {
       s << ss.GetString();
       return true;
-    } else {
-      const char *name = nullptr;
-      if (sc->function)
-        name = sc->function->GetName().AsCString(nullptr);
-      else if (sc->symbol)
-        name = sc->symbol->GetName().AsCString(nullptr);
-
-      if (name) {
-        s.PutCString(name);
-        FormatInlinedBlock(s, sc->block);
-        return true;
-      }
     }
+
+    const char *name = sc->GetPossiblyInlinedFunctionName(
+        Mangled::NamePreference::ePreferDemangled);
+    if (!name)
+      return false;
+
+    s.PutCString(name);
+
+    return true;
   }
-    return false;
 
   case Entry::Type::FunctionNameNoArgs: {
     if (!sc)
@@ -1760,20 +1722,17 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
     if (language_plugin_handled) {
       s << ss.GetString();
       return true;
-    } else {
-      ConstString name;
-      if (sc->function)
-        name = sc->function->GetNameNoArguments();
-      else if (sc->symbol)
-        name = sc->symbol->GetNameNoArguments();
-      if (name) {
-        s.PutCString(name.GetCString());
-        FormatInlinedBlock(s, sc->block);
-        return true;
-      }
     }
+
+    const char *name = sc->GetPossiblyInlinedFunctionName(
+        Mangled::NamePreference::ePreferDemangledWithoutArguments);
+    if (!name)
+      return false;
+
+    s.PutCString(name);
+
+    return true;
   }
-    return false;
 
   case Entry::Type::FunctionNameWithArgs: {
     if (!sc)
@@ -1815,19 +1774,13 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
     if (!sc)
       return false;
 
-    const char *name = nullptr;
-    if (sc->symbol)
-      name =
-          
sc->symbol->GetMangled().GetName(Mangled::ePreferMangled).AsCString();
-    else if (sc->function)
-      name = sc->function->GetMangled()
-                 .GetName(Mangled::ePreferMangled)
-                 .AsCString();
-
+    const char *name = sc->GetPossiblyInlinedFunctionName(
+        Mangled::NamePreference::ePreferMangled);
     if (!name)
       return false;
+
     s.PutCString(name);
-    FormatInlinedBlock(s, sc->block);
+
     return true;
   }
   case Entry::Type::FunctionAddrOffset:

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 8c05f092dec71..9bd48ec55022a 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1707,22 +1707,6 @@ static VariableListSP GetFunctionVariableList(const 
SymbolContext &sc) {
   return sc.function->GetBlock(true).GetBlockVariableList(true);
 }
 
-static char const *GetInlinedFunctionName(const SymbolContext &sc) {
-  if (!sc.block)
-    return nullptr;
-
-  const Block *inline_block = sc.block->GetContainingInlinedBlock();
-  if (!inline_block)
-    return nullptr;
-
-  const InlineFunctionInfo *inline_info =
-      inline_block->GetInlinedFunctionInfo();
-  if (!inline_info)
-    return nullptr;
-
-  return inline_info->GetName().AsCString(nullptr);
-}
-
 static bool PrintFunctionNameWithArgs(Stream &s,
                                       const ExecutionContext *exe_ctx,
                                       const SymbolContext &sc) {
@@ -1731,16 +1715,11 @@ static bool PrintFunctionNameWithArgs(Stream &s,
   ExecutionContextScope *exe_scope =
       exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
 
-  const char *cstr = sc.function->GetName().AsCString(nullptr);
+  const char *cstr = sc.GetPossiblyInlinedFunctionName(
+      Mangled::NamePreference::ePreferDemangled);
   if (!cstr)
     return false;
 
-  if (const char *inlined_name = GetInlinedFunctionName(sc)) {
-    s.PutCString(cstr);
-    s.PutCString(" [inlined] ");
-    cstr = inlined_name;
-  }
-
   VariableList args;
   if (auto variable_list_sp = GetFunctionVariableList(sc))
     variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,

diff  --git a/lldb/source/Symbol/SymbolContext.cpp 
b/lldb/source/Symbol/SymbolContext.cpp
index 183947a694363..a9626bbc37777 100644
--- a/lldb/source/Symbol/SymbolContext.cpp
+++ b/lldb/source/Symbol/SymbolContext.cpp
@@ -872,6 +872,36 @@ const Symbol 
*SymbolContext::FindBestGlobalDataSymbol(ConstString name,
   return nullptr; // no error; we just didn't find anything
 }
 
+char const *SymbolContext::GetPossiblyInlinedFunctionName(
+    Mangled::NamePreference mangling_preference) const {
+  const char *name = nullptr;
+  if (function)
+    name = function->GetMangled().GetName(mangling_preference).AsCString();
+  else if (symbol)
+    name = symbol->GetMangled().GetName(mangling_preference).AsCString();
+
+  if (!block)
+    return name;
+
+  const Block *inline_block = block->GetContainingInlinedBlock();
+  if (!inline_block)
+    return name;
+
+  const InlineFunctionInfo *inline_info =
+      inline_block->GetInlinedFunctionInfo();
+  if (!inline_info)
+    return name;
+
+  // If we do have an inlined frame name, return that.
+  if (char const *inline_name =
+          inline_info->GetMangled().GetName(mangling_preference).AsCString())
+    return inline_name;
+
+  // Sometimes an inline frame may not have mangling information,
+  // but does have a valid name.
+  return inline_info->GetName().AsCString();
+}
+
 //
 //  SymbolContextSpecifier
 //

diff  --git 
a/lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp 
b/lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp
index 7ad72b4880d79..64e2a5b479675 100644
--- a/lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp
+++ b/lldb/test/API/functionalities/param_entry_vals/basic_entry_values/main.cpp
@@ -70,8 +70,8 @@ __attribute__((noinline)) void func6(int &sink, int x) {
 __attribute__((noinline)) void func7(int &sink, int x) {
   //% self.filecheck("bt", "main.cpp", "-check-prefix=FUNC7-BT")
   // FUNC7-BT: func7
-  // FUNC7-BT-NEXT: [inlined] func8_inlined
-  // FUNC7-BT-NEXT: [inlined] func9_inlined
+  // FUNC7-BT-NEXT: func8_inlined
+  // FUNC7-BT-NEXT: func9_inlined
   // FUNC7-BT-NEXT: func10
   use<int &, int>(sink, x);
   use<int &, int>(dummy, 0);

diff  --git 
a/lldb/test/API/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp
 
b/lldb/test/API/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp
index 9829e0246fc2b..0a7d365d776c6 100644
--- 
a/lldb/test/API/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp
+++ 
b/lldb/test/API/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp
@@ -1,13 +1,13 @@
 volatile int x;
 
+// clang-format off
 void __attribute__((noinline)) tail_call_sink() {
   x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=TAIL-CALL-SINK")
   // TAIL-CALL-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`tail_call_sink() at 
main.cpp:[[@LINE-1]]:4
-  // TAIL-CALL-SINK-NEXT: func3{{.*}} [artificial]
+  // TAIL-CALL-SINK-NEXT: inlinable_function_which_tail_calls() at 
main.cpp{{.*}} [artificial]
   // TAIL-CALL-SINK-NEXT: main{{.*}}
-
-  // TODO: The backtrace should include inlinable_function_which_tail_calls.
 }
+// clang-format on
 
 void __attribute__((always_inline)) inlinable_function_which_tail_calls() {
   tail_call_sink();
@@ -17,13 +17,15 @@ void __attribute__((noinline)) func3() {
   inlinable_function_which_tail_calls();
 }
 
+// clang-format off
 void __attribute__((always_inline)) inline_sink() {
   x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=INLINE-SINK")
-  // INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`func2() [inlined] 
inline_sink() at main.cpp:[[@LINE-1]]:4
+  // INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`inline_sink() at 
main.cpp:[[@LINE-1]]:4
   // INLINE-SINK-NEXT: func2{{.*}}
   // INLINE-SINK-NEXT: func1{{.*}} [artificial]
   // INLINE-SINK-NEXT: main{{.*}}
 }
+// clang-format on
 
 void __attribute__((noinline)) func2() { inline_sink(); /* inlined */ }
 

diff  --git a/lldb/test/Shell/Recognizer/verbose_trap-in-stl-max-depth.test 
b/lldb/test/Shell/Recognizer/verbose_trap-in-stl-max-depth.test
index 0c3275c571b3d..2ea6594643c9c 100644
--- a/lldb/test/Shell/Recognizer/verbose_trap-in-stl-max-depth.test
+++ b/lldb/test/Shell/Recognizer/verbose_trap-in-stl-max-depth.test
@@ -12,5 +12,5 @@ run
 frame recognizer info 0
 # CHECK: frame 0 is recognized by Verbose Trap StackFrame Recognizer
 frame info
-# CHECK: frame #0: {{.*}}`std::recursively_aborts(int) {{.*}} at 
verbose_trap-in-stl-max-depth.cpp
+# CHECK: frame #0: {{.*}}`__clang_trap_msg$Error$max depth at 
verbose_trap-in-stl-max-depth.cpp
 q

diff  --git a/lldb/test/Shell/Settings/TestFrameFormatName.test 
b/lldb/test/Shell/Settings/TestFrameFormatName.test
index caa3242527c6e..110daceb47b40 100644
--- a/lldb/test/Shell/Settings/TestFrameFormatName.test
+++ b/lldb/test/Shell/Settings/TestFrameFormatName.test
@@ -30,7 +30,7 @@ c
 c
 # NAME_WITH_ARGS: frame Foo::returns_func_ptr<int>(this={{.*}}, (null)={{.*}})
 c
-# NAME_WITH_ARGS: frame main [inlined] inlined_foo(str="bar")
+# NAME_WITH_ARGS: frame inlined_foo(str="bar")
 q
 
 #--- name.input
@@ -38,18 +38,18 @@ q
 settings set -f frame-format "frame ${function.name}\n"
 break set -n inlined_foo
 run
-# NAME: frame main [inlined] inlined_foo(char const*)
+# NAME: frame inlined_foo(char const*)
 
 #--- name_without_args.input
 # RUN: %lldb -b -s %t/name_without_args.input %t.out | FileCheck %s 
--check-prefix=NAME_WITHOUT_ARGS
 settings set -f frame-format "frame ${function.name-without-args}\n"
 break set -n inlined_foo
 run
-# NAME_WITHOUT_ARGS: frame main [inlined] inlined_foo(char const*)
+# NAME_WITHOUT_ARGS: frame inlined_foo
 
 #--- mangled_name.input
 # RUN: %lldb -b -s %t/mangled_name.input %t.out | FileCheck %s 
--check-prefix=MANGLED_NAME
 settings set -f frame-format "frame ${function.mangled-name}\n"
 break set -n inlined_foo
 run
-# MANGLED_NAME: frame main [inlined] inlined_foo(char const*)
+# MANGLED_NAME: frame _Z11inlined_fooPKc


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to