| 1 | //===-- InitializeRequestHandler.cpp --------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "CommandPlugins.h" |
| 10 | #include "DAP.h" |
| 11 | #include "EventHelper.h" |
| 12 | #include "JSONUtils.h" |
| 13 | #include "LLDBUtils.h" |
| 14 | #include "Protocol/ProtocolRequests.h" |
| 15 | #include "RequestHandler.h" |
| 16 | #include "lldb/API/SBTarget.h" |
| 17 | |
| 18 | using namespace lldb_dap; |
| 19 | using namespace lldb_dap::protocol; |
| 20 | |
| 21 | /// Initialize request; value of command field is 'initialize'. |
| 22 | llvm::Expected<InitializeResponse> InitializeRequestHandler::Run( |
| 23 | const InitializeRequestArguments &arguments) const { |
| 24 | dap.clientFeatures = arguments.supportedFeatures; |
| 25 | |
| 26 | // Do not source init files until in/out/err are configured. |
| 27 | dap.debugger = lldb::SBDebugger::Create(source_init_files: false); |
| 28 | dap.debugger.SetInputFile(dap.in); |
| 29 | dap.target = dap.debugger.GetDummyTarget(); |
| 30 | |
| 31 | llvm::Expected<int> out_fd = dap.out.GetWriteFileDescriptor(); |
| 32 | if (!out_fd) |
| 33 | return out_fd.takeError(); |
| 34 | dap.debugger.SetOutputFile(lldb::SBFile(*out_fd, "w" , false)); |
| 35 | |
| 36 | llvm::Expected<int> err_fd = dap.err.GetWriteFileDescriptor(); |
| 37 | if (!err_fd) |
| 38 | return err_fd.takeError(); |
| 39 | dap.debugger.SetErrorFile(lldb::SBFile(*err_fd, "w" , false)); |
| 40 | |
| 41 | auto interp = dap.debugger.GetCommandInterpreter(); |
| 42 | |
| 43 | // The sourceInitFile option is not part of the DAP specification. It is an |
| 44 | // extension used by the test suite to prevent sourcing `.lldbinit` and |
| 45 | // changing its behavior. |
| 46 | if (arguments.lldbExtSourceInitFile.value_or(u: true)) { |
| 47 | dap.debugger.SkipLLDBInitFiles(b: false); |
| 48 | dap.debugger.SkipAppInitFiles(b: false); |
| 49 | lldb::SBCommandReturnObject init; |
| 50 | interp.SourceInitFileInGlobalDirectory(result&: init); |
| 51 | interp.SourceInitFileInHomeDirectory(result&: init); |
| 52 | } |
| 53 | |
| 54 | if (llvm::Error err = dap.RunPreInitCommands()) |
| 55 | return err; |
| 56 | |
| 57 | dap.PopulateExceptionBreakpoints(); |
| 58 | auto cmd = dap.debugger.GetCommandInterpreter().AddMultiwordCommand( |
| 59 | name: "lldb-dap" , help: "Commands for managing lldb-dap." ); |
| 60 | if (arguments.supportedFeatures.contains( |
| 61 | V: eClientFeatureStartDebuggingRequest)) { |
| 62 | cmd.AddCommand( |
| 63 | name: "start-debugging" , impl: new StartDebuggingCommand(dap), |
| 64 | help: "Sends a startDebugging request from the debug adapter to the client " |
| 65 | "to start a child debug session of the same type as the caller." ); |
| 66 | } |
| 67 | cmd.AddCommand( |
| 68 | name: "repl-mode" , impl: new ReplModeCommand(dap), |
| 69 | help: "Get or set the repl behavior of lldb-dap evaluation requests." ); |
| 70 | cmd.AddCommand(name: "send-event" , impl: new SendEventCommand(dap), |
| 71 | help: "Sends an DAP event to the client." ); |
| 72 | |
| 73 | if (arguments.supportedFeatures.contains(V: eClientFeatureProgressReporting)) |
| 74 | dap.StartProgressEventThread(); |
| 75 | |
| 76 | // Start our event thread so we can receive events from the debugger, target, |
| 77 | // process and more. |
| 78 | dap.StartEventThread(); |
| 79 | |
| 80 | return dap.GetCapabilities(); |
| 81 | } |
| 82 | |