[Lldb-commits] [lldb] 4f48a81 - [lldb-dap] Support column breakpoints (#113787)
Author: Adrian Vogelsgesang Date: 2024-11-16T19:01:12+01:00 New Revision: 4f48a81a620bc9280be4780f3554cdc9bda55bd3 URL: https://github.com/llvm/llvm-project/commit/4f48a81a620bc9280be4780f3554cdc9bda55bd3 DIFF: https://github.com/llvm/llvm-project/commit/4f48a81a620bc9280be4780f3554cdc9bda55bd3.diff LOG: [lldb-dap] Support column breakpoints (#113787) This commit adds support for column breakpoints to lldb-dap. To do so, support for the `breakpointLocations` request was added. To find all available breakpoint positions, we iterate over the line table. The `setBreakpoints` request already forwarded the column correctly to `SBTarget::BreakpointCreateByLocation`. However, `SourceBreakpointMap` did not keep track of multiple breakpoints in the same line. To do so, the `SourceBreakpointMap` is now indexed by line+column instead of by line only. See http://jonasdevlieghere.com/post/lldb-column-breakpoints/ for a high-level introduction to column breakpoints. Added: lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py Modified: lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py lldb/test/API/tools/lldb-dap/breakpoint/Makefile lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py lldb/tools/lldb-dap/DAP.h lldb/tools/lldb-dap/lldb-dap.cpp Removed: diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index c29992ce9c7848..043d82e2e2c7d1 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -612,6 +612,28 @@ def request_attach( command_dict = {"command": "attach", "type": "request", "arguments": args_dict} return self.send_recv(command_dict) +def request_breakpointLocations( +self, file_path, line, end_line=None, column=None, end_column=None +): +(dir, base) = os.path.split(file_path) +source_dict = {"name": base, "path": file_path} +args_dict = {} +args_dict["source"] = source_dict +if line is not None: +args_dict["line"] = line +if end_line is not None: +args_dict["endLine"] = end_line +if column is not None: +args_dict["column"] = column +if end_column is not None: +args_dict["endColumn"] = end_column +command_dict = { +"command": "breakpointLocations", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_configurationDone(self): command_dict = { "command": "configurationDone", @@ -851,6 +873,8 @@ def request_next(self, threadId, granularity="statement"): def request_stepIn(self, threadId, targetId, granularity="statement"): if self.exit_status is not None: raise ValueError("request_stepIn called after process exited") +if threadId is None: +threadId = self.get_thread_id() args_dict = { "threadId": threadId, "targetId": targetId, @@ -911,18 +935,14 @@ def request_setBreakpoints(self, file_path, line_array, data=None): breakpoint_data = data[i] bp = {"line": line} if breakpoint_data is not None: -if "condition" in breakpoint_data and breakpoint_data["condition"]: +if breakpoint_data.get("condition"): bp["condition"] = breakpoint_data["condition"] -if ( -"hitCondition" in breakpoint_data -and breakpoint_data["hitCondition"] -): +if breakpoint_data.get("hitCondition"): bp["hitCondition"] = breakpoint_data["hitCondition"] -if ( -"logMessage" in breakpoint_data -and breakpoint_data["logMessage"] -): +if breakpoint_data.get("logMessage"): bp["logMessage"] = breakpoint_data["logMessage"] +if breakpoint_data.get("column"): +bp["column"] = breakpoint_data["column"] breakpoints.append(bp) args_dict["breakpoints"] = breakpoints diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py index a25466f07fa557..34e9b96dbcc3f5 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py @@
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5028,36 +5218,52 @@ int main(int argc, char *argv[]) { #endif // Initialize LLDB first before we do anything. - lldb::SBDebugger::Initialize(); + lldb::SBError error = lldb::SBDebugger::InitializeWithErrorHandling(); + if (error.Fail()) { +llvm::errs() << "Failed to initialize LLDB: " << error.GetCString() << "\n"; +return EXIT_FAILURE; + } // Terminate the debugger before the C++ destructor chain kicks in. auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - DAP dap = DAP(program_path.str(), default_repl_mode); + if (portno != -1) { +llvm::errs() << llvm::format("Listening on port %i...\n", portno); +return AcceptConnection(program_path.str(), pre_init_commands, log, +default_repl_mode, portno); + } + + if (!unix_socket_path.empty()) { vogelsgesang wrote: we might want to handle the case that the user specified both a `portno` and a `socket_path`? Does it make sense to listen on both? Does it maybe also make sense to listen on multiple ports and multiple socket paths? Or should we report an error if both a port and a socket are specified? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb-dap] Support column breakpoints (PR #113787)
https://github.com/vogelsgesang closed https://github.com/llvm/llvm-project/pull/113787 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb-dap] Support column breakpoints (PR #113787)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `lldb-aarch64-ubuntu` running on `linaro-lldb-aarch64-ubuntu` while building `lldb` at step 6 "test". Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/8268 Here is the relevant piece of the build log for the reference ``` Step 6 (test) failure: build (failure) ... PASS: lldb-api :: python_api/target/TestTargetAPI.py (1104 of 2050) PASS: lldb-api :: symbol_ondemand/breakpoint_source_regex/TestSourceTextRegexBreakpoint.py (1105 of 2050) PASS: lldb-api :: symbol_ondemand/breakpoint_language/TestBreakpointLanguageOnDemand.py (1106 of 2050) PASS: lldb-api :: test_utils/TestDecorators.py (1107 of 2050) PASS: lldb-api :: terminal/TestSTTYBeforeAndAfter.py (1108 of 2050) PASS: lldb-api :: test_utils/TestInlineTest.py (1109 of 2050) PASS: lldb-api :: test_utils/TestPExpectTest.py (1110 of 2050) PASS: lldb-api :: test_utils/base/TestBaseTest.py ( of 2050) PASS: lldb-api :: symbol_ondemand/shared_library/TestSharedLibOnDemand.py (1112 of 2050) UNSUPPORTED: lldb-api :: tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py (1113 of 2050) FAIL: lldb-api :: tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py (1114 of 2050) TEST 'lldb-api :: tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py' FAILED Script: -- /usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --make /usr/bin/make --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/tools/lldb-dap/breakpoint -p TestDAP_breakpointLocations.py -- Exit Code: 1 Command Output (stdout): -- lldb version 20.0.0git (https://github.com/llvm/llvm-project.git revision 4f48a81a620bc9280be4780f3554cdc9bda55bd3) clang revision 4f48a81a620bc9280be4780f3554cdc9bda55bd3 llvm revision 4f48a81a620bc9280be4780f3554cdc9bda55bd3 Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc'] = DEBUG ADAPTER PROTOCOL LOGS = 1731780632.250944853 --> Content-Length: 344 { "arguments": { "adapterID": "lldb-native", "clientID": "vscode", "columnsStartAt1": true, "linesStartAt1": true, "locale": "en-us", "pathFormat": "path", "sourceInitFile": false, "supportsRunInTerminalRequest": true, "supportsStartDebuggingRequest": true, "supportsVariablePaging": true, "supportsVariableType": true }, "command": "initialize", "seq": 1, "type": "request" } 1731780632.252939463 <-- Content-Length: 1631 ``` https://github.com/llvm/llvm-project/pull/113787 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb-dap] Support column breakpoints (PR #113787)
@@ -910,6 +911,183 @@ void request_attach(const llvm::json::Object &request) { } } +// "BreakpointLocationsRequest": { +// "allOf": [ { "$ref": "#/definitions/Request" }, { +// "type": "object", +// "description": "The `breakpointLocations` request returns all possible +// locations for source breakpoints in a given range.\nClients should only +// call this request if the corresponding capability +// `supportsBreakpointLocationsRequest` is true.", +// "properties": { +// "command": { +// "type": "string", +// "enum": [ "breakpointLocations" ] +// }, +// "arguments": { +// "$ref": "#/definitions/BreakpointLocationsArguments" +// } +// }, +// "required": [ "command" ] +// }] +// }, +// "BreakpointLocationsArguments": { +// "type": "object", +// "description": "Arguments for `breakpointLocations` request.", +// "properties": { +// "source": { +// "$ref": "#/definitions/Source", +// "description": "The source location of the breakpoints; either +// `source.path` or `source.sourceReference` must be specified." +// }, +// "line": { +// "type": "integer", +// "description": "Start line of range to search possible breakpoint +// locations in. If only the line is specified, the request returns all +// possible locations in that line." +// }, +// "column": { +// "type": "integer", +// "description": "Start position within `line` to search possible +// breakpoint locations in. It is measured in UTF-16 code units and the +// client capability `columnsStartAt1` determines whether it is 0- or +// 1-based. If no column is given, the first position in the start line is +// assumed." +// }, +// "endLine": { +// "type": "integer", +// "description": "End line of range to search possible breakpoint +// locations in. If no end line is given, then the end line is assumed to +// be the start line." +// }, +// "endColumn": { +// "type": "integer", +// "description": "End position within `endLine` to search possible +// breakpoint locations in. It is measured in UTF-16 code units and the +// client capability `columnsStartAt1` determines whether it is 0- or +// 1-based. If no end column is given, the last position in the end line +// is assumed." +// } +// }, +// "required": [ "source", "line" ] +// }, +// "BreakpointLocationsResponse": { +// "allOf": [ { "$ref": "#/definitions/Response" }, { +// "type": "object", +// "description": "Response to `breakpointLocations` request.\nContains +// possible locations for source breakpoints.", +// "properties": { +// "body": { +// "type": "object", +// "properties": { +// "breakpoints": { +// "type": "array", +// "items": { +// "$ref": "#/definitions/BreakpointLocation" +// }, +// "description": "Sorted set of possible breakpoint locations." +// } +// }, +// "required": [ "breakpoints" ] +// } +// }, +// "required": [ "body" ] +// }] +// }, +// "BreakpointLocation": { +// "type": "object", +// "description": "Properties of a breakpoint location returned from the +// `breakpointLocations` request.", +// "properties": { +// "line": { +// "type": "integer", +// "description": "Start line of breakpoint location." +// }, +// "column": { +// "type": "integer", +// "description": "The start position of a breakpoint location. Position +// is measured in UTF-16 code units and the client capability +// `columnsStartAt1` determines whether it is 0- or 1-based." +// }, +// "endLine": { +// "type": "integer", +// "description": "The end line of breakpoint location if the location +// covers a range." +// }, +// "endColumn": { +// "type": "integer", +// "description": "The end position of a breakpoint location (if the +// location covers a range). Position is measured in UTF-16 code units and +// the client capability `columnsStartAt1` determines whether it is 0- or +// 1-based." +// } +// }, +// "required": [ "line" ] +// }, +void request_breakpointLocations(const llvm::json::Object &request) { + llvm::json::Object response; + FillResponse(request, response); + auto *arguments = request.getObject("arguments"); + auto *source = arguments->getObject("source"); + std::string path = GetString(source, "path").str(); + uint64_t start_line = GetUnsigned(arguments, "line", 0); + uint64_t start_column = GetUnsigned(arguments, "column", 0); + uint64_t end_line = GetUnsigned(arguments, "endLine", start_line); + uint64_t end_column = + GetUnsigned(arguments, "endColumn", std::numeric_limits::max()); + + lldb::SBFileSpec file_spec
[Lldb-commits] [lldb] [llvm] [lldb-dap] Support column breakpoints (PR #113787)
https://github.com/vogelsgesang edited https://github.com/llvm/llvm-project/pull/113787 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb-dap] Support column breakpoints (PR #113787)
https://github.com/vogelsgesang updated https://github.com/llvm/llvm-project/pull/113787 >From af45bc2e24623d7225d24a4680a28630d67d636e Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Sat, 26 Oct 2024 14:34:31 + Subject: [PATCH 01/10] [lldb-dap] Support column breakpoints This commit adds support for column breakpoints to lldb-dap. To do so, support for `breakpointLocations` was added. To find all available breakpoint positions, we iterate over the line table. The `setBreakpoints` request already forwarded the column correctly to `SBTarget::BreakpointCreateByLocation`. However, `SourceBreakpointMap` did not keep track of multiple breakpoints in the same line. To do so, the `SourceBreakpointMap` is now indexed by line+column instead of by line only. See http://jonasdevlieghere.com/post/lldb-column-breakpoints/ for a high-level introduction to column breakpoints. --- .../test/tools/lldb-dap/dap_server.py | 30 ++- .../API/tools/lldb-dap/breakpoint/Makefile| 2 +- .../breakpoint/TestDAP_breakpointLocations.py | 74 +++ .../breakpoint/TestDAP_setBreakpoints.py | 172 +-- lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/lldb-dap.cpp | 197 +- .../llvm/DebugInfo/DWARF/DWARFDebugLine.h | 2 +- 7 files changed, 393 insertions(+), 86 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 63748a71f1122d..659408c709a249 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -612,6 +612,22 @@ def request_attach( command_dict = {"command": "attach", "type": "request", "arguments": args_dict} return self.send_recv(command_dict) +def request_breakpointLocations(self, file_path, line, end_line=None, column=None, end_column=None): +(dir, base) = os.path.split(file_path) +source_dict = {"name": base, "path": file_path} +args_dict = {} +args_dict["source"] = source_dict +if line is not None: + args_dict["line"] = line +if end_line is not None: +args_dict["endLine"] = end_line +if column is not None: +args_dict["column"] = column +if end_column is not None: +args_dict["endColumn"] = end_column +command_dict = {"command": "breakpointLocations", "type": "request", "arguments": args_dict} +return self.send_recv(command_dict) + def request_configurationDone(self): command_dict = { "command": "configurationDone", @@ -912,18 +928,14 @@ def request_setBreakpoints(self, file_path, line_array, data=None): breakpoint_data = data[i] bp = {"line": line} if breakpoint_data is not None: -if "condition" in breakpoint_data and breakpoint_data["condition"]: +if breakpoint_data.get("condition"): bp["condition"] = breakpoint_data["condition"] -if ( -"hitCondition" in breakpoint_data -and breakpoint_data["hitCondition"] -): +if breakpoint_data.get("hitCondition"): bp["hitCondition"] = breakpoint_data["hitCondition"] -if ( -"logMessage" in breakpoint_data -and breakpoint_data["logMessage"] -): +if breakpoint_data.get("logMessage"): bp["logMessage"] = breakpoint_data["logMessage"] +if breakpoint_data.get("column"): +bp["column"] = breakpoint_data["column"] breakpoints.append(bp) args_dict["breakpoints"] = breakpoints diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/Makefile b/lldb/test/API/tools/lldb-dap/breakpoint/Makefile index 7634f513e85233..06438b3e6e3139 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint/Makefile +++ b/lldb/test/API/tools/lldb-dap/breakpoint/Makefile @@ -16,4 +16,4 @@ main-copy.cpp: main.cpp # The following shared library will be used to test breakpoints under dynamic loading libother: other-copy.c "$(MAKE)" -f $(MAKEFILE_RULES) \ - DYLIB_ONLY=YES DYLIB_C_SOURCES=other-copy.c DYLIB_NAME=other + DYLIB_ONLY=YES DYLIB_C_SOURCES=other-copy.c DYLIB_NAME=other diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py new file mode 100644 index 00..d84ce843e3fba8 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP
[Lldb-commits] [lldb] [llvm] [lldb-dap] Support column breakpoints (PR #113787)
@@ -1062,6 +1063,16 @@ void request_breakpointLocations(const llvm::json::Object &request) { continue; if (line == end_line && column > end_column) continue; + + // Make sure we are in the right file. + // We might have a match on line & column range and still + // be in the wrong file, e.g. for included files. + if (std::string_view(line_entry.GetFileSpec().GetFilename()) != vogelsgesang wrote: Thanks for that background. Fixed. https://github.com/llvm/llvm-project/pull/113787 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5028,36 +5218,52 @@ int main(int argc, char *argv[]) { #endif // Initialize LLDB first before we do anything. - lldb::SBDebugger::Initialize(); + lldb::SBError error = lldb::SBDebugger::InitializeWithErrorHandling(); + if (error.Fail()) { +llvm::errs() << "Failed to initialize LLDB: " << error.GetCString() << "\n"; +return EXIT_FAILURE; + } // Terminate the debugger before the C++ destructor chain kicks in. auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - DAP dap = DAP(program_path.str(), default_repl_mode); + if (portno != -1) { +llvm::errs() << llvm::format("Listening on port %i...\n", portno); +return AcceptConnection(program_path.str(), pre_init_commands, log, +default_repl_mode, portno); + } + + if (!unix_socket_path.empty()) { +return AcceptConnection(program_path.str(), pre_init_commands, log, +default_repl_mode, unix_socket_path); + } + + DAP dap = DAP(program_path.str(), log, default_repl_mode, pre_init_commands); vogelsgesang wrote: maybe we should factor out the rest of `main` into a `HandelStdinStdoutConnection`? Could we reuse `HandleClient` also for `stdin`/`stdout` communications? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -137,42 +141,232 @@ lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) { } } -SOCKET AcceptConnection(DAP &dap, int portno) { - // Accept a socket connection from any host on "portno". - SOCKET newsockfd = -1; - struct sockaddr_in serv_addr, cli_addr; +/// Redirect stdout and stderr fo the IDE's console output. +/// +/// Errors in this operation will be printed to the log file and the IDE's +/// console output as well. +/// +/// \return +/// A fd pointing to the original stdout. +void SetupRedirection(DAP &dap, int stdoutfd = -1, int stderrfd = -1) { + auto output_callback_stderr = [&dap](llvm::StringRef data) { +dap.SendOutput(OutputType::Stderr, data); + }; + auto output_callback_stdout = [&dap](llvm::StringRef data) { +dap.SendOutput(OutputType::Stdout, data); + }; + + llvm::Expected new_stdout_fd = + RedirectFd(stdoutfd, output_callback_stdout); + if (auto err = new_stdout_fd.takeError()) { +std::string error_message = llvm::toString(std::move(err)); +if (dap.log) + *dap.log << error_message << std::endl; +output_callback_stderr(error_message); + } + dap.out = lldb::SBFile(new_stdout_fd.get(), "w", false); + + llvm::Expected new_stderr_fd = + RedirectFd(stderrfd, output_callback_stderr); + if (auto err = new_stderr_fd.takeError()) { +std::string error_message = llvm::toString(std::move(err)); +if (dap.log) + *dap.log << error_message << std::endl; +output_callback_stderr(error_message); + } + dap.err = lldb::SBFile(new_stderr_fd.get(), "w", false); +} + +void HandleClient(int clientfd, llvm::StringRef program_path, + const std::vector &pre_init_commands, + std::shared_ptr log, + ReplMode default_repl_mode) { + if (log) +*log << "client[" << clientfd << "] connected\n"; + DAP dap = DAP(program_path, log, default_repl_mode, pre_init_commands); + dap.debug_adaptor_path = program_path; + + SetupRedirection(dap); + RegisterRequestCallbacks(dap); + + dap.input.descriptor = StreamDescriptor::from_socket(clientfd, false); + dap.output.descriptor = StreamDescriptor::from_socket(clientfd, false); + + for (const std::string &arg : pre_init_commands) { +dap.pre_init_commands.push_back(arg); + } + + if (auto Err = dap.Loop()) { +if (log) + *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + } + + if (log) +*log << "client[" << clientfd << "] connection closed\n"; +#if defined(_WIN32) + closesocket(clientfd); +#else + close(clientfd); +#endif +} + +std::error_code getLastSocketErrorCode() { +#ifdef _WIN32 + return std::error_code(::WSAGetLastError(), std::system_category()); +#else + return llvm::errnoAsErrorCode(); +#endif +} + +llvm::Expected getSocketFD(llvm::StringRef path) { + if (llvm::sys::fs::exists(path) && (::remove(path.str().c_str()) == -1)) { +return llvm::make_error(getLastSocketErrorCode(), + "Remove existing socket failed"); + } + + SOCKET sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) { +return llvm::make_error(getLastSocketErrorCode(), + "Create socket failed"); + } + + struct sockaddr_un addr; + bzero(&addr, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path.str().c_str(), sizeof(addr.sun_path) - 1); + + if (::bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { +#if defined(_WIN32) +closesocket(sockfd); +#else +close(sockfd); +#endif +return llvm::make_error(getLastSocketErrorCode(), + "Socket bind() failed"); + } + + if (listen(sockfd, llvm::hardware_concurrency().compute_thread_count()) < 0) { +#if defined(_WIN32) +closesocket(sockfd); +#else +close(sockfd); +#endif +return llvm::make_error(getLastSocketErrorCode(), + "Socket listen() failed"); + } + + return sockfd; +} + +llvm::Expected getSocketFD(int portno) { SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { -if (dap.log) - *dap.log << "error: opening socket (" << strerror(errno) << ")" - << std::endl; - } else { -memset((char *)&serv_addr, 0, sizeof(serv_addr)); -serv_addr.sin_family = AF_INET; -// serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); -serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); -serv_addr.sin_port = htons(portno); -if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - if (dap.log) -*dap.log << "error: binding socket (" << strerror(errno) << ")" - << std::endl; -} else { - listen(sockfd, 5); - socklen_t clilen = sizeof(cli_addr); - newsockfd = - llvm::sys::RetryAfterSignal(static_cast(-1), accept, sockfd, - (struct sockaddr *)&cli_addr, &
[Lldb-commits] [lldb] [lldb/API] Hoist some of SBFrame logic to lldb_private::StackFrame (NFC) (PR #116298)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Med Ismail Bennani (medismailben) Changes This patch moves some of the logic implemented in the SBFrame APIs to the lldb_private::StackFrame class so it can be re-used elsewhere. --- Full diff: https://github.com/llvm/llvm-project/pull/116298.diff 3 Files Affected: - (modified) lldb/include/lldb/Target/StackFrame.h (+12) - (modified) lldb/source/API/SBFrame.cpp (+6-52) - (modified) lldb/source/Target/StackFrame.cpp (+51) ``diff diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index fce3a943413ca4..e85430791b7d93 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -408,6 +408,18 @@ class StackFrame : public ExecutionContextScope, /// system implementation details this way. bool IsHidden(); + /// Get the frame's demangled name. + /// + /// /// \return + /// A C-String containing the function demangled name. Can be null. + const char *GetFunctionName(); + + /// Get the frame's demangled display name. + /// + /// /// \return + /// A C-String containing the function demangled display name. Can be null. + const char *GetDisplayFunctionName(); + /// Query this frame to find what frame it is in this Thread's /// StackFrameList. /// diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index dc41e80b457d7d..e2c691fa9bfd45 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -1173,12 +1173,8 @@ bool SBFrame::IsInlined() const { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process->GetRunLock())) { frame = exe_ctx.GetFramePtr(); - if (frame) { - -Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; -if (block) - return block->GetContainingInlinedBlock() != nullptr; - } + if (frame) +return frame->IsInlined(); } } return false; @@ -1255,29 +1251,8 @@ const char *SBFrame::GetFunctionName() const { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process->GetRunLock())) { frame = exe_ctx.GetFramePtr(); - if (frame) { -SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | - eSymbolContextBlock | - eSymbolContextSymbol)); -if (sc.block) { - Block *inlined_block = sc.block->GetContainingInlinedBlock(); - if (inlined_block) { -const InlineFunctionInfo *inlined_info = -inlined_block->GetInlinedFunctionInfo(); -name = inlined_info->GetName().AsCString(); - } -} - -if (name == nullptr) { - if (sc.function) -name = sc.function->GetName().GetCString(); -} - -if (name == nullptr) { - if (sc.symbol) -name = sc.symbol->GetName().GetCString(); -} - } + if (frame) +return frame->GetFunctionName(); } } return name; @@ -1298,29 +1273,8 @@ const char *SBFrame::GetDisplayFunctionName() { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process->GetRunLock())) { frame = exe_ctx.GetFramePtr(); - if (frame) { -SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | - eSymbolContextBlock | - eSymbolContextSymbol)); -if (sc.block) { - Block *inlined_block = sc.block->GetContainingInlinedBlock(); - if (inlined_block) { -const InlineFunctionInfo *inlined_info = -inlined_block->GetInlinedFunctionInfo(); -name = inlined_info->GetDisplayName().AsCString(); - } -} - -if (name == nullptr) { - if (sc.function) -name = sc.function->GetDisplayName().GetCString(); -} - -if (name == nullptr) { - if (sc.symbol) -name = sc.symbol->GetDisplayName().GetCString(); -} - } + if (frame) +return frame->GetDisplayFunctionName(); } } return name; diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 20d8425c578a33..77179fec3ed438 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1230,6 +1230,57 @@ bool StackFrame::IsHidden() { return false; } +const char *StackFrame::GetFunctionName() { + const char *name = nullptr; + SymbolContext sc = GetSymbolContext( + eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol); + if (sc.block) { +Block *inlined_block = sc.block->GetContainingInlinedBlock(); +if (inlined_block) { + const InlineFunctionInfo *inlined_info = + inlined_block->GetInlinedFunctionInfo(); + name = inlined_info->GetName().AsCString(); +}
[Lldb-commits] [lldb] [lldb/Target] Add null-check before dereferencing inlined_info (NFC) (PR #116300)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Med Ismail Bennani (medismailben) Changes This patch is a follow-up to 9c7701fa78037af03be10ed168fd3c75a2ed1aef and adds extra-null checks before dereferencing the inlined_info pointer. --- Full diff: https://github.com/llvm/llvm-project/pull/116300.diff 1 Files Affected: - (modified) lldb/source/Target/StackFrame.cpp (+4-2) ``diff diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 77179fec3ed438..1bca9786fb7c70 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1239,7 +1239,8 @@ const char *StackFrame::GetFunctionName() { if (inlined_block) { const InlineFunctionInfo *inlined_info = inlined_block->GetInlinedFunctionInfo(); - name = inlined_info->GetName().AsCString(); + if (inlined_info) +name = inlined_info->GetName().AsCString(); } } @@ -1265,7 +1266,8 @@ const char *StackFrame::GetDisplayFunctionName() { if (inlined_block) { const InlineFunctionInfo *inlined_info = inlined_block->GetInlinedFunctionInfo(); - name = inlined_info->GetDisplayName().AsCString(); + if (inlined_info) +name = inlined_info->GetDisplayName().AsCString(); } } `` https://github.com/llvm/llvm-project/pull/116300 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -137,42 +141,232 @@ lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) { } } -SOCKET AcceptConnection(DAP &dap, int portno) { - // Accept a socket connection from any host on "portno". - SOCKET newsockfd = -1; - struct sockaddr_in serv_addr, cli_addr; +/// Redirect stdout and stderr fo the IDE's console output. +/// +/// Errors in this operation will be printed to the log file and the IDE's +/// console output as well. +/// +/// \return +/// A fd pointing to the original stdout. +void SetupRedirection(DAP &dap, int stdoutfd = -1, int stderrfd = -1) { + auto output_callback_stderr = [&dap](llvm::StringRef data) { +dap.SendOutput(OutputType::Stderr, data); + }; + auto output_callback_stdout = [&dap](llvm::StringRef data) { +dap.SendOutput(OutputType::Stdout, data); + }; + + llvm::Expected new_stdout_fd = + RedirectFd(stdoutfd, output_callback_stdout); + if (auto err = new_stdout_fd.takeError()) { +std::string error_message = llvm::toString(std::move(err)); +if (dap.log) + *dap.log << error_message << std::endl; +output_callback_stderr(error_message); + } + dap.out = lldb::SBFile(new_stdout_fd.get(), "w", false); + + llvm::Expected new_stderr_fd = + RedirectFd(stderrfd, output_callback_stderr); + if (auto err = new_stderr_fd.takeError()) { +std::string error_message = llvm::toString(std::move(err)); +if (dap.log) + *dap.log << error_message << std::endl; +output_callback_stderr(error_message); + } + dap.err = lldb::SBFile(new_stderr_fd.get(), "w", false); +} + +void HandleClient(int clientfd, llvm::StringRef program_path, + const std::vector &pre_init_commands, + std::shared_ptr log, + ReplMode default_repl_mode) { + if (log) +*log << "client[" << clientfd << "] connected\n"; + DAP dap = DAP(program_path, log, default_repl_mode, pre_init_commands); + dap.debug_adaptor_path = program_path; + + SetupRedirection(dap); + RegisterRequestCallbacks(dap); + + dap.input.descriptor = StreamDescriptor::from_socket(clientfd, false); + dap.output.descriptor = StreamDescriptor::from_socket(clientfd, false); + + for (const std::string &arg : pre_init_commands) { +dap.pre_init_commands.push_back(arg); + } + + if (auto Err = dap.Loop()) { +if (log) + *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + } + + if (log) +*log << "client[" << clientfd << "] connection closed\n"; +#if defined(_WIN32) + closesocket(clientfd); +#else + close(clientfd); +#endif +} + +std::error_code getLastSocketErrorCode() { +#ifdef _WIN32 + return std::error_code(::WSAGetLastError(), std::system_category()); +#else + return llvm::errnoAsErrorCode(); +#endif +} + +llvm::Expected getSocketFD(llvm::StringRef path) { + if (llvm::sys::fs::exists(path) && (::remove(path.str().c_str()) == -1)) { +return llvm::make_error(getLastSocketErrorCode(), + "Remove existing socket failed"); + } + + SOCKET sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) { +return llvm::make_error(getLastSocketErrorCode(), + "Create socket failed"); + } + + struct sockaddr_un addr; + bzero(&addr, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path.str().c_str(), sizeof(addr.sun_path) - 1); + + if (::bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { +#if defined(_WIN32) +closesocket(sockfd); +#else +close(sockfd); +#endif +return llvm::make_error(getLastSocketErrorCode(), + "Socket bind() failed"); + } + + if (listen(sockfd, llvm::hardware_concurrency().compute_thread_count()) < 0) { +#if defined(_WIN32) +closesocket(sockfd); +#else +close(sockfd); +#endif +return llvm::make_error(getLastSocketErrorCode(), + "Socket listen() failed"); + } + + return sockfd; +} + +llvm::Expected getSocketFD(int portno) { SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { -if (dap.log) - *dap.log << "error: opening socket (" << strerror(errno) << ")" - << std::endl; - } else { -memset((char *)&serv_addr, 0, sizeof(serv_addr)); -serv_addr.sin_family = AF_INET; -// serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); -serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); -serv_addr.sin_port = htons(portno); -if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - if (dap.log) -*dap.log << "error: binding socket (" << strerror(errno) << ")" - << std::endl; -} else { - listen(sockfd, 5); - socklen_t clilen = sizeof(cli_addr); - newsockfd = - llvm::sys::RetryAfterSignal(static_cast(-1), accept, sockfd, - (struct sockaddr *)&cli_addr, &
[Lldb-commits] [lldb] [lldb] Unify/improve MainLoop signal handling (PR #115197)
@@ -295,26 +243,17 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback, sigaddset(&new_action.sa_mask, signo); sigset_t old_set; - g_signal_flags[signo] = 0; + // Set signal info before installing the signal handler! + g_signal_info[signo].pipe_fd = m_trigger_pipe.GetWriteFileDescriptor(); mgorny wrote: Do we actually expect having different `pipe_fd` for different signals? https://github.com/llvm/llvm-project/pull/115197 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits