1ac7ddfbfSEd Maste //===-- Debugger.cpp --------------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
10ac7ddfbfSEd Maste #include "lldb/Core/Debugger.h"
11ac7ddfbfSEd Maste
12*b5893f02SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h"
131c3bbb01SEd Maste #include "lldb/Core/FormatEntity.h"
14*b5893f02SDimitry Andric #include "lldb/Core/Mangled.h"
15*b5893f02SDimitry Andric #include "lldb/Core/ModuleList.h"
16ac7ddfbfSEd Maste #include "lldb/Core/PluginManager.h"
17ac7ddfbfSEd Maste #include "lldb/Core/StreamAsynchronousIO.h"
1812b93ac6SEd Maste #include "lldb/Core/StreamFile.h"
19ac7ddfbfSEd Maste #include "lldb/DataFormatters/DataVisualization.h"
209f2f44ceSEd Maste #include "lldb/Expression/REPL.h"
21*b5893f02SDimitry Andric #include "lldb/Host/File.h"
22*b5893f02SDimitry Andric #include "lldb/Host/FileSystem.h"
230127ef0fSEd Maste #include "lldb/Host/HostInfo.h"
24ac7ddfbfSEd Maste #include "lldb/Host/Terminal.h"
257aa51b79SEd Maste #include "lldb/Host/ThreadLauncher.h"
26ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
27*b5893f02SDimitry Andric #include "lldb/Interpreter/OptionValue.h"
281c3bbb01SEd Maste #include "lldb/Interpreter/OptionValueProperties.h"
29ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionValueSInt64.h"
30ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionValueString.h"
31*b5893f02SDimitry Andric #include "lldb/Interpreter/Property.h"
32*b5893f02SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
33ac7ddfbfSEd Maste #include "lldb/Symbol/Function.h"
34ac7ddfbfSEd Maste #include "lldb/Symbol/Symbol.h"
35*b5893f02SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
369f2f44ceSEd Maste #include "lldb/Target/Language.h"
37ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
38435933ddSDimitry Andric #include "lldb/Target/StructuredDataPlugin.h"
39ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
40435933ddSDimitry Andric #include "lldb/Target/TargetList.h"
41ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
42*b5893f02SDimitry Andric #include "lldb/Target/ThreadList.h"
43ac7ddfbfSEd Maste #include "lldb/Utility/AnsiTerminal.h"
44*b5893f02SDimitry Andric #include "lldb/Utility/Event.h"
45*b5893f02SDimitry Andric #include "lldb/Utility/Listener.h"
46*b5893f02SDimitry Andric #include "lldb/Utility/Log.h"
47*b5893f02SDimitry Andric #include "lldb/Utility/Reproducer.h"
48*b5893f02SDimitry Andric #include "lldb/Utility/State.h"
49*b5893f02SDimitry Andric #include "lldb/Utility/Stream.h"
50f678e45dSDimitry Andric #include "lldb/Utility/StreamCallback.h"
51f678e45dSDimitry Andric #include "lldb/Utility/StreamString.h"
52f678e45dSDimitry Andric
534ba319b5SDimitry Andric #if defined(_WIN32)
54*b5893f02SDimitry Andric #include "lldb/Host/windows/PosixApi.h"
55*b5893f02SDimitry Andric #include "lldb/Host/windows/windows.h"
56f678e45dSDimitry Andric #endif
57f678e45dSDimitry Andric
58*b5893f02SDimitry Andric #include "llvm/ADT/None.h"
59*b5893f02SDimitry Andric #include "llvm/ADT/STLExtras.h"
60f678e45dSDimitry Andric #include "llvm/ADT/StringRef.h"
61*b5893f02SDimitry Andric #include "llvm/ADT/iterator.h"
62f678e45dSDimitry Andric #include "llvm/Support/DynamicLibrary.h"
63f678e45dSDimitry Andric #include "llvm/Support/FileSystem.h"
64*b5893f02SDimitry Andric #include "llvm/Support/Process.h"
65f678e45dSDimitry Andric #include "llvm/Support/Threading.h"
66*b5893f02SDimitry Andric #include "llvm/Support/raw_ostream.h"
67f678e45dSDimitry Andric
68*b5893f02SDimitry Andric #include <list>
69*b5893f02SDimitry Andric #include <memory>
70f678e45dSDimitry Andric #include <mutex>
71*b5893f02SDimitry Andric #include <set>
72*b5893f02SDimitry Andric #include <stdio.h>
73*b5893f02SDimitry Andric #include <stdlib.h>
74*b5893f02SDimitry Andric #include <string.h>
75*b5893f02SDimitry Andric #include <string>
76*b5893f02SDimitry Andric #include <system_error>
77f678e45dSDimitry Andric
78f678e45dSDimitry Andric namespace lldb_private {
79f678e45dSDimitry Andric class Address;
80f678e45dSDimitry Andric }
81ac7ddfbfSEd Maste
82ac7ddfbfSEd Maste using namespace lldb;
83ac7ddfbfSEd Maste using namespace lldb_private;
84ac7ddfbfSEd Maste
85ac7ddfbfSEd Maste static lldb::user_id_t g_unique_id = 1;
867aa51b79SEd Maste static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
87ac7ddfbfSEd Maste
88ac7ddfbfSEd Maste #pragma mark Static Functions
89ac7ddfbfSEd Maste
90ac7ddfbfSEd Maste typedef std::vector<DebuggerSP> DebuggerList;
91435933ddSDimitry Andric static std::recursive_mutex *g_debugger_list_mutex_ptr =
92435933ddSDimitry Andric nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
93435933ddSDimitry Andric static DebuggerList *g_debugger_list_ptr =
94435933ddSDimitry Andric nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
95ac7ddfbfSEd Maste
96*b5893f02SDimitry Andric static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
97435933ddSDimitry Andric {Debugger::eStopDisassemblyTypeNever, "never",
98435933ddSDimitry Andric "Never show disassembly when displaying a stop context."},
99435933ddSDimitry Andric {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo",
100435933ddSDimitry Andric "Show disassembly when there is no debug information."},
101435933ddSDimitry Andric {Debugger::eStopDisassemblyTypeNoSource, "no-source",
102435933ddSDimitry Andric "Show disassembly when there is no source information, or the source file "
103435933ddSDimitry Andric "is missing when displaying a stop context."},
104435933ddSDimitry Andric {Debugger::eStopDisassemblyTypeAlways, "always",
105*b5893f02SDimitry Andric "Always show disassembly when displaying a stop context."} };
106ac7ddfbfSEd Maste
107*b5893f02SDimitry Andric static constexpr OptionEnumValueElement g_language_enumerators[] = {
108ac7ddfbfSEd Maste {eScriptLanguageNone, "none", "Disable scripting languages."},
109435933ddSDimitry Andric {eScriptLanguagePython, "python",
110435933ddSDimitry Andric "Select python as the default scripting language."},
111435933ddSDimitry Andric {eScriptLanguageDefault, "default",
112*b5893f02SDimitry Andric "Select the lldb default as the default scripting language."} };
113ac7ddfbfSEd Maste
114435933ddSDimitry Andric #define MODULE_WITH_FUNC \
115435933ddSDimitry Andric "{ " \
116435933ddSDimitry Andric "${module.file.basename}{`${function.name-with-args}" \
117435933ddSDimitry Andric "{${frame.no-debug}${function.pc-offset}}}}"
11824d58133SDimitry Andric
11924d58133SDimitry Andric #define MODULE_WITH_FUNC_NO_ARGS \
12024d58133SDimitry Andric "{ " \
12124d58133SDimitry Andric "${module.file.basename}{`${function.name-without-args}" \
12224d58133SDimitry Andric "{${frame.no-debug}${function.pc-offset}}}}"
12324d58133SDimitry Andric
124*b5893f02SDimitry Andric #define FILE_AND_LINE \
125*b5893f02SDimitry Andric "{ at ${line.file.basename}:${line.number}{:${line.column}}}"
1269f2f44ceSEd Maste #define IS_OPTIMIZED "{${function.is-optimized} [opt]}"
127ac7ddfbfSEd Maste
128*b5893f02SDimitry Andric #define IS_ARTIFICIAL "{${frame.is-artificial} [artificial]}"
129*b5893f02SDimitry Andric
130435933ddSDimitry Andric #define DEFAULT_THREAD_FORMAT \
131435933ddSDimitry Andric "thread #${thread.index}: tid = ${thread.id%tid}" \
132435933ddSDimitry Andric "{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE \
133ac7ddfbfSEd Maste "{, name = '${thread.name}'}" \
134ac7ddfbfSEd Maste "{, queue = '${thread.queue}'}" \
1350127ef0fSEd Maste "{, activity = '${thread.info.activity.name}'}" \
1360127ef0fSEd Maste "{, ${thread.info.trace_messages} messages}" \
137ac7ddfbfSEd Maste "{, stop reason = ${thread.stop-reason}}" \
138ac7ddfbfSEd Maste "{\\nReturn value: ${thread.return-value}}" \
1390127ef0fSEd Maste "{\\nCompleted expression: ${thread.completed-expression}}" \
140ac7ddfbfSEd Maste "\\n"
141ac7ddfbfSEd Maste
142435933ddSDimitry Andric #define DEFAULT_THREAD_STOP_FORMAT \
143435933ddSDimitry Andric "thread #${thread.index}{, name = '${thread.name}'}" \
144435933ddSDimitry Andric "{, queue = '${thread.queue}'}" \
145435933ddSDimitry Andric "{, activity = '${thread.info.activity.name}'}" \
146435933ddSDimitry Andric "{, ${thread.info.trace_messages} messages}" \
147435933ddSDimitry Andric "{, stop reason = ${thread.stop-reason}}" \
148435933ddSDimitry Andric "{\\nReturn value: ${thread.return-value}}" \
149435933ddSDimitry Andric "{\\nCompleted expression: ${thread.completed-expression}}" \
150ac7ddfbfSEd Maste "\\n"
151ac7ddfbfSEd Maste
152435933ddSDimitry Andric #define DEFAULT_FRAME_FORMAT \
153f678e45dSDimitry Andric "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC FILE_AND_LINE \
154*b5893f02SDimitry Andric IS_OPTIMIZED IS_ARTIFICIAL "\\n"
155435933ddSDimitry Andric
15624d58133SDimitry Andric #define DEFAULT_FRAME_FORMAT_NO_ARGS \
15724d58133SDimitry Andric "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC_NO_ARGS FILE_AND_LINE \
158*b5893f02SDimitry Andric IS_OPTIMIZED IS_ARTIFICIAL "\\n"
15924d58133SDimitry Andric
1601c3bbb01SEd Maste // Three parts to this disassembly format specification:
1611c3bbb01SEd Maste // 1. If this is a new function/symbol (no previous symbol/function), print
1621c3bbb01SEd Maste // dylib`funcname:\n
163435933ddSDimitry Andric // 2. If this is a symbol context change (different from previous
164435933ddSDimitry Andric // symbol/function), print
1651c3bbb01SEd Maste // dylib`funcname:\n
1661c3bbb01SEd Maste // 3. print
1671c3bbb01SEd Maste // address <+offset>:
168435933ddSDimitry Andric #define DEFAULT_DISASSEMBLY_FORMAT \
169435933ddSDimitry Andric "{${function.initial-function}{${module.file.basename}`}{${function.name-" \
170*b5893f02SDimitry Andric "without-args}}:\\n}{${function.changed}\\n{${module.file.basename}`}{${" \
171*b5893f02SDimitry Andric "function.name-without-args}}:\\n}{${current-pc-arrow} " \
172435933ddSDimitry Andric "}${addr-file-or-load}{ " \
173435933ddSDimitry Andric "<${function.concrete-only-addr-offset-no-padding}>}: "
1741c3bbb01SEd Maste
1754ba319b5SDimitry Andric // gdb's disassembly format can be emulated with ${current-pc-arrow}${addr-
1764ba319b5SDimitry Andric // file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-
1774ba319b5SDimitry Andric // offset-no-padding}>}:
1781c3bbb01SEd Maste
1791c3bbb01SEd Maste // lldb's original format for disassembly would look like this format string -
1804ba319b5SDimitry Andric // {${function.initial-function}{${module.file.basename}`}{${function.name-
1814ba319b5SDimitry Andric // without-
1824ba319b5SDimitry Andric // args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-
1834ba319b5SDimitry Andric // without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}:
1841c3bbb01SEd Maste
185*b5893f02SDimitry Andric static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
186435933ddSDimitry Andric {eStopShowColumnAnsiOrCaret, "ansi-or-caret",
187435933ddSDimitry Andric "Highlight the stop column with ANSI terminal codes when color/ANSI mode "
188435933ddSDimitry Andric "is enabled; otherwise, fall back to using a text-only caret (^) as if "
189435933ddSDimitry Andric "\"caret-only\" mode was selected."},
190435933ddSDimitry Andric {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI "
191435933ddSDimitry Andric "terminal codes when running LLDB with "
192435933ddSDimitry Andric "color/ANSI enabled."},
193435933ddSDimitry Andric {eStopShowColumnCaret, "caret",
194435933ddSDimitry Andric "Highlight the stop column with a caret character (^) underneath the stop "
195435933ddSDimitry Andric "column. This method introduces a new line in source listings that "
196435933ddSDimitry Andric "display thread stop locations."},
197*b5893f02SDimitry Andric {eStopShowColumnNone, "none", "Do not highlight the stop column."}};
198435933ddSDimitry Andric
199*b5893f02SDimitry Andric static constexpr PropertyDefinition g_properties[] = {
200*b5893f02SDimitry Andric {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, {},
201435933ddSDimitry Andric "If true all confirmation prompts will receive their default reply."},
202435933ddSDimitry Andric {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0,
203*b5893f02SDimitry Andric DEFAULT_DISASSEMBLY_FORMAT, {},
20424d58133SDimitry Andric "The default disassembly format "
205435933ddSDimitry Andric "string to use when disassembling "
206435933ddSDimitry Andric "instruction sequences."},
207435933ddSDimitry Andric {"frame-format", OptionValue::eTypeFormatEntity, true, 0,
208*b5893f02SDimitry Andric DEFAULT_FRAME_FORMAT, {},
20924d58133SDimitry Andric "The default frame format string to use "
210435933ddSDimitry Andric "when displaying stack frame information "
211435933ddSDimitry Andric "for threads."},
212*b5893f02SDimitry Andric {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, {},
213435933ddSDimitry Andric "Notify the user explicitly if an expression returns void (default: "
214435933ddSDimitry Andric "false)."},
215435933ddSDimitry Andric {"prompt", OptionValue::eTypeString, true,
216*b5893f02SDimitry Andric OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", {},
217*b5893f02SDimitry Andric "The debugger command line prompt displayed for the user."},
218435933ddSDimitry Andric {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython,
219*b5893f02SDimitry Andric nullptr, OptionEnumValues(g_language_enumerators),
220435933ddSDimitry Andric "The script language to be used for evaluating user-written scripts."},
221*b5893f02SDimitry Andric {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, {},
22224d58133SDimitry Andric "The number of disassembly lines to show when displaying a "
223435933ddSDimitry Andric "stopped context."},
224435933ddSDimitry Andric {"stop-disassembly-display", OptionValue::eTypeEnum, true,
225435933ddSDimitry Andric Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr,
226*b5893f02SDimitry Andric OptionEnumValues(g_show_disassembly_enum_values),
227435933ddSDimitry Andric "Control when to display disassembly when displaying a stopped context."},
228*b5893f02SDimitry Andric {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, {},
22924d58133SDimitry Andric "The number of sources lines to display that come after the "
230435933ddSDimitry Andric "current source line when displaying a stopped context."},
231*b5893f02SDimitry Andric {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, {},
23224d58133SDimitry Andric "The number of sources lines to display that come before the "
233435933ddSDimitry Andric "current source line when displaying a stopped context."},
234*b5893f02SDimitry Andric {"highlight-source", OptionValue::eTypeBoolean, true, true, nullptr, {},
235*b5893f02SDimitry Andric "If true, LLDB will highlight the displayed source code."},
236435933ddSDimitry Andric {"stop-show-column", OptionValue::eTypeEnum, false,
237*b5893f02SDimitry Andric eStopShowColumnAnsiOrCaret, nullptr, OptionEnumValues(s_stop_show_column_values),
238435933ddSDimitry Andric "If true, LLDB will use the column information from the debug info to "
239435933ddSDimitry Andric "mark the current position when displaying a stopped context."},
240*b5893f02SDimitry Andric {"stop-show-column-ansi-prefix", OptionValue::eTypeString, true, 0,
241*b5893f02SDimitry Andric "${ansi.underline}", {},
242435933ddSDimitry Andric "When displaying the column marker in a color-enabled (i.e. ANSI) "
243435933ddSDimitry Andric "terminal, use the ANSI terminal code specified in this format at the "
244435933ddSDimitry Andric "immediately before the column to be marked."},
245*b5893f02SDimitry Andric {"stop-show-column-ansi-suffix", OptionValue::eTypeString, true, 0,
246*b5893f02SDimitry Andric "${ansi.normal}", {},
247435933ddSDimitry Andric "When displaying the column marker in a color-enabled (i.e. ANSI) "
248435933ddSDimitry Andric "terminal, use the ANSI terminal code specified in this format "
249435933ddSDimitry Andric "immediately after the column to be marked."},
250*b5893f02SDimitry Andric {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, {},
251435933ddSDimitry Andric "The maximum number of columns to use for displaying text."},
252435933ddSDimitry Andric {"thread-format", OptionValue::eTypeFormatEntity, true, 0,
253*b5893f02SDimitry Andric DEFAULT_THREAD_FORMAT, {},
25424d58133SDimitry Andric "The default thread format string to use "
255435933ddSDimitry Andric "when displaying thread information."},
256435933ddSDimitry Andric {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0,
257*b5893f02SDimitry Andric DEFAULT_THREAD_STOP_FORMAT, {},
25824d58133SDimitry Andric "The default thread format "
259435933ddSDimitry Andric "string to use when displaying thread "
260435933ddSDimitry Andric "information as part of the stop display."},
261*b5893f02SDimitry Andric {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, {},
262*b5893f02SDimitry Andric "Whether to use an external editor or not."},
263*b5893f02SDimitry Andric {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, {},
264435933ddSDimitry Andric "Whether to use Ansi color codes or not."},
265435933ddSDimitry Andric {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr,
266*b5893f02SDimitry Andric {},
26724d58133SDimitry Andric "If true, LLDB will automatically display small structs in "
268435933ddSDimitry Andric "one-liner format (default: true)."},
269*b5893f02SDimitry Andric {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, {},
270435933ddSDimitry Andric "If true, LLDB will auto indent/outdent code. Currently only supported in "
271435933ddSDimitry Andric "the REPL (default: true)."},
272*b5893f02SDimitry Andric {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, {},
273435933ddSDimitry Andric "If true, LLDB will print the values of variables declared in an "
274435933ddSDimitry Andric "expression. Currently only supported in the REPL (default: true)."},
275*b5893f02SDimitry Andric {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, {},
276435933ddSDimitry Andric "The tab size to use when indenting code in multi-line input mode "
277435933ddSDimitry Andric "(default: 4)."},
278435933ddSDimitry Andric {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr,
279*b5893f02SDimitry Andric {},
28024d58133SDimitry Andric "If true, LLDB will automatically escape non-printable and "
281435933ddSDimitry Andric "escape characters when formatting strings."},
28224d58133SDimitry Andric {"frame-format-unique", OptionValue::eTypeFormatEntity, true, 0,
283*b5893f02SDimitry Andric DEFAULT_FRAME_FORMAT_NO_ARGS, {},
28424d58133SDimitry Andric "The default frame format string to use when displaying stack frame"
285*b5893f02SDimitry Andric "information for threads from thread backtrace unique."}};
286435933ddSDimitry Andric
287435933ddSDimitry Andric enum {
288ac7ddfbfSEd Maste ePropertyAutoConfirm = 0,
2897aa51b79SEd Maste ePropertyDisassemblyFormat,
290ac7ddfbfSEd Maste ePropertyFrameFormat,
291ac7ddfbfSEd Maste ePropertyNotiftVoid,
292ac7ddfbfSEd Maste ePropertyPrompt,
293ac7ddfbfSEd Maste ePropertyScriptLanguage,
294ac7ddfbfSEd Maste ePropertyStopDisassemblyCount,
295ac7ddfbfSEd Maste ePropertyStopDisassemblyDisplay,
296ac7ddfbfSEd Maste ePropertyStopLineCountAfter,
297ac7ddfbfSEd Maste ePropertyStopLineCountBefore,
298*b5893f02SDimitry Andric ePropertyHighlightSource,
299435933ddSDimitry Andric ePropertyStopShowColumn,
300435933ddSDimitry Andric ePropertyStopShowColumnAnsiPrefix,
301435933ddSDimitry Andric ePropertyStopShowColumnAnsiSuffix,
302ac7ddfbfSEd Maste ePropertyTerminalWidth,
303ac7ddfbfSEd Maste ePropertyThreadFormat,
304435933ddSDimitry Andric ePropertyThreadStopFormat,
305ac7ddfbfSEd Maste ePropertyUseExternalEditor,
306ac7ddfbfSEd Maste ePropertyUseColor,
3077aa51b79SEd Maste ePropertyAutoOneLineSummaries,
3089f2f44ceSEd Maste ePropertyAutoIndent,
3099f2f44ceSEd Maste ePropertyPrintDecls,
3109f2f44ceSEd Maste ePropertyTabSize,
31124d58133SDimitry Andric ePropertyEscapeNonPrintables,
31224d58133SDimitry Andric ePropertyFrameFormatUnique,
313ac7ddfbfSEd Maste };
314ac7ddfbfSEd Maste
3154bb0738eSEd Maste LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
316ac7ddfbfSEd Maste
SetPropertyValue(const ExecutionContext * exe_ctx,VarSetOperationType op,llvm::StringRef property_path,llvm::StringRef value)3175517e702SDimitry Andric Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
318ac7ddfbfSEd Maste VarSetOperationType op,
3195517e702SDimitry Andric llvm::StringRef property_path,
3205517e702SDimitry Andric llvm::StringRef value) {
321435933ddSDimitry Andric bool is_load_script = (property_path == "target.load-script-from-symbol-file");
322435933ddSDimitry Andric bool is_escape_non_printables = (property_path == "escape-non-printables");
323ac7ddfbfSEd Maste TargetSP target_sp;
324ac7ddfbfSEd Maste LoadScriptFromSymFile load_script_old_value;
325435933ddSDimitry Andric if (is_load_script && exe_ctx->GetTargetSP()) {
326ac7ddfbfSEd Maste target_sp = exe_ctx->GetTargetSP();
327435933ddSDimitry Andric load_script_old_value =
328435933ddSDimitry Andric target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
329ac7ddfbfSEd Maste }
3305517e702SDimitry Andric Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
331435933ddSDimitry Andric if (error.Success()) {
332ac7ddfbfSEd Maste // FIXME it would be nice to have "on-change" callbacks for properties
333435933ddSDimitry Andric if (property_path == g_properties[ePropertyPrompt].name) {
334435933ddSDimitry Andric llvm::StringRef new_prompt = GetPrompt();
335435933ddSDimitry Andric std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes(
336435933ddSDimitry Andric new_prompt, GetUseColor());
337ac7ddfbfSEd Maste if (str.length())
338435933ddSDimitry Andric new_prompt = str;
33912b93ac6SEd Maste GetCommandInterpreter().UpdatePrompt(new_prompt);
340f678e45dSDimitry Andric auto bytes = llvm::make_unique<EventDataBytes>(new_prompt);
341f678e45dSDimitry Andric auto prompt_change_event_sp = std::make_shared<Event>(
342f678e45dSDimitry Andric CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
343ac7ddfbfSEd Maste GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
344435933ddSDimitry Andric } else if (property_path == g_properties[ePropertyUseColor].name) {
345435933ddSDimitry Andric // use-color changed. Ping the prompt so it can reset the ansi terminal
346435933ddSDimitry Andric // codes.
347ac7ddfbfSEd Maste SetPrompt(GetPrompt());
348435933ddSDimitry Andric } else if (is_load_script && target_sp &&
349435933ddSDimitry Andric load_script_old_value == eLoadScriptFromSymFileWarn) {
350435933ddSDimitry Andric if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
351435933ddSDimitry Andric eLoadScriptFromSymFileTrue) {
3525517e702SDimitry Andric std::list<Status> errors;
353ac7ddfbfSEd Maste StreamString feedback_stream;
354435933ddSDimitry Andric if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
35512b93ac6SEd Maste StreamFileSP stream_sp(GetErrorFile());
356435933ddSDimitry Andric if (stream_sp) {
357435933ddSDimitry Andric for (auto error : errors) {
35812b93ac6SEd Maste stream_sp->Printf("%s\n", error.AsCString());
359ac7ddfbfSEd Maste }
360ac7ddfbfSEd Maste if (feedback_stream.GetSize())
361435933ddSDimitry Andric stream_sp->PutCString(feedback_stream.GetString());
36212b93ac6SEd Maste }
363ac7ddfbfSEd Maste }
364ac7ddfbfSEd Maste }
365435933ddSDimitry Andric } else if (is_escape_non_printables) {
3667aa51b79SEd Maste DataVisualization::ForceUpdate();
3677aa51b79SEd Maste }
368ac7ddfbfSEd Maste }
369ac7ddfbfSEd Maste return error;
370ac7ddfbfSEd Maste }
371ac7ddfbfSEd Maste
GetAutoConfirm() const372435933ddSDimitry Andric bool Debugger::GetAutoConfirm() const {
373ac7ddfbfSEd Maste const uint32_t idx = ePropertyAutoConfirm;
374435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsBoolean(
375435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value != 0);
376ac7ddfbfSEd Maste }
377ac7ddfbfSEd Maste
GetDisassemblyFormat() const378435933ddSDimitry Andric const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
3797aa51b79SEd Maste const uint32_t idx = ePropertyDisassemblyFormat;
3804bb0738eSEd Maste return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
3817aa51b79SEd Maste }
3827aa51b79SEd Maste
GetFrameFormat() const383435933ddSDimitry Andric const FormatEntity::Entry *Debugger::GetFrameFormat() const {
384ac7ddfbfSEd Maste const uint32_t idx = ePropertyFrameFormat;
3854bb0738eSEd Maste return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
386ac7ddfbfSEd Maste }
387ac7ddfbfSEd Maste
GetFrameFormatUnique() const38824d58133SDimitry Andric const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
38924d58133SDimitry Andric const uint32_t idx = ePropertyFrameFormatUnique;
39024d58133SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
39124d58133SDimitry Andric }
39224d58133SDimitry Andric
GetNotifyVoid() const393435933ddSDimitry Andric bool Debugger::GetNotifyVoid() const {
394ac7ddfbfSEd Maste const uint32_t idx = ePropertyNotiftVoid;
395435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsBoolean(
396435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value != 0);
397ac7ddfbfSEd Maste }
398ac7ddfbfSEd Maste
GetPrompt() const399435933ddSDimitry Andric llvm::StringRef Debugger::GetPrompt() const {
400ac7ddfbfSEd Maste const uint32_t idx = ePropertyPrompt;
401435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsString(
402435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_cstr_value);
403ac7ddfbfSEd Maste }
404ac7ddfbfSEd Maste
SetPrompt(llvm::StringRef p)405435933ddSDimitry Andric void Debugger::SetPrompt(llvm::StringRef p) {
406ac7ddfbfSEd Maste const uint32_t idx = ePropertyPrompt;
4074bb0738eSEd Maste m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
408435933ddSDimitry Andric llvm::StringRef new_prompt = GetPrompt();
409435933ddSDimitry Andric std::string str =
410435933ddSDimitry Andric lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
411ac7ddfbfSEd Maste if (str.length())
412435933ddSDimitry Andric new_prompt = str;
41312b93ac6SEd Maste GetCommandInterpreter().UpdatePrompt(new_prompt);
414ac7ddfbfSEd Maste }
415ac7ddfbfSEd Maste
GetReproducerPath() const416*b5893f02SDimitry Andric llvm::StringRef Debugger::GetReproducerPath() const {
417*b5893f02SDimitry Andric auto &r = repro::Reproducer::Instance();
418*b5893f02SDimitry Andric return r.GetReproducerPath().GetCString();
419*b5893f02SDimitry Andric }
420*b5893f02SDimitry Andric
GetThreadFormat() const421435933ddSDimitry Andric const FormatEntity::Entry *Debugger::GetThreadFormat() const {
422ac7ddfbfSEd Maste const uint32_t idx = ePropertyThreadFormat;
4234bb0738eSEd Maste return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
424ac7ddfbfSEd Maste }
425ac7ddfbfSEd Maste
GetThreadStopFormat() const426435933ddSDimitry Andric const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
427435933ddSDimitry Andric const uint32_t idx = ePropertyThreadStopFormat;
428435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
429ac7ddfbfSEd Maste }
430ac7ddfbfSEd Maste
GetScriptLanguage() const431435933ddSDimitry Andric lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
432ac7ddfbfSEd Maste const uint32_t idx = ePropertyScriptLanguage;
433435933ddSDimitry Andric return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
434435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value);
435ac7ddfbfSEd Maste }
436ac7ddfbfSEd Maste
SetScriptLanguage(lldb::ScriptLanguage script_lang)437435933ddSDimitry Andric bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
438435933ddSDimitry Andric const uint32_t idx = ePropertyScriptLanguage;
439435933ddSDimitry Andric return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
440435933ddSDimitry Andric script_lang);
441435933ddSDimitry Andric }
442435933ddSDimitry Andric
GetTerminalWidth() const443435933ddSDimitry Andric uint32_t Debugger::GetTerminalWidth() const {
444ac7ddfbfSEd Maste const uint32_t idx = ePropertyTerminalWidth;
445435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsSInt64(
446435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value);
447ac7ddfbfSEd Maste }
448ac7ddfbfSEd Maste
SetTerminalWidth(uint32_t term_width)449435933ddSDimitry Andric bool Debugger::SetTerminalWidth(uint32_t term_width) {
450ac7ddfbfSEd Maste const uint32_t idx = ePropertyTerminalWidth;
4514bb0738eSEd Maste return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
452ac7ddfbfSEd Maste }
453ac7ddfbfSEd Maste
GetUseExternalEditor() const454435933ddSDimitry Andric bool Debugger::GetUseExternalEditor() const {
455ac7ddfbfSEd Maste const uint32_t idx = ePropertyUseExternalEditor;
456435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsBoolean(
457435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value != 0);
458ac7ddfbfSEd Maste }
459ac7ddfbfSEd Maste
SetUseExternalEditor(bool b)460435933ddSDimitry Andric bool Debugger::SetUseExternalEditor(bool b) {
461ac7ddfbfSEd Maste const uint32_t idx = ePropertyUseExternalEditor;
4624bb0738eSEd Maste return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
463ac7ddfbfSEd Maste }
464ac7ddfbfSEd Maste
GetUseColor() const465435933ddSDimitry Andric bool Debugger::GetUseColor() const {
466ac7ddfbfSEd Maste const uint32_t idx = ePropertyUseColor;
467435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsBoolean(
468435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value != 0);
469ac7ddfbfSEd Maste }
470ac7ddfbfSEd Maste
SetUseColor(bool b)471435933ddSDimitry Andric bool Debugger::SetUseColor(bool b) {
472ac7ddfbfSEd Maste const uint32_t idx = ePropertyUseColor;
4734bb0738eSEd Maste bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
474ac7ddfbfSEd Maste SetPrompt(GetPrompt());
475ac7ddfbfSEd Maste return ret;
476ac7ddfbfSEd Maste }
477ac7ddfbfSEd Maste
GetHighlightSource() const478*b5893f02SDimitry Andric bool Debugger::GetHighlightSource() const {
479*b5893f02SDimitry Andric const uint32_t idx = ePropertyHighlightSource;
480*b5893f02SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsBoolean(
481*b5893f02SDimitry Andric nullptr, idx, g_properties[idx].default_uint_value);
482*b5893f02SDimitry Andric }
483*b5893f02SDimitry Andric
GetStopShowColumn() const484435933ddSDimitry Andric StopShowColumn Debugger::GetStopShowColumn() const {
485435933ddSDimitry Andric const uint32_t idx = ePropertyStopShowColumn;
486435933ddSDimitry Andric return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
487435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value);
488ac7ddfbfSEd Maste }
489ac7ddfbfSEd Maste
GetStopShowColumnAnsiPrefix() const490*b5893f02SDimitry Andric llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
491435933ddSDimitry Andric const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
492*b5893f02SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
493435933ddSDimitry Andric }
494435933ddSDimitry Andric
GetStopShowColumnAnsiSuffix() const495*b5893f02SDimitry Andric llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
496435933ddSDimitry Andric const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
497*b5893f02SDimitry Andric return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
498435933ddSDimitry Andric }
499435933ddSDimitry Andric
GetStopSourceLineCount(bool before) const500435933ddSDimitry Andric uint32_t Debugger::GetStopSourceLineCount(bool before) const {
501435933ddSDimitry Andric const uint32_t idx =
502435933ddSDimitry Andric before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
503435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsSInt64(
504435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value);
505435933ddSDimitry Andric }
506435933ddSDimitry Andric
GetStopDisassemblyDisplay() const507435933ddSDimitry Andric Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
508ac7ddfbfSEd Maste const uint32_t idx = ePropertyStopDisassemblyDisplay;
509435933ddSDimitry Andric return (Debugger::StopDisassemblyType)
510435933ddSDimitry Andric m_collection_sp->GetPropertyAtIndexAsEnumeration(
511435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value);
512ac7ddfbfSEd Maste }
513ac7ddfbfSEd Maste
GetDisassemblyLineCount() const514435933ddSDimitry Andric uint32_t Debugger::GetDisassemblyLineCount() const {
515ac7ddfbfSEd Maste const uint32_t idx = ePropertyStopDisassemblyCount;
516435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsSInt64(
517435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value);
518ac7ddfbfSEd Maste }
519ac7ddfbfSEd Maste
GetAutoOneLineSummaries() const520435933ddSDimitry Andric bool Debugger::GetAutoOneLineSummaries() const {
52135617911SEd Maste const uint32_t idx = ePropertyAutoOneLineSummaries;
5224bb0738eSEd Maste return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5237aa51b79SEd Maste }
52435617911SEd Maste
GetEscapeNonPrintables() const525435933ddSDimitry Andric bool Debugger::GetEscapeNonPrintables() const {
5267aa51b79SEd Maste const uint32_t idx = ePropertyEscapeNonPrintables;
5274bb0738eSEd Maste return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
52835617911SEd Maste }
52935617911SEd Maste
GetAutoIndent() const530435933ddSDimitry Andric bool Debugger::GetAutoIndent() const {
5319f2f44ceSEd Maste const uint32_t idx = ePropertyAutoIndent;
5324bb0738eSEd Maste return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5339f2f44ceSEd Maste }
5349f2f44ceSEd Maste
SetAutoIndent(bool b)535435933ddSDimitry Andric bool Debugger::SetAutoIndent(bool b) {
5369f2f44ceSEd Maste const uint32_t idx = ePropertyAutoIndent;
5374bb0738eSEd Maste return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5389f2f44ceSEd Maste }
5399f2f44ceSEd Maste
GetPrintDecls() const540435933ddSDimitry Andric bool Debugger::GetPrintDecls() const {
5419f2f44ceSEd Maste const uint32_t idx = ePropertyPrintDecls;
5424bb0738eSEd Maste return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5439f2f44ceSEd Maste }
5449f2f44ceSEd Maste
SetPrintDecls(bool b)545435933ddSDimitry Andric bool Debugger::SetPrintDecls(bool b) {
5469f2f44ceSEd Maste const uint32_t idx = ePropertyPrintDecls;
5474bb0738eSEd Maste return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5489f2f44ceSEd Maste }
5499f2f44ceSEd Maste
GetTabSize() const550435933ddSDimitry Andric uint32_t Debugger::GetTabSize() const {
5519f2f44ceSEd Maste const uint32_t idx = ePropertyTabSize;
552435933ddSDimitry Andric return m_collection_sp->GetPropertyAtIndexAsUInt64(
553435933ddSDimitry Andric nullptr, idx, g_properties[idx].default_uint_value);
5549f2f44ceSEd Maste }
5559f2f44ceSEd Maste
SetTabSize(uint32_t tab_size)556435933ddSDimitry Andric bool Debugger::SetTabSize(uint32_t tab_size) {
5579f2f44ceSEd Maste const uint32_t idx = ePropertyTabSize;
5584bb0738eSEd Maste return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
5599f2f44ceSEd Maste }
5609f2f44ceSEd Maste
561ac7ddfbfSEd Maste #pragma mark Debugger
562ac7ddfbfSEd Maste
563ac7ddfbfSEd Maste // const DebuggerPropertiesSP &
564ac7ddfbfSEd Maste // Debugger::GetSettings() const
565ac7ddfbfSEd Maste //{
566ac7ddfbfSEd Maste // return m_properties_sp;
567ac7ddfbfSEd Maste //}
568ac7ddfbfSEd Maste //
569ac7ddfbfSEd Maste
Initialize(LoadPluginCallbackType load_plugin_callback)570435933ddSDimitry Andric void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
571435933ddSDimitry Andric assert(g_debugger_list_ptr == nullptr &&
572435933ddSDimitry Andric "Debugger::Initialize called more than once!");
5734bb0738eSEd Maste g_debugger_list_mutex_ptr = new std::recursive_mutex();
5744bb0738eSEd Maste g_debugger_list_ptr = new DebuggerList();
575b952cd58SEd Maste g_load_plugin_callback = load_plugin_callback;
576ac7ddfbfSEd Maste }
577ac7ddfbfSEd Maste
Terminate()578435933ddSDimitry Andric void Debugger::Terminate() {
579435933ddSDimitry Andric assert(g_debugger_list_ptr &&
580435933ddSDimitry Andric "Debugger::Terminate called without a matching Debugger::Initialize!");
581ac7ddfbfSEd Maste
582435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
583ac7ddfbfSEd Maste // Clear our master list of debugger objects
5844bb0738eSEd Maste {
5854bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
5864bb0738eSEd Maste for (const auto &debugger : *g_debugger_list_ptr)
5879f2f44ceSEd Maste debugger->Clear();
5884bb0738eSEd Maste g_debugger_list_ptr->clear();
5894bb0738eSEd Maste }
5904bb0738eSEd Maste }
591ac7ddfbfSEd Maste }
592ac7ddfbfSEd Maste
SettingsInitialize()593435933ddSDimitry Andric void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
594ac7ddfbfSEd Maste
SettingsTerminate()595435933ddSDimitry Andric void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
596ac7ddfbfSEd Maste
LoadPlugin(const FileSpec & spec,Status & error)5975517e702SDimitry Andric bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
598435933ddSDimitry Andric if (g_load_plugin_callback) {
599435933ddSDimitry Andric llvm::sys::DynamicLibrary dynlib =
600435933ddSDimitry Andric g_load_plugin_callback(shared_from_this(), spec, error);
601435933ddSDimitry Andric if (dynlib.isValid()) {
6020127ef0fSEd Maste m_loaded_plugins.push_back(dynlib);
603ac7ddfbfSEd Maste return true;
604ac7ddfbfSEd Maste }
605435933ddSDimitry Andric } else {
6064ba319b5SDimitry Andric // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
6074ba319b5SDimitry Andric // if the public API layer isn't available (code is linking against all of
6084ba319b5SDimitry Andric // the internal LLDB static libraries), then we can't load plugins
609b952cd58SEd Maste error.SetErrorString("Public API layer is not available");
610b952cd58SEd Maste }
611ac7ddfbfSEd Maste return false;
612ac7ddfbfSEd Maste }
613ac7ddfbfSEd Maste
614*b5893f02SDimitry Andric static FileSystem::EnumerateDirectoryResult
LoadPluginCallback(void * baton,llvm::sys::fs::file_type ft,llvm::StringRef path)615f678e45dSDimitry Andric LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
616*b5893f02SDimitry Andric llvm::StringRef path) {
6175517e702SDimitry Andric Status error;
618ac7ddfbfSEd Maste
6194ba319b5SDimitry Andric static ConstString g_dylibext(".dylib");
6204ba319b5SDimitry Andric static ConstString g_solibext(".so");
621ac7ddfbfSEd Maste
622ac7ddfbfSEd Maste if (!baton)
623*b5893f02SDimitry Andric return FileSystem::eEnumerateDirectoryResultQuit;
624ac7ddfbfSEd Maste
625ac7ddfbfSEd Maste Debugger *debugger = (Debugger *)baton;
626ac7ddfbfSEd Maste
627f678e45dSDimitry Andric namespace fs = llvm::sys::fs;
6284ba319b5SDimitry Andric // If we have a regular file, a symbolic link or unknown file type, try and
6294ba319b5SDimitry Andric // process the file. We must handle unknown as sometimes the directory
630ac7ddfbfSEd Maste // enumeration might be enumerating a file system that doesn't have correct
631ac7ddfbfSEd Maste // file type information.
632f678e45dSDimitry Andric if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
633f678e45dSDimitry Andric ft == fs::file_type::type_unknown) {
634*b5893f02SDimitry Andric FileSpec plugin_file_spec(path);
635*b5893f02SDimitry Andric FileSystem::Instance().Resolve(plugin_file_spec);
636ac7ddfbfSEd Maste
637ac7ddfbfSEd Maste if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
638435933ddSDimitry Andric plugin_file_spec.GetFileNameExtension() != g_solibext) {
639*b5893f02SDimitry Andric return FileSystem::eEnumerateDirectoryResultNext;
640ac7ddfbfSEd Maste }
641ac7ddfbfSEd Maste
6425517e702SDimitry Andric Status plugin_load_error;
643ac7ddfbfSEd Maste debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
644ac7ddfbfSEd Maste
645*b5893f02SDimitry Andric return FileSystem::eEnumerateDirectoryResultNext;
646f678e45dSDimitry Andric } else if (ft == fs::file_type::directory_file ||
647f678e45dSDimitry Andric ft == fs::file_type::symlink_file ||
648f678e45dSDimitry Andric ft == fs::file_type::type_unknown) {
6494ba319b5SDimitry Andric // Try and recurse into anything that a directory or symbolic link. We must
6504ba319b5SDimitry Andric // also do this for unknown as sometimes the directory enumeration might be
6514ba319b5SDimitry Andric // enumerating a file system that doesn't have correct file type
652ac7ddfbfSEd Maste // information.
653*b5893f02SDimitry Andric return FileSystem::eEnumerateDirectoryResultEnter;
654ac7ddfbfSEd Maste }
655ac7ddfbfSEd Maste
656*b5893f02SDimitry Andric return FileSystem::eEnumerateDirectoryResultNext;
657ac7ddfbfSEd Maste }
658ac7ddfbfSEd Maste
InstanceInitialize()659435933ddSDimitry Andric void Debugger::InstanceInitialize() {
660ac7ddfbfSEd Maste const bool find_directories = true;
661ac7ddfbfSEd Maste const bool find_files = true;
662ac7ddfbfSEd Maste const bool find_other = true;
663ac7ddfbfSEd Maste char dir_path[PATH_MAX];
6644ba319b5SDimitry Andric if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
665*b5893f02SDimitry Andric if (FileSystem::Instance().Exists(dir_spec) &&
666*b5893f02SDimitry Andric dir_spec.GetPath(dir_path, sizeof(dir_path))) {
667*b5893f02SDimitry Andric FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
668*b5893f02SDimitry Andric find_files, find_other,
669*b5893f02SDimitry Andric LoadPluginCallback, this);
670ac7ddfbfSEd Maste }
671ac7ddfbfSEd Maste }
672ac7ddfbfSEd Maste
6734ba319b5SDimitry Andric if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
674*b5893f02SDimitry Andric if (FileSystem::Instance().Exists(dir_spec) &&
675*b5893f02SDimitry Andric dir_spec.GetPath(dir_path, sizeof(dir_path))) {
676*b5893f02SDimitry Andric FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
677*b5893f02SDimitry Andric find_files, find_other,
678*b5893f02SDimitry Andric LoadPluginCallback, this);
679ac7ddfbfSEd Maste }
680ac7ddfbfSEd Maste }
681ac7ddfbfSEd Maste
682ac7ddfbfSEd Maste PluginManager::DebuggerInitialize(*this);
683ac7ddfbfSEd Maste }
684ac7ddfbfSEd Maste
CreateInstance(lldb::LogOutputCallback log_callback,void * baton)685435933ddSDimitry Andric DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
686435933ddSDimitry Andric void *baton) {
687ac7ddfbfSEd Maste DebuggerSP debugger_sp(new Debugger(log_callback, baton));
688435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6894bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6904bb0738eSEd Maste g_debugger_list_ptr->push_back(debugger_sp);
691ac7ddfbfSEd Maste }
692ac7ddfbfSEd Maste debugger_sp->InstanceInitialize();
693ac7ddfbfSEd Maste return debugger_sp;
694ac7ddfbfSEd Maste }
695ac7ddfbfSEd Maste
Destroy(DebuggerSP & debugger_sp)696435933ddSDimitry Andric void Debugger::Destroy(DebuggerSP &debugger_sp) {
6974bb0738eSEd Maste if (!debugger_sp)
698ac7ddfbfSEd Maste return;
699ac7ddfbfSEd Maste
700ac7ddfbfSEd Maste debugger_sp->Clear();
701ac7ddfbfSEd Maste
702435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7034bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7044bb0738eSEd Maste DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
705435933ddSDimitry Andric for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
706435933ddSDimitry Andric if ((*pos).get() == debugger_sp.get()) {
7074bb0738eSEd Maste g_debugger_list_ptr->erase(pos);
708ac7ddfbfSEd Maste return;
709ac7ddfbfSEd Maste }
710ac7ddfbfSEd Maste }
711ac7ddfbfSEd Maste }
712ac7ddfbfSEd Maste }
713ac7ddfbfSEd Maste
714ac7ddfbfSEd Maste DebuggerSP
FindDebuggerWithInstanceName(const ConstString & instance_name)715435933ddSDimitry Andric Debugger::FindDebuggerWithInstanceName(const ConstString &instance_name) {
716ac7ddfbfSEd Maste DebuggerSP debugger_sp;
717435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7184bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7194bb0738eSEd Maste DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
720435933ddSDimitry Andric for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
721435933ddSDimitry Andric if ((*pos)->m_instance_name == instance_name) {
722ac7ddfbfSEd Maste debugger_sp = *pos;
723ac7ddfbfSEd Maste break;
724ac7ddfbfSEd Maste }
725ac7ddfbfSEd Maste }
726ac7ddfbfSEd Maste }
727ac7ddfbfSEd Maste return debugger_sp;
728ac7ddfbfSEd Maste }
729ac7ddfbfSEd Maste
FindTargetWithProcessID(lldb::pid_t pid)730435933ddSDimitry Andric TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
731ac7ddfbfSEd Maste TargetSP target_sp;
732435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7334bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7344bb0738eSEd Maste DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
735435933ddSDimitry Andric for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
736ac7ddfbfSEd Maste target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
737ac7ddfbfSEd Maste if (target_sp)
738ac7ddfbfSEd Maste break;
739ac7ddfbfSEd Maste }
740ac7ddfbfSEd Maste }
741ac7ddfbfSEd Maste return target_sp;
742ac7ddfbfSEd Maste }
743ac7ddfbfSEd Maste
FindTargetWithProcess(Process * process)744435933ddSDimitry Andric TargetSP Debugger::FindTargetWithProcess(Process *process) {
745ac7ddfbfSEd Maste TargetSP target_sp;
746435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7474bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7484bb0738eSEd Maste DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
749435933ddSDimitry Andric for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
750ac7ddfbfSEd Maste target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
751ac7ddfbfSEd Maste if (target_sp)
752ac7ddfbfSEd Maste break;
753ac7ddfbfSEd Maste }
754ac7ddfbfSEd Maste }
755ac7ddfbfSEd Maste return target_sp;
756ac7ddfbfSEd Maste }
757ac7ddfbfSEd Maste
Debugger(lldb::LogOutputCallback log_callback,void * baton)758435933ddSDimitry Andric Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
759435933ddSDimitry Andric : UserID(g_unique_id++),
760f678e45dSDimitry Andric Properties(std::make_shared<OptionValueProperties>()),
761f678e45dSDimitry Andric m_input_file_sp(std::make_shared<StreamFile>(stdin, false)),
762f678e45dSDimitry Andric m_output_file_sp(std::make_shared<StreamFile>(stdout, false)),
763f678e45dSDimitry Andric m_error_file_sp(std::make_shared<StreamFile>(stderr, false)),
7644bb0738eSEd Maste m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
765435933ddSDimitry Andric m_terminal_state(), m_target_list(*this), m_platform_list(),
7664bb0738eSEd Maste m_listener_sp(Listener::MakeListener("lldb.Debugger")),
767435933ddSDimitry Andric m_source_manager_ap(), m_source_file_cache(),
768f678e45dSDimitry Andric m_command_interpreter_ap(llvm::make_unique<CommandInterpreter>(
769f678e45dSDimitry Andric *this, eScriptLanguageDefault, false)),
770435933ddSDimitry Andric m_input_reader_stack(), m_instance_name(), m_loaded_plugins(),
771435933ddSDimitry Andric m_event_handler_thread(), m_io_handler_thread(),
7724bb0738eSEd Maste m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
773435933ddSDimitry Andric m_forward_listener_sp(), m_clear_once() {
774ac7ddfbfSEd Maste char instance_cstr[256];
775ac7ddfbfSEd Maste snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
776ac7ddfbfSEd Maste m_instance_name.SetCString(instance_cstr);
777ac7ddfbfSEd Maste if (log_callback)
778f678e45dSDimitry Andric m_log_callback_stream_sp =
779f678e45dSDimitry Andric std::make_shared<StreamCallback>(log_callback, baton);
780ac7ddfbfSEd Maste m_command_interpreter_ap->Initialize();
781ac7ddfbfSEd Maste // Always add our default platform to the platform list
7827aa51b79SEd Maste PlatformSP default_platform_sp(Platform::GetHostPlatform());
7834bb0738eSEd Maste assert(default_platform_sp);
784ac7ddfbfSEd Maste m_platform_list.Append(default_platform_sp, true);
785ac7ddfbfSEd Maste
786ac7ddfbfSEd Maste m_collection_sp->Initialize(g_properties);
787435933ddSDimitry Andric m_collection_sp->AppendProperty(
788435933ddSDimitry Andric ConstString("target"),
789435933ddSDimitry Andric ConstString("Settings specify to debugging targets."), true,
790ac7ddfbfSEd Maste Target::GetGlobalProperties()->GetValueProperties());
791435933ddSDimitry Andric m_collection_sp->AppendProperty(
792435933ddSDimitry Andric ConstString("platform"), ConstString("Platform settings."), true,
7931c3bbb01SEd Maste Platform::GetGlobalPlatformProperties()->GetValueProperties());
7944ba319b5SDimitry Andric m_collection_sp->AppendProperty(
7954ba319b5SDimitry Andric ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
7964ba319b5SDimitry Andric true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
797435933ddSDimitry Andric if (m_command_interpreter_ap) {
798435933ddSDimitry Andric m_collection_sp->AppendProperty(
799435933ddSDimitry Andric ConstString("interpreter"),
800ac7ddfbfSEd Maste ConstString("Settings specify to the debugger's command interpreter."),
801435933ddSDimitry Andric true, m_command_interpreter_ap->GetValueProperties());
802ac7ddfbfSEd Maste }
803435933ddSDimitry Andric OptionValueSInt64 *term_width =
804435933ddSDimitry Andric m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
805435933ddSDimitry Andric nullptr, ePropertyTerminalWidth);
806ac7ddfbfSEd Maste term_width->SetMinimumValue(10);
807ac7ddfbfSEd Maste term_width->SetMaximumValue(1024);
808ac7ddfbfSEd Maste
809ac7ddfbfSEd Maste // Turn off use-color if this is a dumb terminal.
810ac7ddfbfSEd Maste const char *term = getenv("TERM");
811ac7ddfbfSEd Maste if (term && !strcmp(term, "dumb"))
812ac7ddfbfSEd Maste SetUseColor(false);
813*b5893f02SDimitry Andric // Turn off use-color if we don't write to a terminal with color support.
814*b5893f02SDimitry Andric if (!m_output_file_sp->GetFile().GetIsTerminalWithColors())
815*b5893f02SDimitry Andric SetUseColor(false);
816*b5893f02SDimitry Andric
817*b5893f02SDimitry Andric #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
818*b5893f02SDimitry Andric // Enabling use of ANSI color codes because LLDB is using them to highlight
819*b5893f02SDimitry Andric // text.
820*b5893f02SDimitry Andric llvm::sys::Process::UseANSIEscapeCodes(true);
821*b5893f02SDimitry Andric #endif
822ac7ddfbfSEd Maste }
823ac7ddfbfSEd Maste
~Debugger()824435933ddSDimitry Andric Debugger::~Debugger() { Clear(); }
825ac7ddfbfSEd Maste
Clear()826435933ddSDimitry Andric void Debugger::Clear() {
8274bb0738eSEd Maste //----------------------------------------------------------------------
8284ba319b5SDimitry Andric // Make sure we call this function only once. With the C++ global destructor
8294ba319b5SDimitry Andric // chain having a list of debuggers and with code that can be running on
8304ba319b5SDimitry Andric // other threads, we need to ensure this doesn't happen multiple times.
8314bb0738eSEd Maste //
8324bb0738eSEd Maste // The following functions call Debugger::Clear():
8334bb0738eSEd Maste // Debugger::~Debugger();
8344bb0738eSEd Maste // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
8354bb0738eSEd Maste // static void Debugger::Terminate();
8364bb0738eSEd Maste //----------------------------------------------------------------------
837f678e45dSDimitry Andric llvm::call_once(m_clear_once, [this]() {
83812b93ac6SEd Maste ClearIOHandlers();
83912b93ac6SEd Maste StopIOHandlerThread();
84012b93ac6SEd Maste StopEventHandlerThread();
8414bb0738eSEd Maste m_listener_sp->Clear();
842ac7ddfbfSEd Maste int num_targets = m_target_list.GetNumTargets();
843435933ddSDimitry Andric for (int i = 0; i < num_targets; i++) {
844ac7ddfbfSEd Maste TargetSP target_sp(m_target_list.GetTargetAtIndex(i));
845435933ddSDimitry Andric if (target_sp) {
846ac7ddfbfSEd Maste ProcessSP process_sp(target_sp->GetProcessSP());
847ac7ddfbfSEd Maste if (process_sp)
848ac7ddfbfSEd Maste process_sp->Finalize();
849ac7ddfbfSEd Maste target_sp->Destroy();
850ac7ddfbfSEd Maste }
851ac7ddfbfSEd Maste }
8524bb0738eSEd Maste m_broadcaster_manager_sp->Clear();
853ac7ddfbfSEd Maste
854435933ddSDimitry Andric // Close the input file _before_ we close the input read communications
8554ba319b5SDimitry Andric // class as it does NOT own the input file, our m_input_file does.
856ac7ddfbfSEd Maste m_terminal_state.Clear();
85712b93ac6SEd Maste if (m_input_file_sp)
85812b93ac6SEd Maste m_input_file_sp->GetFile().Close();
8590127ef0fSEd Maste
8600127ef0fSEd Maste m_command_interpreter_ap->Clear();
8614bb0738eSEd Maste });
862ac7ddfbfSEd Maste }
863ac7ddfbfSEd Maste
GetCloseInputOnEOF() const864435933ddSDimitry Andric bool Debugger::GetCloseInputOnEOF() const {
86512b93ac6SEd Maste // return m_input_comm.GetCloseOnEOF();
86612b93ac6SEd Maste return false;
867ac7ddfbfSEd Maste }
868ac7ddfbfSEd Maste
SetCloseInputOnEOF(bool b)869435933ddSDimitry Andric void Debugger::SetCloseInputOnEOF(bool b) {
87012b93ac6SEd Maste // m_input_comm.SetCloseOnEOF(b);
871ac7ddfbfSEd Maste }
872ac7ddfbfSEd Maste
GetAsyncExecution()873435933ddSDimitry Andric bool Debugger::GetAsyncExecution() {
874ac7ddfbfSEd Maste return !m_command_interpreter_ap->GetSynchronous();
875ac7ddfbfSEd Maste }
876ac7ddfbfSEd Maste
SetAsyncExecution(bool async_execution)877435933ddSDimitry Andric void Debugger::SetAsyncExecution(bool async_execution) {
878ac7ddfbfSEd Maste m_command_interpreter_ap->SetSynchronous(!async_execution);
879ac7ddfbfSEd Maste }
880ac7ddfbfSEd Maste
SetInputFileHandle(FILE * fh,bool tranfer_ownership)881435933ddSDimitry Andric void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) {
88212b93ac6SEd Maste if (m_input_file_sp)
88312b93ac6SEd Maste m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership);
88412b93ac6SEd Maste else
885f678e45dSDimitry Andric m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
88612b93ac6SEd Maste
88712b93ac6SEd Maste File &in_file = m_input_file_sp->GetFile();
8884bb0738eSEd Maste if (!in_file.IsValid())
889ac7ddfbfSEd Maste in_file.SetStream(stdin, true);
890ac7ddfbfSEd Maste
8914ba319b5SDimitry Andric // Save away the terminal state if that is relevant, so that we can restore
8924ba319b5SDimitry Andric // it in RestoreInputState.
893ac7ddfbfSEd Maste SaveInputTerminalState();
894ac7ddfbfSEd Maste }
895ac7ddfbfSEd Maste
SetOutputFileHandle(FILE * fh,bool tranfer_ownership)896435933ddSDimitry Andric void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
89712b93ac6SEd Maste if (m_output_file_sp)
89812b93ac6SEd Maste m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership);
89912b93ac6SEd Maste else
900f678e45dSDimitry Andric m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
90112b93ac6SEd Maste
90212b93ac6SEd Maste File &out_file = m_output_file_sp->GetFile();
9034bb0738eSEd Maste if (!out_file.IsValid())
904ac7ddfbfSEd Maste out_file.SetStream(stdout, false);
905ac7ddfbfSEd Maste
9064ba319b5SDimitry Andric // do not create the ScriptInterpreter just for setting the output file
9074ba319b5SDimitry Andric // handle as the constructor will know how to do the right thing on its own
908ac7ddfbfSEd Maste const bool can_create = false;
909435933ddSDimitry Andric ScriptInterpreter *script_interpreter =
910435933ddSDimitry Andric GetCommandInterpreter().GetScriptInterpreter(can_create);
911ac7ddfbfSEd Maste if (script_interpreter)
912ac7ddfbfSEd Maste script_interpreter->ResetOutputFileHandle(fh);
913ac7ddfbfSEd Maste }
914ac7ddfbfSEd Maste
SetErrorFileHandle(FILE * fh,bool tranfer_ownership)915435933ddSDimitry Andric void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
91612b93ac6SEd Maste if (m_error_file_sp)
91712b93ac6SEd Maste m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership);
91812b93ac6SEd Maste else
919f678e45dSDimitry Andric m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
92012b93ac6SEd Maste
92112b93ac6SEd Maste File &err_file = m_error_file_sp->GetFile();
9224bb0738eSEd Maste if (!err_file.IsValid())
923ac7ddfbfSEd Maste err_file.SetStream(stderr, false);
924ac7ddfbfSEd Maste }
925ac7ddfbfSEd Maste
SaveInputTerminalState()926435933ddSDimitry Andric void Debugger::SaveInputTerminalState() {
927435933ddSDimitry Andric if (m_input_file_sp) {
92812b93ac6SEd Maste File &in_file = m_input_file_sp->GetFile();
929ac7ddfbfSEd Maste if (in_file.GetDescriptor() != File::kInvalidDescriptor)
930ac7ddfbfSEd Maste m_terminal_state.Save(in_file.GetDescriptor(), true);
931ac7ddfbfSEd Maste }
93212b93ac6SEd Maste }
933ac7ddfbfSEd Maste
RestoreInputTerminalState()934435933ddSDimitry Andric void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
935ac7ddfbfSEd Maste
GetSelectedExecutionContext()936435933ddSDimitry Andric ExecutionContext Debugger::GetSelectedExecutionContext() {
937ac7ddfbfSEd Maste ExecutionContext exe_ctx;
938ac7ddfbfSEd Maste TargetSP target_sp(GetSelectedTarget());
939ac7ddfbfSEd Maste exe_ctx.SetTargetSP(target_sp);
940ac7ddfbfSEd Maste
941435933ddSDimitry Andric if (target_sp) {
942ac7ddfbfSEd Maste ProcessSP process_sp(target_sp->GetProcessSP());
943ac7ddfbfSEd Maste exe_ctx.SetProcessSP(process_sp);
944435933ddSDimitry Andric if (process_sp && !process_sp->IsRunning()) {
945ac7ddfbfSEd Maste ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread());
946435933ddSDimitry Andric if (thread_sp) {
947ac7ddfbfSEd Maste exe_ctx.SetThreadSP(thread_sp);
948ac7ddfbfSEd Maste exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame());
9494bb0738eSEd Maste if (exe_ctx.GetFramePtr() == nullptr)
950ac7ddfbfSEd Maste exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0));
951ac7ddfbfSEd Maste }
952ac7ddfbfSEd Maste }
953ac7ddfbfSEd Maste }
954ac7ddfbfSEd Maste return exe_ctx;
955ac7ddfbfSEd Maste }
956ac7ddfbfSEd Maste
DispatchInputInterrupt()957435933ddSDimitry Andric void Debugger::DispatchInputInterrupt() {
9584bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
95912b93ac6SEd Maste IOHandlerSP reader_sp(m_input_reader_stack.Top());
960ac7ddfbfSEd Maste if (reader_sp)
96112b93ac6SEd Maste reader_sp->Interrupt();
962ac7ddfbfSEd Maste }
963ac7ddfbfSEd Maste
DispatchInputEndOfFile()964435933ddSDimitry Andric void Debugger::DispatchInputEndOfFile() {
9654bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
96612b93ac6SEd Maste IOHandlerSP reader_sp(m_input_reader_stack.Top());
967ac7ddfbfSEd Maste if (reader_sp)
96812b93ac6SEd Maste reader_sp->GotEOF();
969ac7ddfbfSEd Maste }
970ac7ddfbfSEd Maste
ClearIOHandlers()971435933ddSDimitry Andric void Debugger::ClearIOHandlers() {
972435933ddSDimitry Andric // The bottom input reader should be the main debugger input reader. We do
973435933ddSDimitry Andric // not want to close that one here.
9744bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
975435933ddSDimitry Andric while (m_input_reader_stack.GetSize() > 1) {
97612b93ac6SEd Maste IOHandlerSP reader_sp(m_input_reader_stack.Top());
977ac7ddfbfSEd Maste if (reader_sp)
9781c3bbb01SEd Maste PopIOHandler(reader_sp);
979ac7ddfbfSEd Maste }
980ac7ddfbfSEd Maste }
981ac7ddfbfSEd Maste
ExecuteIOHandlers()982435933ddSDimitry Andric void Debugger::ExecuteIOHandlers() {
983435933ddSDimitry Andric while (true) {
98412b93ac6SEd Maste IOHandlerSP reader_sp(m_input_reader_stack.Top());
985ac7ddfbfSEd Maste if (!reader_sp)
986ac7ddfbfSEd Maste break;
987ac7ddfbfSEd Maste
98812b93ac6SEd Maste reader_sp->Run();
98912b93ac6SEd Maste
99012b93ac6SEd Maste // Remove all input readers that are done from the top of the stack
991435933ddSDimitry Andric while (true) {
99212b93ac6SEd Maste IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
99312b93ac6SEd Maste if (top_reader_sp && top_reader_sp->GetIsDone())
9941c3bbb01SEd Maste PopIOHandler(top_reader_sp);
995ac7ddfbfSEd Maste else
996ac7ddfbfSEd Maste break;
997ac7ddfbfSEd Maste }
998ac7ddfbfSEd Maste }
99912b93ac6SEd Maste ClearIOHandlers();
100012b93ac6SEd Maste }
1001ac7ddfbfSEd Maste
IsTopIOHandler(const lldb::IOHandlerSP & reader_sp)1002435933ddSDimitry Andric bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
100312b93ac6SEd Maste return m_input_reader_stack.IsTop(reader_sp);
100412b93ac6SEd Maste }
1005ac7ddfbfSEd Maste
CheckTopIOHandlerTypes(IOHandler::Type top_type,IOHandler::Type second_top_type)1006435933ddSDimitry Andric bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
1007435933ddSDimitry Andric IOHandler::Type second_top_type) {
10089f2f44ceSEd Maste return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
10099f2f44ceSEd Maste }
10109f2f44ceSEd Maste
PrintAsync(const char * s,size_t len,bool is_stdout)1011435933ddSDimitry Andric void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
10121c3bbb01SEd Maste lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile();
10131c3bbb01SEd Maste m_input_reader_stack.PrintAsync(stream.get(), s, len);
10141c3bbb01SEd Maste }
101512b93ac6SEd Maste
GetTopIOHandlerControlSequence(char ch)1016435933ddSDimitry Andric ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
101712b93ac6SEd Maste return m_input_reader_stack.GetTopIOHandlerControlSequence(ch);
1018ac7ddfbfSEd Maste }
1019ac7ddfbfSEd Maste
GetIOHandlerCommandPrefix()1020435933ddSDimitry Andric const char *Debugger::GetIOHandlerCommandPrefix() {
10211c3bbb01SEd Maste return m_input_reader_stack.GetTopIOHandlerCommandPrefix();
10221c3bbb01SEd Maste }
10231c3bbb01SEd Maste
GetIOHandlerHelpPrologue()1024435933ddSDimitry Andric const char *Debugger::GetIOHandlerHelpPrologue() {
10251c3bbb01SEd Maste return m_input_reader_stack.GetTopIOHandlerHelpPrologue();
10261c3bbb01SEd Maste }
10271c3bbb01SEd Maste
RunIOHandler(const IOHandlerSP & reader_sp)1028435933ddSDimitry Andric void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
102912b93ac6SEd Maste PushIOHandler(reader_sp);
10300127ef0fSEd Maste
10310127ef0fSEd Maste IOHandlerSP top_reader_sp = reader_sp;
1032435933ddSDimitry Andric while (top_reader_sp) {
10330127ef0fSEd Maste top_reader_sp->Run();
10340127ef0fSEd Maste
1035435933ddSDimitry Andric if (top_reader_sp.get() == reader_sp.get()) {
10360127ef0fSEd Maste if (PopIOHandler(reader_sp))
10370127ef0fSEd Maste break;
10380127ef0fSEd Maste }
10390127ef0fSEd Maste
1040435933ddSDimitry Andric while (true) {
10410127ef0fSEd Maste top_reader_sp = m_input_reader_stack.Top();
10420127ef0fSEd Maste if (top_reader_sp && top_reader_sp->GetIsDone())
10431c3bbb01SEd Maste PopIOHandler(top_reader_sp);
10440127ef0fSEd Maste else
10450127ef0fSEd Maste break;
10460127ef0fSEd Maste }
10470127ef0fSEd Maste }
104812b93ac6SEd Maste }
104912b93ac6SEd Maste
AdoptTopIOHandlerFilesIfInvalid(StreamFileSP & in,StreamFileSP & out,StreamFileSP & err)1050435933ddSDimitry Andric void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
1051435933ddSDimitry Andric StreamFileSP &out,
1052435933ddSDimitry Andric StreamFileSP &err) {
10534ba319b5SDimitry Andric // Before an IOHandler runs, it must have in/out/err streams. This function
10544ba319b5SDimitry Andric // is called when one ore more of the streams are nullptr. We use the top
10554ba319b5SDimitry Andric // input reader's in/out/err streams, or fall back to the debugger file
10564ba319b5SDimitry Andric // handles, or we fall back onto stdin/stdout/stderr as a last resort.
105712b93ac6SEd Maste
10584bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
105912b93ac6SEd Maste IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
106012b93ac6SEd Maste // If no STDIN has been set, then set it appropriately
1061435933ddSDimitry Andric if (!in) {
106212b93ac6SEd Maste if (top_reader_sp)
106312b93ac6SEd Maste in = top_reader_sp->GetInputStreamFile();
106412b93ac6SEd Maste else
106512b93ac6SEd Maste in = GetInputFile();
106612b93ac6SEd Maste
106712b93ac6SEd Maste // If there is nothing, use stdin
106812b93ac6SEd Maste if (!in)
1069f678e45dSDimitry Andric in = std::make_shared<StreamFile>(stdin, false);
107012b93ac6SEd Maste }
107112b93ac6SEd Maste // If no STDOUT has been set, then set it appropriately
1072435933ddSDimitry Andric if (!out) {
107312b93ac6SEd Maste if (top_reader_sp)
107412b93ac6SEd Maste out = top_reader_sp->GetOutputStreamFile();
107512b93ac6SEd Maste else
107612b93ac6SEd Maste out = GetOutputFile();
107712b93ac6SEd Maste
107812b93ac6SEd Maste // If there is nothing, use stdout
107912b93ac6SEd Maste if (!out)
1080f678e45dSDimitry Andric out = std::make_shared<StreamFile>(stdout, false);
108112b93ac6SEd Maste }
108212b93ac6SEd Maste // If no STDERR has been set, then set it appropriately
1083435933ddSDimitry Andric if (!err) {
108412b93ac6SEd Maste if (top_reader_sp)
108512b93ac6SEd Maste err = top_reader_sp->GetErrorStreamFile();
108612b93ac6SEd Maste else
108712b93ac6SEd Maste err = GetErrorFile();
108812b93ac6SEd Maste
108912b93ac6SEd Maste // If there is nothing, use stderr
109012b93ac6SEd Maste if (!err)
1091f678e45dSDimitry Andric err = std::make_shared<StreamFile>(stdout, false);
109212b93ac6SEd Maste }
109312b93ac6SEd Maste }
109412b93ac6SEd Maste
PushIOHandler(const IOHandlerSP & reader_sp,bool cancel_top_handler)1095*b5893f02SDimitry Andric void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
1096*b5893f02SDimitry Andric bool cancel_top_handler) {
1097ac7ddfbfSEd Maste if (!reader_sp)
1098ac7ddfbfSEd Maste return;
1099ac7ddfbfSEd Maste
11004bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
11011c3bbb01SEd Maste
11021c3bbb01SEd Maste // Get the current top input reader...
110312b93ac6SEd Maste IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
1104ac7ddfbfSEd Maste
11050127ef0fSEd Maste // Don't push the same IO handler twice...
11061c3bbb01SEd Maste if (reader_sp == top_reader_sp)
11071c3bbb01SEd Maste return;
11081c3bbb01SEd Maste
110912b93ac6SEd Maste // Push our new input reader
1110ac7ddfbfSEd Maste m_input_reader_stack.Push(reader_sp);
11111c3bbb01SEd Maste reader_sp->Activate();
111212b93ac6SEd Maste
11134ba319b5SDimitry Andric // Interrupt the top input reader to it will exit its Run() function and let
11144ba319b5SDimitry Andric // this new input reader take over
1115435933ddSDimitry Andric if (top_reader_sp) {
111612b93ac6SEd Maste top_reader_sp->Deactivate();
1117*b5893f02SDimitry Andric if (cancel_top_handler)
11181c3bbb01SEd Maste top_reader_sp->Cancel();
1119ac7ddfbfSEd Maste }
11200127ef0fSEd Maste }
1121ac7ddfbfSEd Maste
PopIOHandler(const IOHandlerSP & pop_reader_sp)1122435933ddSDimitry Andric bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
11231c3bbb01SEd Maste if (!pop_reader_sp)
11241c3bbb01SEd Maste return false;
1125ac7ddfbfSEd Maste
11264bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
112712b93ac6SEd Maste
11284ba319b5SDimitry Andric // The reader on the stop of the stack is done, so let the next read on the
11294ba319b5SDimitry Andric // stack refresh its prompt and if there is one...
11301c3bbb01SEd Maste if (m_input_reader_stack.IsEmpty())
11311c3bbb01SEd Maste return false;
11321c3bbb01SEd Maste
113312b93ac6SEd Maste IOHandlerSP reader_sp(m_input_reader_stack.Top());
1134ac7ddfbfSEd Maste
11351c3bbb01SEd Maste if (pop_reader_sp != reader_sp)
11361c3bbb01SEd Maste return false;
11371c3bbb01SEd Maste
113812b93ac6SEd Maste reader_sp->Deactivate();
11390127ef0fSEd Maste reader_sp->Cancel();
1140ac7ddfbfSEd Maste m_input_reader_stack.Pop();
1141ac7ddfbfSEd Maste
1142ac7ddfbfSEd Maste reader_sp = m_input_reader_stack.Top();
1143ac7ddfbfSEd Maste if (reader_sp)
114412b93ac6SEd Maste reader_sp->Activate();
114512b93ac6SEd Maste
114612b93ac6SEd Maste return true;
1147ac7ddfbfSEd Maste }
1148ac7ddfbfSEd Maste
GetAsyncOutputStream()1149435933ddSDimitry Andric StreamSP Debugger::GetAsyncOutputStream() {
1150f678e45dSDimitry Andric return std::make_shared<StreamAsynchronousIO>(*this, true);
1151ac7ddfbfSEd Maste }
1152ac7ddfbfSEd Maste
GetAsyncErrorStream()1153435933ddSDimitry Andric StreamSP Debugger::GetAsyncErrorStream() {
1154f678e45dSDimitry Andric return std::make_shared<StreamAsynchronousIO>(*this, false);
1155ac7ddfbfSEd Maste }
1156ac7ddfbfSEd Maste
GetNumDebuggers()1157435933ddSDimitry Andric size_t Debugger::GetNumDebuggers() {
1158435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11594bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11604bb0738eSEd Maste return g_debugger_list_ptr->size();
1161ac7ddfbfSEd Maste }
1162ac7ddfbfSEd Maste return 0;
1163ac7ddfbfSEd Maste }
1164ac7ddfbfSEd Maste
GetDebuggerAtIndex(size_t index)1165435933ddSDimitry Andric lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1166ac7ddfbfSEd Maste DebuggerSP debugger_sp;
1167ac7ddfbfSEd Maste
1168435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11694bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11704bb0738eSEd Maste if (index < g_debugger_list_ptr->size())
11714bb0738eSEd Maste debugger_sp = g_debugger_list_ptr->at(index);
1172ac7ddfbfSEd Maste }
1173ac7ddfbfSEd Maste
1174ac7ddfbfSEd Maste return debugger_sp;
1175ac7ddfbfSEd Maste }
1176ac7ddfbfSEd Maste
FindDebuggerWithID(lldb::user_id_t id)1177435933ddSDimitry Andric DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
1178ac7ddfbfSEd Maste DebuggerSP debugger_sp;
1179ac7ddfbfSEd Maste
1180435933ddSDimitry Andric if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11814bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11824bb0738eSEd Maste DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1183435933ddSDimitry Andric for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1184435933ddSDimitry Andric if ((*pos)->GetID() == id) {
1185ac7ddfbfSEd Maste debugger_sp = *pos;
1186ac7ddfbfSEd Maste break;
1187ac7ddfbfSEd Maste }
1188ac7ddfbfSEd Maste }
1189ac7ddfbfSEd Maste }
1190ac7ddfbfSEd Maste return debugger_sp;
1191ac7ddfbfSEd Maste }
1192ac7ddfbfSEd Maste
FormatDisassemblerAddress(const FormatEntity::Entry * format,const SymbolContext * sc,const SymbolContext * prev_sc,const ExecutionContext * exe_ctx,const Address * addr,Stream & s)1193435933ddSDimitry Andric bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
11947aa51b79SEd Maste const SymbolContext *sc,
11957aa51b79SEd Maste const SymbolContext *prev_sc,
11967aa51b79SEd Maste const ExecutionContext *exe_ctx,
1197435933ddSDimitry Andric const Address *addr, Stream &s) {
11981c3bbb01SEd Maste FormatEntity::Entry format_entry;
11991c3bbb01SEd Maste
1200435933ddSDimitry Andric if (format == nullptr) {
12014bb0738eSEd Maste if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
12027aa51b79SEd Maste format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1203435933ddSDimitry Andric if (format == nullptr) {
12041c3bbb01SEd Maste FormatEntity::Parse("${addr}: ", format_entry);
12051c3bbb01SEd Maste format = &format_entry;
12061c3bbb01SEd Maste }
12077aa51b79SEd Maste }
12087aa51b79SEd Maste bool function_changed = false;
12097aa51b79SEd Maste bool initial_function = false;
1210435933ddSDimitry Andric if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1211435933ddSDimitry Andric if (sc && (sc->function || sc->symbol)) {
1212435933ddSDimitry Andric if (prev_sc->symbol && sc->symbol) {
1213435933ddSDimitry Andric if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1214435933ddSDimitry Andric prev_sc->symbol->GetType())) {
12157aa51b79SEd Maste function_changed = true;
12167aa51b79SEd Maste }
1217435933ddSDimitry Andric } else if (prev_sc->function && sc->function) {
1218435933ddSDimitry Andric if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
12197aa51b79SEd Maste function_changed = true;
12207aa51b79SEd Maste }
12217aa51b79SEd Maste }
12227aa51b79SEd Maste }
12237aa51b79SEd Maste }
12244ba319b5SDimitry Andric // The first context on a list of instructions will have a prev_sc that has
12254ba319b5SDimitry Andric // no Function or Symbol -- if SymbolContext had an IsValid() method, it
12267aa51b79SEd Maste // would return false. But we do get a prev_sc pointer.
1227435933ddSDimitry Andric if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1228435933ddSDimitry Andric (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
12297aa51b79SEd Maste initial_function = true;
12307aa51b79SEd Maste }
1231435933ddSDimitry Andric return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1232435933ddSDimitry Andric function_changed, initial_function);
12337aa51b79SEd Maste }
12347aa51b79SEd Maste
SetLoggingCallback(lldb::LogOutputCallback log_callback,void * baton)1235435933ddSDimitry Andric void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1236435933ddSDimitry Andric void *baton) {
1237ac7ddfbfSEd Maste // For simplicity's sake, I am not going to deal with how to close down any
1238ac7ddfbfSEd Maste // open logging streams, I just redirect everything from here on out to the
1239ac7ddfbfSEd Maste // callback.
1240f678e45dSDimitry Andric m_log_callback_stream_sp =
1241f678e45dSDimitry Andric std::make_shared<StreamCallback>(log_callback, baton);
1242ac7ddfbfSEd Maste }
1243ac7ddfbfSEd Maste
EnableLog(llvm::StringRef channel,llvm::ArrayRef<const char * > categories,llvm::StringRef log_file,uint32_t log_options,llvm::raw_ostream & error_stream)1244f678e45dSDimitry Andric bool Debugger::EnableLog(llvm::StringRef channel,
1245f678e45dSDimitry Andric llvm::ArrayRef<const char *> categories,
1246f678e45dSDimitry Andric llvm::StringRef log_file, uint32_t log_options,
1247f678e45dSDimitry Andric llvm::raw_ostream &error_stream) {
1248f678e45dSDimitry Andric const bool should_close = true;
1249f678e45dSDimitry Andric const bool unbuffered = true;
1250f678e45dSDimitry Andric
1251f678e45dSDimitry Andric std::shared_ptr<llvm::raw_ostream> log_stream_sp;
1252435933ddSDimitry Andric if (m_log_callback_stream_sp) {
1253ac7ddfbfSEd Maste log_stream_sp = m_log_callback_stream_sp;
1254ac7ddfbfSEd Maste // For now when using the callback mode you always get thread & timestamp.
1255435933ddSDimitry Andric log_options |=
1256435933ddSDimitry Andric LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
1257f678e45dSDimitry Andric } else if (log_file.empty()) {
1258f678e45dSDimitry Andric log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
1259f678e45dSDimitry Andric GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered);
1260435933ddSDimitry Andric } else {
1261f678e45dSDimitry Andric auto pos = m_log_streams.find(log_file);
1262ac7ddfbfSEd Maste if (pos != m_log_streams.end())
1263ac7ddfbfSEd Maste log_stream_sp = pos->second.lock();
1264435933ddSDimitry Andric if (!log_stream_sp) {
1265f678e45dSDimitry Andric llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text;
1266f678e45dSDimitry Andric if (log_options & LLDB_LOG_OPTION_APPEND)
1267f678e45dSDimitry Andric flags |= llvm::sys::fs::F_Append;
1268f678e45dSDimitry Andric int FD;
12694ba319b5SDimitry Andric if (std::error_code ec = llvm::sys::fs::openFileForWrite(
12704ba319b5SDimitry Andric log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) {
1271f678e45dSDimitry Andric error_stream << "Unable to open log file: " << ec.message();
1272f678e45dSDimitry Andric return false;
1273f678e45dSDimitry Andric }
1274f678e45dSDimitry Andric log_stream_sp =
1275f678e45dSDimitry Andric std::make_shared<llvm::raw_fd_ostream>(FD, should_close, unbuffered);
1276ac7ddfbfSEd Maste m_log_streams[log_file] = log_stream_sp;
1277ac7ddfbfSEd Maste }
1278ac7ddfbfSEd Maste }
12794bb0738eSEd Maste assert(log_stream_sp);
1280ac7ddfbfSEd Maste
1281ac7ddfbfSEd Maste if (log_options == 0)
1282435933ddSDimitry Andric log_options =
1283435933ddSDimitry Andric LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
1284ac7ddfbfSEd Maste
1285435933ddSDimitry Andric return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
1286435933ddSDimitry Andric error_stream);
1287ac7ddfbfSEd Maste }
1288ac7ddfbfSEd Maste
GetSourceManager()1289435933ddSDimitry Andric SourceManager &Debugger::GetSourceManager() {
12904bb0738eSEd Maste if (!m_source_manager_ap)
1291f678e45dSDimitry Andric m_source_manager_ap = llvm::make_unique<SourceManager>(shared_from_this());
1292ac7ddfbfSEd Maste return *m_source_manager_ap;
1293ac7ddfbfSEd Maste }
1294ac7ddfbfSEd Maste
129512b93ac6SEd Maste // This function handles events that were broadcast by the process.
HandleBreakpointEvent(const EventSP & event_sp)1296435933ddSDimitry Andric void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
129712b93ac6SEd Maste using namespace lldb;
1298435933ddSDimitry Andric const uint32_t event_type =
1299435933ddSDimitry Andric Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1300435933ddSDimitry Andric event_sp);
130112b93ac6SEd Maste
130212b93ac6SEd Maste // if (event_type & eBreakpointEventTypeAdded
130312b93ac6SEd Maste // || event_type & eBreakpointEventTypeRemoved
130412b93ac6SEd Maste // || event_type & eBreakpointEventTypeEnabled
130512b93ac6SEd Maste // || event_type & eBreakpointEventTypeDisabled
130612b93ac6SEd Maste // || event_type & eBreakpointEventTypeCommandChanged
130712b93ac6SEd Maste // || event_type & eBreakpointEventTypeConditionChanged
130812b93ac6SEd Maste // || event_type & eBreakpointEventTypeIgnoreChanged
130912b93ac6SEd Maste // || event_type & eBreakpointEventTypeLocationsResolved)
131012b93ac6SEd Maste // {
1311435933ddSDimitry Andric // // Don't do anything about these events, since the breakpoint
1312435933ddSDimitry Andric // commands already echo these actions.
131312b93ac6SEd Maste // }
131412b93ac6SEd Maste //
1315435933ddSDimitry Andric if (event_type & eBreakpointEventTypeLocationsAdded) {
1316435933ddSDimitry Andric uint32_t num_new_locations =
1317435933ddSDimitry Andric Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1318435933ddSDimitry Andric event_sp);
1319435933ddSDimitry Andric if (num_new_locations > 0) {
1320435933ddSDimitry Andric BreakpointSP breakpoint =
1321435933ddSDimitry Andric Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
13221c3bbb01SEd Maste StreamSP output_sp(GetAsyncOutputStream());
1323435933ddSDimitry Andric if (output_sp) {
132412b93ac6SEd Maste output_sp->Printf("%d location%s added to breakpoint %d\n",
1325435933ddSDimitry Andric num_new_locations, num_new_locations == 1 ? "" : "s",
132612b93ac6SEd Maste breakpoint->GetID());
13271c3bbb01SEd Maste output_sp->Flush();
132812b93ac6SEd Maste }
132912b93ac6SEd Maste }
133012b93ac6SEd Maste }
133112b93ac6SEd Maste // else if (event_type & eBreakpointEventTypeLocationsRemoved)
133212b93ac6SEd Maste // {
1333435933ddSDimitry Andric // // These locations just get disabled, not sure it is worth spamming
1334435933ddSDimitry Andric // folks about this on the command line.
133512b93ac6SEd Maste // }
133612b93ac6SEd Maste // else if (event_type & eBreakpointEventTypeLocationsResolved)
133712b93ac6SEd Maste // {
1338435933ddSDimitry Andric // // This might be an interesting thing to note, but I'm going to
1339435933ddSDimitry Andric // leave it quiet for now, it just looked noisy.
134012b93ac6SEd Maste // }
134112b93ac6SEd Maste }
134212b93ac6SEd Maste
GetProcessSTDOUT(Process * process,Stream * stream)1343435933ddSDimitry Andric size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) {
134412b93ac6SEd Maste size_t total_bytes = 0;
13454bb0738eSEd Maste if (stream == nullptr)
134612b93ac6SEd Maste stream = GetOutputFile().get();
134712b93ac6SEd Maste
1348435933ddSDimitry Andric if (stream) {
1349435933ddSDimitry Andric // The process has stuff waiting for stdout; get it and write it out to the
1350435933ddSDimitry Andric // appropriate place.
1351435933ddSDimitry Andric if (process == nullptr) {
135212b93ac6SEd Maste TargetSP target_sp = GetTargetList().GetSelectedTarget();
135312b93ac6SEd Maste if (target_sp)
135412b93ac6SEd Maste process = target_sp->GetProcessSP().get();
135512b93ac6SEd Maste }
1356435933ddSDimitry Andric if (process) {
13575517e702SDimitry Andric Status error;
135812b93ac6SEd Maste size_t len;
135912b93ac6SEd Maste char stdio_buffer[1024];
1360435933ddSDimitry Andric while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
1361435933ddSDimitry Andric error)) > 0) {
136212b93ac6SEd Maste stream->Write(stdio_buffer, len);
136312b93ac6SEd Maste total_bytes += len;
136412b93ac6SEd Maste }
136512b93ac6SEd Maste }
136612b93ac6SEd Maste stream->Flush();
136712b93ac6SEd Maste }
136812b93ac6SEd Maste return total_bytes;
136912b93ac6SEd Maste }
137012b93ac6SEd Maste
GetProcessSTDERR(Process * process,Stream * stream)1371435933ddSDimitry Andric size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) {
137212b93ac6SEd Maste size_t total_bytes = 0;
13734bb0738eSEd Maste if (stream == nullptr)
137412b93ac6SEd Maste stream = GetOutputFile().get();
137512b93ac6SEd Maste
1376435933ddSDimitry Andric if (stream) {
1377435933ddSDimitry Andric // The process has stuff waiting for stderr; get it and write it out to the
1378435933ddSDimitry Andric // appropriate place.
1379435933ddSDimitry Andric if (process == nullptr) {
138012b93ac6SEd Maste TargetSP target_sp = GetTargetList().GetSelectedTarget();
138112b93ac6SEd Maste if (target_sp)
138212b93ac6SEd Maste process = target_sp->GetProcessSP().get();
138312b93ac6SEd Maste }
1384435933ddSDimitry Andric if (process) {
13855517e702SDimitry Andric Status error;
138612b93ac6SEd Maste size_t len;
138712b93ac6SEd Maste char stdio_buffer[1024];
1388435933ddSDimitry Andric while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
1389435933ddSDimitry Andric error)) > 0) {
139012b93ac6SEd Maste stream->Write(stdio_buffer, len);
139112b93ac6SEd Maste total_bytes += len;
139212b93ac6SEd Maste }
139312b93ac6SEd Maste }
139412b93ac6SEd Maste stream->Flush();
139512b93ac6SEd Maste }
139612b93ac6SEd Maste return total_bytes;
139712b93ac6SEd Maste }
139812b93ac6SEd Maste
139912b93ac6SEd Maste // This function handles events that were broadcast by the process.
HandleProcessEvent(const EventSP & event_sp)1400435933ddSDimitry Andric void Debugger::HandleProcessEvent(const EventSP &event_sp) {
140112b93ac6SEd Maste using namespace lldb;
140212b93ac6SEd Maste const uint32_t event_type = event_sp->GetType();
1403435933ddSDimitry Andric ProcessSP process_sp =
1404435933ddSDimitry Andric (event_type == Process::eBroadcastBitStructuredData)
1405435933ddSDimitry Andric ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
1406435933ddSDimitry Andric : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
140712b93ac6SEd Maste
14081c3bbb01SEd Maste StreamSP output_stream_sp = GetAsyncOutputStream();
14091c3bbb01SEd Maste StreamSP error_stream_sp = GetAsyncErrorStream();
141012b93ac6SEd Maste const bool gui_enabled = IsForwardingEvents();
141112b93ac6SEd Maste
1412435933ddSDimitry Andric if (!gui_enabled) {
14130127ef0fSEd Maste bool pop_process_io_handler = false;
141412b93ac6SEd Maste assert(process_sp);
141512b93ac6SEd Maste
14161c3bbb01SEd Maste bool state_is_stopped = false;
1417435933ddSDimitry Andric const bool got_state_changed =
1418435933ddSDimitry Andric (event_type & Process::eBroadcastBitStateChanged) != 0;
14191c3bbb01SEd Maste const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
14201c3bbb01SEd Maste const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1421435933ddSDimitry Andric const bool got_structured_data =
1422435933ddSDimitry Andric (event_type & Process::eBroadcastBitStructuredData) != 0;
1423435933ddSDimitry Andric
1424435933ddSDimitry Andric if (got_state_changed) {
1425435933ddSDimitry Andric StateType event_state =
1426435933ddSDimitry Andric Process::ProcessEventData::GetStateFromEvent(event_sp.get());
14271c3bbb01SEd Maste state_is_stopped = StateIsStoppedState(event_state, false);
142812b93ac6SEd Maste }
14290127ef0fSEd Maste
14301c3bbb01SEd Maste // Display running state changes first before any STDIO
1431435933ddSDimitry Andric if (got_state_changed && !state_is_stopped) {
1432435933ddSDimitry Andric Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1433435933ddSDimitry Andric pop_process_io_handler);
143412b93ac6SEd Maste }
14350127ef0fSEd Maste
14361c3bbb01SEd Maste // Now display and STDOUT
1437435933ddSDimitry Andric if (got_stdout || got_state_changed) {
14381c3bbb01SEd Maste GetProcessSTDOUT(process_sp.get(), output_stream_sp.get());
143912b93ac6SEd Maste }
14400127ef0fSEd Maste
14411c3bbb01SEd Maste // Now display and STDERR
1442435933ddSDimitry Andric if (got_stderr || got_state_changed) {
14431c3bbb01SEd Maste GetProcessSTDERR(process_sp.get(), error_stream_sp.get());
14440127ef0fSEd Maste }
14450127ef0fSEd Maste
1446435933ddSDimitry Andric // Give structured data events an opportunity to display.
1447435933ddSDimitry Andric if (got_structured_data) {
1448435933ddSDimitry Andric StructuredDataPluginSP plugin_sp =
1449435933ddSDimitry Andric EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1450435933ddSDimitry Andric if (plugin_sp) {
1451435933ddSDimitry Andric auto structured_data_sp =
1452435933ddSDimitry Andric EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1453435933ddSDimitry Andric if (output_stream_sp) {
1454435933ddSDimitry Andric StreamString content_stream;
14555517e702SDimitry Andric Status error =
1456435933ddSDimitry Andric plugin_sp->GetDescription(structured_data_sp, content_stream);
1457435933ddSDimitry Andric if (error.Success()) {
1458435933ddSDimitry Andric if (!content_stream.GetString().empty()) {
1459435933ddSDimitry Andric // Add newline.
1460435933ddSDimitry Andric content_stream.PutChar('\n');
1461435933ddSDimitry Andric content_stream.Flush();
1462435933ddSDimitry Andric
1463435933ddSDimitry Andric // Print it.
1464435933ddSDimitry Andric output_stream_sp->PutCString(content_stream.GetString());
1465435933ddSDimitry Andric }
1466435933ddSDimitry Andric } else {
1467435933ddSDimitry Andric error_stream_sp->Printf("Failed to print structured "
1468435933ddSDimitry Andric "data with plugin %s: %s",
1469435933ddSDimitry Andric plugin_sp->GetPluginName().AsCString(),
1470435933ddSDimitry Andric error.AsCString());
1471435933ddSDimitry Andric }
1472435933ddSDimitry Andric }
1473435933ddSDimitry Andric }
1474435933ddSDimitry Andric }
1475435933ddSDimitry Andric
14761c3bbb01SEd Maste // Now display any stopped state changes after any STDIO
1477435933ddSDimitry Andric if (got_state_changed && state_is_stopped) {
1478435933ddSDimitry Andric Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1479435933ddSDimitry Andric pop_process_io_handler);
148012b93ac6SEd Maste }
148112b93ac6SEd Maste
14821c3bbb01SEd Maste output_stream_sp->Flush();
14831c3bbb01SEd Maste error_stream_sp->Flush();
148412b93ac6SEd Maste
14850127ef0fSEd Maste if (pop_process_io_handler)
14860127ef0fSEd Maste process_sp->PopProcessIOHandler();
14870127ef0fSEd Maste }
14880127ef0fSEd Maste }
14890127ef0fSEd Maste
HandleThreadEvent(const EventSP & event_sp)1490435933ddSDimitry Andric void Debugger::HandleThreadEvent(const EventSP &event_sp) {
14914ba319b5SDimitry Andric // At present the only thread event we handle is the Frame Changed event, and
14924ba319b5SDimitry Andric // all we do for that is just reprint the thread status for that thread.
149312b93ac6SEd Maste using namespace lldb;
149412b93ac6SEd Maste const uint32_t event_type = event_sp->GetType();
1495435933ddSDimitry Andric const bool stop_format = true;
149612b93ac6SEd Maste if (event_type == Thread::eBroadcastBitStackChanged ||
1497435933ddSDimitry Andric event_type == Thread::eBroadcastBitThreadSelected) {
1498435933ddSDimitry Andric ThreadSP thread_sp(
1499435933ddSDimitry Andric Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1500435933ddSDimitry Andric if (thread_sp) {
1501435933ddSDimitry Andric thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
150212b93ac6SEd Maste }
150312b93ac6SEd Maste }
150412b93ac6SEd Maste }
150512b93ac6SEd Maste
IsForwardingEvents()1506435933ddSDimitry Andric bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
150712b93ac6SEd Maste
EnableForwardEvents(const ListenerSP & listener_sp)1508435933ddSDimitry Andric void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
150912b93ac6SEd Maste m_forward_listener_sp = listener_sp;
151012b93ac6SEd Maste }
151112b93ac6SEd Maste
CancelForwardEvents(const ListenerSP & listener_sp)1512435933ddSDimitry Andric void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
151312b93ac6SEd Maste m_forward_listener_sp.reset();
151412b93ac6SEd Maste }
151512b93ac6SEd Maste
DefaultEventHandler()1516435933ddSDimitry Andric void Debugger::DefaultEventHandler() {
15174bb0738eSEd Maste ListenerSP listener_sp(GetListener());
151812b93ac6SEd Maste ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
151912b93ac6SEd Maste ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
152012b93ac6SEd Maste ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
152112b93ac6SEd Maste BroadcastEventSpec target_event_spec(broadcaster_class_target,
152212b93ac6SEd Maste Target::eBroadcastBitBreakpointChanged);
152312b93ac6SEd Maste
1524435933ddSDimitry Andric BroadcastEventSpec process_event_spec(
1525435933ddSDimitry Andric broadcaster_class_process,
1526435933ddSDimitry Andric Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1527435933ddSDimitry Andric Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
152812b93ac6SEd Maste
152912b93ac6SEd Maste BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
153012b93ac6SEd Maste Thread::eBroadcastBitStackChanged |
153112b93ac6SEd Maste Thread::eBroadcastBitThreadSelected);
153212b93ac6SEd Maste
1533435933ddSDimitry Andric listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1534435933ddSDimitry Andric target_event_spec);
1535435933ddSDimitry Andric listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1536435933ddSDimitry Andric process_event_spec);
1537435933ddSDimitry Andric listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1538435933ddSDimitry Andric thread_event_spec);
1539435933ddSDimitry Andric listener_sp->StartListeningForEvents(
1540435933ddSDimitry Andric m_command_interpreter_ap.get(),
154112b93ac6SEd Maste CommandInterpreter::eBroadcastBitQuitCommandReceived |
154212b93ac6SEd Maste CommandInterpreter::eBroadcastBitAsynchronousOutputData |
154312b93ac6SEd Maste CommandInterpreter::eBroadcastBitAsynchronousErrorData);
154412b93ac6SEd Maste
15454ba319b5SDimitry Andric // Let the thread that spawned us know that we have started up and that we
15464ba319b5SDimitry Andric // are now listening to all required events so no events get missed
15477aa51b79SEd Maste m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
15487aa51b79SEd Maste
154912b93ac6SEd Maste bool done = false;
1550435933ddSDimitry Andric while (!done) {
155112b93ac6SEd Maste EventSP event_sp;
1552435933ddSDimitry Andric if (listener_sp->GetEvent(event_sp, llvm::None)) {
1553435933ddSDimitry Andric if (event_sp) {
155412b93ac6SEd Maste Broadcaster *broadcaster = event_sp->GetBroadcaster();
1555435933ddSDimitry Andric if (broadcaster) {
155612b93ac6SEd Maste uint32_t event_type = event_sp->GetType();
155712b93ac6SEd Maste ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1558435933ddSDimitry Andric if (broadcaster_class == broadcaster_class_process) {
155912b93ac6SEd Maste HandleProcessEvent(event_sp);
1560435933ddSDimitry Andric } else if (broadcaster_class == broadcaster_class_target) {
1561435933ddSDimitry Andric if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1562435933ddSDimitry Andric event_sp.get())) {
156312b93ac6SEd Maste HandleBreakpointEvent(event_sp);
156412b93ac6SEd Maste }
1565435933ddSDimitry Andric } else if (broadcaster_class == broadcaster_class_thread) {
156612b93ac6SEd Maste HandleThreadEvent(event_sp);
1567435933ddSDimitry Andric } else if (broadcaster == m_command_interpreter_ap.get()) {
1568435933ddSDimitry Andric if (event_type &
1569435933ddSDimitry Andric CommandInterpreter::eBroadcastBitQuitCommandReceived) {
157012b93ac6SEd Maste done = true;
1571435933ddSDimitry Andric } else if (event_type &
1572435933ddSDimitry Andric CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
1573435933ddSDimitry Andric const char *data = reinterpret_cast<const char *>(
1574435933ddSDimitry Andric EventDataBytes::GetBytesFromEvent(event_sp.get()));
1575435933ddSDimitry Andric if (data && data[0]) {
15761c3bbb01SEd Maste StreamSP error_sp(GetAsyncErrorStream());
1577435933ddSDimitry Andric if (error_sp) {
157812b93ac6SEd Maste error_sp->PutCString(data);
157912b93ac6SEd Maste error_sp->Flush();
158012b93ac6SEd Maste }
158112b93ac6SEd Maste }
1582435933ddSDimitry Andric } else if (event_type & CommandInterpreter::
1583435933ddSDimitry Andric eBroadcastBitAsynchronousOutputData) {
1584435933ddSDimitry Andric const char *data = reinterpret_cast<const char *>(
1585435933ddSDimitry Andric EventDataBytes::GetBytesFromEvent(event_sp.get()));
1586435933ddSDimitry Andric if (data && data[0]) {
15871c3bbb01SEd Maste StreamSP output_sp(GetAsyncOutputStream());
1588435933ddSDimitry Andric if (output_sp) {
158912b93ac6SEd Maste output_sp->PutCString(data);
159012b93ac6SEd Maste output_sp->Flush();
159112b93ac6SEd Maste }
159212b93ac6SEd Maste }
159312b93ac6SEd Maste }
159412b93ac6SEd Maste }
159512b93ac6SEd Maste }
159612b93ac6SEd Maste
159712b93ac6SEd Maste if (m_forward_listener_sp)
159812b93ac6SEd Maste m_forward_listener_sp->AddEvent(event_sp);
159912b93ac6SEd Maste }
160012b93ac6SEd Maste }
160112b93ac6SEd Maste }
160212b93ac6SEd Maste }
160312b93ac6SEd Maste
EventHandlerThread(lldb::thread_arg_t arg)1604435933ddSDimitry Andric lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
160512b93ac6SEd Maste ((Debugger *)arg)->DefaultEventHandler();
160612b93ac6SEd Maste return NULL;
160712b93ac6SEd Maste }
160812b93ac6SEd Maste
StartEventHandlerThread()1609435933ddSDimitry Andric bool Debugger::StartEventHandlerThread() {
1610435933ddSDimitry Andric if (!m_event_handler_thread.IsJoinable()) {
16114ba319b5SDimitry Andric // We must synchronize with the DefaultEventHandler() thread to ensure it
16124ba319b5SDimitry Andric // is up and running and listening to events before we return from this
16134ba319b5SDimitry Andric // function. We do this by listening to events for the
16147aa51b79SEd Maste // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
16154ba319b5SDimitry Andric ConstString full_name("lldb.debugger.event-handler");
16164ba319b5SDimitry Andric ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
1617435933ddSDimitry Andric listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1618435933ddSDimitry Andric eBroadcastBitEventThreadIsListening);
16197aa51b79SEd Maste
16204ba319b5SDimitry Andric auto thread_name =
16214ba319b5SDimitry Andric full_name.GetLength() < llvm::get_max_thread_name_length() ?
16224ba319b5SDimitry Andric full_name.AsCString() : "dbg.evt-handler";
16237aa51b79SEd Maste
16244ba319b5SDimitry Andric // Use larger 8MB stack for this thread
16254ba319b5SDimitry Andric m_event_handler_thread = ThreadLauncher::LaunchThread(thread_name,
16264ba319b5SDimitry Andric EventHandlerThread, this, nullptr, g_debugger_event_thread_stack_bytes);
16274ba319b5SDimitry Andric
16284ba319b5SDimitry Andric // Make sure DefaultEventHandler() is running and listening to events
16294ba319b5SDimitry Andric // before we return from this function. We are only listening for events of
16304ba319b5SDimitry Andric // type eBroadcastBitEventThreadIsListening so we don't need to check the
16314ba319b5SDimitry Andric // event, we just need to wait an infinite amount of time for it (nullptr
16324ba319b5SDimitry Andric // timeout as the first parameter)
16337aa51b79SEd Maste lldb::EventSP event_sp;
1634435933ddSDimitry Andric listener_sp->GetEvent(event_sp, llvm::None);
16357aa51b79SEd Maste }
16367aa51b79SEd Maste return m_event_handler_thread.IsJoinable();
163712b93ac6SEd Maste }
163812b93ac6SEd Maste
StopEventHandlerThread()1639435933ddSDimitry Andric void Debugger::StopEventHandlerThread() {
1640435933ddSDimitry Andric if (m_event_handler_thread.IsJoinable()) {
1641435933ddSDimitry Andric GetCommandInterpreter().BroadcastEvent(
1642435933ddSDimitry Andric CommandInterpreter::eBroadcastBitQuitCommandReceived);
16437aa51b79SEd Maste m_event_handler_thread.Join(nullptr);
164412b93ac6SEd Maste }
164512b93ac6SEd Maste }
164612b93ac6SEd Maste
IOHandlerThread(lldb::thread_arg_t arg)1647435933ddSDimitry Andric lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) {
164812b93ac6SEd Maste Debugger *debugger = (Debugger *)arg;
16491c3bbb01SEd Maste debugger->ExecuteIOHandlers();
165012b93ac6SEd Maste debugger->StopEventHandlerThread();
165112b93ac6SEd Maste return NULL;
165212b93ac6SEd Maste }
165312b93ac6SEd Maste
HasIOHandlerThread()1654435933ddSDimitry Andric bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
16559f2f44ceSEd Maste
StartIOHandlerThread()1656435933ddSDimitry Andric bool Debugger::StartIOHandlerThread() {
16577aa51b79SEd Maste if (!m_io_handler_thread.IsJoinable())
1658435933ddSDimitry Andric m_io_handler_thread = ThreadLauncher::LaunchThread(
1659435933ddSDimitry Andric "lldb.debugger.io-handler", IOHandlerThread, this, nullptr,
16607aa51b79SEd Maste 8 * 1024 * 1024); // Use larger 8MB stack for this thread
16617aa51b79SEd Maste return m_io_handler_thread.IsJoinable();
166212b93ac6SEd Maste }
166312b93ac6SEd Maste
StopIOHandlerThread()1664435933ddSDimitry Andric void Debugger::StopIOHandlerThread() {
1665435933ddSDimitry Andric if (m_io_handler_thread.IsJoinable()) {
166612b93ac6SEd Maste if (m_input_file_sp)
166712b93ac6SEd Maste m_input_file_sp->GetFile().Close();
16687aa51b79SEd Maste m_io_handler_thread.Join(nullptr);
166912b93ac6SEd Maste }
167012b93ac6SEd Maste }
167112b93ac6SEd Maste
JoinIOHandlerThread()1672435933ddSDimitry Andric void Debugger::JoinIOHandlerThread() {
1673435933ddSDimitry Andric if (HasIOHandlerThread()) {
16749f2f44ceSEd Maste thread_result_t result;
16759f2f44ceSEd Maste m_io_handler_thread.Join(&result);
16769f2f44ceSEd Maste m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
16779f2f44ceSEd Maste }
16789f2f44ceSEd Maste }
16799f2f44ceSEd Maste
GetDummyTarget()1680435933ddSDimitry Andric Target *Debugger::GetDummyTarget() {
16817aa51b79SEd Maste return m_target_list.GetDummyTarget(*this).get();
16827aa51b79SEd Maste }
16837aa51b79SEd Maste
GetSelectedOrDummyTarget(bool prefer_dummy)1684435933ddSDimitry Andric Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
16857aa51b79SEd Maste Target *target = nullptr;
1686435933ddSDimitry Andric if (!prefer_dummy) {
16877aa51b79SEd Maste target = m_target_list.GetSelectedTarget().get();
16887aa51b79SEd Maste if (target)
16897aa51b79SEd Maste return target;
16907aa51b79SEd Maste }
16917aa51b79SEd Maste
16927aa51b79SEd Maste return GetDummyTarget();
16937aa51b79SEd Maste }
169412b93ac6SEd Maste
RunREPL(LanguageType language,const char * repl_options)16955517e702SDimitry Andric Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
16965517e702SDimitry Andric Status err;
16979f2f44ceSEd Maste FileSpec repl_executable;
16989f2f44ceSEd Maste
1699435933ddSDimitry Andric if (language == eLanguageTypeUnknown) {
17009f2f44ceSEd Maste std::set<LanguageType> repl_languages;
17019f2f44ceSEd Maste
17029f2f44ceSEd Maste Language::GetLanguagesSupportingREPLs(repl_languages);
17039f2f44ceSEd Maste
1704435933ddSDimitry Andric if (repl_languages.size() == 1) {
17059f2f44ceSEd Maste language = *repl_languages.begin();
1706435933ddSDimitry Andric } else if (repl_languages.empty()) {
1707435933ddSDimitry Andric err.SetErrorStringWithFormat(
1708435933ddSDimitry Andric "LLDB isn't configured with REPL support for any languages.");
17099f2f44ceSEd Maste return err;
1710435933ddSDimitry Andric } else {
1711435933ddSDimitry Andric err.SetErrorStringWithFormat(
1712435933ddSDimitry Andric "Multiple possible REPL languages. Please specify a language.");
17139f2f44ceSEd Maste return err;
17149f2f44ceSEd Maste }
17159f2f44ceSEd Maste }
17169f2f44ceSEd Maste
1717435933ddSDimitry Andric Target *const target =
1718435933ddSDimitry Andric nullptr; // passing in an empty target means the REPL must create one
17199f2f44ceSEd Maste
17209f2f44ceSEd Maste REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
17219f2f44ceSEd Maste
1722435933ddSDimitry Andric if (!err.Success()) {
17239f2f44ceSEd Maste return err;
17249f2f44ceSEd Maste }
17259f2f44ceSEd Maste
1726435933ddSDimitry Andric if (!repl_sp) {
1727435933ddSDimitry Andric err.SetErrorStringWithFormat("couldn't find a REPL for %s",
1728435933ddSDimitry Andric Language::GetNameForLanguageType(language));
17299f2f44ceSEd Maste return err;
17309f2f44ceSEd Maste }
17319f2f44ceSEd Maste
17329f2f44ceSEd Maste repl_sp->SetCompilerOptions(repl_options);
17339f2f44ceSEd Maste repl_sp->RunLoop();
17349f2f44ceSEd Maste
17359f2f44ceSEd Maste return err;
17369f2f44ceSEd Maste }
1737