brintos

brintos / llvm-project-archived public Read only

0
0
Text · 85.1 KiB · 02f38e9 Raw
2445 lines · cpp
1//===-- Debugger.cpp ------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/Debugger.h"10 11#include "lldb/Breakpoint/Breakpoint.h"12#include "lldb/Core/DebuggerEvents.h"13#include "lldb/Core/FormatEntity.h"14#include "lldb/Core/Mangled.h"15#include "lldb/Core/ModuleList.h"16#include "lldb/Core/ModuleSpec.h"17#include "lldb/Core/PluginManager.h"18#include "lldb/Core/Progress.h"19#include "lldb/Core/ProtocolServer.h"20#include "lldb/Core/StreamAsynchronousIO.h"21#include "lldb/Core/Telemetry.h"22#include "lldb/DataFormatters/DataVisualization.h"23#include "lldb/Expression/REPL.h"24#include "lldb/Host/File.h"25#include "lldb/Host/FileSystem.h"26#include "lldb/Host/HostInfo.h"27#include "lldb/Host/StreamFile.h"28#include "lldb/Host/Terminal.h"29#include "lldb/Host/ThreadLauncher.h"30#include "lldb/Interpreter/CommandInterpreter.h"31#include "lldb/Interpreter/CommandReturnObject.h"32#include "lldb/Interpreter/OptionValue.h"33#include "lldb/Interpreter/OptionValueLanguage.h"34#include "lldb/Interpreter/OptionValueProperties.h"35#include "lldb/Interpreter/OptionValueSInt64.h"36#include "lldb/Interpreter/OptionValueString.h"37#include "lldb/Interpreter/Property.h"38#include "lldb/Interpreter/ScriptInterpreter.h"39#include "lldb/Symbol/Function.h"40#include "lldb/Symbol/Symbol.h"41#include "lldb/Symbol/SymbolContext.h"42#include "lldb/Target/Language.h"43#include "lldb/Target/Process.h"44#include "lldb/Target/StructuredDataPlugin.h"45#include "lldb/Target/Target.h"46#include "lldb/Target/TargetList.h"47#include "lldb/Target/Thread.h"48#include "lldb/Target/ThreadList.h"49#include "lldb/Utility/AnsiTerminal.h"50#include "lldb/Utility/Event.h"51#include "lldb/Utility/LLDBLog.h"52#include "lldb/Utility/Listener.h"53#include "lldb/Utility/Log.h"54#include "lldb/Utility/State.h"55#include "lldb/Utility/Stream.h"56#include "lldb/Utility/StreamString.h"57#include "lldb/Version/Version.h"58#include "lldb/lldb-enumerations.h"59 60#if defined(_WIN32)61#include "lldb/Host/windows/PosixApi.h"62#include "lldb/Host/windows/windows.h"63#endif64 65#include "llvm/ADT/STLExtras.h"66#include "llvm/ADT/StringRef.h"67#include "llvm/ADT/iterator.h"68#include "llvm/Config/llvm-config.h"69#include "llvm/Support/DynamicLibrary.h"70#include "llvm/Support/FileSystem.h"71#include "llvm/Support/Process.h"72#include "llvm/Support/ThreadPool.h"73#include "llvm/Support/Threading.h"74#include "llvm/Support/raw_ostream.h"75 76#include <chrono>77#include <cstdio>78#include <cstdlib>79#include <cstring>80#include <list>81#include <memory>82#include <mutex>83#include <optional>84#include <set>85#include <string>86#include <system_error>87 88// Includes for pipe()89#if defined(_WIN32)90#include <fcntl.h>91#include <io.h>92#else93#include <unistd.h>94#endif95 96namespace lldb_private {97class Address;98}99 100using namespace lldb;101using namespace lldb_private;102 103static lldb::user_id_t g_unique_id = 1;104static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;105 106#pragma mark Static Functions107 108static std::recursive_mutex *g_debugger_list_mutex_ptr =109    nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain110static Debugger::DebuggerList *g_debugger_list_ptr =111    nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain112static llvm::DefaultThreadPool *g_thread_pool = nullptr;113 114static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {115    {116        lldb::eStopDisassemblyTypeNever,117        "never",118        "Never show disassembly when displaying a stop context.",119    },120    {121        lldb::eStopDisassemblyTypeNoDebugInfo,122        "no-debuginfo",123        "Show disassembly when there is no debug information.",124    },125    {126        lldb::eStopDisassemblyTypeNoSource,127        "no-source",128        "Show disassembly when there is no source information, or the source "129        "file "130        "is missing when displaying a stop context.",131    },132    {133        lldb::eStopDisassemblyTypeAlways,134        "always",135        "Always show disassembly when displaying a stop context.",136    },137};138 139static constexpr OptionEnumValueElement g_language_enumerators[] = {140    {141        eScriptLanguageNone,142        "none",143        "Disable scripting languages.",144    },145    {146        eScriptLanguagePython,147        "python",148        "Select python as the default scripting language.",149    },150    {151        eScriptLanguageDefault,152        "default",153        "Select the lldb default as the default scripting language.",154    },155};156 157static constexpr OptionEnumValueElement g_dwim_print_verbosities[] = {158    {eDWIMPrintVerbosityNone, "none",159     "Use no verbosity when running dwim-print."},160    {eDWIMPrintVerbosityExpression, "expression",161     "Use partial verbosity when running dwim-print - display a message when "162     "`expression` evaluation is used."},163    {eDWIMPrintVerbosityFull, "full",164     "Use full verbosity when running dwim-print."},165};166 167static constexpr OptionEnumValueElement s_stop_show_column_values[] = {168    {169        eStopShowColumnAnsiOrCaret,170        "ansi-or-caret",171        "Highlight the stop column with ANSI terminal codes when color/ANSI "172        "mode is enabled; otherwise, fall back to using a text-only caret (^) "173        "as if \"caret-only\" mode was selected.",174    },175    {176        eStopShowColumnAnsi,177        "ansi",178        "Highlight the stop column with ANSI terminal codes when running LLDB "179        "with color/ANSI enabled.",180    },181    {182        eStopShowColumnCaret,183        "caret",184        "Highlight the stop column with a caret character (^) underneath the "185        "stop column. This method introduces a new line in source listings "186        "that display thread stop locations.",187    },188    {189        eStopShowColumnNone,190        "none",191        "Do not highlight the stop column.",192    },193};194 195#define LLDB_PROPERTIES_debugger196#include "CoreProperties.inc"197 198enum {199#define LLDB_PROPERTIES_debugger200#include "CorePropertiesEnum.inc"201};202 203LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;204 205Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,206                                  VarSetOperationType op,207                                  llvm::StringRef property_path,208                                  llvm::StringRef value) {209  bool is_load_script =210      (property_path == "target.load-script-from-symbol-file");211  // These properties might change how we visualize data.212  bool invalidate_data_vis = (property_path == "escape-non-printables");213  invalidate_data_vis |=214      (property_path == "target.max-zero-padding-in-float-format");215  if (invalidate_data_vis) {216    DataVisualization::ForceUpdate();217  }218 219  TargetSP target_sp;220  LoadScriptFromSymFile load_script_old_value = eLoadScriptFromSymFileFalse;221  if (is_load_script && exe_ctx && exe_ctx->GetTargetSP()) {222    target_sp = exe_ctx->GetTargetSP();223    load_script_old_value =224        target_sp->TargetProperties::GetLoadScriptFromSymbolFile();225  }226  Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));227  if (error.Success()) {228    // FIXME it would be nice to have "on-change" callbacks for properties229    if (property_path == g_debugger_properties[ePropertyPrompt].name) {230      llvm::StringRef new_prompt = GetPrompt();231      std::string str = lldb_private::ansi::FormatAnsiTerminalCodes(232          new_prompt, GetUseColor());233      if (str.length())234        new_prompt = str;235      GetCommandInterpreter().UpdatePrompt(new_prompt);236      auto bytes = std::make_unique<EventDataBytes>(new_prompt);237      auto prompt_change_event_sp = std::make_shared<Event>(238          CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());239      GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);240    } else if (property_path == g_debugger_properties[ePropertyUseColor].name) {241      // use-color changed. set use-color, this also pings the prompt so it can242      // reset the ansi terminal codes.243      SetUseColor(GetUseColor());244    } else if (property_path ==245                   g_debugger_properties[ePropertyPromptAnsiPrefix].name ||246               property_path ==247                   g_debugger_properties[ePropertyPromptAnsiSuffix].name) {248      // Prompt color changed. set use-color, this also pings the prompt so it249      // can reset the ansi terminal codes.250      SetUseColor(GetUseColor());251    } else if (property_path ==252               g_debugger_properties[ePropertyShowStatusline].name) {253      // Statusline setting changed. If we have a statusline instance, update it254      // now. Otherwise it will get created in the default event handler.255      std::lock_guard<std::mutex> guard(m_statusline_mutex);256      if (StatuslineSupported()) {257        m_statusline.emplace(*this);258        m_statusline->Enable(GetSelectedExecutionContextRef());259      } else {260        m_statusline.reset();261      }262    } else if (property_path ==263                   g_debugger_properties[ePropertyStatuslineFormat].name ||264               property_path ==265                   g_debugger_properties[ePropertySeparator].name) {266      // Statusline format changed. Redraw the statusline.267      RedrawStatusline(std::nullopt);268    } else if (property_path ==269               g_debugger_properties[ePropertyUseSourceCache].name) {270      // use-source-cache changed. Wipe out the cache contents if it was271      // disabled.272      if (!GetUseSourceCache()) {273        m_source_file_cache.Clear();274      }275    } else if (is_load_script && target_sp &&276               load_script_old_value == eLoadScriptFromSymFileWarn) {277      if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==278          eLoadScriptFromSymFileTrue) {279        std::list<Status> errors;280        StreamString feedback_stream;281        if (!target_sp->LoadScriptingResources(errors, feedback_stream)) {282          lldb::StreamUP s = GetAsyncErrorStream();283          for (auto &error : errors)284            s->Printf("%s\n", error.AsCString());285          if (feedback_stream.GetSize())286            s->PutCString(feedback_stream.GetString());287        }288      }289    }290  }291  return error;292}293 294bool Debugger::GetAutoConfirm() const {295  constexpr uint32_t idx = ePropertyAutoConfirm;296  return GetPropertyAtIndexAs<bool>(297      idx, g_debugger_properties[idx].default_uint_value != 0);298}299 300FormatEntity::Entry Debugger::GetDisassemblyFormat() const {301  constexpr uint32_t idx = ePropertyDisassemblyFormat;302  return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {});303}304 305FormatEntity::Entry Debugger::GetFrameFormat() const {306  constexpr uint32_t idx = ePropertyFrameFormat;307  return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {});308}309 310FormatEntity::Entry Debugger::GetFrameFormatUnique() const {311  constexpr uint32_t idx = ePropertyFrameFormatUnique;312  return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {});313}314 315uint64_t Debugger::GetStopDisassemblyMaxSize() const {316  constexpr uint32_t idx = ePropertyStopDisassemblyMaxSize;317  return GetPropertyAtIndexAs<uint64_t>(318      idx, g_debugger_properties[idx].default_uint_value);319}320 321bool Debugger::GetNotifyVoid() const {322  constexpr uint32_t idx = ePropertyNotiftVoid;323  return GetPropertyAtIndexAs<uint64_t>(324      idx, g_debugger_properties[idx].default_uint_value != 0);325}326 327llvm::StringRef Debugger::GetPrompt() const {328  constexpr uint32_t idx = ePropertyPrompt;329  return GetPropertyAtIndexAs<llvm::StringRef>(330      idx, g_debugger_properties[idx].default_cstr_value);331}332 333llvm::StringRef Debugger::GetPromptAnsiPrefix() const {334  const uint32_t idx = ePropertyPromptAnsiPrefix;335  return GetPropertyAtIndexAs<llvm::StringRef>(336      idx, g_debugger_properties[idx].default_cstr_value);337}338 339llvm::StringRef Debugger::GetPromptAnsiSuffix() const {340  const uint32_t idx = ePropertyPromptAnsiSuffix;341  return GetPropertyAtIndexAs<llvm::StringRef>(342      idx, g_debugger_properties[idx].default_cstr_value);343}344 345void Debugger::SetPrompt(llvm::StringRef p) {346  constexpr uint32_t idx = ePropertyPrompt;347  SetPropertyAtIndex(idx, p);348  llvm::StringRef new_prompt = GetPrompt();349  std::string str =350      lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());351  if (str.length())352    new_prompt = str;353  GetCommandInterpreter().UpdatePrompt(new_prompt);354}355 356FormatEntity::Entry Debugger::GetThreadFormat() const {357  constexpr uint32_t idx = ePropertyThreadFormat;358  return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {});359}360 361FormatEntity::Entry Debugger::GetThreadStopFormat() const {362  constexpr uint32_t idx = ePropertyThreadStopFormat;363  return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {});364}365 366lldb::ScriptLanguage Debugger::GetScriptLanguage() const {367  const uint32_t idx = ePropertyScriptLanguage;368  return GetPropertyAtIndexAs<lldb::ScriptLanguage>(369      idx, static_cast<lldb::ScriptLanguage>(370               g_debugger_properties[idx].default_uint_value));371}372 373bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {374  const uint32_t idx = ePropertyScriptLanguage;375  return SetPropertyAtIndex(idx, script_lang);376}377 378lldb::LanguageType Debugger::GetREPLLanguage() const {379  const uint32_t idx = ePropertyREPLLanguage;380  return GetPropertyAtIndexAs<LanguageType>(idx, {});381}382 383bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) {384  const uint32_t idx = ePropertyREPLLanguage;385  return SetPropertyAtIndex(idx, repl_lang);386}387 388uint64_t Debugger::GetTerminalWidth() const {389  const uint32_t idx = ePropertyTerminalWidth;390  return GetPropertyAtIndexAs<uint64_t>(391      idx, g_debugger_properties[idx].default_uint_value);392}393 394bool Debugger::SetTerminalWidth(uint64_t term_width) {395  const uint32_t idx = ePropertyTerminalWidth;396  const bool success = SetPropertyAtIndex(idx, term_width);397 398  if (auto handler_sp = m_io_handler_stack.Top())399    handler_sp->TerminalSizeChanged();400 401  {402    std::lock_guard<std::mutex> guard(m_statusline_mutex);403    if (m_statusline)404      m_statusline->TerminalSizeChanged();405  }406 407  return success;408}409 410uint64_t Debugger::GetTerminalHeight() const {411  const uint32_t idx = ePropertyTerminalHeight;412  return GetPropertyAtIndexAs<uint64_t>(413      idx, g_debugger_properties[idx].default_uint_value);414}415 416bool Debugger::SetTerminalHeight(uint64_t term_height) {417  const uint32_t idx = ePropertyTerminalHeight;418  const bool success = SetPropertyAtIndex(idx, term_height);419 420  if (auto handler_sp = m_io_handler_stack.Top())421    handler_sp->TerminalSizeChanged();422 423  {424    std::lock_guard<std::mutex> guard(m_statusline_mutex);425    if (m_statusline)426      m_statusline->TerminalSizeChanged();427  }428 429  return success;430}431 432bool Debugger::GetUseExternalEditor() const {433  const uint32_t idx = ePropertyUseExternalEditor;434  return GetPropertyAtIndexAs<bool>(435      idx, g_debugger_properties[idx].default_uint_value != 0);436}437 438bool Debugger::SetUseExternalEditor(bool b) {439  const uint32_t idx = ePropertyUseExternalEditor;440  return SetPropertyAtIndex(idx, b);441}442 443llvm::StringRef Debugger::GetExternalEditor() const {444  const uint32_t idx = ePropertyExternalEditor;445  return GetPropertyAtIndexAs<llvm::StringRef>(446      idx, g_debugger_properties[idx].default_cstr_value);447}448 449bool Debugger::SetExternalEditor(llvm::StringRef editor) {450  const uint32_t idx = ePropertyExternalEditor;451  return SetPropertyAtIndex(idx, editor);452}453 454bool Debugger::GetUseColor() const {455  const uint32_t idx = ePropertyUseColor;456  return GetPropertyAtIndexAs<bool>(457      idx, g_debugger_properties[idx].default_uint_value != 0);458}459 460bool Debugger::SetUseColor(bool b) {461  const uint32_t idx = ePropertyUseColor;462  bool ret = SetPropertyAtIndex(idx, b);463 464  GetCommandInterpreter().UpdateUseColor(b);465  SetPrompt(GetPrompt());466  return ret;467}468 469bool Debugger::GetShowProgress() const {470  const uint32_t idx = ePropertyShowProgress;471  return GetPropertyAtIndexAs<bool>(472      idx, g_debugger_properties[idx].default_uint_value != 0);473}474 475bool Debugger::SetShowProgress(bool show_progress) {476  const uint32_t idx = ePropertyShowProgress;477  return SetPropertyAtIndex(idx, show_progress);478}479 480llvm::StringRef Debugger::GetShowProgressAnsiPrefix() const {481  const uint32_t idx = ePropertyShowProgressAnsiPrefix;482  return GetPropertyAtIndexAs<llvm::StringRef>(483      idx, g_debugger_properties[idx].default_cstr_value);484}485 486llvm::StringRef Debugger::GetShowProgressAnsiSuffix() const {487  const uint32_t idx = ePropertyShowProgressAnsiSuffix;488  return GetPropertyAtIndexAs<llvm::StringRef>(489      idx, g_debugger_properties[idx].default_cstr_value);490}491 492bool Debugger::GetShowStatusline() const {493  const uint32_t idx = ePropertyShowStatusline;494  return GetPropertyAtIndexAs<bool>(495      idx, g_debugger_properties[idx].default_uint_value != 0);496}497 498FormatEntity::Entry Debugger::GetStatuslineFormat() const {499  constexpr uint32_t idx = ePropertyStatuslineFormat;500  return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {});501}502 503bool Debugger::SetStatuslineFormat(const FormatEntity::Entry &format) {504  constexpr uint32_t idx = ePropertyStatuslineFormat;505  bool ret = SetPropertyAtIndex(idx, format);506  RedrawStatusline(std::nullopt);507  return ret;508}509 510llvm::StringRef Debugger::GetSeparator() const {511  constexpr uint32_t idx = ePropertySeparator;512  return GetPropertyAtIndexAs<llvm::StringRef>(513      idx, g_debugger_properties[idx].default_cstr_value);514}515 516llvm::StringRef Debugger::GetDisabledAnsiPrefix() const {517  const uint32_t idx = ePropertyShowDisabledAnsiPrefix;518  return GetPropertyAtIndexAs<llvm::StringRef>(519      idx, g_debugger_properties[idx].default_cstr_value);520}521 522llvm::StringRef Debugger::GetDisabledAnsiSuffix() const {523  const uint32_t idx = ePropertyShowDisabledAnsiSuffix;524  return GetPropertyAtIndexAs<llvm::StringRef>(525      idx, g_debugger_properties[idx].default_cstr_value);526}527 528bool Debugger::SetSeparator(llvm::StringRef s) {529  constexpr uint32_t idx = ePropertySeparator;530  bool ret = SetPropertyAtIndex(idx, s);531  RedrawStatusline(std::nullopt);532  return ret;533}534 535bool Debugger::GetUseAutosuggestion() const {536  const uint32_t idx = ePropertyShowAutosuggestion;537  return GetPropertyAtIndexAs<bool>(538      idx, g_debugger_properties[idx].default_uint_value != 0);539}540 541llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const {542  const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix;543  return GetPropertyAtIndexAs<llvm::StringRef>(544      idx, g_debugger_properties[idx].default_cstr_value);545}546 547llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const {548  const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix;549  return GetPropertyAtIndexAs<llvm::StringRef>(550      idx, g_debugger_properties[idx].default_cstr_value);551}552 553llvm::StringRef Debugger::GetRegexMatchAnsiPrefix() const {554  const uint32_t idx = ePropertyShowRegexMatchAnsiPrefix;555  return GetPropertyAtIndexAs<llvm::StringRef>(556      idx, g_debugger_properties[idx].default_cstr_value);557}558 559llvm::StringRef Debugger::GetRegexMatchAnsiSuffix() const {560  const uint32_t idx = ePropertyShowRegexMatchAnsiSuffix;561  return GetPropertyAtIndexAs<llvm::StringRef>(562      idx, g_debugger_properties[idx].default_cstr_value);563}564 565bool Debugger::GetShowDontUsePoHint() const {566  const uint32_t idx = ePropertyShowDontUsePoHint;567  return GetPropertyAtIndexAs<bool>(568      idx, g_debugger_properties[idx].default_uint_value != 0);569}570 571bool Debugger::GetUseSourceCache() const {572  const uint32_t idx = ePropertyUseSourceCache;573  return GetPropertyAtIndexAs<bool>(574      idx, g_debugger_properties[idx].default_uint_value != 0);575}576 577bool Debugger::SetUseSourceCache(bool b) {578  const uint32_t idx = ePropertyUseSourceCache;579  bool ret = SetPropertyAtIndex(idx, b);580  if (!ret) {581    m_source_file_cache.Clear();582  }583  return ret;584}585bool Debugger::GetHighlightSource() const {586  const uint32_t idx = ePropertyHighlightSource;587  return GetPropertyAtIndexAs<bool>(588      idx, g_debugger_properties[idx].default_uint_value != 0);589}590 591StopShowColumn Debugger::GetStopShowColumn() const {592  const uint32_t idx = ePropertyStopShowColumn;593  return GetPropertyAtIndexAs<lldb::StopShowColumn>(594      idx, static_cast<lldb::StopShowColumn>(595               g_debugger_properties[idx].default_uint_value));596}597 598llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {599  const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;600  return GetPropertyAtIndexAs<llvm::StringRef>(601      idx, g_debugger_properties[idx].default_cstr_value);602}603 604llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {605  const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;606  return GetPropertyAtIndexAs<llvm::StringRef>(607      idx, g_debugger_properties[idx].default_cstr_value);608}609 610llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const {611  const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix;612  return GetPropertyAtIndexAs<llvm::StringRef>(613      idx, g_debugger_properties[idx].default_cstr_value);614}615 616llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const {617  const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix;618  return GetPropertyAtIndexAs<llvm::StringRef>(619      idx, g_debugger_properties[idx].default_cstr_value);620}621 622uint64_t Debugger::GetStopSourceLineCount(bool before) const {623  const uint32_t idx =624      before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;625  return GetPropertyAtIndexAs<uint64_t>(626      idx, g_debugger_properties[idx].default_uint_value);627}628 629lldb::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {630  const uint32_t idx = ePropertyStopDisassemblyDisplay;631  return GetPropertyAtIndexAs<lldb::StopDisassemblyType>(632      idx, static_cast<lldb::StopDisassemblyType>(633               g_debugger_properties[idx].default_uint_value));634}635 636uint64_t Debugger::GetDisassemblyLineCount() const {637  const uint32_t idx = ePropertyStopDisassemblyCount;638  return GetPropertyAtIndexAs<uint64_t>(639      idx, g_debugger_properties[idx].default_uint_value);640}641 642bool Debugger::GetAutoOneLineSummaries() const {643  const uint32_t idx = ePropertyAutoOneLineSummaries;644  return GetPropertyAtIndexAs<bool>(645      idx, g_debugger_properties[idx].default_uint_value != 0);646}647 648bool Debugger::GetEscapeNonPrintables() const {649  const uint32_t idx = ePropertyEscapeNonPrintables;650  return GetPropertyAtIndexAs<bool>(651      idx, g_debugger_properties[idx].default_uint_value != 0);652}653 654bool Debugger::GetAutoIndent() const {655  const uint32_t idx = ePropertyAutoIndent;656  return GetPropertyAtIndexAs<bool>(657      idx, g_debugger_properties[idx].default_uint_value != 0);658}659 660bool Debugger::SetAutoIndent(bool b) {661  const uint32_t idx = ePropertyAutoIndent;662  return SetPropertyAtIndex(idx, b);663}664 665bool Debugger::GetPrintDecls() const {666  const uint32_t idx = ePropertyPrintDecls;667  return GetPropertyAtIndexAs<bool>(668      idx, g_debugger_properties[idx].default_uint_value != 0);669}670 671bool Debugger::SetPrintDecls(bool b) {672  const uint32_t idx = ePropertyPrintDecls;673  return SetPropertyAtIndex(idx, b);674}675 676uint64_t Debugger::GetTabSize() const {677  const uint32_t idx = ePropertyTabSize;678  return GetPropertyAtIndexAs<uint64_t>(679      idx, g_debugger_properties[idx].default_uint_value);680}681 682bool Debugger::SetTabSize(uint64_t tab_size) {683  const uint32_t idx = ePropertyTabSize;684  return SetPropertyAtIndex(idx, tab_size);685}686 687lldb::DWIMPrintVerbosity Debugger::GetDWIMPrintVerbosity() const {688  const uint32_t idx = ePropertyDWIMPrintVerbosity;689  return GetPropertyAtIndexAs<lldb::DWIMPrintVerbosity>(690      idx, static_cast<lldb::DWIMPrintVerbosity>(691               g_debugger_properties[idx].default_uint_value != 0));692}693 694bool Debugger::GetShowInlineDiagnostics() const {695  const uint32_t idx = ePropertyShowInlineDiagnostics;696  return GetPropertyAtIndexAs<bool>(697      idx, g_debugger_properties[idx].default_uint_value);698}699 700bool Debugger::SetShowInlineDiagnostics(bool b) {701  const uint32_t idx = ePropertyShowInlineDiagnostics;702  return SetPropertyAtIndex(idx, b);703}704 705#pragma mark Debugger706 707// const DebuggerPropertiesSP &708// Debugger::GetSettings() const709//{710//    return m_properties_sp;711//}712//713 714void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {715  assert(g_debugger_list_ptr == nullptr &&716         "Debugger::Initialize called more than once!");717  g_debugger_list_mutex_ptr = new std::recursive_mutex();718  g_debugger_list_ptr = new DebuggerList();719  g_thread_pool = new llvm::DefaultThreadPool(llvm::optimal_concurrency());720  g_load_plugin_callback = load_plugin_callback;721}722 723void Debugger::Terminate() {724  assert(g_debugger_list_ptr &&725         "Debugger::Terminate called without a matching Debugger::Initialize!");726 727  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {728    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);729    for (const auto &debugger : *g_debugger_list_ptr)730      debugger->HandleDestroyCallback();731  }732 733  if (g_thread_pool) {734    // The destructor will wait for all the threads to complete.735    delete g_thread_pool;736  }737 738  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {739    // Clear our global list of debugger objects740    {741      std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);742      for (const auto &debugger : *g_debugger_list_ptr)743        debugger->Clear();744      g_debugger_list_ptr->clear();745    }746  }747}748 749void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }750 751void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }752 753bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {754  if (g_load_plugin_callback) {755    llvm::sys::DynamicLibrary dynlib =756        g_load_plugin_callback(shared_from_this(), spec, error);757    if (dynlib.isValid()) {758      m_loaded_plugins.push_back(dynlib);759      return true;760    }761  } else {762    // The g_load_plugin_callback is registered in SBDebugger::Initialize() and763    // if the public API layer isn't available (code is linking against all of764    // the internal LLDB static libraries), then we can't load plugins765    error = Status::FromErrorString("Public API layer is not available");766  }767  return false;768}769 770static FileSystem::EnumerateDirectoryResult771LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,772                   llvm::StringRef path) {773  Status error;774 775  static constexpr llvm::StringLiteral g_dylibext(".dylib");776  static constexpr llvm::StringLiteral g_solibext(".so");777 778  if (!baton)779    return FileSystem::eEnumerateDirectoryResultQuit;780 781  Debugger *debugger = (Debugger *)baton;782 783  namespace fs = llvm::sys::fs;784  // If we have a regular file, a symbolic link or unknown file type, try and785  // process the file. We must handle unknown as sometimes the directory786  // enumeration might be enumerating a file system that doesn't have correct787  // file type information.788  if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||789      ft == fs::file_type::type_unknown) {790    FileSpec plugin_file_spec(path);791    FileSystem::Instance().Resolve(plugin_file_spec);792 793    if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&794        plugin_file_spec.GetFileNameExtension() != g_solibext) {795      return FileSystem::eEnumerateDirectoryResultNext;796    }797 798    Status plugin_load_error;799    debugger->LoadPlugin(plugin_file_spec, plugin_load_error);800 801    return FileSystem::eEnumerateDirectoryResultNext;802  } else if (ft == fs::file_type::directory_file ||803             ft == fs::file_type::symlink_file ||804             ft == fs::file_type::type_unknown) {805    // Try and recurse into anything that a directory or symbolic link. We must806    // also do this for unknown as sometimes the directory enumeration might be807    // enumerating a file system that doesn't have correct file type808    // information.809    return FileSystem::eEnumerateDirectoryResultEnter;810  }811 812  return FileSystem::eEnumerateDirectoryResultNext;813}814 815void Debugger::InstanceInitialize() {816  const bool find_directories = true;817  const bool find_files = true;818  const bool find_other = true;819  char dir_path[PATH_MAX];820  if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {821    if (FileSystem::Instance().Exists(dir_spec) &&822        dir_spec.GetPath(dir_path, sizeof(dir_path))) {823      FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,824                                                find_files, find_other,825                                                LoadPluginCallback, this);826    }827  }828 829  if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {830    if (FileSystem::Instance().Exists(dir_spec) &&831        dir_spec.GetPath(dir_path, sizeof(dir_path))) {832      FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,833                                                find_files, find_other,834                                                LoadPluginCallback, this);835    }836  }837 838  PluginManager::DebuggerInitialize(*this);839}840 841DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,842                                    void *baton) {843  lldb_private::telemetry::ScopedDispatcher<844      lldb_private::telemetry::DebuggerInfo>845      helper([](lldb_private::telemetry::DebuggerInfo *entry) {846        entry->lldb_version = lldb_private::GetVersion();847      });848  DebuggerSP debugger_sp(new Debugger(log_callback, baton));849  helper.SetDebugger(debugger_sp.get());850 851  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {852    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);853    g_debugger_list_ptr->push_back(debugger_sp);854  }855  debugger_sp->InstanceInitialize();856  return debugger_sp;857}858 859void Debugger::DispatchClientTelemetry(860    const lldb_private::StructuredDataImpl &entry) {861  lldb_private::telemetry::TelemetryManager::GetInstance()862      ->DispatchClientTelemetry(entry, this);863}864 865void Debugger::HandleDestroyCallback() {866  const lldb::user_id_t user_id = GetID();867  // Invoke and remove all the callbacks in an FIFO order. Callbacks which are868  // added during this loop will be appended, invoked and then removed last.869  // Callbacks which are removed during this loop will not be invoked.870  while (true) {871    DestroyCallbackInfo callback_info;872    {873      std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);874      if (m_destroy_callbacks.empty())875        break;876      // Pop the first item in the list877      callback_info = m_destroy_callbacks.front();878      m_destroy_callbacks.erase(m_destroy_callbacks.begin());879    }880    // Call the destroy callback with user id and baton881    callback_info.callback(user_id, callback_info.baton);882  }883}884 885void Debugger::Destroy(DebuggerSP &debugger_sp) {886  if (!debugger_sp)887    return;888 889  debugger_sp->HandleDestroyCallback();890  CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();891 892  if (cmd_interpreter.GetSaveSessionOnQuit()) {893    CommandReturnObject result(debugger_sp->GetUseColor());894    cmd_interpreter.SaveTranscript(result);895    if (result.Succeeded())896      (*debugger_sp->GetAsyncOutputStream())897          << result.GetOutputString() << '\n';898    else899      (*debugger_sp->GetAsyncErrorStream()) << result.GetErrorString() << '\n';900  }901 902  debugger_sp->Clear();903 904  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {905    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);906    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();907    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {908      if ((*pos).get() == debugger_sp.get()) {909        g_debugger_list_ptr->erase(pos);910        return;911      }912    }913  }914}915 916DebuggerSP917Debugger::FindDebuggerWithInstanceName(llvm::StringRef instance_name) {918  if (!g_debugger_list_ptr || !g_debugger_list_mutex_ptr)919    return DebuggerSP();920 921  std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);922  for (const DebuggerSP &debugger_sp : *g_debugger_list_ptr) {923    if (!debugger_sp)924      continue;925 926    if (llvm::StringRef(debugger_sp->GetInstanceName()) == instance_name)927      return debugger_sp;928  }929  return DebuggerSP();930}931 932TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {933  TargetSP target_sp;934  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {935    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);936    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();937    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {938      target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);939      if (target_sp)940        break;941    }942  }943  return target_sp;944}945 946TargetSP Debugger::FindTargetWithProcess(Process *process) {947  TargetSP target_sp;948  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {949    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);950    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();951    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {952      target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);953      if (target_sp)954        break;955    }956  }957  return target_sp;958}959 960llvm::StringRef Debugger::GetStaticBroadcasterClass() {961  static constexpr llvm::StringLiteral class_name("lldb.debugger");962  return class_name;963}964 965Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)966    : UserID(g_unique_id++),967      Properties(std::make_shared<OptionValueProperties>()),968      m_input_file_sp(std::make_shared<NativeFile>(969          stdin, File::eOpenOptionReadOnly, NativeFile::Unowned)),970      m_output_stream_sp(std::make_shared<LockableStreamFile>(971          stdout, NativeFile::Unowned, m_output_mutex)),972      m_error_stream_sp(std::make_shared<LockableStreamFile>(973          stderr, NativeFile::Unowned, m_output_mutex)),974      m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),975      m_terminal_state(), m_target_list(*this), m_platform_list(),976      m_listener_sp(Listener::MakeListener("lldb.Debugger")),977      m_source_manager_up(), m_source_file_cache(),978      m_command_interpreter_up(979          std::make_unique<CommandInterpreter>(*this, false)),980      m_io_handler_stack(),981      m_instance_name(llvm::formatv("debugger_{0}", GetID()).str()),982      m_loaded_plugins(), m_event_handler_thread(), m_io_handler_thread(),983      m_sync_broadcaster(nullptr, "lldb.debugger.sync"),984      m_broadcaster(m_broadcaster_manager_sp,985                    GetStaticBroadcasterClass().str()),986      m_forward_listener_sp(), m_clear_once() {987  // Initialize the debugger properties as early as possible as other parts of988  // LLDB will start querying them during construction.989  m_collection_sp->Initialize(g_debugger_properties);990  m_collection_sp->AppendProperty(991      "target", "Settings specify to debugging targets.", true,992      Target::GetGlobalProperties().GetValueProperties());993  m_collection_sp->AppendProperty(994      "platform", "Platform settings.", true,995      Platform::GetGlobalPlatformProperties().GetValueProperties());996  m_collection_sp->AppendProperty(997      "symbols", "Symbol lookup and cache settings.", true,998      ModuleList::GetGlobalModuleListProperties().GetValueProperties());999  m_collection_sp->AppendProperty(1000      LanguageProperties::GetSettingName(), "Language settings.", true,1001      Language::GetGlobalLanguageProperties().GetValueProperties());1002  if (m_command_interpreter_up) {1003    m_collection_sp->AppendProperty(1004        "interpreter",1005        "Settings specify to the debugger's command interpreter.", true,1006        m_command_interpreter_up->GetValueProperties());1007  }1008  if (log_callback)1009    m_callback_handler_sp =1010        std::make_shared<CallbackLogHandler>(log_callback, baton);1011  m_command_interpreter_up->Initialize();1012  // Always add our default platform to the platform list1013  PlatformSP default_platform_sp(Platform::GetHostPlatform());1014  assert(default_platform_sp);1015  m_platform_list.Append(default_platform_sp, true);1016 1017  // Create the dummy target.1018  {1019    ArchSpec arch(Target::GetDefaultArchitecture());1020    if (!arch.IsValid())1021      arch = HostInfo::GetArchitecture();1022    assert(arch.IsValid() && "No valid default or host archspec");1023    const bool is_dummy_target = true;1024    m_dummy_target_sp.reset(1025        new Target(*this, arch, default_platform_sp, is_dummy_target));1026  }1027  assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?");1028 1029  OptionValueUInt64 *term_width =1030      m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(1031          ePropertyTerminalWidth);1032  term_width->SetMinimumValue(10);1033 1034  OptionValueUInt64 *term_height =1035      m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(1036          ePropertyTerminalHeight);1037  term_height->SetMinimumValue(10);1038 1039  // Turn off use-color if this is a dumb terminal.1040  const char *term = getenv("TERM");1041  auto disable_color = [&]() {1042    SetUseColor(false);1043    SetSeparator("| ");1044  };1045 1046  if (term && !strcmp(term, "dumb"))1047    disable_color();1048  // Turn off use-color if we don't write to a terminal with color support.1049  if (!GetOutputFileSP()->GetIsTerminalWithColors())1050    disable_color();1051 1052  if (Diagnostics::Enabled()) {1053    m_diagnostics_callback_id = Diagnostics::Instance().AddCallback(1054        [this](const FileSpec &dir) -> llvm::Error {1055          for (auto &entry : m_stream_handlers) {1056            llvm::StringRef log_path = entry.first();1057            llvm::StringRef file_name = llvm::sys::path::filename(log_path);1058            FileSpec destination = dir.CopyByAppendingPathComponent(file_name);1059            std::error_code ec =1060                llvm::sys::fs::copy_file(log_path, destination.GetPath());1061            if (ec)1062              return llvm::errorCodeToError(ec);1063          }1064          return llvm::Error::success();1065        });1066  }1067 1068#if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)1069  // Enabling use of ANSI color codes because LLDB is using them to highlight1070  // text.1071  llvm::sys::Process::UseANSIEscapeCodes(true);1072#endif1073}1074 1075Debugger::~Debugger() { Clear(); }1076 1077void Debugger::Clear() {1078  // Make sure we call this function only once. With the C++ global destructor1079  // chain having a list of debuggers and with code that can be running on1080  // other threads, we need to ensure this doesn't happen multiple times.1081  //1082  // The following functions call Debugger::Clear():1083  //     Debugger::~Debugger();1084  //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);1085  //     static void Debugger::Terminate();1086  llvm::call_once(m_clear_once, [this]() {1087    telemetry::ScopedDispatcher<telemetry::DebuggerInfo> helper(1088        [this](lldb_private::telemetry::DebuggerInfo *info) {1089          assert(this == info->debugger);1090          (void)this;1091          info->is_exit_entry = true;1092        },1093        this);1094    ClearIOHandlers();1095    StopIOHandlerThread();1096    StopEventHandlerThread();1097    m_listener_sp->Clear();1098    for (TargetSP target_sp : m_target_list.Targets()) {1099      if (target_sp) {1100        if (ProcessSP process_sp = target_sp->GetProcessSP())1101          process_sp->Finalize(false /* not destructing */);1102        target_sp->Destroy();1103      }1104    }1105    m_broadcaster_manager_sp->Clear();1106 1107    // Close the input file _before_ we close the input read communications1108    // class as it does NOT own the input file, our m_input_file does.1109    m_terminal_state.Clear();1110    GetInputFile().Close();1111 1112    m_command_interpreter_up->Clear();1113 1114    if (Diagnostics::Enabled())1115      Diagnostics::Instance().RemoveCallback(m_diagnostics_callback_id);1116  });1117}1118 1119bool Debugger::GetAsyncExecution() {1120  return !m_command_interpreter_up->GetSynchronous();1121}1122 1123void Debugger::SetAsyncExecution(bool async_execution) {1124  m_command_interpreter_up->SetSynchronous(!async_execution);1125}1126 1127static inline int OpenPipe(int fds[2], std::size_t size) {1128#ifdef _WIN321129  return _pipe(fds, size, O_BINARY);1130#else1131  (void)size;1132  return pipe(fds);1133#endif1134}1135 1136Status Debugger::SetInputString(const char *data) {1137  Status result;1138  enum PIPES { READ, WRITE }; // Indexes for the read and write fds1139  int fds[2] = {-1, -1};1140 1141  if (data == nullptr) {1142    result = Status::FromErrorString("String data is null");1143    return result;1144  }1145 1146  size_t size = strlen(data);1147  if (size == 0) {1148    result = Status::FromErrorString("String data is empty");1149    return result;1150  }1151 1152  if (OpenPipe(fds, size) != 0) {1153    result = Status::FromErrorString(1154        "can't create pipe file descriptors for LLDB commands");1155    return result;1156  }1157 1158  int r = write(fds[WRITE], data, size);1159  (void)r;1160  // Close the write end of the pipe, so that the command interpreter will exit1161  // when it consumes all the data.1162  llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);1163 1164  // Open the read file descriptor as a FILE * that we can return as an input1165  // handle.1166  FILE *commands_file = fdopen(fds[READ], "rb");1167  if (commands_file == nullptr) {1168    result = Status::FromErrorStringWithFormat(1169        "fdopen(%i, \"rb\") failed (errno = %i) "1170        "when trying to open LLDB commands pipe",1171        fds[READ], errno);1172    llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);1173    return result;1174  }1175 1176  SetInputFile((FileSP)std::make_shared<NativeFile>(1177      commands_file, File::eOpenOptionReadOnly, true));1178  return result;1179}1180 1181void Debugger::SetInputFile(FileSP file_sp) {1182  assert(file_sp && file_sp->IsValid());1183  m_input_file_sp = std::move(file_sp);1184  // Save away the terminal state if that is relevant, so that we can restore1185  // it in RestoreInputState.1186  SaveInputTerminalState();1187}1188 1189void Debugger::SetOutputFile(FileSP file_sp) {1190  assert(file_sp && file_sp->IsValid());1191  m_output_stream_sp =1192      std::make_shared<LockableStreamFile>(file_sp, m_output_mutex);1193}1194 1195void Debugger::SetErrorFile(FileSP file_sp) {1196  assert(file_sp && file_sp->IsValid());1197  m_error_stream_sp =1198      std::make_shared<LockableStreamFile>(file_sp, m_output_mutex);1199}1200 1201void Debugger::SaveInputTerminalState() {1202  {1203    std::lock_guard<std::mutex> guard(m_statusline_mutex);1204    if (m_statusline)1205      m_statusline->Disable();1206  }1207  int fd = GetInputFile().GetDescriptor();1208  if (fd != File::kInvalidDescriptor)1209    m_terminal_state.Save(fd, true);1210}1211 1212void Debugger::RestoreInputTerminalState() {1213  m_terminal_state.Restore();1214  {1215    std::lock_guard<std::mutex> guard(m_statusline_mutex);1216    if (m_statusline)1217      m_statusline->Enable(GetSelectedExecutionContext());1218  }1219}1220 1221void Debugger::RedrawStatusline(1222    std::optional<ExecutionContextRef> exe_ctx_ref) {1223  std::lock_guard<std::mutex> guard(m_statusline_mutex);1224 1225  if (!m_statusline)1226    return;1227 1228  m_statusline->Redraw(exe_ctx_ref);1229}1230 1231ExecutionContext Debugger::GetSelectedExecutionContext() {1232  bool adopt_selected = true;1233  ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected);1234  return ExecutionContext(exe_ctx_ref);1235}1236 1237ExecutionContextRef Debugger::GetSelectedExecutionContextRef() {1238  if (TargetSP selected_target_sp = GetSelectedTarget())1239    return ExecutionContextRef(selected_target_sp.get(),1240                               /*adopt_selected=*/true);1241  return ExecutionContextRef(m_dummy_target_sp.get(), /*adopt_selected=*/false);1242}1243 1244void Debugger::DispatchInputInterrupt() {1245  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());1246  IOHandlerSP reader_sp(m_io_handler_stack.Top());1247  if (reader_sp)1248    reader_sp->Interrupt();1249}1250 1251void Debugger::DispatchInputEndOfFile() {1252  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());1253  IOHandlerSP reader_sp(m_io_handler_stack.Top());1254  if (reader_sp)1255    reader_sp->GotEOF();1256}1257 1258void Debugger::ClearIOHandlers() {1259  // The bottom input reader should be the main debugger input reader.  We do1260  // not want to close that one here.1261  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());1262  while (m_io_handler_stack.GetSize() > 1) {1263    IOHandlerSP reader_sp(m_io_handler_stack.Top());1264    if (reader_sp)1265      PopIOHandler(reader_sp);1266  }1267}1268 1269void Debugger::RunIOHandlers() {1270  IOHandlerSP reader_sp = m_io_handler_stack.Top();1271  while (true) {1272    if (!reader_sp)1273      break;1274 1275    reader_sp->Run();1276    {1277      std::lock_guard<std::recursive_mutex> guard(1278          m_io_handler_synchronous_mutex);1279 1280      // Remove all input readers that are done from the top of the stack1281      while (true) {1282        IOHandlerSP top_reader_sp = m_io_handler_stack.Top();1283        if (top_reader_sp && top_reader_sp->GetIsDone())1284          PopIOHandler(top_reader_sp);1285        else1286          break;1287      }1288      reader_sp = m_io_handler_stack.Top();1289    }1290  }1291  ClearIOHandlers();1292}1293 1294void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) {1295  std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex);1296 1297  PushIOHandler(reader_sp);1298  IOHandlerSP top_reader_sp = reader_sp;1299 1300  while (top_reader_sp) {1301    top_reader_sp->Run();1302 1303    // Don't unwind past the starting point.1304    if (top_reader_sp.get() == reader_sp.get()) {1305      if (PopIOHandler(reader_sp))1306        break;1307    }1308 1309    // If we pushed new IO handlers, pop them if they're done or restart the1310    // loop to run them if they're not.1311    while (true) {1312      top_reader_sp = m_io_handler_stack.Top();1313      if (top_reader_sp && top_reader_sp->GetIsDone()) {1314        PopIOHandler(top_reader_sp);1315        // Don't unwind past the starting point.1316        if (top_reader_sp.get() == reader_sp.get())1317          return;1318      } else {1319        break;1320      }1321    }1322  }1323}1324 1325bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {1326  return m_io_handler_stack.IsTop(reader_sp);1327}1328 1329bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,1330                                      IOHandler::Type second_top_type) {1331  return m_io_handler_stack.CheckTopIOHandlerTypes(top_type, second_top_type);1332}1333 1334void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {1335  bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout);1336  if (!printed) {1337    LockableStreamFileSP stream_sp =1338        is_stdout ? m_output_stream_sp : m_error_stream_sp;1339    LockedStreamFile locked_stream = stream_sp->Lock();1340    locked_stream.Write(s, len);1341  }1342}1343 1344llvm::StringRef Debugger::GetTopIOHandlerControlSequence(char ch) {1345  return m_io_handler_stack.GetTopIOHandlerControlSequence(ch);1346}1347 1348const char *Debugger::GetIOHandlerCommandPrefix() {1349  return m_io_handler_stack.GetTopIOHandlerCommandPrefix();1350}1351 1352const char *Debugger::GetIOHandlerHelpPrologue() {1353  return m_io_handler_stack.GetTopIOHandlerHelpPrologue();1354}1355 1356bool Debugger::RemoveIOHandler(const IOHandlerSP &reader_sp) {1357  return PopIOHandler(reader_sp);1358}1359 1360void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp,1361                                 bool cancel_top_handler) {1362  PushIOHandler(reader_sp, cancel_top_handler);1363}1364 1365void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in,1366                                               LockableStreamFileSP &out,1367                                               LockableStreamFileSP &err) {1368  // Before an IOHandler runs, it must have in/out/err streams. This function1369  // is called when one ore more of the streams are nullptr. We use the top1370  // input reader's in/out/err streams, or fall back to the debugger file1371  // handles, or we fall back onto stdin/stdout/stderr as a last resort.1372 1373  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());1374  IOHandlerSP top_reader_sp(m_io_handler_stack.Top());1375  // If no STDIN has been set, then set it appropriately1376  if (!in || !in->IsValid()) {1377    if (top_reader_sp)1378      in = top_reader_sp->GetInputFileSP();1379    else1380      in = GetInputFileSP();1381    // If there is nothing, use stdin1382    if (!in)1383      in = std::make_shared<NativeFile>(stdin, File::eOpenOptionReadOnly,1384                                        NativeFile::Unowned);1385  }1386  // If no STDOUT has been set, then set it appropriately1387  if (!out || !out->GetUnlockedFile().IsValid()) {1388    if (top_reader_sp)1389      out = top_reader_sp->GetOutputStreamFileSP();1390    else1391      out = GetOutputStreamSP();1392    // If there is nothing, use stdout1393    if (!out)1394      out = std::make_shared<LockableStreamFile>(stdout, NativeFile::Unowned,1395                                                 m_output_mutex);1396  }1397  // If no STDERR has been set, then set it appropriately1398  if (!err || !err->GetUnlockedFile().IsValid()) {1399    if (top_reader_sp)1400      err = top_reader_sp->GetErrorStreamFileSP();1401    else1402      err = GetErrorStreamSP();1403    // If there is nothing, use stderr1404    if (!err)1405      err = std::make_shared<LockableStreamFile>(stderr, NativeFile::Unowned,1406                                                 m_output_mutex);1407  }1408}1409 1410void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,1411                             bool cancel_top_handler) {1412  if (!reader_sp)1413    return;1414 1415  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());1416 1417  // Get the current top input reader...1418  IOHandlerSP top_reader_sp(m_io_handler_stack.Top());1419 1420  // Don't push the same IO handler twice...1421  if (reader_sp == top_reader_sp)1422    return;1423 1424  // Push our new input reader1425  m_io_handler_stack.Push(reader_sp);1426  reader_sp->Activate();1427 1428  // Interrupt the top input reader to it will exit its Run() function and let1429  // this new input reader take over1430  if (top_reader_sp) {1431    top_reader_sp->Deactivate();1432    if (cancel_top_handler)1433      top_reader_sp->Cancel();1434  }1435}1436 1437bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {1438  if (!pop_reader_sp)1439    return false;1440 1441  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());1442 1443  // The reader on the stop of the stack is done, so let the next read on the1444  // stack refresh its prompt and if there is one...1445  if (m_io_handler_stack.IsEmpty())1446    return false;1447 1448  IOHandlerSP reader_sp(m_io_handler_stack.Top());1449 1450  if (pop_reader_sp != reader_sp)1451    return false;1452 1453  reader_sp->Deactivate();1454  reader_sp->Cancel();1455  m_io_handler_stack.Pop();1456 1457  reader_sp = m_io_handler_stack.Top();1458  if (reader_sp)1459    reader_sp->Activate();1460 1461  return true;1462}1463 1464void Debugger::RefreshIOHandler() {1465  std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());1466  IOHandlerSP reader_sp(m_io_handler_stack.Top());1467  if (reader_sp)1468    reader_sp->Refresh();1469}1470 1471StreamUP Debugger::GetAsyncOutputStream() {1472  return std::make_unique<StreamAsynchronousIO>(*this,1473                                                StreamAsynchronousIO::STDOUT);1474}1475 1476StreamUP Debugger::GetAsyncErrorStream() {1477  return std::make_unique<StreamAsynchronousIO>(*this,1478                                                StreamAsynchronousIO::STDERR);1479}1480 1481void Debugger::RequestInterrupt() {1482  std::lock_guard<std::mutex> guard(m_interrupt_mutex);1483  m_interrupt_requested++;1484}1485 1486void Debugger::CancelInterruptRequest() {1487  std::lock_guard<std::mutex> guard(m_interrupt_mutex);1488  if (m_interrupt_requested > 0)1489    m_interrupt_requested--;1490}1491 1492bool Debugger::InterruptRequested() {1493  // This is the one we should call internally.  This will return true either1494  // if there's a debugger interrupt and we aren't on the IOHandler thread,1495  // or if we are on the IOHandler thread and there's a CommandInterpreter1496  // interrupt.1497  if (!IsIOHandlerThreadCurrentThread()) {1498    std::lock_guard<std::mutex> guard(m_interrupt_mutex);1499    return m_interrupt_requested != 0;1500  }1501  return GetCommandInterpreter().WasInterrupted();1502}1503 1504Debugger::InterruptionReport::InterruptionReport(1505    std::string function_name, const llvm::formatv_object_base &payload)1506    : m_function_name(std::move(function_name)),1507      m_interrupt_time(std::chrono::system_clock::now()),1508      m_thread_id(llvm::get_threadid()) {1509  llvm::raw_string_ostream desc(m_description);1510  desc << payload << "\n";1511}1512 1513void Debugger::ReportInterruption(const InterruptionReport &report) {1514  // For now, just log the description:1515  Log *log = GetLog(LLDBLog::Host);1516  LLDB_LOG(log, "Interruption: {0}", report.m_description);1517}1518 1519Debugger::DebuggerList Debugger::DebuggersRequestingInterruption() {1520  DebuggerList result;1521  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {1522    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);1523    for (auto debugger_sp : *g_debugger_list_ptr) {1524      if (debugger_sp->InterruptRequested())1525        result.push_back(debugger_sp);1526    }1527  }1528  return result;1529}1530 1531size_t Debugger::GetNumDebuggers() {1532  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {1533    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);1534    return g_debugger_list_ptr->size();1535  }1536  return 0;1537}1538 1539lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {1540  DebuggerSP debugger_sp;1541 1542  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {1543    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);1544    if (index < g_debugger_list_ptr->size())1545      debugger_sp = g_debugger_list_ptr->at(index);1546  }1547 1548  return debugger_sp;1549}1550 1551DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {1552  DebuggerSP debugger_sp;1553 1554  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {1555    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);1556    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();1557    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {1558      if ((*pos)->GetID() == id) {1559        debugger_sp = *pos;1560        break;1561      }1562    }1563  }1564  return debugger_sp;1565}1566 1567bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,1568                                         const SymbolContext *sc,1569                                         const SymbolContext *prev_sc,1570                                         const ExecutionContext *exe_ctx,1571                                         const Address *addr, Stream &s) {1572  FormatEntity::Entry format_entry;1573 1574  if (format == nullptr) {1575    if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) {1576      format_entry =1577          exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();1578      format = &format_entry;1579    }1580    if (format == nullptr) {1581      FormatEntity::Parse("${addr}: ", format_entry);1582      format = &format_entry;1583    }1584  }1585  bool function_changed = false;1586  bool initial_function = false;1587  if (prev_sc && (prev_sc->function || prev_sc->symbol)) {1588    if (sc && (sc->function || sc->symbol)) {1589      if (prev_sc->symbol && sc->symbol) {1590        if (!sc->symbol->Compare(prev_sc->symbol->GetName(),1591                                 prev_sc->symbol->GetType())) {1592          function_changed = true;1593        }1594      } else if (prev_sc->function && sc->function) {1595        if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {1596          function_changed = true;1597        }1598      }1599    }1600  }1601  // The first context on a list of instructions will have a prev_sc that has1602  // no Function or Symbol -- if SymbolContext had an IsValid() method, it1603  // would return false.  But we do get a prev_sc pointer.1604  if ((sc && (sc->function || sc->symbol)) && prev_sc &&1605      (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {1606    initial_function = true;1607  }1608  return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,1609                              function_changed, initial_function);1610}1611 1612void Debugger::AssertCallback(llvm::StringRef message,1613                              llvm::StringRef backtrace,1614                              llvm::StringRef prompt) {1615  Debugger::ReportError(llvm::formatv("{0}\n{1}{2}\n{3}", message, backtrace,1616                                      GetVersion(), prompt)1617                            .str());1618}1619 1620void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,1621                                  void *baton) {1622  // For simplicity's sake, I am not going to deal with how to close down any1623  // open logging streams, I just redirect everything from here on out to the1624  // callback.1625  m_callback_handler_sp =1626      std::make_shared<CallbackLogHandler>(log_callback, baton);1627}1628 1629void Debugger::SetDestroyCallback(1630    lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) {1631  std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);1632  m_destroy_callbacks.clear();1633  const lldb::callback_token_t token = m_destroy_callback_next_token++;1634  m_destroy_callbacks.emplace_back(token, destroy_callback, baton);1635}1636 1637lldb::callback_token_t Debugger::AddDestroyCallback(1638    lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) {1639  std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);1640  const lldb::callback_token_t token = m_destroy_callback_next_token++;1641  m_destroy_callbacks.emplace_back(token, destroy_callback, baton);1642  return token;1643}1644 1645bool Debugger::RemoveDestroyCallback(lldb::callback_token_t token) {1646  std::lock_guard<std::mutex> guard(m_destroy_callback_mutex);1647  for (auto it = m_destroy_callbacks.begin(); it != m_destroy_callbacks.end();1648       ++it) {1649    if (it->token == token) {1650      m_destroy_callbacks.erase(it);1651      return true;1652    }1653  }1654  return false;1655}1656 1657static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,1658                                  std::string title, std::string details,1659                                  uint64_t completed, uint64_t total,1660                                  bool is_debugger_specific,1661                                  uint32_t progress_broadcast_bit) {1662  // Only deliver progress events if we have any progress listeners.1663  if (!debugger.GetBroadcaster().EventTypeHasListeners(progress_broadcast_bit))1664    return;1665 1666  EventSP event_sp(new Event(1667      progress_broadcast_bit,1668      new ProgressEventData(progress_id, std::move(title), std::move(details),1669                            completed, total, is_debugger_specific)));1670  debugger.GetBroadcaster().BroadcastEvent(event_sp);1671}1672 1673void Debugger::ReportProgress(uint64_t progress_id, std::string title,1674                              std::string details, uint64_t completed,1675                              uint64_t total,1676                              std::optional<lldb::user_id_t> debugger_id,1677                              uint32_t progress_broadcast_bit) {1678  // Check if this progress is for a specific debugger.1679  if (debugger_id) {1680    // It is debugger specific, grab it and deliver the event if the debugger1681    // still exists.1682    DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);1683    if (debugger_sp)1684      PrivateReportProgress(*debugger_sp, progress_id, std::move(title),1685                            std::move(details), completed, total,1686                            /*is_debugger_specific*/ true,1687                            progress_broadcast_bit);1688    return;1689  }1690  // The progress event is not debugger specific, iterate over all debuggers1691  // and deliver a progress event to each one.1692  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {1693    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);1694    DebuggerList::iterator pos, end = g_debugger_list_ptr->end();1695    for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)1696      PrivateReportProgress(*(*pos), progress_id, title, details, completed,1697                            total, /*is_debugger_specific*/ false,1698                            progress_broadcast_bit);1699  }1700}1701 1702static void PrivateReportDiagnostic(Debugger &debugger, Severity severity,1703                                    std::string message,1704                                    bool debugger_specific) {1705  uint32_t event_type = 0;1706  switch (severity) {1707  case eSeverityInfo:1708    assert(false && "eSeverityInfo should not be broadcast");1709    return;1710  case eSeverityWarning:1711    event_type = lldb::eBroadcastBitWarning;1712    break;1713  case eSeverityError:1714    event_type = lldb::eBroadcastBitError;1715    break;1716  }1717 1718  Broadcaster &broadcaster = debugger.GetBroadcaster();1719  if (!broadcaster.EventTypeHasListeners(event_type)) {1720    // Diagnostics are too important to drop. If nobody is listening, print the1721    // diagnostic directly to the debugger's error stream.1722    DiagnosticEventData event_data(severity, std::move(message),1723                                   debugger_specific);1724    event_data.Dump(debugger.GetAsyncErrorStream().get());1725    return;1726  }1727  EventSP event_sp = std::make_shared<Event>(1728      event_type,1729      new DiagnosticEventData(severity, std::move(message), debugger_specific));1730  broadcaster.BroadcastEvent(event_sp);1731}1732 1733void Debugger::ReportDiagnosticImpl(Severity severity, std::string message,1734                                    std::optional<lldb::user_id_t> debugger_id,1735                                    std::once_flag *once) {1736  auto ReportDiagnosticLambda = [&]() {1737    // Always log diagnostics to the system log.1738    Host::SystemLog(severity, message);1739 1740    // The diagnostic subsystem is optional but we still want to broadcast1741    // events when it's disabled.1742    if (Diagnostics::Enabled())1743      Diagnostics::Instance().Report(message);1744 1745    // We don't broadcast info events.1746    if (severity == lldb::eSeverityInfo)1747      return;1748 1749    // Check if this diagnostic is for a specific debugger.1750    if (debugger_id) {1751      // It is debugger specific, grab it and deliver the event if the debugger1752      // still exists.1753      DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);1754      if (debugger_sp)1755        PrivateReportDiagnostic(*debugger_sp, severity, std::move(message),1756                                true);1757      return;1758    }1759    // The diagnostic event is not debugger specific, iterate over all debuggers1760    // and deliver a diagnostic event to each one.1761    if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {1762      std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);1763      for (const auto &debugger : *g_debugger_list_ptr)1764        PrivateReportDiagnostic(*debugger, severity, message, false);1765    }1766  };1767 1768  if (once)1769    std::call_once(*once, ReportDiagnosticLambda);1770  else1771    ReportDiagnosticLambda();1772}1773 1774void Debugger::ReportWarning(std::string message,1775                             std::optional<lldb::user_id_t> debugger_id,1776                             std::once_flag *once) {1777  ReportDiagnosticImpl(eSeverityWarning, std::move(message), debugger_id, once);1778}1779 1780void Debugger::ReportError(std::string message,1781                           std::optional<lldb::user_id_t> debugger_id,1782                           std::once_flag *once) {1783  ReportDiagnosticImpl(eSeverityError, std::move(message), debugger_id, once);1784}1785 1786void Debugger::ReportInfo(std::string message,1787                          std::optional<lldb::user_id_t> debugger_id,1788                          std::once_flag *once) {1789  ReportDiagnosticImpl(eSeverityInfo, std::move(message), debugger_id, once);1790}1791 1792void Debugger::ReportSymbolChange(const ModuleSpec &module_spec) {1793  if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {1794    std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);1795    for (DebuggerSP debugger_sp : *g_debugger_list_ptr) {1796      EventSP event_sp = std::make_shared<Event>(1797          lldb::eBroadcastSymbolChange,1798          new SymbolChangeEventData(debugger_sp, module_spec));1799      debugger_sp->GetBroadcaster().BroadcastEvent(event_sp);1800    }1801  }1802}1803 1804static std::shared_ptr<LogHandler>1805CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close,1806                 size_t buffer_size) {1807  switch (log_handler_kind) {1808  case eLogHandlerStream:1809    return std::make_shared<StreamLogHandler>(fd, should_close, buffer_size);1810  case eLogHandlerCircular:1811    return std::make_shared<RotatingLogHandler>(buffer_size);1812  case eLogHandlerSystem:1813    return std::make_shared<SystemLogHandler>();1814  case eLogHandlerCallback:1815    return {};1816  }1817  return {};1818}1819 1820bool Debugger::EnableLog(llvm::StringRef channel,1821                         llvm::ArrayRef<const char *> categories,1822                         llvm::StringRef log_file, uint32_t log_options,1823                         size_t buffer_size, LogHandlerKind log_handler_kind,1824                         llvm::raw_ostream &error_stream) {1825 1826  std::shared_ptr<LogHandler> log_handler_sp;1827  if (m_callback_handler_sp) {1828    log_handler_sp = m_callback_handler_sp;1829    // For now when using the callback mode you always get thread & timestamp.1830    log_options |=1831        LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;1832  } else if (log_file.empty()) {1833    log_handler_sp =1834        CreateLogHandler(log_handler_kind, GetOutputFileSP()->GetDescriptor(),1835                         /*should_close=*/false, buffer_size);1836  } else {1837    auto pos = m_stream_handlers.find(log_file);1838    if (pos != m_stream_handlers.end())1839      log_handler_sp = pos->second.lock();1840    if (!log_handler_sp) {1841      File::OpenOptions flags =1842          File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;1843      if (log_options & LLDB_LOG_OPTION_APPEND)1844        flags |= File::eOpenOptionAppend;1845      else1846        flags |= File::eOpenOptionTruncate;1847      llvm::Expected<FileUP> file = FileSystem::Instance().Open(1848          FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false);1849      if (!file) {1850        error_stream << "Unable to open log file '" << log_file1851                     << "': " << llvm::toString(file.takeError()) << "\n";1852        return false;1853      }1854 1855      log_handler_sp =1856          CreateLogHandler(log_handler_kind, (*file)->GetDescriptor(),1857                           /*should_close=*/true, buffer_size);1858      m_stream_handlers[log_file] = log_handler_sp;1859    }1860  }1861  assert(log_handler_sp);1862 1863  if (log_options == 0)1864    log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME;1865 1866  return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,1867                               error_stream);1868}1869 1870ScriptInterpreter *1871Debugger::GetScriptInterpreter(bool can_create,1872                               std::optional<lldb::ScriptLanguage> language) {1873  std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex);1874  lldb::ScriptLanguage script_language =1875      language ? *language : GetScriptLanguage();1876 1877  if (!m_script_interpreters[script_language]) {1878    if (!can_create)1879      return nullptr;1880    m_script_interpreters[script_language] =1881        PluginManager::GetScriptInterpreterForLanguage(script_language, *this);1882  }1883 1884  return m_script_interpreters[script_language].get();1885}1886 1887SourceManager &Debugger::GetSourceManager() {1888  if (!m_source_manager_up)1889    m_source_manager_up = std::make_unique<SourceManager>(shared_from_this());1890  return *m_source_manager_up;1891}1892 1893// This function handles events that were broadcast by the process.1894void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {1895  using namespace lldb;1896  const uint32_t event_type =1897      Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(1898          event_sp);1899 1900  //    if (event_type & eBreakpointEventTypeAdded1901  //        || event_type & eBreakpointEventTypeRemoved1902  //        || event_type & eBreakpointEventTypeEnabled1903  //        || event_type & eBreakpointEventTypeDisabled1904  //        || event_type & eBreakpointEventTypeCommandChanged1905  //        || event_type & eBreakpointEventTypeConditionChanged1906  //        || event_type & eBreakpointEventTypeIgnoreChanged1907  //        || event_type & eBreakpointEventTypeLocationsResolved)1908  //    {1909  //        // Don't do anything about these events, since the breakpoint1910  //        commands already echo these actions.1911  //    }1912  //1913  if (event_type & eBreakpointEventTypeLocationsAdded) {1914    uint32_t num_new_locations =1915        Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(1916            event_sp);1917    if (num_new_locations > 0) {1918      BreakpointSP breakpoint =1919          Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);1920      if (StreamUP output_up = GetAsyncOutputStream()) {1921        output_up->Printf("%d location%s added to breakpoint %d\n",1922                          num_new_locations, num_new_locations == 1 ? "" : "s",1923                          breakpoint->GetID());1924        output_up->Flush();1925      }1926    }1927  }1928  //    else if (event_type & eBreakpointEventTypeLocationsRemoved)1929  //    {1930  //        // These locations just get disabled, not sure it is worth spamming1931  //        folks about this on the command line.1932  //    }1933  //    else if (event_type & eBreakpointEventTypeLocationsResolved)1934  //    {1935  //        // This might be an interesting thing to note, but I'm going to1936  //        leave it quiet for now, it just looked noisy.1937  //    }1938}1939 1940void Debugger::FlushProcessOutput(Process &process, bool flush_stdout,1941                                  bool flush_stderr) {1942  const auto &flush = [&](Stream &stream,1943                          size_t (Process::*get)(char *, size_t, Status &)) {1944    Status error;1945    size_t len;1946    char buffer[1024];1947    while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0)1948      stream.Write(buffer, len);1949    stream.Flush();1950  };1951 1952  std::lock_guard<std::mutex> guard(m_output_flush_mutex);1953  if (flush_stdout)1954    flush(*GetAsyncOutputStream(), &Process::GetSTDOUT);1955  if (flush_stderr)1956    flush(*GetAsyncErrorStream(), &Process::GetSTDERR);1957}1958 1959// This function handles events that were broadcast by the process.1960ProcessSP Debugger::HandleProcessEvent(const EventSP &event_sp) {1961  const uint32_t event_type = event_sp->GetType();1962  ProcessSP process_sp =1963      (event_type == Process::eBroadcastBitStructuredData)1964          ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())1965          : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());1966 1967  StreamUP output_stream_up = GetAsyncOutputStream();1968  StreamUP error_stream_up = GetAsyncErrorStream();1969  const bool gui_enabled = IsForwardingEvents();1970 1971  if (!gui_enabled) {1972    bool pop_process_io_handler = false;1973    assert(process_sp);1974 1975    bool state_is_stopped = false;1976    const bool got_state_changed =1977        (event_type & Process::eBroadcastBitStateChanged) != 0;1978    const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;1979    const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;1980    const bool got_structured_data =1981        (event_type & Process::eBroadcastBitStructuredData) != 0;1982 1983    if (got_state_changed) {1984      StateType event_state =1985          Process::ProcessEventData::GetStateFromEvent(event_sp.get());1986      state_is_stopped = StateIsStoppedState(event_state, false);1987    }1988 1989    // Display running state changes first before any STDIO1990    if (got_state_changed && !state_is_stopped) {1991      // This is a public stop which we are going to announce to the user, so1992      // we should force the most relevant frame selection here.1993      Process::HandleProcessStateChangedEvent(event_sp, output_stream_up.get(),1994                                              SelectMostRelevantFrame,1995                                              pop_process_io_handler);1996    }1997 1998    // Now display STDOUT and STDERR1999    FlushProcessOutput(*process_sp, got_stdout || got_state_changed,2000                       got_stderr || got_state_changed);2001 2002    // Give structured data events an opportunity to display.2003    if (got_structured_data) {2004      StructuredDataPluginSP plugin_sp =2005          EventDataStructuredData::GetPluginFromEvent(event_sp.get());2006      if (plugin_sp) {2007        auto structured_data_sp =2008            EventDataStructuredData::GetObjectFromEvent(event_sp.get());2009        StreamString content_stream;2010        Status error =2011            plugin_sp->GetDescription(structured_data_sp, content_stream);2012        if (error.Success()) {2013          if (!content_stream.GetString().empty()) {2014            // Add newline.2015            content_stream.PutChar('\n');2016            content_stream.Flush();2017 2018            // Print it.2019            output_stream_up->PutCString(content_stream.GetString());2020          }2021        } else {2022          error_stream_up->Format("Failed to print structured "2023                                  "data with plugin {0}: {1}",2024                                  plugin_sp->GetPluginName(), error);2025        }2026      }2027    }2028 2029    // Now display any stopped state changes after any STDIO2030    if (got_state_changed && state_is_stopped) {2031      Process::HandleProcessStateChangedEvent(event_sp, output_stream_up.get(),2032                                              SelectMostRelevantFrame,2033                                              pop_process_io_handler);2034    }2035 2036    output_stream_up->Flush();2037    error_stream_up->Flush();2038 2039    if (pop_process_io_handler)2040      process_sp->PopProcessIOHandler();2041  }2042  return process_sp;2043}2044 2045ThreadSP Debugger::HandleThreadEvent(const EventSP &event_sp) {2046  // At present the only thread event we handle is the Frame Changed event, and2047  // all we do for that is just reprint the thread status for that thread.2048  const uint32_t event_type = event_sp->GetType();2049  const bool stop_format = true;2050  ThreadSP thread_sp;2051  if (event_type == Thread::eBroadcastBitStackChanged ||2052      event_type == Thread::eBroadcastBitThreadSelected) {2053    thread_sp = Thread::ThreadEventData::GetThreadFromEvent(event_sp.get());2054    if (thread_sp) {2055      thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format,2056                           /*show_hidden*/ true);2057    }2058  }2059  return thread_sp;2060}2061 2062bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }2063 2064void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {2065  m_forward_listener_sp = listener_sp;2066}2067 2068void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {2069  m_forward_listener_sp.reset();2070}2071 2072bool Debugger::IsEscapeCodeCapableTTY() {2073  if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {2074    File &file = stream_sp->GetUnlockedFile();2075    return file.GetIsInteractive() && file.GetIsRealTerminal() &&2076           file.GetIsTerminalWithColors();2077  }2078  return false;2079}2080 2081bool Debugger::StatuslineSupported() {2082// We have trouble with the contol codes on Windows, see2083// https://github.com/llvm/llvm-project/issues/134846.2084#ifndef _WIN322085  return GetShowStatusline() && IsEscapeCodeCapableTTY();2086#else2087  return false;2088#endif2089}2090 2091static bool RequiresFollowChildWorkaround(const Process &process) {2092  // FIXME: https://github.com/llvm/llvm-project/issues/1602162093  return process.GetFollowForkMode() == eFollowChild;2094}2095 2096lldb::thread_result_t Debugger::DefaultEventHandler() {2097  ListenerSP listener_sp(GetListener());2098  ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());2099  ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());2100  ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());2101  BroadcastEventSpec target_event_spec(broadcaster_class_target,2102                                       Target::eBroadcastBitBreakpointChanged);2103 2104  BroadcastEventSpec process_event_spec(2105      broadcaster_class_process,2106      Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |2107          Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);2108 2109  BroadcastEventSpec thread_event_spec(broadcaster_class_thread,2110                                       Thread::eBroadcastBitStackChanged |2111                                           Thread::eBroadcastBitThreadSelected);2112 2113  listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,2114                                          target_event_spec);2115  listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,2116                                          process_event_spec);2117  listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,2118                                          thread_event_spec);2119  listener_sp->StartListeningForEvents(2120      m_command_interpreter_up.get(),2121      CommandInterpreter::eBroadcastBitQuitCommandReceived |2122          CommandInterpreter::eBroadcastBitAsynchronousOutputData |2123          CommandInterpreter::eBroadcastBitAsynchronousErrorData);2124 2125  listener_sp->StartListeningForEvents(2126      &m_broadcaster, lldb::eBroadcastBitProgress | lldb::eBroadcastBitWarning |2127                          lldb::eBroadcastBitError |2128                          lldb::eBroadcastSymbolChange |2129                          lldb::eBroadcastBitExternalProgress);2130 2131  // Let the thread that spawned us know that we have started up and that we2132  // are now listening to all required events so no events get missed2133  m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);2134 2135  if (StatuslineSupported()) {2136    std::lock_guard<std::mutex> guard(m_statusline_mutex);2137    if (!m_statusline) {2138      m_statusline.emplace(*this);2139      m_statusline->Enable(GetSelectedExecutionContextRef());2140    }2141  }2142 2143  bool done = false;2144  while (!done) {2145    EventSP event_sp;2146    if (listener_sp->GetEvent(event_sp, std::nullopt)) {2147      std::optional<ExecutionContextRef> exe_ctx_ref = std::nullopt;2148      if (event_sp) {2149        Broadcaster *broadcaster = event_sp->GetBroadcaster();2150        if (broadcaster) {2151          uint32_t event_type = event_sp->GetType();2152          ConstString broadcaster_class(broadcaster->GetBroadcasterClass());2153          if (broadcaster_class == broadcaster_class_process) {2154            if (ProcessSP process_sp = HandleProcessEvent(event_sp))2155              if (!RequiresFollowChildWorkaround(*process_sp))2156                exe_ctx_ref = ExecutionContextRef(process_sp.get(),2157                                                  /*adopt_selected=*/true);2158          } else if (broadcaster_class == broadcaster_class_target) {2159            if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(2160                    event_sp.get())) {2161              HandleBreakpointEvent(event_sp);2162            }2163          } else if (broadcaster_class == broadcaster_class_thread) {2164            if (ThreadSP thread_sp = HandleThreadEvent(event_sp))2165              if (!RequiresFollowChildWorkaround(*thread_sp->GetProcess()))2166                exe_ctx_ref = ExecutionContextRef(thread_sp.get(),2167                                                  /*adopt_selected=*/true);2168          } else if (broadcaster == m_command_interpreter_up.get()) {2169            if (event_type &2170                CommandInterpreter::eBroadcastBitQuitCommandReceived) {2171              done = true;2172            } else if (event_type &2173                       CommandInterpreter::eBroadcastBitAsynchronousErrorData) {2174              const char *data = static_cast<const char *>(2175                  EventDataBytes::GetBytesFromEvent(event_sp.get()));2176              if (data && data[0]) {2177                StreamUP error_up = GetAsyncErrorStream();2178                error_up->PutCString(data);2179                error_up->Flush();2180              }2181            } else if (event_type & CommandInterpreter::2182                                        eBroadcastBitAsynchronousOutputData) {2183              const char *data = static_cast<const char *>(2184                  EventDataBytes::GetBytesFromEvent(event_sp.get()));2185              if (data && data[0]) {2186                StreamUP output_up = GetAsyncOutputStream();2187                output_up->PutCString(data);2188                output_up->Flush();2189              }2190            }2191          } else if (broadcaster == &m_broadcaster) {2192            if (event_type & lldb::eBroadcastBitProgress ||2193                event_type & lldb::eBroadcastBitExternalProgress)2194              HandleProgressEvent(event_sp);2195            else if (event_type & lldb::eBroadcastBitWarning)2196              HandleDiagnosticEvent(event_sp);2197            else if (event_type & lldb::eBroadcastBitError)2198              HandleDiagnosticEvent(event_sp);2199          }2200        }2201 2202        if (m_forward_listener_sp)2203          m_forward_listener_sp->AddEvent(event_sp);2204      }2205      RedrawStatusline(exe_ctx_ref);2206    }2207  }2208 2209  {2210    std::lock_guard<std::mutex> guard(m_statusline_mutex);2211    if (m_statusline)2212      m_statusline.reset();2213  }2214 2215  return {};2216}2217 2218bool Debugger::StartEventHandlerThread() {2219  if (!m_event_handler_thread.IsJoinable()) {2220    // We must synchronize with the DefaultEventHandler() thread to ensure it2221    // is up and running and listening to events before we return from this2222    // function. We do this by listening to events for the2223    // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster2224    ConstString full_name("lldb.debugger.event-handler");2225    ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));2226    listener_sp->StartListeningForEvents(&m_sync_broadcaster,2227                                         eBroadcastBitEventThreadIsListening);2228 2229    llvm::StringRef thread_name =2230        full_name.GetLength() < llvm::get_max_thread_name_length()2231            ? full_name.GetStringRef()2232            : "dbg.evt-handler";2233 2234    // Use larger 8MB stack for this thread2235    llvm::Expected<HostThread> event_handler_thread =2236        ThreadLauncher::LaunchThread(2237            thread_name, [this] { return DefaultEventHandler(); },2238            g_debugger_event_thread_stack_bytes);2239 2240    if (event_handler_thread) {2241      m_event_handler_thread = *event_handler_thread;2242    } else {2243      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), event_handler_thread.takeError(),2244                     "failed to launch host thread: {0}");2245    }2246 2247    // Make sure DefaultEventHandler() is running and listening to events2248    // before we return from this function. We are only listening for events of2249    // type eBroadcastBitEventThreadIsListening so we don't need to check the2250    // event, we just need to wait an infinite amount of time for it (nullptr2251    // timeout as the first parameter)2252    lldb::EventSP event_sp;2253    listener_sp->GetEvent(event_sp, std::nullopt);2254  }2255  return m_event_handler_thread.IsJoinable();2256}2257 2258void Debugger::StopEventHandlerThread() {2259  if (m_event_handler_thread.IsJoinable()) {2260    GetCommandInterpreter().BroadcastEvent(2261        CommandInterpreter::eBroadcastBitQuitCommandReceived);2262    m_event_handler_thread.Join(nullptr);2263  }2264}2265 2266lldb::thread_result_t Debugger::IOHandlerThread() {2267  RunIOHandlers();2268  StopEventHandlerThread();2269  return {};2270}2271 2272void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {2273  auto *data = ProgressEventData::GetEventDataFromEvent(event_sp.get());2274  if (!data)2275    return;2276 2277  // Make a local copy of the incoming progress report that we'll store.2278  ProgressReport progress_report{data->GetID(), data->GetCompleted(),2279                                 data->GetTotal(), data->GetMessage()};2280 2281  {2282    std::lock_guard<std::mutex> guard(m_progress_reports_mutex);2283 2284    // Do some bookkeeping regardless of whether we're going to display2285    // progress reports.2286    auto it = llvm::find_if(m_progress_reports, [&](const auto &report) {2287      return report.id == progress_report.id;2288    });2289    if (it != m_progress_reports.end()) {2290      const bool complete = data->GetCompleted() == data->GetTotal();2291      if (complete)2292        m_progress_reports.erase(it);2293      else2294        *it = progress_report;2295    } else {2296      m_progress_reports.push_back(progress_report);2297    }2298 2299    // Show progress using Operating System Command (OSC) sequences.2300    if (GetShowProgress() && IsEscapeCodeCapableTTY()) {2301      if (lldb::LockableStreamFileSP stream_sp = GetOutputStreamSP()) {2302 2303        // Clear progress if this was the last progress event.2304        if (m_progress_reports.empty()) {2305          stream_sp->Lock() << OSC_PROGRESS_REMOVE;2306          return;2307        }2308 2309        const ProgressReport &report = m_progress_reports.back();2310 2311        // Show indeterminate progress.2312        if (report.total == UINT64_MAX) {2313          stream_sp->Lock() << OSC_PROGRESS_INDETERMINATE;2314          return;2315        }2316 2317        // Compute and show the progress value (0-100).2318        const unsigned value = (report.completed / report.total) * 100;2319        stream_sp->Lock().Printf(OSC_PROGRESS_SHOW, value);2320      }2321    }2322  }2323}2324 2325std::optional<Debugger::ProgressReport>2326Debugger::GetCurrentProgressReport() const {2327  std::lock_guard<std::mutex> guard(m_progress_reports_mutex);2328  if (m_progress_reports.empty())2329    return std::nullopt;2330  return m_progress_reports.back();2331}2332 2333void Debugger::HandleDiagnosticEvent(const lldb::EventSP &event_sp) {2334  auto *data = DiagnosticEventData::GetEventDataFromEvent(event_sp.get());2335  if (!data)2336    return;2337 2338  data->Dump(GetAsyncErrorStream().get());2339}2340 2341bool Debugger::HasIOHandlerThread() const {2342  return m_io_handler_thread.IsJoinable();2343}2344 2345HostThread Debugger::SetIOHandlerThread(HostThread &new_thread) {2346  HostThread old_host = m_io_handler_thread;2347  m_io_handler_thread = new_thread;2348  return old_host;2349}2350 2351bool Debugger::StartIOHandlerThread() {2352  if (!m_io_handler_thread.IsJoinable()) {2353    llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread(2354        "lldb.debugger.io-handler", [this] { return IOHandlerThread(); },2355        8 * 1024 * 1024); // Use larger 8MB stack for this thread2356    if (io_handler_thread) {2357      m_io_handler_thread = *io_handler_thread;2358    } else {2359      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), io_handler_thread.takeError(),2360                     "failed to launch host thread: {0}");2361    }2362  }2363  return m_io_handler_thread.IsJoinable();2364}2365 2366void Debugger::StopIOHandlerThread() {2367  if (m_io_handler_thread.IsJoinable()) {2368    GetInputFile().Close();2369    m_io_handler_thread.Join(nullptr);2370  }2371}2372 2373void Debugger::JoinIOHandlerThread() {2374  if (HasIOHandlerThread()) {2375    thread_result_t result;2376    m_io_handler_thread.Join(&result);2377    m_io_handler_thread = LLDB_INVALID_HOST_THREAD;2378  }2379}2380 2381bool Debugger::IsIOHandlerThreadCurrentThread() const {2382  if (!HasIOHandlerThread())2383    return false;2384  return m_io_handler_thread.EqualsThread(Host::GetCurrentThread());2385}2386 2387Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {2388  if (!prefer_dummy) {2389    if (TargetSP target = m_target_list.GetSelectedTarget())2390      return *target;2391  }2392  return GetDummyTarget();2393}2394 2395Status Debugger::RunREPL(LanguageType language, const char *repl_options) {2396  Status err;2397  FileSpec repl_executable;2398 2399  if (language == eLanguageTypeUnknown)2400    language = GetREPLLanguage();2401 2402  if (language == eLanguageTypeUnknown) {2403    LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();2404 2405    if (auto single_lang = repl_languages.GetSingularLanguage()) {2406      language = *single_lang;2407    } else if (repl_languages.Empty()) {2408      err = Status::FromErrorString(2409          "LLDB isn't configured with REPL support for any languages.");2410      return err;2411    } else {2412      err = Status::FromErrorString(2413          "Multiple possible REPL languages.  Please specify a language.");2414      return err;2415    }2416  }2417 2418  Target *const target =2419      nullptr; // passing in an empty target means the REPL must create one2420 2421  REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));2422 2423  if (!err.Success()) {2424    return err;2425  }2426 2427  if (!repl_sp) {2428    err = Status::FromErrorStringWithFormat(2429        "couldn't find a REPL for %s",2430        Language::GetNameForLanguageType(language));2431    return err;2432  }2433 2434  repl_sp->SetCompilerOptions(repl_options);2435  repl_sp->RunLoop();2436 2437  return err;2438}2439 2440llvm::ThreadPoolInterface &Debugger::GetThreadPool() {2441  assert(g_thread_pool &&2442         "Debugger::GetThreadPool called before Debugger::Initialize");2443  return *g_thread_pool;2444}2445