aboutsummaryrefslogtreecommitdiffstats
path: root/source/Core/Debugger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/Debugger.cpp')
-rw-r--r--source/Core/Debugger.cpp488
1 files changed, 172 insertions, 316 deletions
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index 1a69fc582d0c..18397d00dcaa 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -93,22 +93,47 @@ static DebuggerList *g_debugger_list_ptr =
nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
- {Debugger::eStopDisassemblyTypeNever, "never",
- "Never show disassembly when displaying a stop context."},
- {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo",
- "Show disassembly when there is no debug information."},
- {Debugger::eStopDisassemblyTypeNoSource, "no-source",
- "Show disassembly when there is no source information, or the source file "
- "is missing when displaying a stop context."},
- {Debugger::eStopDisassemblyTypeAlways, "always",
- "Always show disassembly when displaying a stop context."} };
+ {
+ Debugger::eStopDisassemblyTypeNever,
+ "never",
+ "Never show disassembly when displaying a stop context.",
+ },
+ {
+ Debugger::eStopDisassemblyTypeNoDebugInfo,
+ "no-debuginfo",
+ "Show disassembly when there is no debug information.",
+ },
+ {
+ Debugger::eStopDisassemblyTypeNoSource,
+ "no-source",
+ "Show disassembly when there is no source information, or the source "
+ "file "
+ "is missing when displaying a stop context.",
+ },
+ {
+ Debugger::eStopDisassemblyTypeAlways,
+ "always",
+ "Always show disassembly when displaying a stop context.",
+ },
+};
static constexpr OptionEnumValueElement g_language_enumerators[] = {
- {eScriptLanguageNone, "none", "Disable scripting languages."},
- {eScriptLanguagePython, "python",
- "Select python as the default scripting language."},
- {eScriptLanguageDefault, "default",
- "Select the lldb default as the default scripting language."} };
+ {
+ eScriptLanguageNone,
+ "none",
+ "Disable scripting languages.",
+ },
+ {
+ eScriptLanguagePython,
+ "python",
+ "Select python as the default scripting language.",
+ },
+ {
+ eScriptLanguageDefault,
+ "default",
+ "Select the lldb default as the default scripting language.",
+ },
+};
#define MODULE_WITH_FUNC \
"{ " \
@@ -189,133 +214,39 @@ static constexpr OptionEnumValueElement g_language_enumerators[] = {
// without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}:
static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
- {eStopShowColumnAnsiOrCaret, "ansi-or-caret",
- "Highlight the stop column with ANSI terminal codes when color/ANSI mode "
- "is enabled; otherwise, fall back to using a text-only caret (^) as if "
- "\"caret-only\" mode was selected."},
- {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI "
- "terminal codes when running LLDB with "
- "color/ANSI enabled."},
- {eStopShowColumnCaret, "caret",
- "Highlight the stop column with a caret character (^) underneath the stop "
- "column. This method introduces a new line in source listings that "
- "display thread stop locations."},
- {eStopShowColumnNone, "none", "Do not highlight the stop column."}};
-
-static constexpr PropertyDefinition g_properties[] = {
- {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, {},
- "If true all confirmation prompts will receive their default reply."},
- {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_DISASSEMBLY_FORMAT, {},
- "The default disassembly format "
- "string to use when disassembling "
- "instruction sequences."},
- {"frame-format", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_FRAME_FORMAT, {},
- "The default frame format string to use "
- "when displaying stack frame information "
- "for threads."},
- {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, {},
- "Notify the user explicitly if an expression returns void (default: "
- "false)."},
- {"prompt", OptionValue::eTypeString, true,
- OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", {},
- "The debugger command line prompt displayed for the user."},
- {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython,
- nullptr, OptionEnumValues(g_language_enumerators),
- "The script language to be used for evaluating user-written scripts."},
- {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, {},
- "The number of disassembly lines to show when displaying a "
- "stopped context."},
- {"stop-disassembly-display", OptionValue::eTypeEnum, true,
- Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr,
- OptionEnumValues(g_show_disassembly_enum_values),
- "Control when to display disassembly when displaying a stopped context."},
- {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, {},
- "The number of sources lines to display that come after the "
- "current source line when displaying a stopped context."},
- {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, {},
- "The number of sources lines to display that come before the "
- "current source line when displaying a stopped context."},
- {"highlight-source", OptionValue::eTypeBoolean, true, true, nullptr, {},
- "If true, LLDB will highlight the displayed source code."},
- {"stop-show-column", OptionValue::eTypeEnum, false,
- eStopShowColumnAnsiOrCaret, nullptr, OptionEnumValues(s_stop_show_column_values),
- "If true, LLDB will use the column information from the debug info to "
- "mark the current position when displaying a stopped context."},
- {"stop-show-column-ansi-prefix", OptionValue::eTypeString, true, 0,
- "${ansi.underline}", {},
- "When displaying the column marker in a color-enabled (i.e. ANSI) "
- "terminal, use the ANSI terminal code specified in this format at the "
- "immediately before the column to be marked."},
- {"stop-show-column-ansi-suffix", OptionValue::eTypeString, true, 0,
- "${ansi.normal}", {},
- "When displaying the column marker in a color-enabled (i.e. ANSI) "
- "terminal, use the ANSI terminal code specified in this format "
- "immediately after the column to be marked."},
- {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, {},
- "The maximum number of columns to use for displaying text."},
- {"thread-format", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_THREAD_FORMAT, {},
- "The default thread format string to use "
- "when displaying thread information."},
- {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_THREAD_STOP_FORMAT, {},
- "The default thread format "
- "string to use when displaying thread "
- "information as part of the stop display."},
- {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, {},
- "Whether to use an external editor or not."},
- {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, {},
- "Whether to use Ansi color codes or not."},
- {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr,
- {},
- "If true, LLDB will automatically display small structs in "
- "one-liner format (default: true)."},
- {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, {},
- "If true, LLDB will auto indent/outdent code. Currently only supported in "
- "the REPL (default: true)."},
- {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, {},
- "If true, LLDB will print the values of variables declared in an "
- "expression. Currently only supported in the REPL (default: true)."},
- {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, {},
- "The tab size to use when indenting code in multi-line input mode "
- "(default: 4)."},
- {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr,
- {},
- "If true, LLDB will automatically escape non-printable and "
- "escape characters when formatting strings."},
- {"frame-format-unique", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_FRAME_FORMAT_NO_ARGS, {},
- "The default frame format string to use when displaying stack frame"
- "information for threads from thread backtrace unique."}};
+ {
+ eStopShowColumnAnsiOrCaret,
+ "ansi-or-caret",
+ "Highlight the stop column with ANSI terminal codes when color/ANSI "
+ "mode is enabled; otherwise, fall back to using a text-only caret (^) "
+ "as if \"caret-only\" mode was selected.",
+ },
+ {
+ eStopShowColumnAnsi,
+ "ansi",
+ "Highlight the stop column with ANSI terminal codes when running LLDB "
+ "with color/ANSI enabled.",
+ },
+ {
+ eStopShowColumnCaret,
+ "caret",
+ "Highlight the stop column with a caret character (^) underneath the "
+ "stop column. This method introduces a new line in source listings "
+ "that display thread stop locations.",
+ },
+ {
+ eStopShowColumnNone,
+ "none",
+ "Do not highlight the stop column.",
+ },
+};
+
+#define LLDB_PROPERTIES_debugger
+#include "CoreProperties.inc"
enum {
- ePropertyAutoConfirm = 0,
- ePropertyDisassemblyFormat,
- ePropertyFrameFormat,
- ePropertyNotiftVoid,
- ePropertyPrompt,
- ePropertyScriptLanguage,
- ePropertyStopDisassemblyCount,
- ePropertyStopDisassemblyDisplay,
- ePropertyStopLineCountAfter,
- ePropertyStopLineCountBefore,
- ePropertyHighlightSource,
- ePropertyStopShowColumn,
- ePropertyStopShowColumnAnsiPrefix,
- ePropertyStopShowColumnAnsiSuffix,
- ePropertyTerminalWidth,
- ePropertyThreadFormat,
- ePropertyThreadStopFormat,
- ePropertyUseExternalEditor,
- ePropertyUseColor,
- ePropertyAutoOneLineSummaries,
- ePropertyAutoIndent,
- ePropertyPrintDecls,
- ePropertyTabSize,
- ePropertyEscapeNonPrintables,
- ePropertyFrameFormatUnique,
+#define LLDB_PROPERTIES_debugger
+#include "CorePropertiesEnum.inc"
};
LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
@@ -324,8 +255,16 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
VarSetOperationType op,
llvm::StringRef property_path,
llvm::StringRef value) {
- bool is_load_script = (property_path == "target.load-script-from-symbol-file");
- bool is_escape_non_printables = (property_path == "escape-non-printables");
+ bool is_load_script =
+ (property_path == "target.load-script-from-symbol-file");
+ // These properties might change how we visualize data.
+ bool invalidate_data_vis = (property_path == "escape-non-printables");
+ invalidate_data_vis |=
+ (property_path == "target.max-zero-padding-in-float-format");
+ if (invalidate_data_vis) {
+ DataVisualization::ForceUpdate();
+ }
+
TargetSP target_sp;
LoadScriptFromSymFile load_script_old_value;
if (is_load_script && exe_ctx->GetTargetSP()) {
@@ -336,18 +275,18 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
if (error.Success()) {
// FIXME it would be nice to have "on-change" callbacks for properties
- if (property_path == g_properties[ePropertyPrompt].name) {
+ if (property_path == g_debugger_properties[ePropertyPrompt].name) {
llvm::StringRef new_prompt = GetPrompt();
- std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes(
+ std::string str = lldb_private::ansi::FormatAnsiTerminalCodes(
new_prompt, GetUseColor());
if (str.length())
new_prompt = str;
GetCommandInterpreter().UpdatePrompt(new_prompt);
- auto bytes = llvm::make_unique<EventDataBytes>(new_prompt);
+ auto bytes = std::make_unique<EventDataBytes>(new_prompt);
auto prompt_change_event_sp = std::make_shared<Event>(
CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
- } else if (property_path == g_properties[ePropertyUseColor].name) {
+ } else if (property_path == g_debugger_properties[ePropertyUseColor].name) {
// use-color changed. Ping the prompt so it can reset the ansi terminal
// codes.
SetPrompt(GetPrompt());
@@ -358,18 +297,14 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
std::list<Status> errors;
StreamString feedback_stream;
if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
- StreamFileSP stream_sp(GetErrorFile());
- if (stream_sp) {
- for (auto error : errors) {
- stream_sp->Printf("%s\n", error.AsCString());
- }
- if (feedback_stream.GetSize())
- stream_sp->PutCString(feedback_stream.GetString());
+ Stream &s = GetErrorStream();
+ for (auto error : errors) {
+ s.Printf("%s\n", error.AsCString());
}
+ if (feedback_stream.GetSize())
+ s.PutCString(feedback_stream.GetString());
}
}
- } else if (is_escape_non_printables) {
- DataVisualization::ForceUpdate();
}
}
return error;
@@ -378,7 +313,7 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
bool Debugger::GetAutoConfirm() const {
const uint32_t idx = ePropertyAutoConfirm;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_properties[idx].default_uint_value != 0);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
}
const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
@@ -399,13 +334,13 @@ const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
bool Debugger::GetNotifyVoid() const {
const uint32_t idx = ePropertyNotiftVoid;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_properties[idx].default_uint_value != 0);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
}
llvm::StringRef Debugger::GetPrompt() const {
const uint32_t idx = ePropertyPrompt;
return m_collection_sp->GetPropertyAtIndexAsString(
- nullptr, idx, g_properties[idx].default_cstr_value);
+ nullptr, idx, g_debugger_properties[idx].default_cstr_value);
}
void Debugger::SetPrompt(llvm::StringRef p) {
@@ -413,7 +348,7 @@ void Debugger::SetPrompt(llvm::StringRef p) {
m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
llvm::StringRef new_prompt = GetPrompt();
std::string str =
- lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
+ lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
if (str.length())
new_prompt = str;
GetCommandInterpreter().UpdatePrompt(new_prompt);
@@ -437,7 +372,7 @@ const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
const uint32_t idx = ePropertyScriptLanguage;
return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_properties[idx].default_uint_value);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
}
bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
@@ -449,7 +384,7 @@ bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
uint32_t Debugger::GetTerminalWidth() const {
const uint32_t idx = ePropertyTerminalWidth;
return m_collection_sp->GetPropertyAtIndexAsSInt64(
- nullptr, idx, g_properties[idx].default_uint_value);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
}
bool Debugger::SetTerminalWidth(uint32_t term_width) {
@@ -460,7 +395,7 @@ bool Debugger::SetTerminalWidth(uint32_t term_width) {
bool Debugger::GetUseExternalEditor() const {
const uint32_t idx = ePropertyUseExternalEditor;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_properties[idx].default_uint_value != 0);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
}
bool Debugger::SetUseExternalEditor(bool b) {
@@ -471,7 +406,7 @@ bool Debugger::SetUseExternalEditor(bool b) {
bool Debugger::GetUseColor() const {
const uint32_t idx = ePropertyUseColor;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_properties[idx].default_uint_value != 0);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
}
bool Debugger::SetUseColor(bool b) {
@@ -484,13 +419,13 @@ bool Debugger::SetUseColor(bool b) {
bool Debugger::GetHighlightSource() const {
const uint32_t idx = ePropertyHighlightSource;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_properties[idx].default_uint_value);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
}
StopShowColumn Debugger::GetStopShowColumn() const {
const uint32_t idx = ePropertyStopShowColumn;
return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_properties[idx].default_uint_value);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
}
llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
@@ -507,20 +442,20 @@ uint32_t Debugger::GetStopSourceLineCount(bool before) const {
const uint32_t idx =
before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
return m_collection_sp->GetPropertyAtIndexAsSInt64(
- nullptr, idx, g_properties[idx].default_uint_value);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
}
Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
const uint32_t idx = ePropertyStopDisassemblyDisplay;
return (Debugger::StopDisassemblyType)
m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_properties[idx].default_uint_value);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
}
uint32_t Debugger::GetDisassemblyLineCount() const {
const uint32_t idx = ePropertyStopDisassemblyCount;
return m_collection_sp->GetPropertyAtIndexAsSInt64(
- nullptr, idx, g_properties[idx].default_uint_value);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
}
bool Debugger::GetAutoOneLineSummaries() const {
@@ -556,7 +491,7 @@ bool Debugger::SetPrintDecls(bool b) {
uint32_t Debugger::GetTabSize() const {
const uint32_t idx = ePropertyTabSize;
return m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_properties[idx].default_uint_value);
+ nullptr, idx, g_debugger_properties[idx].default_uint_value);
}
bool Debugger::SetTabSize(uint32_t tab_size) {
@@ -717,8 +652,7 @@ void Debugger::Destroy(DebuggerSP &debugger_sp) {
}
}
-DebuggerSP
-Debugger::FindDebuggerWithInstanceName(ConstString instance_name) {
+DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) {
DebuggerSP debugger_sp;
if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
@@ -764,16 +698,16 @@ TargetSP Debugger::FindTargetWithProcess(Process *process) {
Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
: UserID(g_unique_id++),
Properties(std::make_shared<OptionValueProperties>()),
- m_input_file_sp(std::make_shared<StreamFile>(stdin, false)),
- m_output_file_sp(std::make_shared<StreamFile>(stdout, false)),
- m_error_file_sp(std::make_shared<StreamFile>(stderr, false)),
+ m_input_file_sp(std::make_shared<NativeFile>(stdin, false)),
+ m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)),
+ m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)),
m_input_recorder(nullptr),
m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
m_terminal_state(), m_target_list(*this), m_platform_list(),
m_listener_sp(Listener::MakeListener("lldb.Debugger")),
m_source_manager_up(), m_source_file_cache(),
m_command_interpreter_up(
- llvm::make_unique<CommandInterpreter>(*this, false)),
+ std::make_unique<CommandInterpreter>(*this, false)),
m_script_interpreter_sp(), m_input_reader_stack(), m_instance_name(),
m_loaded_plugins(), m_event_handler_thread(), m_io_handler_thread(),
m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
@@ -790,7 +724,10 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
assert(default_platform_sp);
m_platform_list.Append(default_platform_sp, true);
- m_collection_sp->Initialize(g_properties);
+ m_dummy_target_sp = m_target_list.GetDummyTarget(*this);
+ assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?");
+
+ m_collection_sp->Initialize(g_debugger_properties);
m_collection_sp->AppendProperty(
ConstString("target"),
ConstString("Settings specify to debugging targets."), true,
@@ -818,7 +755,7 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
if (term && !strcmp(term, "dumb"))
SetUseColor(false);
// Turn off use-color if we don't write to a terminal with color support.
- if (!m_output_file_sp->GetFile().GetIsTerminalWithColors())
+ if (!GetOutputFile().GetIsTerminalWithColors())
SetUseColor(false);
#if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
@@ -859,8 +796,7 @@ void Debugger::Clear() {
// Close the input file _before_ we close the input read communications
// class as it does NOT own the input file, our m_input_file does.
m_terminal_state.Clear();
- if (m_input_file_sp)
- m_input_file_sp->GetFile().Close();
+ GetInputFile().Close();
m_command_interpreter_up->Clear();
});
@@ -885,57 +821,29 @@ void Debugger::SetAsyncExecution(bool async_execution) {
repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; }
-void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership,
- repro::DataRecorder *recorder) {
+void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) {
+ assert(file_sp && file_sp->IsValid());
m_input_recorder = recorder;
- if (m_input_file_sp)
- m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership);
- else
- m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
-
- File &in_file = m_input_file_sp->GetFile();
- if (!in_file.IsValid())
- in_file.SetStream(stdin, true);
-
+ m_input_file_sp = file_sp;
// Save away the terminal state if that is relevant, so that we can restore
// it in RestoreInputState.
SaveInputTerminalState();
}
-void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
- if (m_output_file_sp)
- m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership);
- else
- m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
-
- File &out_file = m_output_file_sp->GetFile();
- if (!out_file.IsValid())
- out_file.SetStream(stdout, false);
-
- // Do not create the ScriptInterpreter just for setting the output file
- // handle as the constructor will know how to do the right thing on its own.
- if (ScriptInterpreter *script_interpreter =
- GetScriptInterpreter(/*can_create=*/false))
- script_interpreter->ResetOutputFileHandle(fh);
+void Debugger::SetOutputFile(FileSP file_sp) {
+ assert(file_sp && file_sp->IsValid());
+ m_output_stream_sp = std::make_shared<StreamFile>(file_sp);
}
-void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
- if (m_error_file_sp)
- m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership);
- else
- m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
-
- File &err_file = m_error_file_sp->GetFile();
- if (!err_file.IsValid())
- err_file.SetStream(stderr, false);
+void Debugger::SetErrorFile(FileSP file_sp) {
+ assert(file_sp && file_sp->IsValid());
+ m_error_stream_sp = std::make_shared<StreamFile>(file_sp);
}
void Debugger::SaveInputTerminalState() {
- if (m_input_file_sp) {
- File &in_file = m_input_file_sp->GetFile();
- if (in_file.GetDescriptor() != File::kInvalidDescriptor)
- m_terminal_state.Save(in_file.GetDescriptor(), true);
- }
+ int fd = GetInputFile().GetDescriptor();
+ if (fd != File::kInvalidDescriptor)
+ m_terminal_state.Save(fd, true);
}
void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
@@ -1016,8 +924,9 @@ bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
}
void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
- lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile();
- m_input_reader_stack.PrintAsync(stream.get(), s, len);
+ lldb_private::StreamFile &stream =
+ is_stdout ? GetOutputStream() : GetErrorStream();
+ m_input_reader_stack.PrintAsync(&stream, s, len);
}
ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
@@ -1054,8 +963,7 @@ void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
}
}
-void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
- StreamFileSP &out,
+void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
StreamFileSP &err) {
// Before an IOHandler runs, it must have in/out/err streams. This function
// is called when one ore more of the streams are nullptr. We use the top
@@ -1065,37 +973,34 @@ void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
// If no STDIN has been set, then set it appropriately
- if (!in) {
+ if (!in || !in->IsValid()) {
if (top_reader_sp)
- in = top_reader_sp->GetInputStreamFile();
+ in = top_reader_sp->GetInputFileSP();
else
- in = GetInputFile();
-
+ in = GetInputFileSP();
// If there is nothing, use stdin
if (!in)
- in = std::make_shared<StreamFile>(stdin, false);
+ in = std::make_shared<NativeFile>(stdin, false);
}
// If no STDOUT has been set, then set it appropriately
- if (!out) {
+ if (!out || !out->GetFile().IsValid()) {
if (top_reader_sp)
- out = top_reader_sp->GetOutputStreamFile();
+ out = top_reader_sp->GetOutputStreamFileSP();
else
- out = GetOutputFile();
-
+ out = GetOutputStreamSP();
// If there is nothing, use stdout
if (!out)
out = std::make_shared<StreamFile>(stdout, false);
}
// If no STDERR has been set, then set it appropriately
- if (!err) {
+ if (!err || !err->GetFile().IsValid()) {
if (top_reader_sp)
- err = top_reader_sp->GetErrorStreamFile();
+ err = top_reader_sp->GetErrorStreamFileSP();
else
- err = GetErrorFile();
-
+ err = GetErrorStreamSP();
// If there is nothing, use stderr
if (!err)
- err = std::make_shared<StreamFile>(stdout, false);
+ err = std::make_shared<StreamFile>(stderr, false);
}
}
@@ -1263,15 +1168,15 @@ bool Debugger::EnableLog(llvm::StringRef channel,
LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
} else if (log_file.empty()) {
log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
- GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered);
+ GetOutputFile().GetDescriptor(), !should_close, unbuffered);
} else {
auto pos = m_log_streams.find(log_file);
if (pos != m_log_streams.end())
log_stream_sp = pos->second.lock();
if (!log_stream_sp) {
- llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text;
+ llvm::sys::fs::OpenFlags flags = llvm::sys::fs::OF_Text;
if (log_options & LLDB_LOG_OPTION_APPEND)
- flags |= llvm::sys::fs::F_Append;
+ flags |= llvm::sys::fs::OF_Append;
int FD;
if (std::error_code ec = llvm::sys::fs::openFileForWrite(
log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) {
@@ -1308,7 +1213,7 @@ ScriptInterpreter *Debugger::GetScriptInterpreter(bool can_create) {
SourceManager &Debugger::GetSourceManager() {
if (!m_source_manager_up)
- m_source_manager_up = llvm::make_unique<SourceManager>(shared_from_this());
+ m_source_manager_up = std::make_unique<SourceManager>(shared_from_this());
return *m_source_manager_up;
}
@@ -1360,60 +1265,23 @@ void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
// }
}
-size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) {
- size_t total_bytes = 0;
- if (stream == nullptr)
- stream = GetOutputFile().get();
+void Debugger::FlushProcessOutput(Process &process, bool flush_stdout,
+ bool flush_stderr) {
+ const auto &flush = [&](Stream &stream,
+ size_t (Process::*get)(char *, size_t, Status &)) {
+ Status error;
+ size_t len;
+ char buffer[1024];
+ while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0)
+ stream.Write(buffer, len);
+ stream.Flush();
+ };
- if (stream) {
- // The process has stuff waiting for stdout; get it and write it out to the
- // appropriate place.
- if (process == nullptr) {
- TargetSP target_sp = GetTargetList().GetSelectedTarget();
- if (target_sp)
- process = target_sp->GetProcessSP().get();
- }
- if (process) {
- Status error;
- size_t len;
- char stdio_buffer[1024];
- while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
- error)) > 0) {
- stream->Write(stdio_buffer, len);
- total_bytes += len;
- }
- }
- stream->Flush();
- }
- return total_bytes;
-}
-
-size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) {
- size_t total_bytes = 0;
- if (stream == nullptr)
- stream = GetOutputFile().get();
-
- if (stream) {
- // The process has stuff waiting for stderr; get it and write it out to the
- // appropriate place.
- if (process == nullptr) {
- TargetSP target_sp = GetTargetList().GetSelectedTarget();
- if (target_sp)
- process = target_sp->GetProcessSP().get();
- }
- if (process) {
- Status error;
- size_t len;
- char stdio_buffer[1024];
- while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
- error)) > 0) {
- stream->Write(stdio_buffer, len);
- total_bytes += len;
- }
- }
- stream->Flush();
- }
- return total_bytes;
+ std::lock_guard<std::mutex> guard(m_output_flush_mutex);
+ if (flush_stdout)
+ flush(*GetAsyncOutputStream(), &Process::GetSTDOUT);
+ if (flush_stderr)
+ flush(*GetAsyncErrorStream(), &Process::GetSTDERR);
}
// This function handles events that were broadcast by the process.
@@ -1453,15 +1321,9 @@ void Debugger::HandleProcessEvent(const EventSP &event_sp) {
pop_process_io_handler);
}
- // Now display and STDOUT
- if (got_stdout || got_state_changed) {
- GetProcessSTDOUT(process_sp.get(), output_stream_sp.get());
- }
-
- // Now display and STDERR
- if (got_stderr || got_state_changed) {
- GetProcessSTDERR(process_sp.get(), error_stream_sp.get());
- }
+ // Now display STDOUT and STDERR
+ FlushProcessOutput(*process_sp, got_stdout || got_state_changed,
+ got_stderr || got_state_changed);
// Give structured data events an opportunity to display.
if (got_structured_data) {
@@ -1638,8 +1500,9 @@ bool Debugger::StartEventHandlerThread() {
eBroadcastBitEventThreadIsListening);
auto thread_name =
- full_name.GetLength() < llvm::get_max_thread_name_length() ?
- full_name.AsCString() : "dbg.evt-handler";
+ full_name.GetLength() < llvm::get_max_thread_name_length()
+ ? full_name.AsCString()
+ : "dbg.evt-handler";
// Use larger 8MB stack for this thread
llvm::Expected<HostThread> event_handler_thread =
@@ -1700,8 +1563,7 @@ bool Debugger::StartIOHandlerThread() {
void Debugger::StopIOHandlerThread() {
if (m_io_handler_thread.IsJoinable()) {
- if (m_input_file_sp)
- m_input_file_sp->GetFile().Close();
+ GetInputFile().Close();
m_io_handler_thread.Join(nullptr);
}
}
@@ -1714,10 +1576,6 @@ void Debugger::JoinIOHandlerThread() {
}
}
-Target *Debugger::GetDummyTarget() {
- return m_target_list.GetDummyTarget(*this).get();
-}
-
Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
Target *target = nullptr;
if (!prefer_dummy) {
@@ -1734,13 +1592,11 @@ Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
FileSpec repl_executable;
if (language == eLanguageTypeUnknown) {
- std::set<LanguageType> repl_languages;
-
- Language::GetLanguagesSupportingREPLs(repl_languages);
+ LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();
- if (repl_languages.size() == 1) {
- language = *repl_languages.begin();
- } else if (repl_languages.empty()) {
+ if (auto single_lang = repl_languages.GetSingularLanguage()) {
+ language = *single_lang;
+ } else if (repl_languages.Empty()) {
err.SetErrorStringWithFormat(
"LLDB isn't configured with REPL support for any languages.");
return err;