//===-- 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/Diagnostics.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/ProtocolServer.h"
#include "lldb/Core/StreamAsynchronousIO.h"
#include "lldb/Core/Telemetry.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Host/Config.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/Host/XML.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/OptionValueFileSpecList.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/FormatAdapters.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;

static std::mutex &GetDebuggerListMutex() {
  static std::mutex g_mutex;
  return g_mutex;
}

static Debugger::DebuggerList *g_debugger_list_ptr = nullptr;
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.",
    },
};

static constexpr OptionEnumValueElement g_show_autosuggestion_enum_values[] = {
    {
        eAutosuggestionOff,
        "false",
        "Do not show any autosuggestion.",
    },
    {
        eAutosuggestionOn,
        "true",
        "Show a suggestion sourced from previously entered commands.",
    },
    {
        eAutosuggestionTabMode,
        "tab-mode",
        "Show the prefix that tab completion would insert for the current "
        "line.",
    },
};

#define LLDB_PROPERTIES_debugger
#include "CoreProperties.inc"

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

#ifndef NDEBUG
#define LLDB_PROPERTIES_testing
#include "CoreProperties.inc"

enum {
#define LLDB_PROPERTIES_testing
#include "CorePropertiesEnum.inc"
};
#endif

const FileSpecList &Debugger::GetDefaultSafeAutoLoadPaths() {
  static const FileSpecList sSafePaths = [] {
    // FIXME: in c++20 this could be a std::array (with CTAD deduced size)
    // and we could statically assert that all members are non-empty.
    const llvm::SmallVector<llvm::StringRef> kVendorSafePaths = {
#include "SafeAutoloadPaths.inc"
    };
    FileSpecList fspecs;
    for (auto path : kVendorSafePaths) {
      assert(!path.empty());
      LLDB_LOG(GetLog(SystemLog::System), "Safe auto-load path configured: {0}",
               path);
      fspecs.EmplaceBack(path);
    }

    return fspecs;
  }();

  return sSafePaths;
}

#ifndef NDEBUG
TestingProperties::TestingProperties() {
  m_collection_sp = std::make_shared<OptionValueProperties>("testing");
  m_collection_sp->Initialize(g_testing_properties_def);
}

bool TestingProperties::GetInjectVarLocListError() const {
  const uint32_t idx = ePropertyInjectVarLocListError;
  return GetPropertyAtIndexAs<bool>(
      idx, g_testing_properties[idx].default_uint_value != 0);
}

TestingProperties &TestingProperties::GetGlobalTestingProperties() {
  static TestingProperties g_testing_properties;
  return g_testing_properties;
}

void TestingProperties::SetSafeAutoLoadPaths(FileSpecList paths) {
  const uint32_t idx = ePropertySafeAutoloadPaths;
  OptionValueFileSpecList *option_value =
      m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(idx);
  assert(option_value);
  option_value->SetCurrentValue(std::move(paths));
}

void TestingProperties::AppendSafeAutoLoadPaths(FileSpec path) {
  const uint32_t idx = ePropertySafeAutoloadPaths;
  OptionValueFileSpecList *option_value =
      m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(idx);
  assert(option_value);
  option_value->AppendCurrentValue(path);
}

FileSpecList TestingProperties::GetSafeAutoLoadPaths() const {
  const uint32_t idx = ePropertySafeAutoloadPaths;
  return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}
#endif

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);
        m_statusline->Enable(
            GetSelectedExecutionContextRef(/*adopt_dummy_target=*/true));
      } 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(std::nullopt);
    } 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;
        if (!target_sp->LoadScriptingResources(errors)) {
          lldb::StreamUP s = GetAsyncErrorStream();
          for (auto &error : errors)
            s->Printf("%s\n", error.AsCString());
        }
      }
    }
  }
  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) {
  return SetTerminalDimensions(term_width, GetTerminalHeight());
}

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) {
  return SetTerminalDimensions(GetTerminalWidth(), term_height);
}

bool Debugger::SetTerminalDimensions(uint64_t term_width,
                                     uint64_t term_height) {
  // Set both properties before notifying, so observers never recompute from a
  // mix of fresh and stale dimensions.
  const bool width_success =
      SetPropertyAtIndex(ePropertyTerminalWidth, term_width);
  const bool height_success =
      SetPropertyAtIndex(ePropertyTerminalHeight, 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 width_success && height_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);
}

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

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

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

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

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

llvm::StringRef Debugger::GetDividerAnsiSuffix() const {
  const uint32_t idx = ePropertyDividerAnsiSuffix;
  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(std::nullopt);
  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(std::nullopt);
  return ret;
}

AutosuggestionMode Debugger::GetAutosuggestionMode() const {
  const uint32_t idx = ePropertyShowAutosuggestion;
  return GetPropertyAtIndexAs<AutosuggestionMode>(
      idx, static_cast<AutosuggestionMode>(
               g_debugger_properties[idx].default_uint_value));
}

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::GetMarkHiddenFrames() const {
  const uint32_t idx = ePropertyMarkHiddenFrames;
  return GetPropertyAtIndexAs<bool>(
      idx, g_debugger_properties[idx].default_uint_value != 0);
}

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!");
  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  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!");

  {
    std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
    if (g_debugger_list_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;
  }

  {
    std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
    if (g_debugger_list_ptr) {
      for (const DebuggerSP &debugger : *g_debugger_list_ptr)
        debugger->Clear();
      g_debugger_list_ptr->clear();

      delete g_debugger_list_ptr;
      g_debugger_list_ptr = nullptr;
    }
  }
}

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());
  {
    std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
    if (g_debugger_list_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();

  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  if (g_debugger_list_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) {
  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  if (!g_debugger_list_ptr)
    return nullptr;

  for (const DebuggerSP &debugger_sp : *g_debugger_list_ptr) {
    if (llvm::StringRef(debugger_sp->GetInstanceName()) == instance_name)
      return debugger_sp;
  }

  return nullptr;
}

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, File::eOpenOptionReadOnly, 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_target_group_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_def);
  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());
  m_collection_sp->AppendProperty(
      "diagnostics", "Diagnostics settings.", true,
      Diagnostics::GetGlobalProperties().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());
  }
#ifndef NDEBUG
  m_collection_sp->AppendProperty(
      "testing", "Testing-only settings.", /*is_global=*/true,
      TestingProperties::GetGlobalTestingProperties().GetValueProperties());
#endif

  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 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_target_group_list.Clear();
    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();
  });
}

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, File::eOpenOptionReadOnly, 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(
          GetSelectedExecutionContext(/*adopt_dummy_target=*/true));
  }
}

void Debugger::RedrawStatusline(
    std::optional<ExecutionContextRef> exe_ctx_ref) {
  std::lock_guard<std::mutex> guard(m_statusline_mutex);

  const bool flush = m_flush_statusline.exchange(false);
  if (!m_statusline)
    return;

  if (flush)
    m_statusline->ClearExecutionContext();
  m_statusline->Redraw(exe_ctx_ref);
}

void Debugger::FlushStatusLine() { m_flush_statusline = true; }

ExecutionContext
Debugger::GetSelectedExecutionContext(bool adopt_dummy_target) {
  return ExecutionContext(GetSelectedExecutionContextRef(adopt_dummy_target));
}

ExecutionContextRef
Debugger::GetSelectedExecutionContextRef(bool adopt_dummy_target) {
  if (TargetSP selected_target_sp = m_target_list.GetSelectedTarget())
    return ExecutionContextRef(selected_target_sp.get(),
                               /*adopt_selected=*/true);

  if (adopt_dummy_target)
    return ExecutionContextRef(m_dummy_target_sp.get(),
                               /*adopt_selected=*/false);

  return ExecutionContextRef();
}

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, File::eOpenOptionReadOnly,
                                        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;
}

void Debugger::RefreshIOHandler() {
  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->Refresh();
}

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;
  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  if (g_debugger_list_ptr) {
    for (auto debugger_sp : *g_debugger_list_ptr) {
      if (debugger_sp->InterruptRequested())
        result.push_back(debugger_sp);
    }
  }
  return result;
}

size_t Debugger::GetNumDebuggers() {
  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  if (!g_debugger_list_ptr)
    return 0;

  return g_debugger_list_ptr->size();
}

lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  if (!g_debugger_list_ptr)
    return nullptr;

  if (index < g_debugger_list_ptr->size())
    return g_debugger_list_ptr->at(index);

  return nullptr;
}

DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  if (!g_debugger_list_ptr)
    return nullptr;

  for (const DebuggerSP &debugger_sp : *g_debugger_list_ptr) {
    if (debugger_sp->GetID() == id)
      return debugger_sp;
  }

  return nullptr;
}

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::Formatter(sc, exe_ctx, addr, function_changed,
                                 initial_function)
      .Format(*format, s);
}

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

std::vector<std::string>
Debugger::CopyLogFilesToDirectory(const FileSpec &dir) {
  std::vector<std::string> copied;
  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);
    // Best-effort: skip logs that can't be copied rather than aborting.
    if (!llvm::sys::fs::copy_file(log_path, destination.GetPath()))
      copied.push_back(file_name.str());
  }
  return copied;
}

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.
  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  if (g_debugger_list_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().Record(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.
    std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
    if (g_debugger_list_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) {
  std::lock_guard<std::mutex> guard(GetDebuggerListMutex());
  if (!g_debugger_list_ptr)
    return;

  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 {};
}

llvm::Error 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) {

  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)
        return llvm::createStringErrorV("Unable to open log file '{}': {}",
                                        log_file,
                                        llvm::fmt_consume(file.takeError()));

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

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.
ProcessSP Debugger::HandleProcessEvent(const EventSP &event_sp) {
  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();
  }
  return process_sp;
}

ThreadSP 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.
  const uint32_t event_type = event_sp->GetType();
  const bool stop_format = true;
  ThreadSP thread_sp;
  if (event_type == Thread::eBroadcastBitStackChanged ||
      event_type == Thread::eBroadcastBitThreadSelected) {
    thread_sp = Thread::ThreadEventData::GetThreadFromEvent(event_sp.get());
    if (thread_sp) {
      thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format,
                           /*show_hidden*/ true);
    }
  }
  return thread_sp;
}

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();
}

/// Conservative heuristic to detect whether OSC 9;4 progress is supported by
/// the current terminal.
static bool TerminalSupportsOSCProgress() {
#if defined(_WIN32)
  // On Windows, we assume that the user is using the Windows Terminal.
  return true;
#else
  static std::once_flag g_once_flag;
  static bool g_supports_osc_progress = false;

  std::call_once(g_once_flag, []() {
    // Check TERM_PROGRAM for known supported terminals. This can lead to false
    // negatives, for example when using tmux.
    if (const char *term_program = std::getenv("TERM_PROGRAM")) {
      llvm::StringRef term_program_str(term_program);
      if (term_program_str.starts_with("ghostty") ||
          term_program_str.starts_with("wezterm")) {
        g_supports_osc_progress = true;
        return;
      }
    }

    // Check other known environment variables.
    std::array<const char *, 3> known_env_vars = {
        "ConEmuPID", // https://conemu.github.io/en/ConEmuEnvironment.html
        "GHOSTTY_RESOURCES_DIR", // https://ghostty.org/docs/features/shell-integration
        "OSC_PROGRESS",          // LLDB specific override.
    };
    for (const char *env_var : known_env_vars) {
      if (std::getenv(env_var)) {
        g_supports_osc_progress = true;
        return;
      }
    }
  });

  return g_supports_osc_progress;
#endif
}

bool Debugger::IsEscapeCodeCapableTTY() {
  if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {
    File &file = stream_sp->GetUnlockedFile();
    return file.GetIsInteractive() && file.GetIsRealTerminal() &&
           file.GetIsTerminalWithColors();
  }
  return false;
}

bool Debugger::StatuslineSupported() {
// We have trouble with the contol codes on Windows, see
// https://github.com/llvm/llvm-project/issues/134846.
#ifndef _WIN32
  return GetShowStatusline() && IsEscapeCodeCapableTTY();
#else
  return false;
#endif
}

static bool RequiresFollowChildWorkaround(const Process &process) {
  // FIXME: https://github.com/llvm/llvm-project/issues/160216
  return process.GetFollowForkMode() == eFollowChild;
}

lldb::thread_result_t Debugger::DefaultEventHandler() {
  ListenerSP listener_sp(GetListener());
  llvm::StringRef broadcaster_class_target(Target::GetStaticBroadcasterClass());
  llvm::StringRef broadcaster_class_process(
      Process::GetStaticBroadcasterClass());
  llvm::StringRef 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);
      m_statusline->Enable(
          GetSelectedExecutionContextRef(/*adopt_dummy_target=*/true));
    }
  }

  bool done = false;
  while (!done) {
    EventSP event_sp;
    if (listener_sp->GetEvent(event_sp, std::nullopt)) {
      std::optional<ExecutionContextRef> exe_ctx_ref = std::nullopt;
      if (event_sp) {
        Broadcaster *broadcaster = event_sp->GetBroadcaster();
        if (broadcaster) {
          uint32_t event_type = event_sp->GetType();
          llvm::StringRef broadcaster_class(broadcaster->GetBroadcasterClass());
          if (broadcaster_class == broadcaster_class_process) {
            if (ProcessSP process_sp = HandleProcessEvent(event_sp)) {
              // Don't pass adopt_selected = true if this is a stop for an
              // auto-continue event (e.g. an auto-continue breakpoint).  We
              // would be fetching stale state, since the process resumed since
              // this event, and we'd needlessly interrupt the target to do so.
              const bool adopt_selected =
                  process_sp->GetPrivateState() == eStateStopped &&
                  !Process::ProcessEventData::GetRestartedFromEvent(
                      event_sp.get());
              if (!RequiresFollowChildWorkaround(*process_sp))
                exe_ctx_ref =
                    ExecutionContextRef(process_sp.get(), adopt_selected);
            }
          } else if (broadcaster_class == broadcaster_class_target) {
            if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
                    event_sp.get())) {
              HandleBreakpointEvent(event_sp);
            }
          } else if (broadcaster_class == broadcaster_class_thread) {
            if (ThreadSP thread_sp = HandleThreadEvent(event_sp))
              if (!RequiresFollowChildWorkaround(*thread_sp->GetProcess()))
                exe_ctx_ref = ExecutionContextRef(thread_sp.get(),
                                                  /*adopt_selected=*/true);
          } 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(exe_ctx_ref);
    }
  }

  {
    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
    llvm::StringRef full_name("lldb.debugger.event-handler");
    ListenerSP listener_sp(Listener::MakeListener(full_name));
    listener_sp->StartListeningForEvents(&m_sync_broadcaster,
                                         eBroadcastBitEventThreadIsListening);

    llvm::StringRef thread_name =
        full_name.size() < llvm::get_max_thread_name_length()
            ? full_name
            : "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()};

  {
    std::lock_guard<std::mutex> guard(m_progress_reports_mutex);

    // Do some bookkeeping regardless of whether we're going to display
    // progress reports.
    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);
    }

    // Show progress using Operating System Command (OSC) sequences.
    if (GetShowProgress() && IsEscapeCodeCapableTTY() &&
        TerminalSupportsOSCProgress()) {
      if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {

        // Clear progress if this was the last progress event.
        if (m_progress_reports.empty()) {
          stream_sp->Lock() << OSC_PROGRESS_REMOVE;
          return;
        }

        const ProgressReport &report = m_progress_reports.back();

        // Show indeterminate progress.
        if (report.total == UINT64_MAX) {
          stream_sp->Lock() << OSC_PROGRESS_INDETERMINATE;
          return;
        }

        // Compute and show the progress value (0-100).
        const unsigned value = (report.completed / report.total) * 100;
        stream_sp->Lock().Printf(OSC_PROGRESS_SHOW, value);
      }
    }
  }
}

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;
}

static void AddBoolConfigEntry(StructuredData::Dictionary &dict,
                               llvm::StringRef name, bool value,
                               llvm::StringRef description) {
  auto entry_up = std::make_unique<StructuredData::Dictionary>();
  entry_up->AddBooleanItem("value", value);
  entry_up->AddStringItem("description", description);
  dict.AddItem(name, std::move(entry_up));
}

static void AddLLVMTargets(StructuredData::Dictionary &dict) {
  auto array_up = std::make_unique<StructuredData::Array>();
#define LLVM_TARGET(target)                                                    \
  array_up->AddItem(std::make_unique<StructuredData::String>(#target));
#include "llvm/Config/Targets.def"
  auto entry_up = std::make_unique<StructuredData::Dictionary>();
  entry_up->AddItem("value", std::move(array_up));
  entry_up->AddStringItem("description", "A list of configured LLVM targets.");
  dict.AddItem("targets", std::move(entry_up));
}

StructuredData::DictionarySP Debugger::GetBuildConfiguration() {
  auto config_up = std::make_unique<StructuredData::Dictionary>();
  AddBoolConfigEntry(
      *config_up, "xml", XMLDocument::XMLEnabled(),
      "A boolean value that indicates if XML support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "curl", LLVM_ENABLE_CURL,
      "A boolean value that indicates if CURL support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "curses", LLDB_ENABLE_CURSES,
      "A boolean value that indicates if curses support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "editline", LLDB_ENABLE_LIBEDIT,
      "A boolean value that indicates if editline support is enabled in LLDB");
  AddBoolConfigEntry(*config_up, "editline_wchar", LLDB_EDITLINE_USE_WCHAR,
                     "A boolean value that indicates if editline wide "
                     "characters support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "zlib", LLVM_ENABLE_ZLIB,
      "A boolean value that indicates if zlib support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "lzma", LLVM_ENABLE_LZMA,
      "A boolean value that indicates if lzma support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "python", LLDB_ENABLE_PYTHON,
      "A boolean value that indicates if python support is enabled in LLDB");
  AddBoolConfigEntry(
      *config_up, "lua", LLDB_ENABLE_LUA,
      "A boolean value that indicates if lua support is enabled in LLDB");
  AddLLVMTargets(*config_up);
  return config_up;
}
