Skip to content

[lldb][Format] Add [inlined] marker to names of inlined frames #142952

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 5, 2025

Conversation

Michael137
Copy link
Member

@Michael137 Michael137 commented Jun 5, 2025

This was removed in #135343 in favour of making it a format variable, which we do here. This follows the precedent of the [opt] and [artificial] markers.

Before:

 thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
 * frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3
   frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
   frame #2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43
   frame #3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
   frame #4: 0x0000000186345be4 dyld`start + 7040

After (note the [inlined] markers):

thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
* frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3 [inlined]
  frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
  frame #2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43 [inlined]
  frame #3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
  frame #4: 0x0000000186345be4 dyld`start + 7040

rdar://152642178

This was removed in llvm#135343 in
favour of making it a format variable, which we do here. This follows
the precedent of the `[opt]` and `[artificial]` markers.

rdar://152642178
@Michael137 Michael137 requested a review from JDevlieghere as a code owner June 5, 2025 12:09
@llvmbot llvmbot added the lldb label Jun 5, 2025
@Michael137 Michael137 force-pushed the lldb/inlined-frame-marker branch from 3de64ab to 7d2a640 Compare June 5, 2025 12:09
@llvmbot
Copy link
Member

llvmbot commented Jun 5, 2025

@llvm/pr-subscribers-lldb

Author: Michael Buch (Michael137)

Changes

This was removed in #135343 in favour of making it a format variable, which we do here. This follows the precedent of the [opt] and [artificial] markers.

rdar://152642178


Full diff: https://github.com/llvm/llvm-project/pull/142952.diff

6 Files Affected:

  • (modified) lldb/docs/use/formatting.rst (+2)
  • (modified) lldb/include/lldb/Core/FormatEntity.h (+1)
  • (modified) lldb/source/Core/CoreProperties.td (+2-2)
  • (modified) lldb/source/Core/FormatEntity.cpp (+6)
  • (added) lldb/test/Shell/Settings/TestFrameFunctionInlined.test (+35)
  • (modified) lldb/unittests/Core/FormatEntityTest.cpp (+1)
diff --git a/lldb/docs/use/formatting.rst b/lldb/docs/use/formatting.rst
index e71b08780eb3d..21b3ca1912b02 100644
--- a/lldb/docs/use/formatting.rst
+++ b/lldb/docs/use/formatting.rst
@@ -122,6 +122,8 @@ A complete list of currently supported format string variables is listed below:
 +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | ``function.initial-function``                     | Will evaluate to true if this is the start of the first function, as opposed to a change of functions (may be used in ``disassembly-format`` to print the function name for the first function being disassembled)                                                                          |
 +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| ``function.is-inlined``                           | Will evaluate to true if this function was inlined                                                                                                                                                                                                                                          |
++---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | ``line.file.basename``                            | The line table entry basename to the file for the current line entry in the current frame.                                                                                                                                                                                                  |
 +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | ``line.file.fullpath``                            | The line table entry fullpath to the file for the current line entry in the current frame.                                                                                                                                                                                                  |
diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h
index 18257161eec7b..17fee068230b2 100644
--- a/lldb/include/lldb/Core/FormatEntity.h
+++ b/lldb/include/lldb/Core/FormatEntity.h
@@ -104,6 +104,7 @@ struct Entry {
     FunctionInitial,
     FunctionChanged,
     FunctionIsOptimized,
+    FunctionIsInlined,
     LineEntryFile,
     LineEntryLineNumber,
     LineEntryColumn,
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index 78988ce5b732f..4d1ea5dfec2eb 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -59,7 +59,7 @@ let Definition = "debugger" in {
     Desc<"The default disassembly format string to use when disassembling instruction sequences.">;
   def FrameFormat: Property<"frame-format", "FormatEntity">,
     Global,
-    DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\\\\n">,
+    DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
     Desc<"The default frame format string to use when displaying stack frame information for threads.">;
   def NotiftVoid: Property<"notify-void", "Boolean">,
     Global,
@@ -217,7 +217,7 @@ let Definition = "debugger" in {
     Desc<"If true, LLDB will automatically escape non-printable and escape characters when formatting strings.">;
   def FrameFormatUnique: Property<"frame-format-unique", "FormatEntity">,
     Global,
-    DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\\\\n">,
+    DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
     Desc<"The default frame format string to use when displaying stack frame information for threads from thread backtrace unique.">;
   def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">,
     Global,
diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index 3c591ba15a075..8e3c3c18863fa 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -124,6 +124,7 @@ constexpr Definition g_function_child_entries[] = {
     Definition("initial-function", EntryType::FunctionInitial),
     Definition("changed", EntryType::FunctionChanged),
     Definition("is-optimized", EntryType::FunctionIsOptimized),
+    Definition("is-inlined", EntryType::FunctionIsInlined),
     Definition("prefix", EntryType::FunctionPrefix),
     Definition("scope", EntryType::FunctionScope),
     Definition("basename", EntryType::FunctionBasename),
@@ -402,6 +403,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
     ENUM_TO_CSTR(FunctionInitial);
     ENUM_TO_CSTR(FunctionChanged);
     ENUM_TO_CSTR(FunctionIsOptimized);
+    ENUM_TO_CSTR(FunctionIsInlined);
     ENUM_TO_CSTR(LineEntryFile);
     ENUM_TO_CSTR(LineEntryLineNumber);
     ENUM_TO_CSTR(LineEntryColumn);
@@ -1928,6 +1930,10 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
     return is_optimized;
   }
 
+  case Entry::Type::FunctionIsInlined: {
+    return sc && sc->block && sc->block->GetInlinedFunctionInfo();
+  }
+
   case Entry::Type::FunctionInitial:
     return initial_function;
 
diff --git a/lldb/test/Shell/Settings/TestFrameFunctionInlined.test b/lldb/test/Shell/Settings/TestFrameFunctionInlined.test
new file mode 100644
index 0000000000000..d68a37fff0d31
--- /dev/null
+++ b/lldb/test/Shell/Settings/TestFrameFunctionInlined.test
@@ -0,0 +1,35 @@
+# Test the ${function.is-inlined} 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 regular();
+
+[[clang::always_inline]] void inlined1() {
+  regular();
+}
+void regular() {inlined1();}
+[[clang::always_inline]] void inlined2() {regular();}
+
+int main() {
+  inlined2();
+  return 0;
+}
+
+#--- commands.input
+
+settings set frame-format "frame '${function.name}{${function.is-inlined} (Inlined)}'\n"
+breakpoint set -n inlined1
+run
+bt
+
+# CHECK:      (lldb) bt
+# CHECK:      frame 'inlined1() (Inlined)'
+# CHECK-NEXT: frame 'regular()'
+# CHECK-NEXT: frame 'inlined2() (Inlined)'
+# CHECK-NEXT: frame 'main'
+# CHECK-NEXT: frame 'start'
diff --git a/lldb/unittests/Core/FormatEntityTest.cpp b/lldb/unittests/Core/FormatEntityTest.cpp
index 2cddf8ff4e900..e056b6fe7de52 100644
--- a/lldb/unittests/Core/FormatEntityTest.cpp
+++ b/lldb/unittests/Core/FormatEntityTest.cpp
@@ -129,6 +129,7 @@ constexpr llvm::StringRef lookupStrings[] = {
     "${function.initial-function}",
     "${function.changed}",
     "${function.is-optimized}",
+    "${function.is-inlined}",
     "${line.file.basename}",
     "${line.file.dirname}",
     "${line.file.fullpath}",

@Michael137 Michael137 requested a review from felipepiovezan June 5, 2025 14:05
Copy link
Collaborator

@adrian-prantl adrian-prantl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's consistent with the other markers, so LGTM!

@Michael137 Michael137 merged commit 5a91892 into llvm:main Jun 5, 2025
11 checks passed
@Michael137 Michael137 deleted the lldb/inlined-frame-marker branch June 5, 2025 16:41
Michael137 added a commit to swiftlang/llvm-project that referenced this pull request Jun 5, 2025
…142952)

This was removed in llvm#135343 in
favour of making it a format variable, which we do here. This follows
the precedent of the `[opt]` and `[artificial]` markers.

Before:
```
 thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
 * frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3
   frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
   frame #2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43
   frame #3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
   frame #4: 0x0000000186345be4 dyld`start + 7040
```

After (note the `[inlined]` markers):
```
thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
* frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3 [inlined]
  frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
  frame #2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43 [inlined]
  frame #3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
  frame #4: 0x0000000186345be4 dyld`start + 7040
```

rdar://152642178
(cherry picked from commit 5a91892)
Michael137 added a commit to swiftlang/llvm-project that referenced this pull request Jun 6, 2025
…142952)

This was removed in llvm#135343 in
favour of making it a format variable, which we do here. This follows
the precedent of the `[opt]` and `[artificial]` markers.

Before:
```
 thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
 * frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3
   frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
   frame #2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43
   frame #3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
   frame #4: 0x0000000186345be4 dyld`start + 7040
```

After (note the `[inlined]` markers):
```
thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
* frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3 [inlined]
  frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
  frame #2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43 [inlined]
  frame #3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
  frame #4: 0x0000000186345be4 dyld`start + 7040
```

rdar://152642178
(cherry picked from commit 5a91892)
@DavidSpickett
Copy link
Collaborator

DavidSpickett commented Jun 6, 2025

FYI this was failing on Windows because we misplaced the breakpoint and ended up in a recursive loop that when it finally crashed, took forever to backtrace.

So I've changed the test to use lld on Windows, as it does work if we use DWARF - 95b3fd6. Anywhere else, any linker can be used.

I think I'll start doing this whenever I see a DWARF dependent test, instead of making them unsupported. Ideally we'd make all these work with PDB but we simply don't have the time.

@Michael137
Copy link
Member Author

FYI this was failing on Windows because we misplaced the breakpoint and ended up in a recursive loop that when it finally crashed, took forever to backtrace.

So I've changed the test to use lld on Windows, as it does work if we use DWARF - 95b3fd6. Anywhere else, any linker can be used.

I think I'll start doing this whenever I see a DWARF dependent test, instead of making them unsupported. Ideally we'd make all these work with PDB but we simply don't have the time.

Thanks!

Out of curiosity, what's the extra regex in the test for? Why do windows frames have extra stuff in there? Even if we specify the frame-format

@DavidSpickett
Copy link
Collaborator

The function's "name" includes the return and parameter type like: void foo(void) (and maybe the calling convention)

We've regex'd around this before but I never thought much about why it does that. I'll have another look and raise an issue if there's no good explanation for it.

@DavidSpickett
Copy link
Collaborator

Opened #143149.

adrian-prantl pushed a commit to swiftlang/llvm-project that referenced this pull request Jun 6, 2025
…142952) (#10789)

This was removed in llvm#135343 in
favour of making it a format variable, which we do here. This follows
the precedent of the `[opt]` and `[artificial]` markers.

Before:
```
 thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
 * frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3
   frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
   frame #2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43
   frame #3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
   frame #4: 0x0000000186345be4 dyld`start + 7040
```

After (note the `[inlined]` markers):
```
thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
* frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3 [inlined]
  frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
  frame #2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43 [inlined]
  frame #3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
  frame #4: 0x0000000186345be4 dyld`start + 7040
```

rdar://152642178
(cherry picked from commit 5a91892)
rorth pushed a commit to rorth/llvm-project that referenced this pull request Jun 11, 2025
…142952)

This was removed in llvm#135343 in
favour of making it a format variable, which we do here. This follows
the precedent of the `[opt]` and `[artificial]` markers.

Before:
```
 thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
 * frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3
   frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
   frame llvm#2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43
   frame llvm#3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
   frame llvm#4: 0x0000000186345be4 dyld`start + 7040
```

After (note the `[inlined]` markers):
```
thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
* frame #0: 0x000000010000037c a.out`inlined1() at inline.cpp:4:3 [inlined]
  frame #1: 0x000000010000037c a.out`regular() at inline.cpp:6:17
  frame llvm#2: 0x00000001000003b8 a.out`inlined2() at inline.cpp:7:43 [inlined]
  frame llvm#3: 0x00000001000003b4 a.out`main at inline.cpp:10:3
  frame llvm#4: 0x0000000186345be4 dyld`start + 7040
```

rdar://152642178
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants