mib created this revision. mib requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
It can happen that a line entry reports that some source code is located at line 0. In DWARF, line 0 is a special location which indicates that code has no 1-1 mapping with source. When stopping in one of those artificial locations, lldb doesn't know which line to display and shows the beginning of the file instead. This patch mitigates this behaviour by checking if the current symbol context of the line entry has a matching function, in which case, it slides the source listing to the start of that function. This patch also shows the user a warning explaining why lldb couldn't show sources at that location. rdar://83118425 Signed-off-by: Med Ismail Bennani <medismail.benn...@gmail.com> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D115313 Files: lldb/source/Target/StackFrame.cpp lldb/test/API/source-manager/TestSourceManager.py lldb/test/API/source-manager/artificial_location.c Index: lldb/test/API/source-manager/artificial_location.c =================================================================== --- /dev/null +++ lldb/test/API/source-manager/artificial_location.c @@ -0,0 +1,8 @@ +int foo() { + return 42; +} + +int main() { +#line 0 + return foo(); +} Index: lldb/test/API/source-manager/TestSourceManager.py =================================================================== --- lldb/test/API/source-manager/TestSourceManager.py +++ lldb/test/API/source-manager/TestSourceManager.py @@ -199,7 +199,6 @@ SOURCE_DISPLAYED_CORRECTLY, substrs=['Hello world']) - # The '-b' option shows the line table locations from the debug information # that indicates valid places to set source level breakpoints. @@ -265,3 +264,22 @@ substrs=['stopped', 'main-copy.c:%d' % self.line, 'stop reason = breakpoint']) + + def test_artificial_source_location(self): + src_file = 'artificial_location.c' + d = {'C_SOURCES': src_file } + self.build(dictionary=d) + + lldbutil.run_to_source_breakpoint( + self, 'main', + lldb.SBFileSpec(src_file, False)) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("run", RUN_SUCCEEDED, + substrs=['stop reason = breakpoint', '%s:%d' % (src_file,0), + 'Warning: the current PC is an artificial', + 'location unassociated with a particular line in ', + src_file]) + Index: lldb/source/Target/StackFrame.cpp =================================================================== --- lldb/source/Target/StackFrame.cpp +++ lldb/source/Target/StackFrame.cpp @@ -1883,14 +1883,26 @@ if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { have_debuginfo = true; if (source_lines_before > 0 || source_lines_after > 0) { + uint32_t start_line = m_sc.line_entry.line; + if (!start_line && m_sc.function) { + FileSpec source_file; + m_sc.function->GetStartLineSourceInfo(source_file, start_line); + } + size_t num_lines = target->GetSourceManager().DisplaySourceLinesWithLineNumbers( - m_sc.line_entry.file, m_sc.line_entry.line, + m_sc.line_entry.file, start_line, m_sc.line_entry.column, source_lines_before, source_lines_after, "->", &strm); if (num_lines != 0) have_source = true; - // TODO: Give here a one time warning if source file is missing. + if (!num_lines || !m_sc.line_entry.line || + m_sc.line_entry.line == LLDB_INVALID_LINE_NUMBER) { + strm.Printf("Warning: the current PC is an artificial location " + "unassociated with a particular line in %s.", + m_sc.line_entry.file.GetFilename().GetCString()); + strm.EOL(); + } } } switch (disasm_display) {
Index: lldb/test/API/source-manager/artificial_location.c =================================================================== --- /dev/null +++ lldb/test/API/source-manager/artificial_location.c @@ -0,0 +1,8 @@ +int foo() { + return 42; +} + +int main() { +#line 0 + return foo(); +} Index: lldb/test/API/source-manager/TestSourceManager.py =================================================================== --- lldb/test/API/source-manager/TestSourceManager.py +++ lldb/test/API/source-manager/TestSourceManager.py @@ -199,7 +199,6 @@ SOURCE_DISPLAYED_CORRECTLY, substrs=['Hello world']) - # The '-b' option shows the line table locations from the debug information # that indicates valid places to set source level breakpoints. @@ -265,3 +264,22 @@ substrs=['stopped', 'main-copy.c:%d' % self.line, 'stop reason = breakpoint']) + + def test_artificial_source_location(self): + src_file = 'artificial_location.c' + d = {'C_SOURCES': src_file } + self.build(dictionary=d) + + lldbutil.run_to_source_breakpoint( + self, 'main', + lldb.SBFileSpec(src_file, False)) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("run", RUN_SUCCEEDED, + substrs=['stop reason = breakpoint', '%s:%d' % (src_file,0), + 'Warning: the current PC is an artificial', + 'location unassociated with a particular line in ', + src_file]) + Index: lldb/source/Target/StackFrame.cpp =================================================================== --- lldb/source/Target/StackFrame.cpp +++ lldb/source/Target/StackFrame.cpp @@ -1883,14 +1883,26 @@ if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { have_debuginfo = true; if (source_lines_before > 0 || source_lines_after > 0) { + uint32_t start_line = m_sc.line_entry.line; + if (!start_line && m_sc.function) { + FileSpec source_file; + m_sc.function->GetStartLineSourceInfo(source_file, start_line); + } + size_t num_lines = target->GetSourceManager().DisplaySourceLinesWithLineNumbers( - m_sc.line_entry.file, m_sc.line_entry.line, + m_sc.line_entry.file, start_line, m_sc.line_entry.column, source_lines_before, source_lines_after, "->", &strm); if (num_lines != 0) have_source = true; - // TODO: Give here a one time warning if source file is missing. + if (!num_lines || !m_sc.line_entry.line || + m_sc.line_entry.line == LLDB_INVALID_LINE_NUMBER) { + strm.Printf("Warning: the current PC is an artificial location " + "unassociated with a particular line in %s.", + m_sc.line_entry.file.GetFilename().GetCString()); + strm.EOL(); + } } } switch (disasm_display) {
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits