diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index c205813565d52..05cf823bff682 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -1102,6 +1102,16 @@ class CommandObjectSourceList : public CommandObjectParsed { const char *filename = m_options.file_name.c_str(); bool check_inlines = false; + const InlineStrategy inline_strategy = target.GetInlineStrategy(); + if (inline_strategy == eInlineBreakpointsAlways) + check_inlines = true; + auto re_compute_check_inlines = + [&check_inlines, &inline_strategy](const FileSpec &file_spec) { + if (!file_spec.IsSourceImplementationFile() && + inline_strategy == eInlineBreakpointsHeaders) + check_inlines = true; + }; + SymbolContextList sc_list; size_t num_matches = 0; @@ -1113,17 +1123,25 @@ 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, + FileSpec file_spec(filename); + re_compute_check_inlines(file_spec); + + 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); + FileSpec file_spec(filename); + re_compute_check_inlines(file_spec); + num_matches = target.GetImages().ResolveSymbolContextsForFileSpec( + file_spec, 1, check_inlines, + eSymbolContextModule | eSymbolContextCompUnit | + eSymbolContextLineEntry, + sc_list); } if (num_matches == 0) { @@ -1170,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:` 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; +}