//===-- Debugger.cpp ------------------------------------------------------===//
//
// 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/Core/Debugger.h"

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/DebuggerEvents.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Progress.h"
#include "lldb/Core/StreamAsynchronousIO.h"
#include "lldb/Core/Telemetry.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/OptionValueLanguage.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueSInt64.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StructuredDataPlugin.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Event.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Listener.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Version/Version.h"
#include "lldb/lldb-enumerations.h"

#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h"
#include "lldb/Host/windows/windows.h"
#endif

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"

#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <list>
#include <memory>
#include <mutex>
#include <optional>
#include <set>
#include <string>
#include <system_error>

// Includes for pipe()
#if defined(_WIN32)
#include <fcntl.h>
#include <io.h>
#else
#include <unistd.h>
#endif

namespace lldb_private {
class Address;
}

using namespace lldb;
using namespace lldb_private;

static lldb::user_id_t g_unique_id = 1;
static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;

#pragma mark Static Functions

static std::recursive_mutex *g_debugger_list_mutex_ptr =
    nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
static Debugger::DebuggerList *g_debugger_list_ptr =
    nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
static llvm::DefaultThreadPool *g_thread_pool = nullptr;

static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
    {
        lldb::eStopDisassemblyTypeNever,
        "never",
        "Never show disassembly when displaying a stop context.",
    },
    {
        lldb::eStopDisassemblyTypeNoDebugInfo,
        "no-debuginfo",
        "Show disassembly when there is no debug information.",
    },
    {
        lldb::eStopDisassemblyTypeNoSource,
        "no-source",
        "Show disassembly when there is no source information, or the source "
        "file "
        "is missing when displaying a stop context.",
    },
    {
        lldb::eStopDisassemblyTypeAlways,
        "always",
        "Always show disassembly when displaying a stop context.",
    },
};

static constexpr OptionEnumValueElement g_language_enumerators[] = {
    {
        eScriptLanguageNone,
        "none",
        "Disable scripting languages.",
    },
    {
        eScriptLanguagePython,
        "python",
        "Select python as the default scripting language.",
    },
    {
        eScriptLanguageDefault,
        "default",
        "Select the lldb default as the default scripting language.",
    },
};

static constexpr OptionEnumValueElement g_dwim_print_verbosities[] = {
    {eDWIMPrintVerbosityNone, "none",
     "Use no verbosity when running dwim-print."},
    {eDWIMPrintVerbosityExpression, "expression",
     "Use partial verbosity when running dwim-print - display a message when "
     "`expression` evaluation is used."},
    {eDWIMPrintVerbosityFull, "full",
     "Use full verbosity when running dwim-print."},
};

static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
    {
        eStopShowColumnAnsiOrCaret,
        "ansi-or-caret",
        "Highlight the stop column with ANSI terminal codes when color/ANSI "
        "mode is enabled; otherwise, fall back to using a text-only caret (^) "
        "as if \"caret-only\" mode was selected.",
    },
    {
        eStopShowColumnAnsi,
        "ansi",
        "Highlight the stop column with ANSI terminal codes when running LLDB "
        "with color/ANSI enabled.",
    },
    {
        eStopShowColumnCaret,
        "caret",
        "Highlight the stop column with a caret character (^) underneath the "
        "stop column. This method introduces a new line in source listings "
        "that display thread stop locations.",
    },
    {
        eStopShowColumnNone,
        "none",
        "Do not highlight the stop column.",
    },
};

#define LLDB_PROPERTIES_debugger
#include "CoreProperties.inc"

enum {
#define LLDB_PROPERTIES_debugger
#include "CorePropertiesEnum.inc"
};

LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;

Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
                                  VarSetOperationType op,
                                  llvm::StringRef property_path,
                                  llvm::StringRef value) {
  bool is_load_script =
      (property_path == "target.load-script-from-symbol-file");
  // These properties might change how we visualize data.
  bool invalidate_data_vis = (property_path == "escape-non-printables");
  invalidate_data_vis |=
      (property_path == "target.max-zero-padding-in-float-format");
  if (invalidate_data_vis) {
    DataVisualization::ForceUpdate();
  }

  TargetSP target_sp;
  LoadScriptFromSymFile load_script_old_value = eLoadScriptFromSymFileFalse;
  if (is_load_script && exe_ctx && exe_ctx->GetTargetSP()) {
    target_sp = exe_ctx->GetTargetSP();
    load_script_old_value =
        target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
  }
  Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
  if (error.Success()) {
    // FIXME it would be nice to have "on-change" callbacks for properties
    if (property_path == g_debugger_properties[ePropertyPrompt].name) {
      llvm::StringRef new_prompt = GetPrompt();
      std::string str = lldb_private::ansi::FormatAnsiTerminalCodes(
          new_prompt, GetUseColor());
      if (str.length())
        new_prompt = str;
      GetCommandInterpreter().UpdatePrompt(new_prompt);
      auto bytes = std::make_unique<EventDataBytes>(new_prompt);
      auto prompt_change_event_sp = std::make_shared<Event>(
          CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
      GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
    } else if (property_path == g_debugger_properties[ePropertyUseColor].name) {
      // use-color changed. set use-color, this also pings the prompt so it can
      // reset the ansi terminal codes.
      SetUseColor(GetUseColor());
    } else if (property_path ==
                   g_debugger_properties[ePropertyPromptAnsiPrefix].name ||
               property_path ==
                   g_debugger_properties[ePropertyPromptAnsiSuffix].name) {
      // Prompt color changed. set use-color, this also pings the prompt so it
      // can reset the ansi terminal codes.
      SetUseColor(GetUseColor());
    } else if (property_path ==
               g_debugger_properties[ePropertyShowStatusline].name) {
      // Statusline setting changed. If we have a statusline instance, update it
      // now. Otherwise it will get created in the default event handler.
      std::lock_guard<std::mutex> guard(m_statusline_mutex);
      if (StatuslineSupported())
        m_statusline.emplace(*this);
      else
        m_statusline.reset();
    } else if (property_path ==
                   g_debugger_properties[ePropertyStatuslineFormat].name ||
               property_path ==
                   g_debugger_properties[ePropertySeparator].name) {
      // Statusline format changed. Redraw the statusline.
      RedrawStatusline();
    } else if (property_path ==
               g_debugger_properties[ePropertyUseSourceCache].name) {
      // use-source-cache changed. Wipe out the cache contents if it was
      // disabled.
      if (!GetUseSourceCache()) {
        m_source_file_cache.Clear();
      }
    } else if (is_load_script && target_sp &&
               load_script_old_value == eLoadScriptFromSymFileWarn) {
      if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
          eLoadScriptFromSymFileTrue) {
        std::list<Status> errors;
        StreamString feedback_stream;
        if (!target_sp->LoadScriptingResources(errors, feedback_stream)) {
          lldb::StreamUP s = GetAsyncErrorStream();
          for (auto &error : errors)
            s->Printf("%s\n", error.AsCString());
          if (feedback_stream.GetSize())
            s->PutCString(feedback_stream.GetString());
        }
      }
    }
  }
  return error;
}

bool Debugger::GetAutoConfirm() const {
  constexpr uint32_t idx = ePropertyAutoConfirm;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
  constexpr uint32_t idx = ePropertyDisassemblyFormat;
  return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx);
}

const FormatEntity::Entry *Debugger::GetFrameFormat() const {
  constexpr uint32_t idx = ePropertyFrameFormat;
  return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx);
}

const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
  constexpr uint32_t idx = ePropertyFrameFormatUnique;
  return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx);
}

uint64_t Debugger::GetStopDisassemblyMaxSize() const {
  constexpr uint32_t idx = ePropertyStopDisassemblyMaxSize;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_debugger_properties[idx].default_uint_value);
}

bool Debugger::GetNotifyVoid() const {
  constexpr uint32_t idx = ePropertyNotiftVoid;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

llvm::StringRef Debugger::GetPrompt() const {
  constexpr uint32_t idx = ePropertyPrompt;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetPromptAnsiPrefix() const {
  const uint32_t idx = ePropertyPromptAnsiPrefix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetPromptAnsiSuffix() const {
  const uint32_t idx = ePropertyPromptAnsiSuffix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

void Debugger::SetPrompt(llvm::StringRef p) {
  constexpr uint32_t idx = ePropertyPrompt;
  SetPropertyAtIndex(idx, p);
  llvm::StringRef new_prompt = GetPrompt();
  std::string str =
      lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
  if (str.length())
    new_prompt = str;
  GetCommandInterpreter().UpdatePrompt(new_prompt);
}

const FormatEntity::Entry *Debugger::GetThreadFormat() const {
  constexpr uint32_t idx = ePropertyThreadFormat;
  return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx);
}

const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
  constexpr uint32_t idx = ePropertyThreadStopFormat;
  return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx);
}

lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
  const uint32_t idx = ePropertyScriptLanguage;
  return GetPropertyAtIndexAs<lldb::ScriptLanguage>(
      idx, static_cast<lldb::ScriptLanguage>(
               g_debugger_properties[idx].default_uint_value));
}

bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
  const uint32_t idx = ePropertyScriptLanguage;
  return SetPropertyAtIndex(idx, script_lang);
}

lldb::LanguageType Debugger::GetREPLLanguage() const {
  const uint32_t idx = ePropertyREPLLanguage;
  return GetPropertyAtIndexAs<LanguageType>(idx, {});
}

bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) {
  const uint32_t idx = ePropertyREPLLanguage;
  return SetPropertyAtIndex(idx, repl_lang);
}

uint64_t Debugger::GetTerminalWidth() const {
  const uint32_t idx = ePropertyTerminalWidth;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_debugger_properties[idx].default_uint_value);
}

bool Debugger::SetTerminalWidth(uint64_t term_width) {
  const uint32_t idx = ePropertyTerminalWidth;
  const bool success = SetPropertyAtIndex(idx, term_width);

  if (auto handler_sp = m_io_handler_stack.Top())
    handler_sp->TerminalSizeChanged();

  {
    std::lock_guard<std::mutex> guard(m_statusline_mutex);
    if (m_statusline)
      m_statusline->TerminalSizeChanged();
  }

  return success;
}

uint64_t Debugger::GetTerminalHeight() const {
  const uint32_t idx = ePropertyTerminalHeight;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_debugger_properties[idx].default_uint_value);
}

bool Debugger::SetTerminalHeight(uint64_t term_height) {
  const uint32_t idx = ePropertyTerminalHeight;
  const bool success = SetPropertyAtIndex(idx, term_height);

  if (auto handler_sp = m_io_handler_stack.Top())
    handler_sp->TerminalSizeChanged();

  {
    std::lock_guard<std::mutex> guard(m_statusline_mutex);
    if (m_statusline)
      m_statusline->TerminalSizeChanged();
  }

  return success;
}

bool Debugger::GetUseExternalEditor() const {
  const uint32_t idx = ePropertyUseExternalEditor;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::SetUseExternalEditor(bool b) {
  const uint32_t idx = ePropertyUseExternalEditor;
  return SetPropertyAtIndex(idx, b);
}

llvm::StringRef Debugger::GetExternalEditor() const {
  const uint32_t idx = ePropertyExternalEditor;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

bool Debugger::SetExternalEditor(llvm::StringRef editor) {
  const uint32_t idx = ePropertyExternalEditor;
  return SetPropertyAtIndex(idx, editor);
}

bool Debugger::GetUseColor() const {
  const uint32_t idx = ePropertyUseColor;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::SetUseColor(bool b) {
  const uint32_t idx = ePropertyUseColor;
  bool ret = SetPropertyAtIndex(idx, b);

  GetCommandInterpreter().UpdateUseColor(b);
  SetPrompt(GetPrompt());
  return ret;
}

bool Debugger::GetShowProgress() const {
  const uint32_t idx = ePropertyShowProgress;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::SetShowProgress(bool show_progress) {
  const uint32_t idx = ePropertyShowProgress;
  return SetPropertyAtIndex(idx, show_progress);
}

llvm::StringRef Debugger::GetShowProgressAnsiPrefix() const {
  const uint32_t idx = ePropertyShowProgressAnsiPrefix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetShowProgressAnsiSuffix() const {
  const uint32_t idx = ePropertyShowProgressAnsiSuffix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

bool Debugger::GetShowStatusline() const {
  const uint32_t idx = ePropertyShowStatusline;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

const FormatEntity::Entry *Debugger::GetStatuslineFormat() const {
  constexpr uint32_t idx = ePropertyStatuslineFormat;
  return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx);
}

bool Debugger::SetStatuslineFormat(const FormatEntity::Entry &format) {
  constexpr uint32_t idx = ePropertyStatuslineFormat;
  bool ret = SetPropertyAtIndex(idx, format);
  RedrawStatusline();
  return ret;
}

llvm::StringRef Debugger::GetSeparator() const {
  constexpr uint32_t idx = ePropertySeparator;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

bool Debugger::SetSeparator(llvm::StringRef s) {
  constexpr uint32_t idx = ePropertySeparator;
  bool ret = SetPropertyAtIndex(idx, s);
  RedrawStatusline();
  return ret;
}

bool Debugger::GetUseAutosuggestion() const {
  const uint32_t idx = ePropertyShowAutosuggestion;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const {
  const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const {
  const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetRegexMatchAnsiPrefix() const {
  const uint32_t idx = ePropertyShowRegexMatchAnsiPrefix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetRegexMatchAnsiSuffix() const {
  const uint32_t idx = ePropertyShowRegexMatchAnsiSuffix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

bool Debugger::GetShowDontUsePoHint() const {
  const uint32_t idx = ePropertyShowDontUsePoHint;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::GetUseSourceCache() const {
  const uint32_t idx = ePropertyUseSourceCache;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::SetUseSourceCache(bool b) {
  const uint32_t idx = ePropertyUseSourceCache;
  bool ret = SetPropertyAtIndex(idx, b);
  if (!ret) {
    m_source_file_cache.Clear();
  }
  return ret;
}
bool Debugger::GetHighlightSource() const {
  const uint32_t idx = ePropertyHighlightSource;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

StopShowColumn Debugger::GetStopShowColumn() const {
  const uint32_t idx = ePropertyStopShowColumn;
  return GetPropertyAtIndexAs<lldb::StopShowColumn>(
      idx, static_cast<lldb::StopShowColumn>(
               g_debugger_properties[idx].default_uint_value));
}

llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
  const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
  const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const {
  const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const {
  const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_debugger_properties[idx].default_cstr_value);
}

uint64_t Debugger::GetStopSourceLineCount(bool before) const {
  const uint32_t idx =
      before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_debugger_properties[idx].default_uint_value);
}

lldb::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
  const uint32_t idx = ePropertyStopDisassemblyDisplay;
  return GetPropertyAtIndexAs<lldb::StopDisassemblyType>(
      idx, static_cast<lldb::StopDisassemblyType>(
               g_debugger_properties[idx].default_uint_value));
}

uint64_t Debugger::GetDisassemblyLineCount() const {
  const uint32_t idx = ePropertyStopDisassemblyCount;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_debugger_properties[idx].default_uint_value);
}

bool Debugger::GetAutoOneLineSummaries() const {
  const uint32_t idx = ePropertyAutoOneLineSummaries;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::GetEscapeNonPrintables() const {
  const uint32_t idx = ePropertyEscapeNonPrintables;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::GetAutoIndent() const {
  const uint32_t idx = ePropertyAutoIndent;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::SetAutoIndent(bool b) {
  const uint32_t idx = ePropertyAutoIndent;
  return SetPropertyAtIndex(idx, b);
}

bool Debugger::GetPrintDecls() const {
  const uint32_t idx = ePropertyPrintDecls;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

bool Debugger::SetPrintDecls(bool b) {
  const uint32_t idx = ePropertyPrintDecls;
  return SetPropertyAtIndex(idx, b);
}

uint64_t Debugger::GetTabSize() const {
  const uint32_t idx = ePropertyTabSize;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_debugger_properties[idx].default_uint_value);
}

bool Debugger::SetTabSize(uint64_t tab_size) {
  const uint32_t idx = ePropertyTabSize;
  return SetPropertyAtIndex(idx, tab_size);
}

lldb::DWIMPrintVerbosity Debugger::GetDWIMPrintVerbosity() const {
  const uint32_t idx = ePropertyDWIMPrintVerbosity;
  return GetPropertyAtIndexAs<lldb::DWIMPrintVerbosity>(
      idx, static_cast<lldb::DWIMPrintVerbosity>(
               g_debugger_properties[idx].default_uint_value != 0));
}

bool Debugger::GetShowInlineDiagnostics() const {
  const uint32_t idx = ePropertyShowInlineDiagnostics;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value);
}

bool Debugger::SetShowInlineDiagnostics(bool b) {
  const uint32_t idx = ePropertyShowInlineDiagnostics;
  return SetPropertyAtIndex(idx, b);
}

#pragma mark Debugger

// const DebuggerPropertiesSP &
// Debugger::GetSettings() const
//{
//    return m_properties_sp;
//}
//

void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
  assert(g_debugger_list_ptr == nullptr &&
         "Debugger::Initialize called more than once!");
  g_debugger_list_mutex_ptr = new std::recursive_mutex();
  g_debugger_list_ptr = new DebuggerList();
  g_thread_pool = new llvm::DefaultThreadPool(llvm::optimal_concurrency());
  g_load_plugin_callback = load_plugin_callback;
}

void Debugger::Terminate() {
  assert(g_debugger_list_ptr &&
         "Debugger::Terminate called without a matching Debugger::Initialize!");

  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    for (const auto &debugger : *g_debugger_list_ptr)
      debugger->HandleDestroyCallback();
  }

  if (g_thread_pool) {
    // The destructor will wait for all the threads to complete.
    delete g_thread_pool;
  }

  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    // Clear our global list of debugger objects
    {
      std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
      for (const auto &debugger : *g_debugger_list_ptr)
        debugger->Clear();
      g_debugger_list_ptr->clear();
    }
  }
}

void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }

void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }

bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
  if (g_load_plugin_callback) {
    llvm::sys::DynamicLibrary dynlib =
        g_load_plugin_callback(shared_from_this(), spec, error);
    if (dynlib.isValid()) {
      m_loaded_plugins.push_back(dynlib);
      return true;
    }
  } else {
    // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
    // if the public API layer isn't available (code is linking against all of
    // the internal LLDB static libraries), then we can't load plugins
    error = Status::FromErrorString("Public API layer is not available");
  }
  return false;
}

static FileSystem::EnumerateDirectoryResult
LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
                   llvm::StringRef path) {
  Status error;

  static constexpr llvm::StringLiteral g_dylibext(".dylib");
  static constexpr llvm::StringLiteral g_solibext(".so");

  if (!baton)
    return FileSystem::eEnumerateDirectoryResultQuit;

  Debugger *debugger = (Debugger *)baton;

  namespace fs = llvm::sys::fs;
  // If we have a regular file, a symbolic link or unknown file type, try and
  // process the file. We must handle unknown as sometimes the directory
  // enumeration might be enumerating a file system that doesn't have correct
  // file type information.
  if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
      ft == fs::file_type::type_unknown) {
    FileSpec plugin_file_spec(path);
    FileSystem::Instance().Resolve(plugin_file_spec);

    if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
        plugin_file_spec.GetFileNameExtension() != g_solibext) {
      return FileSystem::eEnumerateDirectoryResultNext;
    }

    Status plugin_load_error;
    debugger->LoadPlugin(plugin_file_spec, plugin_load_error);

    return FileSystem::eEnumerateDirectoryResultNext;
  } else if (ft == fs::file_type::directory_file ||
             ft == fs::file_type::symlink_file ||
             ft == fs::file_type::type_unknown) {
    // Try and recurse into anything that a directory or symbolic link. We must
    // also do this for unknown as sometimes the directory enumeration might be
    // enumerating a file system that doesn't have correct file type
    // information.
    return FileSystem::eEnumerateDirectoryResultEnter;
  }

  return FileSystem::eEnumerateDirectoryResultNext;
}

void Debugger::InstanceInitialize() {
  const bool find_directories = true;
  const bool find_files = true;
  const bool find_other = true;
  char dir_path[PATH_MAX];
  if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
    if (FileSystem::Instance().Exists(dir_spec) &&
        dir_spec.GetPath(dir_path, sizeof(dir_path))) {
      FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
                                                find_files, find_other,
                                                LoadPluginCallback, this);
    }
  }

  if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
    if (FileSystem::Instance().Exists(dir_spec) &&
        dir_spec.GetPath(dir_path, sizeof(dir_path))) {
      FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
                                                find_files, find_other,
                                                LoadPluginCallback, this);
    }
  }

  PluginManager::DebuggerInitialize(*this);
}

DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
                                    void *baton) {
  lldb_private::telemetry::ScopedDispatcher<
      lldb_private::telemetry::DebuggerInfo>
      helper([](lldb_private::telemetry::DebuggerInfo *entry) {
        entry->lldb_version = lldb_private::GetVersion();
      });
  DebuggerSP debugger_sp(new Debugger(log_callback, baton));
  helper.SetDebugger(debugger_sp.get());

  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    g_debugger_list_ptr->push_back(debugger_sp);
  }
  debugger_sp->InstanceInitialize();
  return debugger_sp;
}

void Debugger::DispatchClientTelemetry(
    const lldb_private::StructuredDataImpl &entry) {
  lldb_private::telemetry::TelemetryManager::GetInstance()
      ->DispatchClientTelemetry(entry, this);
}

void Debugger::HandleDestroyCallback() {
  const lldb::user_id_t user_id = GetID();
  // Invoke and remove all the callbacks in an FIFO order. Callbacks which are
  // added during this loop will be appended, invoked and then removed last.
  // Callbacks which are removed during this loop will not be invoked.
  while (true) {
    DestroyCallbackInfo callback_info;
    {
      std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);
      if (m_destroy_callbacks.empty())
        break;
      // Pop the first item in the list
      callback_info = m_destroy_callbacks.front();
      m_destroy_callbacks.erase(m_destroy_callbacks.begin());
    }
    // Call the destroy callback with user id and baton
    callback_info.callback(user_id, callback_info.baton);
  }
}

void Debugger::Destroy(DebuggerSP &debugger_sp) {
  if (!debugger_sp)
    return;

  debugger_sp->HandleDestroyCallback();
  CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();

  if (cmd_interpreter.GetSaveSessionOnQuit()) {
    CommandReturnObject result(debugger_sp->GetUseColor());
    cmd_interpreter.SaveTranscript(result);
    if (result.Succeeded())
      (*debugger_sp->GetAsyncOutputStream())
          << result.GetOutputString() << '\n';
    else
      (*debugger_sp->GetAsyncErrorStream()) << result.GetErrorString() << '\n';
  }

  debugger_sp->Clear();

  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
      if ((*pos).get() == debugger_sp.get()) {
        g_debugger_list_ptr->erase(pos);
        return;
      }
    }
  }
}

DebuggerSP
Debugger::FindDebuggerWithInstanceName(llvm::StringRef instance_name) {
  if (!g_debugger_list_ptr || !g_debugger_list_mutex_ptr)
    return DebuggerSP();

  std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
  for (const DebuggerSP &debugger_sp : *g_debugger_list_ptr) {
    if (!debugger_sp)
      continue;

    if (llvm::StringRef(debugger_sp->GetInstanceName()) == instance_name)
      return debugger_sp;
  }
  return DebuggerSP();
}

TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
  TargetSP target_sp;
  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
      target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
      if (target_sp)
        break;
    }
  }
  return target_sp;
}

TargetSP Debugger::FindTargetWithProcess(Process *process) {
  TargetSP target_sp;
  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
      target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
      if (target_sp)
        break;
    }
  }
  return target_sp;
}

llvm::StringRef Debugger::GetStaticBroadcasterClass() {
  static constexpr llvm::StringLiteral class_name("lldb.debugger");
  return class_name;
}

Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
    : UserID(g_unique_id++),
      Properties(std::make_shared<OptionValueProperties>()),
      m_input_file_sp(std::make_shared<NativeFile>(stdin, NativeFile::Unowned)),
      m_output_stream_sp(std::make_shared<LockableStreamFile>(
          stdout, NativeFile::Unowned, m_output_mutex)),
      m_error_stream_sp(std::make_shared<LockableStreamFile>(
          stderr, NativeFile::Unowned, m_output_mutex)),
      m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
      m_terminal_state(), m_target_list(*this), m_platform_list(),
      m_listener_sp(Listener::MakeListener("lldb.Debugger")),
      m_source_manager_up(), m_source_file_cache(),
      m_command_interpreter_up(
          std::make_unique<CommandInterpreter>(*this, false)),
      m_io_handler_stack(),
      m_instance_name(llvm::formatv("debugger_{0}", GetID()).str()),
      m_loaded_plugins(), m_event_handler_thread(), m_io_handler_thread(),
      m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
      m_broadcaster(m_broadcaster_manager_sp,
                    GetStaticBroadcasterClass().str()),
      m_forward_listener_sp(), m_clear_once() {
  // Initialize the debugger properties as early as possible as other parts of
  // LLDB will start querying them during construction.
  m_collection_sp->Initialize(g_debugger_properties);
  m_collection_sp->AppendProperty(
      "target", "Settings specify to debugging targets.", true,
      Target::GetGlobalProperties().GetValueProperties());
  m_collection_sp->AppendProperty(
      "platform", "Platform settings.", true,
      Platform::GetGlobalPlatformProperties().GetValueProperties());
  m_collection_sp->AppendProperty(
      "symbols", "Symbol lookup and cache settings.", true,
      ModuleList::GetGlobalModuleListProperties().GetValueProperties());
  m_collection_sp->AppendProperty(
      LanguageProperties::GetSettingName(), "Language settings.", true,
      Language::GetGlobalLanguageProperties().GetValueProperties());
  if (m_command_interpreter_up) {
    m_collection_sp->AppendProperty(
        "interpreter",
        "Settings specify to the debugger's command interpreter.", true,
        m_command_interpreter_up->GetValueProperties());
  }
  if (log_callback)
    m_callback_handler_sp =
        std::make_shared<CallbackLogHandler>(log_callback, baton);
  m_command_interpreter_up->Initialize();
  // Always add our default platform to the platform list
  PlatformSP default_platform_sp(Platform::GetHostPlatform());
  assert(default_platform_sp);
  m_platform_list.Append(default_platform_sp, true);

  // Create the dummy target.
  {
    ArchSpec arch(Target::GetDefaultArchitecture());
    if (!arch.IsValid())
      arch = HostInfo::GetArchitecture();
    assert(arch.IsValid() && "No valid default or host archspec");
    const bool is_dummy_target = true;
    m_dummy_target_sp.reset(
        new Target(*this, arch, default_platform_sp, is_dummy_target));
  }
  assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?");

  OptionValueUInt64 *term_width =
      m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(
          ePropertyTerminalWidth);
  term_width->SetMinimumValue(10);

  OptionValueUInt64 *term_height =
      m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(
          ePropertyTerminalHeight);
  term_height->SetMinimumValue(10);

  // Turn off use-color if this is a dumb terminal.
  const char *term = getenv("TERM");
  auto disable_color = [&]() {
    SetUseColor(false);
    SetSeparator("| ");
  };

  if (term && !strcmp(term, "dumb"))
    disable_color();
  // Turn off use-color if we don't write to a terminal with color support.
  if (!GetOutputFileSP()->GetIsTerminalWithColors())
    disable_color();

  if (Diagnostics::Enabled()) {
    m_diagnostics_callback_id = Diagnostics::Instance().AddCallback(
        [this](const FileSpec &dir) -> llvm::Error {
          for (auto &entry : m_stream_handlers) {
            llvm::StringRef log_path = entry.first();
            llvm::StringRef file_name = llvm::sys::path::filename(log_path);
            FileSpec destination = dir.CopyByAppendingPathComponent(file_name);
            std::error_code ec =
                llvm::sys::fs::copy_file(log_path, destination.GetPath());
            if (ec)
              return llvm::errorCodeToError(ec);
          }
          return llvm::Error::success();
        });
  }

#if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
  // Enabling use of ANSI color codes because LLDB is using them to highlight
  // text.
  llvm::sys::Process::UseANSIEscapeCodes(true);
#endif
}

Debugger::~Debugger() { Clear(); }

void Debugger::Clear() {
  // Make sure we call this function only once. With the C++ global destructor
  // chain having a list of debuggers and with code that can be running on
  // other threads, we need to ensure this doesn't happen multiple times.
  //
  // The following functions call Debugger::Clear():
  //     Debugger::~Debugger();
  //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
  //     static void Debugger::Terminate();
  llvm::call_once(m_clear_once, [this]() {
    telemetry::ScopedDispatcher<telemetry::DebuggerInfo> helper(
        [this](lldb_private::telemetry::DebuggerInfo *info) {
          assert(this == info->debugger);
          (void)this;
          info->is_exit_entry = true;
        },
        this);
    ClearIOHandlers();
    StopIOHandlerThread();
    StopEventHandlerThread();
    m_listener_sp->Clear();
    for (TargetSP target_sp : m_target_list.Targets()) {
      if (target_sp) {
        if (ProcessSP process_sp = target_sp->GetProcessSP())
          process_sp->Finalize(false /* not destructing */);
        target_sp->Destroy();
      }
    }
    m_broadcaster_manager_sp->Clear();

    // Close the input file _before_ we close the input read communications
    // class as it does NOT own the input file, our m_input_file does.
    m_terminal_state.Clear();
    GetInputFile().Close();

    m_command_interpreter_up->Clear();

    if (Diagnostics::Enabled())
      Diagnostics::Instance().RemoveCallback(m_diagnostics_callback_id);
  });
}

bool Debugger::GetAsyncExecution() {
  return !m_command_interpreter_up->GetSynchronous();
}

void Debugger::SetAsyncExecution(bool async_execution) {
  m_command_interpreter_up->SetSynchronous(!async_execution);
}

static inline int OpenPipe(int fds[2], std::size_t size) {
#ifdef _WIN32
  return _pipe(fds, size, O_BINARY);
#else
  (void)size;
  return pipe(fds);
#endif
}

Status Debugger::SetInputString(const char *data) {
  Status result;
  enum PIPES { READ, WRITE }; // Indexes for the read and write fds
  int fds[2] = {-1, -1};

  if (data == nullptr) {
    result = Status::FromErrorString("String data is null");
    return result;
  }

  size_t size = strlen(data);
  if (size == 0) {
    result = Status::FromErrorString("String data is empty");
    return result;
  }

  if (OpenPipe(fds, size) != 0) {
    result = Status::FromErrorString(
        "can't create pipe file descriptors for LLDB commands");
    return result;
  }

  int r = write(fds[WRITE], data, size);
  (void)r;
  // Close the write end of the pipe, so that the command interpreter will exit
  // when it consumes all the data.
  llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);

  // Open the read file descriptor as a FILE * that we can return as an input
  // handle.
  FILE *commands_file = fdopen(fds[READ], "rb");
  if (commands_file == nullptr) {
    result = Status::FromErrorStringWithFormat(
        "fdopen(%i, \"rb\") failed (errno = %i) "
        "when trying to open LLDB commands pipe",
        fds[READ], errno);
    llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
    return result;
  }

  SetInputFile((FileSP)std::make_shared<NativeFile>(commands_file, true));
  return result;
}

void Debugger::SetInputFile(FileSP file_sp) {
  assert(file_sp && file_sp->IsValid());
  m_input_file_sp = std::move(file_sp);
  // Save away the terminal state if that is relevant, so that we can restore
  // it in RestoreInputState.
  SaveInputTerminalState();
}

void Debugger::SetOutputFile(FileSP file_sp) {
  assert(file_sp && file_sp->IsValid());
  m_output_stream_sp =
      std::make_shared<LockableStreamFile>(file_sp, m_output_mutex);
}

void Debugger::SetErrorFile(FileSP file_sp) {
  assert(file_sp && file_sp->IsValid());
  m_error_stream_sp =
      std::make_shared<LockableStreamFile>(file_sp, m_output_mutex);
}

void Debugger::SaveInputTerminalState() {
  {
    std::lock_guard<std::mutex> guard(m_statusline_mutex);
    if (m_statusline)
      m_statusline->Disable();
  }
  int fd = GetInputFile().GetDescriptor();
  if (fd != File::kInvalidDescriptor)
    m_terminal_state.Save(fd, true);
}

void Debugger::RestoreInputTerminalState() {
  m_terminal_state.Restore();
  {
    std::lock_guard<std::mutex> guard(m_statusline_mutex);
    if (m_statusline)
      m_statusline->Enable();
  }
}

void Debugger::RedrawStatusline(bool update) {
  std::lock_guard<std::mutex> guard(m_statusline_mutex);
  if (m_statusline)
    m_statusline->Redraw(update);
}

ExecutionContext Debugger::GetSelectedExecutionContext() {
  bool adopt_selected = true;
  ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected);
  return ExecutionContext(exe_ctx_ref);
}

void Debugger::DispatchInputInterrupt() {
  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
  IOHandlerSP reader_sp(m_io_handler_stack.Top());
  if (reader_sp)
    reader_sp->Interrupt();
}

void Debugger::DispatchInputEndOfFile() {
  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
  IOHandlerSP reader_sp(m_io_handler_stack.Top());
  if (reader_sp)
    reader_sp->GotEOF();
}

void Debugger::ClearIOHandlers() {
  // The bottom input reader should be the main debugger input reader.  We do
  // not want to close that one here.
  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
  while (m_io_handler_stack.GetSize() > 1) {
    IOHandlerSP reader_sp(m_io_handler_stack.Top());
    if (reader_sp)
      PopIOHandler(reader_sp);
  }
}

void Debugger::RunIOHandlers() {
  IOHandlerSP reader_sp = m_io_handler_stack.Top();
  while (true) {
    if (!reader_sp)
      break;

    reader_sp->Run();
    {
      std::lock_guard<std::recursive_mutex> guard(
          m_io_handler_synchronous_mutex);

      // Remove all input readers that are done from the top of the stack
      while (true) {
        IOHandlerSP top_reader_sp = m_io_handler_stack.Top();
        if (top_reader_sp && top_reader_sp->GetIsDone())
          PopIOHandler(top_reader_sp);
        else
          break;
      }
      reader_sp = m_io_handler_stack.Top();
    }
  }
  ClearIOHandlers();
}

void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex);

  PushIOHandler(reader_sp);
  IOHandlerSP top_reader_sp = reader_sp;

  while (top_reader_sp) {
    top_reader_sp->Run();

    // Don't unwind past the starting point.
    if (top_reader_sp.get() == reader_sp.get()) {
      if (PopIOHandler(reader_sp))
        break;
    }

    // If we pushed new IO handlers, pop them if they're done or restart the
    // loop to run them if they're not.
    while (true) {
      top_reader_sp = m_io_handler_stack.Top();
      if (top_reader_sp && top_reader_sp->GetIsDone()) {
        PopIOHandler(top_reader_sp);
        // Don't unwind past the starting point.
        if (top_reader_sp.get() == reader_sp.get())
          return;
      } else {
        break;
      }
    }
  }
}

bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
  return m_io_handler_stack.IsTop(reader_sp);
}

bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
                                      IOHandler::Type second_top_type) {
  return m_io_handler_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
}

void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
  bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout);
  if (!printed) {
    LockableStreamFileSP stream_sp =
        is_stdout ? m_output_stream_sp : m_error_stream_sp;
    LockedStreamFile locked_stream = stream_sp->Lock();
    locked_stream.Write(s, len);
  }
}

llvm::StringRef Debugger::GetTopIOHandlerControlSequence(char ch) {
  return m_io_handler_stack.GetTopIOHandlerControlSequence(ch);
}

const char *Debugger::GetIOHandlerCommandPrefix() {
  return m_io_handler_stack.GetTopIOHandlerCommandPrefix();
}

const char *Debugger::GetIOHandlerHelpPrologue() {
  return m_io_handler_stack.GetTopIOHandlerHelpPrologue();
}

bool Debugger::RemoveIOHandler(const IOHandlerSP &reader_sp) {
  return PopIOHandler(reader_sp);
}

void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp,
                                 bool cancel_top_handler) {
  PushIOHandler(reader_sp, cancel_top_handler);
}

void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in,
                                               LockableStreamFileSP &out,
                                               LockableStreamFileSP &err) {
  // Before an IOHandler runs, it must have in/out/err streams. This function
  // is called when one ore more of the streams are nullptr. We use the top
  // input reader's in/out/err streams, or fall back to the debugger file
  // handles, or we fall back onto stdin/stdout/stderr as a last resort.

  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
  IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
  // If no STDIN has been set, then set it appropriately
  if (!in || !in->IsValid()) {
    if (top_reader_sp)
      in = top_reader_sp->GetInputFileSP();
    else
      in = GetInputFileSP();
    // If there is nothing, use stdin
    if (!in)
      in = std::make_shared<NativeFile>(stdin, NativeFile::Unowned);
  }
  // If no STDOUT has been set, then set it appropriately
  if (!out || !out->GetUnlockedFile().IsValid()) {
    if (top_reader_sp)
      out = top_reader_sp->GetOutputStreamFileSP();
    else
      out = GetOutputStreamSP();
    // If there is nothing, use stdout
    if (!out)
      out = std::make_shared<LockableStreamFile>(stdout, NativeFile::Unowned,
                                                 m_output_mutex);
  }
  // If no STDERR has been set, then set it appropriately
  if (!err || !err->GetUnlockedFile().IsValid()) {
    if (top_reader_sp)
      err = top_reader_sp->GetErrorStreamFileSP();
    else
      err = GetErrorStreamSP();
    // If there is nothing, use stderr
    if (!err)
      err = std::make_shared<LockableStreamFile>(stderr, NativeFile::Unowned,
                                                 m_output_mutex);
  }
}

void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
                             bool cancel_top_handler) {
  if (!reader_sp)
    return;

  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());

  // Get the current top input reader...
  IOHandlerSP top_reader_sp(m_io_handler_stack.Top());

  // Don't push the same IO handler twice...
  if (reader_sp == top_reader_sp)
    return;

  // Push our new input reader
  m_io_handler_stack.Push(reader_sp);
  reader_sp->Activate();

  // Interrupt the top input reader to it will exit its Run() function and let
  // this new input reader take over
  if (top_reader_sp) {
    top_reader_sp->Deactivate();
    if (cancel_top_handler)
      top_reader_sp->Cancel();
  }
}

bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
  if (!pop_reader_sp)
    return false;

  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());

  // The reader on the stop of the stack is done, so let the next read on the
  // stack refresh its prompt and if there is one...
  if (m_io_handler_stack.IsEmpty())
    return false;

  IOHandlerSP reader_sp(m_io_handler_stack.Top());

  if (pop_reader_sp != reader_sp)
    return false;

  reader_sp->Deactivate();
  reader_sp->Cancel();
  m_io_handler_stack.Pop();

  reader_sp = m_io_handler_stack.Top();
  if (reader_sp)
    reader_sp->Activate();

  return true;
}

StreamUP Debugger::GetAsyncOutputStream() {
  return std::make_unique<StreamAsynchronousIO>(*this,
                                                StreamAsynchronousIO::STDOUT);
}

StreamUP Debugger::GetAsyncErrorStream() {
  return std::make_unique<StreamAsynchronousIO>(*this,
                                                StreamAsynchronousIO::STDERR);
}

void Debugger::RequestInterrupt() {
  std::lock_guard<std::mutex> guard(m_interrupt_mutex);
  m_interrupt_requested++;
}

void Debugger::CancelInterruptRequest() {
  std::lock_guard<std::mutex> guard(m_interrupt_mutex);
  if (m_interrupt_requested > 0)
    m_interrupt_requested--;
}

bool Debugger::InterruptRequested() {
  // This is the one we should call internally.  This will return true either
  // if there's a debugger interrupt and we aren't on the IOHandler thread,
  // or if we are on the IOHandler thread and there's a CommandInterpreter
  // interrupt.
  if (!IsIOHandlerThreadCurrentThread()) {
    std::lock_guard<std::mutex> guard(m_interrupt_mutex);
    return m_interrupt_requested != 0;
  }
  return GetCommandInterpreter().WasInterrupted();
}

Debugger::InterruptionReport::InterruptionReport(
    std::string function_name, const llvm::formatv_object_base &payload)
    : m_function_name(std::move(function_name)),
      m_interrupt_time(std::chrono::system_clock::now()),
      m_thread_id(llvm::get_threadid()) {
  llvm::raw_string_ostream desc(m_description);
  desc << payload << "\n";
}

void Debugger::ReportInterruption(const InterruptionReport &report) {
  // For now, just log the description:
  Log *log = GetLog(LLDBLog::Host);
  LLDB_LOG(log, "Interruption: {0}", report.m_description);
}

Debugger::DebuggerList Debugger::DebuggersRequestingInterruption() {
  DebuggerList result;
  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    for (auto debugger_sp : *g_debugger_list_ptr) {
      if (debugger_sp->InterruptRequested())
        result.push_back(debugger_sp);
    }
  }
  return result;
}

size_t Debugger::GetNumDebuggers() {
  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    return g_debugger_list_ptr->size();
  }
  return 0;
}

lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
  DebuggerSP debugger_sp;

  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    if (index < g_debugger_list_ptr->size())
      debugger_sp = g_debugger_list_ptr->at(index);
  }

  return debugger_sp;
}

DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
  DebuggerSP debugger_sp;

  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
      if ((*pos)->GetID() == id) {
        debugger_sp = *pos;
        break;
      }
    }
  }
  return debugger_sp;
}

bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
                                         const SymbolContext *sc,
                                         const SymbolContext *prev_sc,
                                         const ExecutionContext *exe_ctx,
                                         const Address *addr, Stream &s) {
  FormatEntity::Entry format_entry;

  if (format == nullptr) {
    if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
      format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
    if (format == nullptr) {
      FormatEntity::Parse("${addr}: ", format_entry);
      format = &format_entry;
    }
  }
  bool function_changed = false;
  bool initial_function = false;
  if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
    if (sc && (sc->function || sc->symbol)) {
      if (prev_sc->symbol && sc->symbol) {
        if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
                                 prev_sc->symbol->GetType())) {
          function_changed = true;
        }
      } else if (prev_sc->function && sc->function) {
        if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
          function_changed = true;
        }
      }
    }
  }
  // The first context on a list of instructions will have a prev_sc that has
  // no Function or Symbol -- if SymbolContext had an IsValid() method, it
  // would return false.  But we do get a prev_sc pointer.
  if ((sc && (sc->function || sc->symbol)) && prev_sc &&
      (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
    initial_function = true;
  }
  return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
                              function_changed, initial_function);
}

void Debugger::AssertCallback(llvm::StringRef message,
                              llvm::StringRef backtrace,
                              llvm::StringRef prompt) {
  Debugger::ReportError(llvm::formatv("{0}\n{1}{2}\n{3}", message, backtrace,
                                      GetVersion(), prompt)
                            .str());
}

void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
                                  void *baton) {
  // For simplicity's sake, I am not going to deal with how to close down any
  // open logging streams, I just redirect everything from here on out to the
  // callback.
  m_callback_handler_sp =
      std::make_shared<CallbackLogHandler>(log_callback, baton);
}

void Debugger::SetDestroyCallback(
    lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) {
  std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);
  m_destroy_callbacks.clear();
  const lldb::callback_token_t token = m_destroy_callback_next_token++;
  m_destroy_callbacks.emplace_back(token, destroy_callback, baton);
}

lldb::callback_token_t Debugger::AddDestroyCallback(
    lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) {
  std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);
  const lldb::callback_token_t token = m_destroy_callback_next_token++;
  m_destroy_callbacks.emplace_back(token, destroy_callback, baton);
  return token;
}

bool Debugger::RemoveDestroyCallback(lldb::callback_token_t token) {
  std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);
  for (auto it = m_destroy_callbacks.begin(); it != m_destroy_callbacks.end();
       ++it) {
    if (it->token == token) {
      m_destroy_callbacks.erase(it);
      return true;
    }
  }
  return false;
}

static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
                                  std::string title, std::string details,
                                  uint64_t completed, uint64_t total,
                                  bool is_debugger_specific,
                                  uint32_t progress_broadcast_bit) {
  // Only deliver progress events if we have any progress listeners.
  if (!debugger.GetBroadcaster().EventTypeHasListeners(progress_broadcast_bit))
    return;

  EventSP event_sp(new Event(
      progress_broadcast_bit,
      new ProgressEventData(progress_id, std::move(title), std::move(details),
                            completed, total, is_debugger_specific)));
  debugger.GetBroadcaster().BroadcastEvent(event_sp);
}

void Debugger::ReportProgress(uint64_t progress_id, std::string title,
                              std::string details, uint64_t completed,
                              uint64_t total,
                              std::optional<lldb::user_id_t> debugger_id,
                              uint32_t progress_broadcast_bit) {
  // Check if this progress is for a specific debugger.
  if (debugger_id) {
    // It is debugger specific, grab it and deliver the event if the debugger
    // still exists.
    DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
    if (debugger_sp)
      PrivateReportProgress(*debugger_sp, progress_id, std::move(title),
                            std::move(details), completed, total,
                            /*is_debugger_specific*/ true,
                            progress_broadcast_bit);
    return;
  }
  // The progress event is not debugger specific, iterate over all debuggers
  // and deliver a progress event to each one.
  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)
      PrivateReportProgress(*(*pos), progress_id, title, details, completed,
                            total, /*is_debugger_specific*/ false,
                            progress_broadcast_bit);
  }
}

static void PrivateReportDiagnostic(Debugger &debugger, Severity severity,
                                    std::string message,
                                    bool debugger_specific) {
  uint32_t event_type = 0;
  switch (severity) {
  case eSeverityInfo:
    assert(false && "eSeverityInfo should not be broadcast");
    return;
  case eSeverityWarning:
    event_type = lldb::eBroadcastBitWarning;
    break;
  case eSeverityError:
    event_type = lldb::eBroadcastBitError;
    break;
  }

  Broadcaster &broadcaster = debugger.GetBroadcaster();
  if (!broadcaster.EventTypeHasListeners(event_type)) {
    // Diagnostics are too important to drop. If nobody is listening, print the
    // diagnostic directly to the debugger's error stream.
    DiagnosticEventData event_data(severity, std::move(message),
                                   debugger_specific);
    event_data.Dump(debugger.GetAsyncErrorStream().get());
    return;
  }
  EventSP event_sp = std::make_shared<Event>(
      event_type,
      new DiagnosticEventData(severity, std::move(message), debugger_specific));
  broadcaster.BroadcastEvent(event_sp);
}

void Debugger::ReportDiagnosticImpl(Severity severity, std::string message,
                                    std::optional<lldb::user_id_t> debugger_id,
                                    std::once_flag *once) {
  auto ReportDiagnosticLambda = [&]() {
    // Always log diagnostics to the system log.
    Host::SystemLog(severity, message);

    // The diagnostic subsystem is optional but we still want to broadcast
    // events when it's disabled.
    if (Diagnostics::Enabled())
      Diagnostics::Instance().Report(message);

    // We don't broadcast info events.
    if (severity == lldb::eSeverityInfo)
      return;

    // Check if this diagnostic is for a specific debugger.
    if (debugger_id) {
      // It is debugger specific, grab it and deliver the event if the debugger
      // still exists.
      DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
      if (debugger_sp)
        PrivateReportDiagnostic(*debugger_sp, severity, std::move(message),
                                true);
      return;
    }
    // The diagnostic event is not debugger specific, iterate over all debuggers
    // and deliver a diagnostic event to each one.
    if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
      std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
      for (const auto &debugger : *g_debugger_list_ptr)
        PrivateReportDiagnostic(*debugger, severity, message, false);
    }
  };

  if (once)
    std::call_once(*once, ReportDiagnosticLambda);
  else
    ReportDiagnosticLambda();
}

void Debugger::ReportWarning(std::string message,
                             std::optional<lldb::user_id_t> debugger_id,
                             std::once_flag *once) {
  ReportDiagnosticImpl(eSeverityWarning, std::move(message), debugger_id, once);
}

void Debugger::ReportError(std::string message,
                           std::optional<lldb::user_id_t> debugger_id,
                           std::once_flag *once) {
  ReportDiagnosticImpl(eSeverityError, std::move(message), debugger_id, once);
}

void Debugger::ReportInfo(std::string message,
                          std::optional<lldb::user_id_t> debugger_id,
                          std::once_flag *once) {
  ReportDiagnosticImpl(eSeverityInfo, std::move(message), debugger_id, once);
}

void Debugger::ReportSymbolChange(const ModuleSpec &module_spec) {
  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
    for (DebuggerSP debugger_sp : *g_debugger_list_ptr) {
      EventSP event_sp = std::make_shared<Event>(
          lldb::eBroadcastSymbolChange,
          new SymbolChangeEventData(debugger_sp, module_spec));
      debugger_sp->GetBroadcaster().BroadcastEvent(event_sp);
    }
  }
}

static std::shared_ptr<LogHandler>
CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close,
                 size_t buffer_size) {
  switch (log_handler_kind) {
  case eLogHandlerStream:
    return std::make_shared<StreamLogHandler>(fd, should_close, buffer_size);
  case eLogHandlerCircular:
    return std::make_shared<RotatingLogHandler>(buffer_size);
  case eLogHandlerSystem:
    return std::make_shared<SystemLogHandler>();
  case eLogHandlerCallback:
    return {};
  }
  return {};
}

bool Debugger::EnableLog(llvm::StringRef channel,
                         llvm::ArrayRef<const char *> categories,
                         llvm::StringRef log_file, uint32_t log_options,
                         size_t buffer_size, LogHandlerKind log_handler_kind,
                         llvm::raw_ostream &error_stream) {

  std::shared_ptr<LogHandler> log_handler_sp;
  if (m_callback_handler_sp) {
    log_handler_sp = m_callback_handler_sp;
    // For now when using the callback mode you always get thread & timestamp.
    log_options |=
        LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
  } else if (log_file.empty()) {
    log_handler_sp =
        CreateLogHandler(log_handler_kind, GetOutputFileSP()->GetDescriptor(),
                         /*should_close=*/false, buffer_size);
  } else {
    auto pos = m_stream_handlers.find(log_file);
    if (pos != m_stream_handlers.end())
      log_handler_sp = pos->second.lock();
    if (!log_handler_sp) {
      File::OpenOptions flags =
          File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
      if (log_options & LLDB_LOG_OPTION_APPEND)
        flags |= File::eOpenOptionAppend;
      else
        flags |= File::eOpenOptionTruncate;
      llvm::Expected<FileUP> file = FileSystem::Instance().Open(
          FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false);
      if (!file) {
        error_stream << "Unable to open log file '" << log_file
                     << "': " << llvm::toString(file.takeError()) << "\n";
        return false;
      }

      log_handler_sp =
          CreateLogHandler(log_handler_kind, (*file)->GetDescriptor(),
                           /*should_close=*/true, buffer_size);
      m_stream_handlers[log_file] = log_handler_sp;
    }
  }
  assert(log_handler_sp);

  if (log_options == 0)
    log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME;

  return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,
                               error_stream);
}

ScriptInterpreter *
Debugger::GetScriptInterpreter(bool can_create,
                               std::optional<lldb::ScriptLanguage> language) {
  std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex);
  lldb::ScriptLanguage script_language =
      language ? *language : GetScriptLanguage();

  if (!m_script_interpreters[script_language]) {
    if (!can_create)
      return nullptr;
    m_script_interpreters[script_language] =
        PluginManager::GetScriptInterpreterForLanguage(script_language, *this);
  }

  return m_script_interpreters[script_language].get();
}

SourceManager &Debugger::GetSourceManager() {
  if (!m_source_manager_up)
    m_source_manager_up = std::make_unique<SourceManager>(shared_from_this());
  return *m_source_manager_up;
}

// This function handles events that were broadcast by the process.
void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
  using namespace lldb;
  const uint32_t event_type =
      Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
          event_sp);

  //    if (event_type & eBreakpointEventTypeAdded
  //        || event_type & eBreakpointEventTypeRemoved
  //        || event_type & eBreakpointEventTypeEnabled
  //        || event_type & eBreakpointEventTypeDisabled
  //        || event_type & eBreakpointEventTypeCommandChanged
  //        || event_type & eBreakpointEventTypeConditionChanged
  //        || event_type & eBreakpointEventTypeIgnoreChanged
  //        || event_type & eBreakpointEventTypeLocationsResolved)
  //    {
  //        // Don't do anything about these events, since the breakpoint
  //        commands already echo these actions.
  //    }
  //
  if (event_type & eBreakpointEventTypeLocationsAdded) {
    uint32_t num_new_locations =
        Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
            event_sp);
    if (num_new_locations > 0) {
      BreakpointSP breakpoint =
          Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
      if (StreamUP output_up = GetAsyncOutputStream()) {
        output_up->Printf("%d location%s added to breakpoint %d\n",
                          num_new_locations, num_new_locations == 1 ? "" : "s",
                          breakpoint->GetID());
        output_up->Flush();
      }
    }
  }
  //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
  //    {
  //        // These locations just get disabled, not sure it is worth spamming
  //        folks about this on the command line.
  //    }
  //    else if (event_type & eBreakpointEventTypeLocationsResolved)
  //    {
  //        // This might be an interesting thing to note, but I'm going to
  //        leave it quiet for now, it just looked noisy.
  //    }
}

void Debugger::FlushProcessOutput(Process &process, bool flush_stdout,
                                  bool flush_stderr) {
  const auto &flush = [&](Stream &stream,
                          size_t (Process::*get)(char *, size_t, Status &)) {
    Status error;
    size_t len;
    char buffer[1024];
    while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0)
      stream.Write(buffer, len);
    stream.Flush();
  };

  std::lock_guard<std::mutex> guard(m_output_flush_mutex);
  if (flush_stdout)
    flush(*GetAsyncOutputStream(), &Process::GetSTDOUT);
  if (flush_stderr)
    flush(*GetAsyncErrorStream(), &Process::GetSTDERR);
}

// This function handles events that were broadcast by the process.
void Debugger::HandleProcessEvent(const EventSP &event_sp) {
  using namespace lldb;
  const uint32_t event_type = event_sp->GetType();
  ProcessSP process_sp =
      (event_type == Process::eBroadcastBitStructuredData)
          ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
          : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());

  StreamUP output_stream_up = GetAsyncOutputStream();
  StreamUP error_stream_up = GetAsyncErrorStream();
  const bool gui_enabled = IsForwardingEvents();

  if (!gui_enabled) {
    bool pop_process_io_handler = false;
    assert(process_sp);

    bool state_is_stopped = false;
    const bool got_state_changed =
        (event_type & Process::eBroadcastBitStateChanged) != 0;
    const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
    const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
    const bool got_structured_data =
        (event_type & Process::eBroadcastBitStructuredData) != 0;

    if (got_state_changed) {
      StateType event_state =
          Process::ProcessEventData::GetStateFromEvent(event_sp.get());
      state_is_stopped = StateIsStoppedState(event_state, false);
    }

    // Display running state changes first before any STDIO
    if (got_state_changed && !state_is_stopped) {
      // This is a public stop which we are going to announce to the user, so
      // we should force the most relevant frame selection here.
      Process::HandleProcessStateChangedEvent(event_sp, output_stream_up.get(),
                                              SelectMostRelevantFrame,
                                              pop_process_io_handler);
    }

    // Now display STDOUT and STDERR
    FlushProcessOutput(*process_sp, got_stdout || got_state_changed,
                       got_stderr || got_state_changed);

    // Give structured data events an opportunity to display.
    if (got_structured_data) {
      StructuredDataPluginSP plugin_sp =
          EventDataStructuredData::GetPluginFromEvent(event_sp.get());
      if (plugin_sp) {
        auto structured_data_sp =
            EventDataStructuredData::GetObjectFromEvent(event_sp.get());
        StreamString content_stream;
        Status error =
            plugin_sp->GetDescription(structured_data_sp, content_stream);
        if (error.Success()) {
          if (!content_stream.GetString().empty()) {
            // Add newline.
            content_stream.PutChar('\n');
            content_stream.Flush();

            // Print it.
            output_stream_up->PutCString(content_stream.GetString());
          }
        } else {
          error_stream_up->Format("Failed to print structured "
                                  "data with plugin {0}: {1}",
                                  plugin_sp->GetPluginName(), error);
        }
      }
    }

    // Now display any stopped state changes after any STDIO
    if (got_state_changed && state_is_stopped) {
      Process::HandleProcessStateChangedEvent(event_sp, output_stream_up.get(),
                                              SelectMostRelevantFrame,
                                              pop_process_io_handler);
    }

    output_stream_up->Flush();
    error_stream_up->Flush();

    if (pop_process_io_handler)
      process_sp->PopProcessIOHandler();
  }
}

void Debugger::HandleThreadEvent(const EventSP &event_sp) {
  // At present the only thread event we handle is the Frame Changed event, and
  // all we do for that is just reprint the thread status for that thread.
  using namespace lldb;
  const uint32_t event_type = event_sp->GetType();
  const bool stop_format = true;
  if (event_type == Thread::eBroadcastBitStackChanged ||
      event_type == Thread::eBroadcastBitThreadSelected) {
    ThreadSP thread_sp(
        Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
    if (thread_sp) {
      thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format,
                           /*show_hidden*/ true);
    }
  }
}

bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }

void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
  m_forward_listener_sp = listener_sp;
}

void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
  m_forward_listener_sp.reset();
}

bool Debugger::StatuslineSupported() {
// We have trouble with the contol codes on Windows, see
// https://github.com/llvm/llvm-project/issues/134846.
#ifndef _WIN32
  if (GetShowStatusline()) {
    if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {
      File &file = stream_sp->GetUnlockedFile();
      return file.GetIsInteractive() && file.GetIsRealTerminal() &&
             file.GetIsTerminalWithColors();
    }
  }
#endif
  return false;
}

lldb::thread_result_t Debugger::DefaultEventHandler() {
  ListenerSP listener_sp(GetListener());
  ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
  ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
  ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
  BroadcastEventSpec target_event_spec(broadcaster_class_target,
                                       Target::eBroadcastBitBreakpointChanged);

  BroadcastEventSpec process_event_spec(
      broadcaster_class_process,
      Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
          Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);

  BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
                                       Thread::eBroadcastBitStackChanged |
                                           Thread::eBroadcastBitThreadSelected);

  listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
                                          target_event_spec);
  listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
                                          process_event_spec);
  listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
                                          thread_event_spec);
  listener_sp->StartListeningForEvents(
      m_command_interpreter_up.get(),
      CommandInterpreter::eBroadcastBitQuitCommandReceived |
          CommandInterpreter::eBroadcastBitAsynchronousOutputData |
          CommandInterpreter::eBroadcastBitAsynchronousErrorData);

  listener_sp->StartListeningForEvents(
      &m_broadcaster, lldb::eBroadcastBitProgress | lldb::eBroadcastBitWarning |
                          lldb::eBroadcastBitError |
                          lldb::eBroadcastSymbolChange |
                          lldb::eBroadcastBitExternalProgress);

  // Let the thread that spawned us know that we have started up and that we
  // are now listening to all required events so no events get missed
  m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);

  if (StatuslineSupported()) {
    std::lock_guard<std::mutex> guard(m_statusline_mutex);
    if (!m_statusline)
      m_statusline.emplace(*this);
  }

  bool done = false;
  while (!done) {
    EventSP event_sp;
    if (listener_sp->GetEvent(event_sp, std::nullopt)) {
      if (event_sp) {
        Broadcaster *broadcaster = event_sp->GetBroadcaster();
        if (broadcaster) {
          uint32_t event_type = event_sp->GetType();
          ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
          if (broadcaster_class == broadcaster_class_process) {
            HandleProcessEvent(event_sp);
          } else if (broadcaster_class == broadcaster_class_target) {
            if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
                    event_sp.get())) {
              HandleBreakpointEvent(event_sp);
            }
          } else if (broadcaster_class == broadcaster_class_thread) {
            HandleThreadEvent(event_sp);
          } else if (broadcaster == m_command_interpreter_up.get()) {
            if (event_type &
                CommandInterpreter::eBroadcastBitQuitCommandReceived) {
              done = true;
            } else if (event_type &
                       CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
              const char *data = static_cast<const char *>(
                  EventDataBytes::GetBytesFromEvent(event_sp.get()));
              if (data && data[0]) {
                StreamUP error_up = GetAsyncErrorStream();
                error_up->PutCString(data);
                error_up->Flush();
              }
            } else if (event_type & CommandInterpreter::
                                        eBroadcastBitAsynchronousOutputData) {
              const char *data = static_cast<const char *>(
                  EventDataBytes::GetBytesFromEvent(event_sp.get()));
              if (data && data[0]) {
                StreamUP output_up = GetAsyncOutputStream();
                output_up->PutCString(data);
                output_up->Flush();
              }
            }
          } else if (broadcaster == &m_broadcaster) {
            if (event_type & lldb::eBroadcastBitProgress ||
                event_type & lldb::eBroadcastBitExternalProgress)
              HandleProgressEvent(event_sp);
            else if (event_type & lldb::eBroadcastBitWarning)
              HandleDiagnosticEvent(event_sp);
            else if (event_type & lldb::eBroadcastBitError)
              HandleDiagnosticEvent(event_sp);
          }
        }

        if (m_forward_listener_sp)
          m_forward_listener_sp->AddEvent(event_sp);
      }
      RedrawStatusline();
    }
  }

  {
    std::lock_guard<std::mutex> guard(m_statusline_mutex);
    if (m_statusline)
      m_statusline.reset();
  }

  return {};
}

bool Debugger::StartEventHandlerThread() {
  if (!m_event_handler_thread.IsJoinable()) {
    // We must synchronize with the DefaultEventHandler() thread to ensure it
    // is up and running and listening to events before we return from this
    // function. We do this by listening to events for the
    // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
    ConstString full_name("lldb.debugger.event-handler");
    ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
    listener_sp->StartListeningForEvents(&m_sync_broadcaster,
                                         eBroadcastBitEventThreadIsListening);

    llvm::StringRef thread_name =
        full_name.GetLength() < llvm::get_max_thread_name_length()
            ? full_name.GetStringRef()
            : "dbg.evt-handler";

    // Use larger 8MB stack for this thread
    llvm::Expected<HostThread> event_handler_thread =
        ThreadLauncher::LaunchThread(
            thread_name, [this] { return DefaultEventHandler(); },
            g_debugger_event_thread_stack_bytes);

    if (event_handler_thread) {
      m_event_handler_thread = *event_handler_thread;
    } else {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), event_handler_thread.takeError(),
                     "failed to launch host thread: {0}");
    }

    // Make sure DefaultEventHandler() is running and listening to events
    // before we return from this function. We are only listening for events of
    // type eBroadcastBitEventThreadIsListening so we don't need to check the
    // event, we just need to wait an infinite amount of time for it (nullptr
    // timeout as the first parameter)
    lldb::EventSP event_sp;
    listener_sp->GetEvent(event_sp, std::nullopt);
  }
  return m_event_handler_thread.IsJoinable();
}

void Debugger::StopEventHandlerThread() {
  if (m_event_handler_thread.IsJoinable()) {
    GetCommandInterpreter().BroadcastEvent(
        CommandInterpreter::eBroadcastBitQuitCommandReceived);
    m_event_handler_thread.Join(nullptr);
  }
}

lldb::thread_result_t Debugger::IOHandlerThread() {
  RunIOHandlers();
  StopEventHandlerThread();
  return {};
}

void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
  auto *data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
  if (!data)
    return;

  // Make a local copy of the incoming progress report that we'll store.
  ProgressReport progress_report{data->GetID(), data->GetCompleted(),
                                 data->GetTotal(), data->GetMessage()};

  // Do some bookkeeping regardless of whether we're going to display
  // progress reports.
  {
    std::lock_guard<std::mutex> guard(m_progress_reports_mutex);
    auto it = std::find_if(
        m_progress_reports.begin(), m_progress_reports.end(),
        [&](const auto &report) { return report.id == progress_report.id; });
    if (it != m_progress_reports.end()) {
      const bool complete = data->GetCompleted() == data->GetTotal();
      if (complete)
        m_progress_reports.erase(it);
      else
        *it = progress_report;
    } else {
      m_progress_reports.push_back(progress_report);
    }
  }
}

std::optional<Debugger::ProgressReport>
Debugger::GetCurrentProgressReport() const {
  std::lock_guard<std::mutex> guard(m_progress_reports_mutex);
  if (m_progress_reports.empty())
    return std::nullopt;
  return m_progress_reports.back();
}

void Debugger::HandleDiagnosticEvent(const lldb::EventSP &event_sp) {
  auto *data = DiagnosticEventData::GetEventDataFromEvent(event_sp.get());
  if (!data)
    return;

  data->Dump(GetAsyncErrorStream().get());
}

bool Debugger::HasIOHandlerThread() const {
  return m_io_handler_thread.IsJoinable();
}

HostThread Debugger::SetIOHandlerThread(HostThread &new_thread) {
  HostThread old_host = m_io_handler_thread;
  m_io_handler_thread = new_thread;
  return old_host;
}

bool Debugger::StartIOHandlerThread() {
  if (!m_io_handler_thread.IsJoinable()) {
    llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread(
        "lldb.debugger.io-handler", [this] { return IOHandlerThread(); },
        8 * 1024 * 1024); // Use larger 8MB stack for this thread
    if (io_handler_thread) {
      m_io_handler_thread = *io_handler_thread;
    } else {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), io_handler_thread.takeError(),
                     "failed to launch host thread: {0}");
    }
  }
  return m_io_handler_thread.IsJoinable();
}

void Debugger::StopIOHandlerThread() {
  if (m_io_handler_thread.IsJoinable()) {
    GetInputFile().Close();
    m_io_handler_thread.Join(nullptr);
  }
}

void Debugger::JoinIOHandlerThread() {
  if (HasIOHandlerThread()) {
    thread_result_t result;
    m_io_handler_thread.Join(&result);
    m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
  }
}

bool Debugger::IsIOHandlerThreadCurrentThread() const {
  if (!HasIOHandlerThread())
    return false;
  return m_io_handler_thread.EqualsThread(Host::GetCurrentThread());
}

Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
  if (!prefer_dummy) {
    if (TargetSP target = m_target_list.GetSelectedTarget())
      return *target;
  }
  return GetDummyTarget();
}

Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
  Status err;
  FileSpec repl_executable;

  if (language == eLanguageTypeUnknown)
    language = GetREPLLanguage();

  if (language == eLanguageTypeUnknown) {
    LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();

    if (auto single_lang = repl_languages.GetSingularLanguage()) {
      language = *single_lang;
    } else if (repl_languages.Empty()) {
      err = Status::FromErrorString(
          "LLDB isn't configured with REPL support for any languages.");
      return err;
    } else {
      err = Status::FromErrorString(
          "Multiple possible REPL languages.  Please specify a language.");
      return err;
    }
  }

  Target *const target =
      nullptr; // passing in an empty target means the REPL must create one

  REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));

  if (!err.Success()) {
    return err;
  }

  if (!repl_sp) {
    err = Status::FromErrorStringWithFormat(
        "couldn't find a REPL for %s",
        Language::GetNameForLanguageType(language));
    return err;
  }

  repl_sp->SetCompilerOptions(repl_options);
  repl_sp->RunLoop();

  return err;
}

llvm::ThreadPoolInterface &Debugger::GetThreadPool() {
  assert(g_thread_pool &&
         "Debugger::GetThreadPool called before Debugger::Initialize");
  return *g_thread_pool;
}
