summaryrefslogtreecommitdiff
path: root/lldb/source/Interpreter/ScriptInterpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Interpreter/ScriptInterpreter.cpp')
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp128
1 files changed, 120 insertions, 8 deletions
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index 00c460612ac19..86620449f2f4d 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -1,4 +1,4 @@
-//===-- ScriptInterpreter.cpp -----------------------------------*- C++ -*-===//
+//===-- ScriptInterpreter.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,16 +7,21 @@
//===----------------------------------------------------------------------===//
#include "lldb/Interpreter/ScriptInterpreter.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string>
-
+#include "lldb/Core/Debugger.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/Pipe.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
+#if defined(_WIN32)
+#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
+#endif
+#include <memory>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
using namespace lldb;
using namespace lldb_private;
@@ -102,6 +107,113 @@ Status ScriptInterpreter::SetBreakpointCommandCallbackFunction(
std::unique_ptr<ScriptInterpreterLocker>
ScriptInterpreter::AcquireInterpreterLock() {
- return std::unique_ptr<ScriptInterpreterLocker>(
- new ScriptInterpreterLocker());
+ return std::make_unique<ScriptInterpreterLocker>();
+}
+
+static void ReadThreadBytesReceived(void *baton, const void *src,
+ size_t src_len) {
+ if (src && src_len) {
+ Stream *strm = (Stream *)baton;
+ strm->Write(src, src_len);
+ strm->Flush();
+ }
+}
+
+llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
+ScriptInterpreterIORedirect::Create(bool enable_io, Debugger &debugger,
+ CommandReturnObject *result) {
+ if (enable_io)
+ return std::unique_ptr<ScriptInterpreterIORedirect>(
+ new ScriptInterpreterIORedirect(debugger, result));
+
+ auto nullin = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),
+ File::eOpenOptionRead);
+ if (!nullin)
+ return nullin.takeError();
+
+ auto nullout = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),
+ File::eOpenOptionWrite);
+ if (!nullout)
+ return nullin.takeError();
+
+ return std::unique_ptr<ScriptInterpreterIORedirect>(
+ new ScriptInterpreterIORedirect(std::move(*nullin), std::move(*nullout)));
+}
+
+ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(
+ std::unique_ptr<File> input, std::unique_ptr<File> output)
+ : m_input_file_sp(std::move(input)),
+ m_output_file_sp(std::make_shared<StreamFile>(std::move(output))),
+ m_error_file_sp(m_output_file_sp),
+ m_communication("lldb.ScriptInterpreterIORedirect.comm"),
+ m_disconnect(false) {}
+
+ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(
+ Debugger &debugger, CommandReturnObject *result)
+ : m_communication("lldb.ScriptInterpreterIORedirect.comm"),
+ m_disconnect(false) {
+
+ if (result) {
+ m_input_file_sp = debugger.GetInputFileSP();
+
+ Pipe pipe;
+ Status pipe_result = pipe.CreateNew(false);
+#if defined(_WIN32)
+ lldb::file_t read_file = pipe.GetReadNativeHandle();
+ pipe.ReleaseReadFileDescriptor();
+ std::unique_ptr<ConnectionGenericFile> conn_up =
+ std::make_unique<ConnectionGenericFile>(read_file, true);
+#else
+ std::unique_ptr<ConnectionFileDescriptor> conn_up =
+ std::make_unique<ConnectionFileDescriptor>(
+ pipe.ReleaseReadFileDescriptor(), true);
+#endif
+
+ if (conn_up->IsConnected()) {
+ m_communication.SetConnection(std::move(conn_up));
+ m_communication.SetReadThreadBytesReceivedCallback(
+ ReadThreadBytesReceived, &result->GetOutputStream());
+ m_communication.StartReadThread();
+ m_disconnect = true;
+
+ FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
+ m_output_file_sp = std::make_shared<StreamFile>(outfile_handle, true);
+ m_error_file_sp = m_output_file_sp;
+ if (outfile_handle)
+ ::setbuf(outfile_handle, nullptr);
+
+ result->SetImmediateOutputFile(debugger.GetOutputStream().GetFileSP());
+ result->SetImmediateErrorFile(debugger.GetErrorStream().GetFileSP());
+ }
+ }
+
+ if (!m_input_file_sp || !m_output_file_sp || !m_error_file_sp)
+ debugger.AdoptTopIOHandlerFilesIfInvalid(m_input_file_sp, m_output_file_sp,
+ m_error_file_sp);
+}
+
+void ScriptInterpreterIORedirect::Flush() {
+ if (m_output_file_sp)
+ m_output_file_sp->Flush();
+ if (m_error_file_sp)
+ m_error_file_sp->Flush();
+}
+
+ScriptInterpreterIORedirect::~ScriptInterpreterIORedirect() {
+ if (!m_disconnect)
+ return;
+
+ assert(m_output_file_sp);
+ assert(m_error_file_sp);
+ assert(m_output_file_sp == m_error_file_sp);
+
+ // Close the write end of the pipe since we are done with our one line
+ // script. This should cause the read thread that output_comm is using to
+ // exit.
+ m_output_file_sp->GetFile().Close();
+ // The close above should cause this thread to exit when it gets to the end
+ // of file, so let it get all its data.
+ m_communication.JoinReadThread();
+ // Now we can close the read end of the pipe.
+ m_communication.Disconnect();
}