eclipse-cdt-cloud / cdt-gdb-adapter

CDT GDB Debug Adapter
Eclipse Public License 2.0
27 stars 40 forks source link

Can not remove breakpoint when debugging #330

Open jonahgraham opened 5 days ago

jonahgraham commented 5 days ago

Discussed in https://github.com/eclipse-cdt-cloud/cdt-cloud/discussions/42

Originally posted by **wss29** July 2, 2024 I set a breakpoint in a loop code when debugging I click to remove the breakpoint, but I find it will be triggered at the point in the next loop ```C #include "Rectangle.h" #include void Rectangle::set_values(int x, int y) { width = x; height = y; } void Rectangle::sleep(int millisecond) { Sleep(millisecond); } int Rectangle::area() { return width * height; } ``` ```C #include "Rectangle.h" #include using namespace std; int main() { Rectangle rect, rectb; rect.set_values(3, 4); rectb.set_values(5, 6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; int i = 20; while (i > 10) { rect.sleep(1000); cout << i << endl; } return 0; } ``` ![2024-07-02_14-36-48](https://github.com/eclipse-cdt-cloud/cdt-cloud/assets/4537809/352e7ca1-4657-42e4-87b2-e6928d183f25)
jonahgraham commented 5 days ago

It looks like the logic that compares breakpoints is incorrect in regards (probably) to D: vs d: in Windows path. Extracted from the log (and edited for brevity):

[07:21:05.912 UTC] From client: setBreakpoints({"source":{"name":"main.cpp","path":"d:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp"},"sourceModified":false,"breakpoints":[{"line":19},{"line":22}],"lines":[19,22]})
[07:21:05.912 UTC] GDB command: 4 -break-list
-- here GDB replies to say no breakpoints exist in target as expected
[07:21:05.922 UTC] GDB command: 5 -break-insert "\"d:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp:19\""
[07:21:05.939 UTC] GDB command: 6 -break-insert "\"d:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp:22\""
-- at this point the two breakpoints are properly inserted

--- later when breakpointis removed from UI (as you can see only line 22 should now have a breakpoint)
[07:21:15.058 UTC] From client: setBreakpoints({"source":{"name":"main.cpp","path":"D:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp","sourceReference":0},"sourceModified":true,"breakpoints":[{"line":22}],"lines":[22]})

--- the adapter asks GDB what breakpoints are installed, and the return value shows the one at line 19 and 22
[07:21:15.058 UTC] GDB command: 39 -break-list
[07:21:15.063 UTC] GDB result: 39 done,BreakpointTable={nr_rows="2",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x004015a8",func="main()",file="D:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp",fullname="D:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp",line="19",thread-groups=["i1"],times="4",original-location="d:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp:19"},bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="0x004015ce",func="main()",file="D:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp",fullname="D:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp",line="22",thread-groups=["i1"
[07:21:15.063 UTC] GDB -cont-: 39 ],times="0",original-location="d:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp:22"}]}

--- but the adapter goes on to install an additional breakpoint at line 22:

[07:21:15.063 UTC] GDB command: 40 -break-insert "\"D:\\WorkGroup\\workspace\\workspace\\cpp\\src\\main.cpp:22\""

I think this happens because the first request from Theia has setBreakpoints of d: and the later one is D:.

The adapter relies on comparing original-location to identify matching files. Since the files don't match, we assume the second request is about a different file.

For the adapter we could use a case-insensitive comparison, but it would be really useful if Theia sent canonical file names to the backend too.