-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Fix lldb-dap non-leaf frame source resolution issue #165944
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| C_SOURCES := main.c | ||
|
|
||
| include Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| """ | ||
| Test lldb-dap stackTrace request for compiler generated code | ||
| """ | ||
|
|
||
| import os | ||
|
|
||
| import lldbdap_testcase | ||
| from lldbsuite.test.decorators import * | ||
| from lldbsuite.test.lldbtest import * | ||
|
|
||
|
|
||
| class TestDAP_stackTraceCompilerGeneratedCode(lldbdap_testcase.DAPTestCaseBase): | ||
| def test_non_leaf_frame_compiler_generate_code(self): | ||
| """ | ||
| Test that non-leaf frames with compiler-generated code are properly resolved. | ||
|
|
||
| This test verifies that LLDB correctly handles stack frames containing | ||
| compiler-generated code (code without valid source location information). | ||
| When a non-leaf frame contains compiler-generated code immediately after a | ||
| call instruction, LLDB should resolve the frame's source location to the | ||
| call instruction's line, rather than to the compiler-generated code that | ||
| follows, which lacks proper symbolication information. | ||
| """ | ||
| program = self.getBuildArtifact("a.out") | ||
| self.build_and_launch(program) | ||
| source = "main.c" | ||
|
|
||
| # Set breakpoint inside bar() function | ||
| lines = [line_number(source, "// breakpoint here")] | ||
| breakpoint_ids = self.set_source_breakpoints(source, lines) | ||
| self.assertEqual( | ||
| len(breakpoint_ids), len(lines), "expect correct number of breakpoints" | ||
| ) | ||
|
|
||
| self.continue_to_breakpoints(breakpoint_ids) | ||
|
|
||
| # Get the stack frames: [0] = bar(), [1] = foo(), [2] = main() | ||
| stack_frames = self.get_stackFrames() | ||
| self.assertGreater(len(stack_frames), 2, "Expected more than 2 stack frames") | ||
|
|
||
| # Examine the foo() frame (stack_frames[1]) | ||
| # This is the critical frame containing compiler-generated code | ||
| foo_frame = stack_frames[1] | ||
|
|
||
| # Verify that the frame's line number points to the bar() call, | ||
| # not to the compiler-generated code after it | ||
| foo_call_bar_source_line = foo_frame.get("line") | ||
| self.assertEqual( | ||
| foo_call_bar_source_line, | ||
| line_number(source, "foo call bar"), | ||
| "Expected foo call bar to be the source line of the frame", | ||
| ) | ||
|
|
||
| # Verify the source file name is correctly resolved | ||
| foo_source_name = foo_frame.get("source", {}).get("name") | ||
| self.assertEqual( | ||
| foo_source_name, "main.c", "Expected foo source name to be main.c" | ||
| ) | ||
|
|
||
| # When lldb fails to symbolicate a frame it will emit a fake assembly | ||
| # source with path of format <module>`<symbol> or <module>`<address> with | ||
| # sourceReference to retrieve disassembly source file. | ||
| # Verify that this didn't happen - the path should be a real file path. | ||
| foo_path = foo_frame.get("source", {}).get("path") | ||
| self.assertNotIn("`", foo_path, "Expected foo source path to not contain `") | ||
| self.continue_to_exit() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| void bar() { | ||
| int val = 32; // breakpoint here | ||
| } | ||
|
|
||
| void at_line_zero() {} | ||
|
|
||
| int foo(); | ||
|
|
||
| int main(int argc, char const *argv[]) { | ||
| foo(); | ||
| return 0; | ||
| } | ||
|
|
||
| int foo() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please, forward declare |
||
| bar(); // foo call bar | ||
| #line 0 "test.cpp" | ||
| at_line_zero(); | ||
| return 0; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest using a function call for more predictable code generation |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.