[Lldb-commits] [lldb] dc25ab3 - [lldb]Make `list` command work with headers when possible. (#139002)

via lldb-commits lldb-commits at lists.llvm.org
Mon May 19 08:04:04 PDT 2025


Author: Vy Nguyen
Date: 2025-05-19T11:04:01-04:00
New Revision: dc25ab389c2d441ba378d4db56a4a61e3eedb889

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

LOG: [lldb]Make `list` command work with  headers when possible. (#139002)

Given this simple test case:

```
// foo.h
extern int* ptr;
inline void g(int x) {
  *ptr = x; // should raise a SIGILL
}
//--------------
// foo.cc
#include "foo.h"
int* ptr;

//--------------
// main.cc

#include "foo.h"

int main() {
  g(123); // Call the inlined function and crash
  return 0;
}

$ clang -g main.cc foo.cc -o main.out
$ lldb main.out
```

When you run `main.out` under lldb, it'd stop inside `void g(int)`
because of the crash.
The stack trace would show that it had crashed in `foo.h`, but if you do
`list foo.h:2`, lldb would complain that it could not find the source
file, which is confusing.

This patch make `list` work with headers.

Added: 
    lldb/test/Shell/Commands/list-header.test

Modified: 
    lldb/source/Commands/CommandObjectSource.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp
index 8c87af590a372..7e7d3f065b622 100644
--- a/lldb/source/Commands/CommandObjectSource.cpp
+++ b/lldb/source/Commands/CommandObjectSource.cpp
@@ -1108,9 +1108,15 @@ class CommandObjectSourceList : public CommandObjectParsed {
         }
       }
     } else {
-      const char *filename = m_options.file_name.c_str();
-
+      //      const char *filename = m_options.file_name.c_str();
+      FileSpec file_spec(m_options.file_name);
       bool check_inlines = false;
+      const InlineStrategy inline_strategy = target.GetInlineStrategy();
+      if (inline_strategy == eInlineBreakpointsAlways ||
+          (inline_strategy == eInlineBreakpointsHeaders &&
+           !file_spec.IsSourceImplementationFile()))
+        check_inlines = true;
+
       SymbolContextList sc_list;
       size_t num_matches = 0;
 
@@ -1122,17 +1128,20 @@ class CommandObjectSourceList : public CommandObjectParsed {
             ModuleSpec module_spec(module_file_spec);
             matching_modules.Clear();
             target.GetImages().FindModules(module_spec, matching_modules);
-            num_matches += matching_modules.ResolveSymbolContextForFilePath(
-                filename, 0, check_inlines,
+            num_matches += matching_modules.ResolveSymbolContextsForFileSpec(
+                file_spec, 1, check_inlines,
                 SymbolContextItem(eSymbolContextModule |
-                                  eSymbolContextCompUnit),
+                                  eSymbolContextCompUnit |
+                                  eSymbolContextLineEntry),
                 sc_list);
           }
         }
       } else {
-        num_matches = target.GetImages().ResolveSymbolContextForFilePath(
-            filename, 0, check_inlines,
-            eSymbolContextModule | eSymbolContextCompUnit, sc_list);
+        num_matches = target.GetImages().ResolveSymbolContextsForFileSpec(
+            file_spec, 1, check_inlines,
+            eSymbolContextModule | eSymbolContextCompUnit |
+                eSymbolContextLineEntry,
+            sc_list);
       }
 
       if (num_matches == 0) {
@@ -1179,10 +1188,18 @@ class CommandObjectSourceList : public CommandObjectParsed {
           if (m_options.num_lines == 0)
             m_options.num_lines = 10;
           const uint32_t column = 0;
+
+          // Headers aren't always in the DWARF but if they have
+          // executable code (eg., inlined-functions) then the callsite's
+          // file(s) will be found and assigned to
+          // sc.comp_unit->GetPrimarySupportFile, which is NOT what we want to
+          // print. Instead, we want to print the one from the line entry.
+          lldb::SupportFileSP found_file_sp = sc.line_entry.file_sp;
+
           target.GetSourceManager().DisplaySourceLinesWithLineNumbers(
-              sc.comp_unit->GetPrimarySupportFile(),
-              m_options.start_line, column, 0, m_options.num_lines, "",
-              &result.GetOutputStream(), GetBreakpointLocations());
+              found_file_sp, m_options.start_line, column, 0,
+              m_options.num_lines, "", &result.GetOutputStream(),
+              GetBreakpointLocations());
 
           result.SetStatus(eReturnStatusSuccessFinishResult);
         } else {

diff  --git a/lldb/test/Shell/Commands/list-header.test b/lldb/test/Shell/Commands/list-header.test
new file mode 100644
index 0000000000000..08bcedd3fc946
--- /dev/null
+++ b/lldb/test/Shell/Commands/list-header.test
@@ -0,0 +1,57 @@
+## Test that `list header.h:<line>` works correctly when header is available.
+## 
+# RUN: split-file %s %t
+
+# RUN: %clang_host -g %t/main_with_inlined.cc %t/foo.cc -o %t/main_with_inlined.out
+# RUN: %clang_host -g %t/main_no_inlined.cc %t/foo.cc -o %t/main_no_inlined.out
+
+# RUN: %lldb %t/main_with_inlined.out -o "list foo.h:2" -o "exit" 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=CHECK-INLINED
+
+## Would be nice if this listed the header too - but probably not something
+## we want to support right now.
+# RUN: echo quit | %lldb %t/main_no_inlined.out -o "list foo.h:2" -o "exit" 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=CHECK-NO-INLINED
+
+# CHECK-INLINED: 2      extern int* ptr;
+# CHECK-INLINED: 3   	void f(int x);
+# CHECK-INLINED: 4   	
+# CHECK-INLINED: 5   	inline void g(int x) {
+# CHECK-INLINED: 6   	  *ptr = x; // should crash here
+# CHECK-INLINED: 7   	}
+
+# CHECK-NO-INLINED: error: Could not find source file "foo.h".
+
+#--- foo.h
+// foo.h
+extern int* ptr;
+void f(int x);
+
+inline void g(int x) {
+  *ptr = x; // should crash here
+}
+
+#--- foo.cc
+#include "foo.h"
+
+int* ptr;
+
+void f(int x) {
+  *ptr = x;
+}
+
+#--- main_with_inlined.cc
+#include "foo.h"
+
+int main() {
+  g(123); // Call the inlined function
+  return 0;
+}
+
+#--- main_no_inlined.cc
+#include "foo.h"
+
+int main() {
+  f(234);
+  return 0;
+}


        


More information about the lldb-commits mailing list