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