66//
77// ===----------------------------------------------------------------------===//
88
9- #include < chrono>
10- #include < cstdarg>
11- #include < fstream>
12- #include < mutex>
13-
149#include " DAP.h"
1510#include " JSONUtils.h"
1611#include " LLDBUtils.h"
12+ #include " OutputRedirector.h"
13+ #include " lldb/API/SBBreakpoint.h"
1714#include " lldb/API/SBCommandInterpreter.h"
15+ #include " lldb/API/SBCommandReturnObject.h"
1816#include " lldb/API/SBLanguageRuntime.h"
1917#include " lldb/API/SBListener.h"
18+ #include " lldb/API/SBProcess.h"
2019#include " lldb/API/SBStream.h"
20+ #include " lldb/Host/FileSystem.h"
21+ #include " lldb/Utility/Status.h"
22+ #include " lldb/lldb-defines.h"
23+ #include " lldb/lldb-enumerations.h"
24+ #include " llvm/ADT/ArrayRef.h"
2125#include " llvm/ADT/StringExtras.h"
26+ #include " llvm/ADT/Twine.h"
27+ #include " llvm/Support/Error.h"
28+ #include " llvm/Support/ErrorHandling.h"
2229#include " llvm/Support/FormatVariadic.h"
30+ #include " llvm/Support/raw_ostream.h"
31+ #include < algorithm>
32+ #include < cassert>
33+ #include < chrono>
34+ #include < cstdarg>
35+ #include < cstdio>
36+ #include < fstream>
37+ #include < mutex>
38+ #include < utility>
2339
2440#if defined(_WIN32)
2541#define NOMINMAX
2642#include < fcntl.h>
2743#include < io.h>
2844#include < windows.h>
45+ #else
46+ #include < unistd.h>
2947#endif
3048
3149using namespace lldb_dap ;
3250
51+ namespace {
52+ #ifdef _WIN32
53+ const char DEV_NULL[] = " nul" ;
54+ #else
55+ const char DEV_NULL[] = " /dev/null" ;
56+ #endif
57+ } // namespace
58+
3359namespace lldb_dap {
3460
35- DAP::DAP (llvm::StringRef path, ReplMode repl_mode)
36- : debug_adaptor_path(path), broadcaster(" lldb-dap" ),
61+ DAP::DAP (llvm::StringRef path, std::ofstream *log, ReplMode repl_mode,
62+ StreamDescriptor input, StreamDescriptor output)
63+ : debug_adaptor_path(path), log(log), input(std::move(input)),
64+ output (std::move(output)), broadcaster(" lldb-dap" ),
3765 exception_breakpoints(), focus_tid(LLDB_INVALID_THREAD_ID),
3866 stop_at_entry(false ), is_attach(false ),
3967 enable_auto_variable_summaries(false ),
@@ -43,21 +71,7 @@ DAP::DAP(llvm::StringRef path, ReplMode repl_mode)
4371 configuration_done_sent(false ), waiting_for_run_in_terminal(false ),
4472 progress_event_reporter(
4573 [&](const ProgressEvent &event) { SendJSON (event.ToJSON ()); }),
46- reverse_request_seq (0 ), repl_mode(repl_mode) {
47- const char *log_file_path = getenv (" LLDBDAP_LOG" );
48- #if defined(_WIN32)
49- // Windows opens stdout and stdin in text mode which converts \n to 13,10
50- // while the value is just 10 on Darwin/Linux. Setting the file mode to binary
51- // fixes this.
52- int result = _setmode (fileno (stdout), _O_BINARY);
53- assert (result);
54- result = _setmode (fileno (stdin), _O_BINARY);
55- UNUSED_IF_ASSERT_DISABLED (result);
56- assert (result);
57- #endif
58- if (log_file_path)
59- log.reset (new std::ofstream (log_file_path));
60- }
74+ reverse_request_seq (0 ), repl_mode(repl_mode) {}
6175
6276DAP::~DAP () = default ;
6377
@@ -173,6 +187,45 @@ ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const lldb::break_id_t bp_id) {
173187 return nullptr ;
174188}
175189
190+ llvm::Error DAP::ConfigureIO (std::FILE *overrideOut, std::FILE *overrideErr) {
191+ in = lldb::SBFile (std::fopen (DEV_NULL, " r" ), /* transfer_ownership=*/ true );
192+
193+ if (auto Error = out.RedirectTo ([this ](llvm::StringRef output) {
194+ SendOutput (OutputType::Stdout, output);
195+ }))
196+ return Error;
197+
198+ if (overrideOut) {
199+ auto fd = out.GetWriteFileDescriptor ();
200+ if (auto Error = fd.takeError ())
201+ return Error;
202+
203+ if (dup2 (*fd, fileno (overrideOut)) == -1 )
204+ return llvm::errorCodeToError (llvm::errnoAsErrorCode ());
205+ }
206+
207+ if (auto Error = err.RedirectTo ([this ](llvm::StringRef output) {
208+ SendOutput (OutputType::Stderr, output);
209+ }))
210+ return Error;
211+
212+ if (overrideErr) {
213+ auto fd = err.GetWriteFileDescriptor ();
214+ if (auto Error = fd.takeError ())
215+ return Error;
216+
217+ if (dup2 (*fd, fileno (overrideErr)) == -1 )
218+ return llvm::errorCodeToError (llvm::errnoAsErrorCode ());
219+ }
220+
221+ return llvm::Error::success ();
222+ }
223+
224+ void DAP::StopIO () {
225+ out.Stop ();
226+ err.Stop ();
227+ }
228+
176229// Send the JSON in "json_str" to the "out" stream. Correctly send the
177230// "Content-Length:" field followed by the length, followed by the raw
178231// JSON bytes.
@@ -208,19 +261,19 @@ std::string DAP::ReadJSON() {
208261 std::string json_str;
209262 int length;
210263
211- if (!input.read_expected (log. get () , " Content-Length: " ))
264+ if (!input.read_expected (log, " Content-Length: " ))
212265 return json_str;
213266
214- if (!input.read_line (log. get () , length_str))
267+ if (!input.read_line (log, length_str))
215268 return json_str;
216269
217270 if (!llvm::to_integer (length_str, length))
218271 return json_str;
219272
220- if (!input.read_expected (log. get () , " \r\n " ))
273+ if (!input.read_expected (log, " \r\n " ))
221274 return json_str;
222275
223- if (!input.read_full (log. get () , length, json_str))
276+ if (!input.read_full (log, length, json_str))
224277 return json_str;
225278
226279 if (log) {
0 commit comments