blob: 7d6fed56044c8f0acb7652dfb805b11d8c844c0f [file] [log] [blame] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Host/windows/ConnectionConPTYWindows.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
using namespace lldb_private;
/// Strips the ConPTY initialization sequences that Windows unconditionally
/// emits when a process is first attached to a pseudo console.
///
/// These are emitted by ConPTY's host process (conhost.exe) at process attach
/// time, not by the debuggee. They are always the first bytes on the output
/// pipe and are always present as a contiguous prefix.
///
/// \param dst Buffer containing the data read from the ConPTY output pipe.
/// Modified in place: if the initialization sequences are present
/// as a prefix, they are removed by shifting the remaining bytes
/// to the front of the buffer.
/// \param dst_len The size of \p dst.
/// \param len On input, the number of valid bytes in \p dst. On output,
/// reduced by the number of bytes stripped.
/// \return
/// \p true if the sequence was found and stripped.
static bool StripConPTYInitSequences(void *dst, size_t dst_len, size_t &len) {
static const char sequences[] = "\x1b[?9001l\x1b[?1004l";
static const size_t sequences_len = sizeof(sequences) - 1;
char *buf = static_cast<char *>(dst);
if (len >= sequences_len) {
assert(dst_len >= len - sequences_len);
if (memcmp(buf, sequences, sequences_len) == 0) {
memmove(buf, buf + sequences_len, len - sequences_len);
len -= sequences_len;
return true;
}
}
return false;
}
ConnectionConPTY::ConnectionConPTY(std::shared_ptr<PseudoConsole> pty)
: m_pty(pty), ConnectionGenericFile(pty->GetSTDOUTHandle(), false) {};
ConnectionConPTY::~ConnectionConPTY() {}
lldb::ConnectionStatus ConnectionConPTY::Connect(llvm::StringRef s,
Status *error_ptr) {
if (m_pty->IsConnected())
return eConnectionStatusSuccess;
return eConnectionStatusNoConnection;
}
lldb::ConnectionStatus ConnectionConPTY::Disconnect(Status *error_ptr) {
m_pty->Close();
return eConnectionStatusSuccess;
}
size_t ConnectionConPTY::Read(void *dst, size_t dst_len,
const Timeout<std::micro> &timeout,
lldb::ConnectionStatus &status,
Status *error_ptr) {
std::unique_lock<std::mutex> guard(m_pty->GetMutex());
if (m_pty->IsStopping()) {
m_pty->GetCV().wait(guard, [this] { return !m_pty->IsStopping(); });
}
size_t bytes_read =
ConnectionGenericFile::Read(dst, dst_len, timeout, status, error_ptr);
if (bytes_read > 0 && !m_pty_vt_sequence_was_stripped) {
if (StripConPTYInitSequences(dst, dst_len, bytes_read))
m_pty_vt_sequence_was_stripped = true;
}
return bytes_read;
}
size_t ConnectionConPTY::Write(const void *src, size_t src_len,
lldb::ConnectionStatus &status,
Status *error_ptr) {
llvm_unreachable("not implemented");
}