//===-- 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);
}

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

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

FormatEntity::Entry Debugger::GetFrameFormatUnique() const {
  constexpr uint32_t idx = ePropertyFrameFormatUnique;
  return GetPropertyAtIndexAs<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);
}

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

FormatEntity::Entry Debugger::GetThreadStopFormat() const {
  constexpr uint32_t idx = ePropertyThreadStopFormat;
  return GetPropertyAtIndexAs<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);
}

FormatEntity::Entry Debugger::GetStatuslineFormat() const {
  constexpr uint32_t idx = ePropertyStatuslineFormat;
  return GetPropertyAtIndexAs<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);
}

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

llvm::StringRef Debugger::GetDisabledAnsiSuffix() const {
  const uint32_t idx = ePropertyShowDisabledAnsiSuffix;
  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_entry =
          exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
      format = &format_entry;
    }
    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 = llvm::find_if(m_progress_reports, [&](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;
}
