aboutsummaryrefslogtreecommitdiff
path: root/lldb/tools/lldb-dap/tool/lldb-dap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/tools/lldb-dap/tool/lldb-dap.cpp')
-rw-r--r--lldb/tools/lldb-dap/tool/lldb-dap.cpp87
1 files changed, 86 insertions, 1 deletions
diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
index 93446c0..e59cef9 100644
--- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
@@ -16,6 +16,7 @@
#include "lldb/API/SBStream.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/File.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/MainLoop.h"
#include "lldb/Host/MainLoopBase.h"
#include "lldb/Host/MemoryMonitor.h"
@@ -24,7 +25,9 @@
#include "lldb/Utility/UriParser.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Option/Arg.h"
@@ -42,8 +45,10 @@
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <condition_variable>
+#include <cstddef>
#include <cstdio>
#include <cstdlib>
+#include <exception>
#include <fcntl.h>
#include <map>
#include <memory>
@@ -143,6 +148,74 @@ static void PrintVersion() {
llvm::outs() << "liblldb: " << lldb::SBDebugger::GetVersionString() << '\n';
}
+#if not defined(_WIN32)
+struct FDGroup {
+ int GetFlags() const {
+ if (read && write)
+ return O_NOCTTY | O_CREAT | O_RDWR;
+ if (read)
+ return O_NOCTTY | O_RDONLY;
+ return O_NOCTTY | O_CREAT | O_WRONLY | O_TRUNC;
+ }
+
+ std::vector<int> fds;
+ bool read = false;
+ bool write = false;
+};
+
+static llvm::Error RedirectToFile(const FDGroup &fdg, llvm::StringRef file) {
+ if (!fdg.read && !fdg.write)
+ return llvm::Error::success();
+ int target_fd = lldb_private::FileSystem::Instance().Open(
+ file.str().c_str(), fdg.GetFlags(), 0666);
+ if (target_fd == -1)
+ return llvm::errorCodeToError(
+ std::error_code(errno, std::generic_category()));
+ for (int fd : fdg.fds) {
+ if (target_fd == fd)
+ continue;
+ if (::dup2(target_fd, fd) == -1)
+ return llvm::errorCodeToError(
+ std::error_code(errno, std::generic_category()));
+ }
+ ::close(target_fd);
+ return llvm::Error::success();
+}
+
+static llvm::Error
+SetupIORedirection(const llvm::SmallVectorImpl<llvm::StringRef> &files) {
+ llvm::SmallDenseMap<llvm::StringRef, FDGroup> groups;
+ for (size_t i = 0; i < files.size(); i++) {
+ if (files[i].empty())
+ continue;
+ auto group = groups.find(files[i]);
+ if (group == groups.end())
+ group = groups.insert({files[i], {{static_cast<int>(i)}}}).first;
+ else
+ group->second.fds.push_back(i);
+ switch (i) {
+ case 0:
+ group->second.read = true;
+ break;
+ case 1:
+ case 2:
+ group->second.write = true;
+ break;
+ default:
+ group->second.read = true;
+ group->second.write = true;
+ break;
+ }
+ }
+ for (const auto &[file, group] : groups) {
+ if (llvm::Error err = RedirectToFile(group, file))
+ return llvm::createStringError(
+ llvm::formatv("{0}: {1}", file, llvm::toString(std::move(err))));
+ }
+ return llvm::Error::success();
+}
+#endif
+
// If --launch-target is provided, this instance of lldb-dap becomes a
// runInTerminal launcher. It will ultimately launch the program specified in
// the --launch-target argument, which is the original program the user wanted
@@ -165,6 +238,7 @@ static void PrintVersion() {
static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg,
llvm::StringRef comm_file,
lldb::pid_t debugger_pid,
+ llvm::StringRef stdio,
char *argv[]) {
#if defined(_WIN32)
return llvm::createStringError(
@@ -179,6 +253,16 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg,
(void)prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0);
#endif
+ lldb_private::FileSystem::Initialize();
+ if (!stdio.empty()) {
+ llvm::SmallVector<llvm::StringRef, 3> files;
+ stdio.split(files, ':');
+ while (files.size() < 3)
+ files.push_back(files.back());
+ if (llvm::Error err = SetupIORedirection(files))
+ return err;
+ }
+
RunInTerminalLauncherCommChannel comm_channel(comm_file);
if (llvm::Error err = comm_channel.NotifyPid())
return err;
@@ -484,9 +568,10 @@ int main(int argc, char *argv[]) {
break;
}
}
+ llvm::StringRef stdio = input_args.getLastArgValue(OPT_stdio);
if (llvm::Error err =
LaunchRunInTerminalTarget(*target_arg, comm_file->getValue(), pid,
- argv + target_args_pos)) {
+ stdio, argv + target_args_pos)) {
llvm::errs() << llvm::toString(std::move(err)) << '\n';
return EXIT_FAILURE;
}