Skip to content

Commit 15e7294

Browse files
committed
return errors for invalid assembly breakpoints, fix request_setBreakpoints in python tests to support both paths and source_reference
1 parent 71dce6c commit 15e7294

File tree

12 files changed

+126
-59
lines changed

12 files changed

+126
-59
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,14 @@ def get_local_variable_child(
551551
return child
552552
return None
553553

554+
def get_source_for_source_reference(self, source_reference):
555+
return {"sourceReference": source_reference}
556+
557+
def get_source_for_path(self, file_path):
558+
(dir, base) = os.path.split(file_path)
559+
source_dict = {"name": base, "path": file_path}
560+
return source_dict
561+
554562
def replay_packets(self, replay_file_path):
555563
f = open(replay_file_path, "r")
556564
mode = "invalid"
@@ -948,20 +956,11 @@ def request_scopes(self, frameId):
948956
command_dict = {"command": "scopes", "type": "request", "arguments": args_dict}
949957
return self.send_recv(command_dict)
950958

951-
def request_setBreakpoints(self, file_path, line_array, data=None):
959+
def request_setBreakpoints(self, source_dict, line_array, data=None):
952960
"""data is array of parameters for breakpoints in line_array.
953961
Each parameter object is 1:1 mapping with entries in line_entry.
954962
It contains optional location/hitCondition/logMessage parameters.
955963
"""
956-
(dir, base) = os.path.split(file_path)
957-
source_dict = {"name": base, "path": file_path}
958-
return self.request_setBreakpoints_with_source(source_dict, line_array, data)
959-
960-
def request_setBreakpointsAssembly(self, sourceReference, line_array, data=None):
961-
source_dict = {"sourceReference": sourceReference}
962-
return self.request_setBreakpoints_with_source(source_dict, line_array, data)
963-
964-
def request_setBreakpoints_with_source(self, source_dict, line_array, data=None):
965964
args_dict = {
966965
"source": source_dict,
967966
"sourceModified": False,
@@ -1388,7 +1387,9 @@ def run_vscode(dbg, args, options):
13881387
else:
13891388
source_to_lines[path] = [int(line)]
13901389
for source in source_to_lines:
1391-
dbg.request_setBreakpoints(source, source_to_lines[source])
1390+
dbg.request_setBreakpoints(
1391+
dbg.get_source_for_path(source), source_to_lines[source]
1392+
)
13921393
if options.funcBreakpoints:
13931394
dbg.request_setFunctionBreakpoints(options.funcBreakpoints)
13941395

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ def set_source_breakpoints(self, source_path, lines, data=None):
5555
Each object in data is 1:1 mapping with the entry in lines.
5656
It contains optional location/hitCondition/logMessage parameters.
5757
"""
58-
response = self.dap_server.request_setBreakpoints(source_path, lines, data)
58+
response = self.dap_server.request_setBreakpoints(
59+
self.dap_server.get_source_for_path(source_path), lines, data
60+
)
5961
if response is None or not response["success"]:
6062
return []
6163
breakpoints = response["body"]["breakpoints"]
@@ -65,8 +67,10 @@ def set_source_breakpoints(self, source_path, lines, data=None):
6567
return breakpoint_ids
6668

6769
def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
68-
response = self.dap_server.request_setBreakpointsAssembly(
69-
source_reference, lines, data
70+
response = self.dap_server.request_setBreakpoints(
71+
self.dap_server.get_source_for_source_reference(source_reference),
72+
lines,
73+
data,
7074
)
7175
if response is None:
7276
return []

lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,19 @@
11
"""
2-
Test lldb-dap setBreakpoints request
2+
Test lldb-dap setBreakpoints request in assembly source references.
33
"""
44

55

6-
import dap_server
7-
import shutil
86
from lldbsuite.test.decorators import *
9-
from lldbsuite.test.lldbtest import line_number
10-
from lldbsuite.test import lldbutil
117
import lldbdap_testcase
12-
import os
138

149

10+
# @skipIfWindows
1511
class TestDAP_setBreakpointsAssembly(lldbdap_testcase.DAPTestCaseBase):
16-
# @skipIfWindows
17-
def test_functionality(self):
12+
def test_can_break_in_source_references(self):
1813
"""Tests hitting assembly source breakpoints"""
1914
program = self.getBuildArtifact("a.out")
2015
self.build_and_launch(program)
2116

22-
self.dap_server.request_evaluate(
23-
"`settings set stop-disassembly-display no-debuginfo", context="repl"
24-
)
25-
26-
finish_line = line_number("main.c", "// Break here")
27-
finish_breakpoints = self.set_source_breakpoints("main.c", [finish_line])
28-
2917
assmebly_func_breakpoints = self.set_function_breakpoints(["assembly_func"])
3018
self.continue_to_breakpoints(assmebly_func_breakpoints)
3119

@@ -52,4 +40,43 @@ def test_functionality(self):
5240
# Clear the breakpoint and then check that the assembly breakpoint does not hit next time
5341
self.set_source_breakpoints_assembly(source_reference, [])
5442
self.continue_to_breakpoints(assmebly_func_breakpoints)
55-
self.continue_to_breakpoints(finish_breakpoints)
43+
self.continue_to_exit()
44+
45+
def test_break_on_invalid_source_reference(self):
46+
"""Tests hitting assembly source breakpoints"""
47+
program = self.getBuildArtifact("a.out")
48+
self.build_and_launch(program)
49+
50+
# Verify that setting a breakpoint on an invalid source reference fails
51+
response = self.dap_server.request_setBreakpoints(
52+
self.dap_server.get_source_for_source_reference(-1), [1]
53+
)
54+
self.assertIsNotNone(response)
55+
breakpoints = response["body"]["breakpoints"]
56+
self.assertEqual(len(breakpoints), 1)
57+
breakpoint = breakpoints[0]
58+
self.assertFalse(
59+
breakpoint["verified"], "Expected breakpoint to not be verified"
60+
)
61+
self.assertIn("message", breakpoint, "Expected message to be present")
62+
self.assertEqual(
63+
breakpoint["message"],
64+
"Invalid sourceReference.",
65+
)
66+
67+
# Verify that setting a breakpoint on a source reference without a symbol also fails
68+
response = self.dap_server.request_setBreakpoints(
69+
self.dap_server.get_source_for_source_reference(0), [1]
70+
)
71+
self.assertIsNotNone(response)
72+
breakpoints = response["body"]["breakpoints"]
73+
self.assertEqual(len(breakpoints), 1)
74+
breakpoint = breakpoints[0]
75+
self.assertFalse(
76+
breakpoint["verified"], "Expected breakpoint to not be verified"
77+
)
78+
self.assertIn("message", breakpoint, "Expected message to be present")
79+
self.assertEqual(
80+
breakpoint["message"],
81+
"Breakpoints in assembly without a valid symbol are not supported yet.",
82+
)

lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <stddef.h>
2-
31
__attribute__((nodebug)) int assembly_func(int n) {
42
n += 1;
53
n += 2;
@@ -12,5 +10,5 @@ int main(int argc, char const *argv[]) {
1210
assembly_func(10);
1311
assembly_func(20);
1412
assembly_func(30);
15-
return 0; // Break here
13+
return 0;
1614
}

lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def test_breakpoint_events(self):
5858
# Set breakpoints and verify that they got set correctly
5959
dap_breakpoint_ids = []
6060
response = self.dap_server.request_setBreakpoints(
61-
main_source_path, [main_bp_line]
61+
self.dap_server.get_source_for_path(main_source_path), [main_bp_line]
6262
)
6363
self.assertTrue(response["success"])
6464
breakpoints = response["body"]["breakpoints"]
@@ -70,7 +70,7 @@ def test_breakpoint_events(self):
7070
)
7171

7272
response = self.dap_server.request_setBreakpoints(
73-
foo_source_path, [foo_bp1_line]
73+
self.dap_server.get_source_for_path(foo_source_path), [foo_bp1_line]
7474
)
7575
self.assertTrue(response["success"])
7676
breakpoints = response["body"]["breakpoints"]

lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ def test_source_map(self):
5858
self.launch(program, sourceMap=source_map)
5959

6060
# breakpoint in main.cpp
61-
response = self.dap_server.request_setBreakpoints(new_main_path, [main_line])
61+
response = self.dap_server.request_setBreakpoints(
62+
self.dap_server.get_source_for_path(new_main_path), [main_line]
63+
)
6264
breakpoints = response["body"]["breakpoints"]
6365
self.assertEqual(len(breakpoints), 1)
6466
breakpoint = breakpoints[0]
@@ -68,7 +70,9 @@ def test_source_map(self):
6870
self.assertEqual(new_main_path, breakpoint["source"]["path"])
6971

7072
# 2nd breakpoint, which is from a dynamically loaded library
71-
response = self.dap_server.request_setBreakpoints(new_other_path, [other_line])
73+
response = self.dap_server.request_setBreakpoints(
74+
self.dap_server.get_source_for_path(new_other_path), [other_line]
75+
)
7276
breakpoints = response["body"]["breakpoints"]
7377
breakpoint = breakpoints[0]
7478
self.assertEqual(breakpoint["line"], other_line)
@@ -81,7 +85,9 @@ def test_source_map(self):
8185
self.verify_breakpoint_hit([other_breakpoint_id])
8286

8387
# 2nd breakpoint again, which should be valid at this point
84-
response = self.dap_server.request_setBreakpoints(new_other_path, [other_line])
88+
response = self.dap_server.request_setBreakpoints(
89+
self.dap_server.get_source_for_path(new_other_path), [other_line]
90+
)
8591
breakpoints = response["body"]["breakpoints"]
8692
breakpoint = breakpoints[0]
8793
self.assertEqual(breakpoint["line"], other_line)
@@ -124,7 +130,9 @@ def test_set_and_clear(self):
124130
self.build_and_launch(program)
125131

126132
# Set 3 breakpoints and verify that they got set correctly
127-
response = self.dap_server.request_setBreakpoints(self.main_path, lines)
133+
response = self.dap_server.request_setBreakpoints(
134+
self.dap_server.get_source_for_path(self.main_path), lines
135+
)
128136
line_to_id = {}
129137
breakpoints = response["body"]["breakpoints"]
130138
self.assertEqual(
@@ -149,7 +157,9 @@ def test_set_and_clear(self):
149157
lines.remove(second_line)
150158
# Set 2 breakpoints and verify that the previous breakpoints that were
151159
# set above are still set.
152-
response = self.dap_server.request_setBreakpoints(self.main_path, lines)
160+
response = self.dap_server.request_setBreakpoints(
161+
self.dap_server.get_source_for_path(self.main_path), lines
162+
)
153163
breakpoints = response["body"]["breakpoints"]
154164
self.assertEqual(
155165
len(breakpoints),
@@ -194,7 +204,9 @@ def test_set_and_clear(self):
194204
# Now clear all breakpoints for the source file by passing down an
195205
# empty lines array
196206
lines = []
197-
response = self.dap_server.request_setBreakpoints(self.main_path, lines)
207+
response = self.dap_server.request_setBreakpoints(
208+
self.dap_server.get_source_for_path(self.main_path), lines
209+
)
198210
breakpoints = response["body"]["breakpoints"]
199211
self.assertEqual(
200212
len(breakpoints),
@@ -214,7 +226,9 @@ def test_set_and_clear(self):
214226
# Now set a breakpoint again in the same source file and verify it
215227
# was added.
216228
lines = [second_line]
217-
response = self.dap_server.request_setBreakpoints(self.main_path, lines)
229+
response = self.dap_server.request_setBreakpoints(
230+
self.dap_server.get_source_for_path(self.main_path), lines
231+
)
218232
if response:
219233
breakpoints = response["body"]["breakpoints"]
220234
self.assertEqual(
@@ -265,7 +279,9 @@ def test_clear_breakpoints_unset_breakpoints(self):
265279
self.build_and_launch(program)
266280

267281
# Set one breakpoint and verify that it got set correctly.
268-
response = self.dap_server.request_setBreakpoints(self.main_path, lines)
282+
response = self.dap_server.request_setBreakpoints(
283+
self.dap_server.get_source_for_path(self.main_path), lines
284+
)
269285
line_to_id = {}
270286
breakpoints = response["body"]["breakpoints"]
271287
self.assertEqual(
@@ -281,7 +297,9 @@ def test_clear_breakpoints_unset_breakpoints(self):
281297
# Now clear all breakpoints for the source file by not setting the
282298
# lines array.
283299
lines = None
284-
response = self.dap_server.request_setBreakpoints(self.main_path, lines)
300+
response = self.dap_server.request_setBreakpoints(
301+
self.dap_server.get_source_for_path(self.main_path), lines
302+
)
285303
breakpoints = response["body"]["breakpoints"]
286304
self.assertEqual(len(breakpoints), 0, "expect no source breakpoints")
287305

@@ -357,7 +375,9 @@ def test_column_breakpoints(self):
357375
# Set two breakpoints on the loop line at different columns.
358376
columns = [13, 39]
359377
response = self.dap_server.request_setBreakpoints(
360-
self.main_path, [loop_line, loop_line], list({"column": c} for c in columns)
378+
self.dap_server.get_source_for_path(self.main_path),
379+
[loop_line, loop_line],
380+
list({"column": c} for c in columns),
361381
)
362382

363383
# Verify the breakpoints were set correctly

lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ def instruction_breakpoint_test(self):
3333
self.build_and_launch(program)
3434

3535
# Set source breakpoint 1
36-
response = self.dap_server.request_setBreakpoints(self.main_path, [main_line])
36+
response = self.dap_server.request_setBreakpoints(
37+
self.dap_server.get_source_for_path(self.main_path), [main_line]
38+
)
3739
breakpoints = response["body"]["breakpoints"]
3840
self.assertEqual(len(breakpoints), 1)
3941
breakpoint = breakpoints[0]

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,9 +1658,16 @@ std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints(
16581658
const auto [iv, inserted] =
16591659
existing_breakpoints.try_emplace(bp_pos, src_bp);
16601660
// We check if this breakpoint already exists to update it.
1661-
if (inserted)
1662-
iv->second.SetBreakpoint(source);
1663-
else
1661+
if (inserted) {
1662+
if (auto error = iv->second.SetBreakpoint(source)) {
1663+
protocol::Breakpoint invalid_breakpoint;
1664+
invalid_breakpoint.message = llvm::toString(std::move(error));
1665+
invalid_breakpoint.verified = false;
1666+
response_breakpoints.push_back(std::move(invalid_breakpoint));
1667+
existing_breakpoints.erase(iv);
1668+
continue;
1669+
}
1670+
} else
16641671
iv->second.UpdateBreakpoint(src_bp);
16651672

16661673
protocol::Breakpoint response_breakpoint =
@@ -1673,7 +1680,7 @@ std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints(
16731680
if (!response_breakpoint.column &&
16741681
src_bp.GetColumn() != LLDB_INVALID_COLUMN_NUMBER)
16751682
response_breakpoint.column = src_bp.GetColumn();
1676-
response_breakpoints.push_back(response_breakpoint);
1683+
response_breakpoints.push_back(std::move(response_breakpoint));
16771684
}
16781685
}
16791686

lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ BreakpointLocationsRequestHandler::GetSourceBreakpointLocations(
104104

105105
std::vector<std::pair<uint32_t, uint32_t>>
106106
BreakpointLocationsRequestHandler::GetAssemblyBreakpointLocations(
107-
int64_t sourceReference, uint32_t start_line, uint32_t end_line) const {
107+
int64_t source_reference, uint32_t start_line, uint32_t end_line) const {
108108
std::vector<std::pair<uint32_t, uint32_t>> locations;
109-
lldb::SBAddress address(sourceReference, dap.target);
109+
lldb::SBAddress address(source_reference, dap.target);
110110
if (!address.IsValid())
111111
return locations;
112112

lldb/tools/lldb-dap/Handler/RequestHandler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class BreakpointLocationsRequestHandler
239239
uint32_t start_column, uint32_t end_line,
240240
uint32_t end_column) const;
241241
std::vector<std::pair<uint32_t, uint32_t>>
242-
GetAssemblyBreakpointLocations(int64_t sourceReference, uint32_t start_line,
242+
GetAssemblyBreakpointLocations(int64_t source_reference, uint32_t start_line,
243243
uint32_t end_line) const;
244244
};
245245

0 commit comments

Comments
 (0)