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

source code of lldb/source/Core/Debugger.cpp