6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
9
- #include < chrono>
10
- #include < cstdarg>
11
- #include < fstream>
12
- #include < mutex>
13
-
14
9
#include " DAP.h"
15
10
#include " JSONUtils.h"
16
11
#include " LLDBUtils.h"
12
+ #include " OutputRedirector.h"
13
+ #include " lldb/API/SBBreakpoint.h"
17
14
#include " lldb/API/SBCommandInterpreter.h"
15
+ #include " lldb/API/SBCommandReturnObject.h"
18
16
#include " lldb/API/SBLanguageRuntime.h"
19
17
#include " lldb/API/SBListener.h"
18
+ #include " lldb/API/SBProcess.h"
20
19
#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"
21
25
#include " llvm/ADT/StringExtras.h"
26
+ #include " llvm/ADT/Twine.h"
27
+ #include " llvm/Support/Error.h"
28
+ #include " llvm/Support/ErrorHandling.h"
22
29
#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>
23
39
24
40
#if defined(_WIN32)
25
41
#define NOMINMAX
26
42
#include < fcntl.h>
27
43
#include < io.h>
28
44
#include < windows.h>
45
+ #else
46
+ #include < unistd.h>
29
47
#endif
30
48
31
49
using namespace lldb_dap ;
32
50
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
+
33
59
namespace lldb_dap {
34
60
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" ),
37
65
exception_breakpoints(), focus_tid(LLDB_INVALID_THREAD_ID),
38
66
stop_at_entry(false ), is_attach(false ),
39
67
enable_auto_variable_summaries(false ),
@@ -43,21 +71,7 @@ DAP::DAP(llvm::StringRef path, ReplMode repl_mode)
43
71
configuration_done_sent(false ), waiting_for_run_in_terminal(false ),
44
72
progress_event_reporter(
45
73
[&](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) {}
61
75
62
76
DAP::~DAP () = default ;
63
77
@@ -173,6 +187,45 @@ ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const lldb::break_id_t bp_id) {
173
187
return nullptr ;
174
188
}
175
189
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
+
176
229
// Send the JSON in "json_str" to the "out" stream. Correctly send the
177
230
// "Content-Length:" field followed by the length, followed by the raw
178
231
// JSON bytes.
@@ -208,19 +261,19 @@ std::string DAP::ReadJSON() {
208
261
std::string json_str;
209
262
int length;
210
263
211
- if (!input.read_expected (log . get () , " Content-Length: " ))
264
+ if (!input.read_expected (log , " Content-Length: " ))
212
265
return json_str;
213
266
214
- if (!input.read_line (log . get () , length_str))
267
+ if (!input.read_line (log , length_str))
215
268
return json_str;
216
269
217
270
if (!llvm::to_integer (length_str, length))
218
271
return json_str;
219
272
220
- if (!input.read_expected (log . get () , " \r\n " ))
273
+ if (!input.read_expected (log , " \r\n " ))
221
274
return json_str;
222
275
223
- if (!input.read_full (log . get () , length, json_str))
276
+ if (!input.read_full (log , length, json_str))
224
277
return json_str;
225
278
226
279
if (log ) {
0 commit comments