diff --git a/lldb/test/API/tools/lldb-vscode/breakpoint-events/Makefile b/lldb/test/API/tools/lldb-vscode/breakpoint-events/Makefile --- a/lldb/test/API/tools/lldb-vscode/breakpoint-events/Makefile +++ b/lldb/test/API/tools/lldb-vscode/breakpoint-events/Makefile @@ -1,4 +1,15 @@ DYLIB_NAME := unlikely_name DYLIB_CXX_SOURCES := foo.cpp CXX_SOURCES := main.cpp +USE_LIBDL := 1 + +dylib.so: dylib.c + $(MAKE) -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_NAME=dylib DYLIB_C_SOURCES=dylib.c + +dylib_loader: dylib_loader.c + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-rpath "-Wl,$(shell pwd)" -o $@ $^ + +all: dylib.so dylib_loader + include Makefile.rules diff --git a/lldb/test/API/tools/lldb-vscode/breakpoint-events/TestVSCode_breakpointLocationResolvedEvent.py b/lldb/test/API/tools/lldb-vscode/breakpoint-events/TestVSCode_breakpointLocationResolvedEvent.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/tools/lldb-vscode/breakpoint-events/TestVSCode_breakpointLocationResolvedEvent.py @@ -0,0 +1,71 @@ +""" +Test lldb-vscode setBreakpoints request +""" + + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_breakpointLocationResolvedEvent(lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + def build_launch_and_attach(self): + self.build_and_create_debug_adaptor() + # launch externally + exe = self.getBuildArtifact("dylib_loader") + popen = self.spawnSubprocess(exe) + # attach + self.attach(exe, popen.pid) + + def set_breakpoint(self, filename, comment): + source_basename = filename + source_path = os.path.join(os.getcwd(), source_basename) + bp_line = line_number(filename, comment) + return self.vscode.request_setBreakpoints(source_path, + [bp_line]) + + @skipUnlessPlatform(["linux"]) + def test_breakpoint_location_resolved_event(self): + ''' + This test sets a breakpoint in a shared library before it's loaded. + This will make the client receive a breakpoint notification of + unresolved location. Once the library is loaded the client should + receive another change event indicating the location is resolved. + ''' + self.build_launch_and_attach() + self.set_breakpoint('dylib_loader.c', 'break after dlopen') + response = self.set_breakpoint('dylib.c', 'breakpoint dylib') + if response: + breakpoints = response['body']['breakpoints'] + for breakpoint in breakpoints: + bp_id = breakpoint['id'] + self.assertFalse(breakpoint['verified'], + "expect dylib breakpoint to be unverified") + break + response = self.vscode.request_evaluate("flip_to_1_to_continue = 1") + self.assertTrue(response['success']) + + self.continue_to_next_stop() + self.assertTrue(len(self.vscode.breakpoint_events) > 1, + "make sure we got a breakpoint event") + + # find the last breakpoint event for bp_id + for event in reversed(self.vscode.breakpoint_events): + if event['body']['breakpoint']['id'] == bp_id: + break + body = event['body'] + # Verify the details of the breakpoint changed notification. + self.assertTrue(body['reason'] == 'changed', + "breakpoint event reason should be changed") + breakpoint = body['breakpoint'] + self.assertTrue(breakpoint['verified'] == True, + "breakpoint event should be verified") + self.assertTrue(breakpoint['id'] == bp_id, + "breakpoint event is for breakpoint %i" % (bp_id)) diff --git a/lldb/test/API/tools/lldb-vscode/breakpoint-events/dylib.c b/lldb/test/API/tools/lldb-vscode/breakpoint-events/dylib.c new file mode 100644 --- /dev/null +++ b/lldb/test/API/tools/lldb-vscode/breakpoint-events/dylib.c @@ -0,0 +1,3 @@ +extern void foo() { + // breakpoint dylib +} diff --git a/lldb/test/API/tools/lldb-vscode/breakpoint-events/dylib_loader.c b/lldb/test/API/tools/lldb-vscode/breakpoint-events/dylib_loader.c new file mode 100644 --- /dev/null +++ b/lldb/test/API/tools/lldb-vscode/breakpoint-events/dylib_loader.c @@ -0,0 +1,14 @@ +#include +#include +#include + +volatile int flip_to_1_to_continue = 0; + +int main() { + lldb_enable_attach(); + while (! flip_to_1_to_continue) // Wait for debugger to attach + sleep(1); + void *dylib = dlopen("libdylib.so", RTLD_LAZY); + assert(dylib && "dlopen failed?"); + return 0; // break after dlopen +} diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp --- a/lldb/tools/lldb-vscode/lldb-vscode.cpp +++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -417,7 +417,8 @@ // of wether the locations were added or removed, the breakpoint // ins't going away, so we the reason is always "changed". if ((event_type & lldb::eBreakpointEventTypeLocationsAdded || - event_type & lldb::eBreakpointEventTypeLocationsRemoved) && + event_type & lldb::eBreakpointEventTypeLocationsRemoved || + event_type & lldb::eBreakpointEventTypeLocationsResolved) && bp.MatchesName(BreakpointBase::GetBreakpointLabel())) { auto bp_event = CreateEventObject("breakpoint"); llvm::json::Object body;