Skip to content

Commit 6f7f37f

Browse files
author
Jeffrey Tan
committed
Add Test
1 parent 0f9f57f commit 6f7f37f

File tree

4 files changed

+88
-3
lines changed

4 files changed

+88
-3
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
C_SOURCES := main.c
2+
3+
include Makefile.rules
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""
2+
Test lldb-dap stackTrace request for compiler generated code
3+
"""
4+
5+
import os
6+
7+
import lldbdap_testcase
8+
from lldbsuite.test.decorators import *
9+
from lldbsuite.test.lldbtest import *
10+
11+
12+
class TestDAP_stackTraceCompilerGeneratedCode(lldbdap_testcase.DAPTestCaseBase):
13+
@skipIfWindows
14+
def test_non_leaf_frame_compiler_generate_code(self):
15+
"""
16+
Test that non-leaf frames with compiler-generated code are properly resolved.
17+
18+
This test verifies that LLDB correctly handles stack frames containing
19+
compiler-generated code (code without valid source location information).
20+
When a non-leaf frame contains compiler-generated code immediately after a
21+
call instruction, LLDB should resolve the frame's source location to the
22+
call instruction's line, rather than to the compiler-generated code that
23+
follows, which lacks proper symbolication information.
24+
"""
25+
program = self.getBuildArtifact("a.out")
26+
self.build_and_launch(program)
27+
source = "main.c"
28+
29+
# Set breakpoint inside bar() function
30+
lines = [line_number(source, "// breakpoint here")]
31+
breakpoint_ids = self.set_source_breakpoints(source, lines)
32+
self.assertEqual(
33+
len(breakpoint_ids), len(lines), "expect correct number of breakpoints"
34+
)
35+
36+
self.continue_to_breakpoints(breakpoint_ids)
37+
38+
# Get the stack frames: [0] = bar(), [1] = foo(), [2] = main()
39+
stack_frames = self.get_stackFrames()
40+
self.assertGreater(len(stack_frames), 2, "Expected more than 2 stack frames")
41+
42+
# Examine the foo() frame (stack_frames[1])
43+
# This is the critical frame containing compiler-generated code
44+
foo_frame = stack_frames[1]
45+
print(f"foo_frame: {foo_frame}")
46+
47+
# Verify that the frame's line number points to the bar() call,
48+
# not to the compiler-generated code after it
49+
foo_call_bar_source_line = foo_frame.get("line")
50+
self.assertEqual(
51+
foo_call_bar_source_line,
52+
line_number(source, "foo call bar"),
53+
"Expected foo call bar to be the source line of the frame",
54+
)
55+
56+
# Verify the source file name is correctly resolved
57+
foo_source_name = foo_frame.get("source", {}).get("name")
58+
self.assertEqual(
59+
foo_source_name, "main.c", "Expected foo source name to be main.c"
60+
)
61+
62+
# When lldb fails to symbolicate a frame it will emit a fake assembly
63+
# source with path of format <module>`<symbol> or <module>`<address> with
64+
# sourceReference to retrieve disassembly source file.
65+
# Verify that this didn't happen - the path should be a real file path.
66+
foo_path = foo_frame.get("source", {}).get("path")
67+
self.assertNotIn("`", foo_path, "Expected foo source path to not contain `")
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
void bar() {
2+
int val = 32; // breakpoint here
3+
}
4+
5+
void at_line_zero() {}
6+
7+
int foo() {
8+
bar(); // foo call bar
9+
#line 0 "test.cpp"
10+
at_line_zero();
11+
return 0;
12+
}
13+
14+
int main(int argc, char const *argv[]) {
15+
foo();
16+
return 0;
17+
}

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,7 @@ std::optional<protocol::Source> DAP::ResolveSource(const lldb::SBFrame &frame) {
665665
// EXAMPLE: If PC is at 0x1004 (frame return address after the call
666666
// instruction) with no line info, but 0x1003 (in the middle of previous call
667667
// instruction) is at line 42, symbol context returns line 42.
668-
//
669-
// NOTE: This issue is non-deterministic and depends on compiler debug info
670-
// generation, making it difficult to create a reliable automated test.
668+
671669
const lldb::SBLineEntry frame_line_entry = frame.GetLineEntry();
672670
if (DisplayAssemblySource(debugger, frame_line_entry)) {
673671
const lldb::SBAddress frame_pc = frame.GetPCAddress();

0 commit comments

Comments
 (0)