JDevlieghere created this revision.
JDevlieghere added reviewers: clayborg, jingham, teemperor.
JDevlieghere added a project: LLDB.
For the reproducer feature I need to be able to export and import the current
LLDB configuration. To realize this I've extended the existing functionality to
print settings. With the help of a new formatting option, we can now write the
settings and their values to a file structured as regular commands.
Concretely the functionality works as follows:
(lldb) settings export /path/to/file
This file contains a bunch of `settings set` commands, followed by the
setting's name and value.
settings set use-external-editor false
settings set use-color true
settings set auto-one-line-summaries true
settings set auto-indent true
Loading the settings again is as simple as sourcing the newly created file:
(lldb) command source /path/to/file
I had to make a few small changes here to make this work:
- When a value is not set `settings set <setting>` is equal to `settings clear
<setting>`. This is because not all settings have a meaningful default For
example for `settings set` we used to print `unknown` which is not a value the
user can set.
- I introduced a new printing option and group for printing options as
commands. This relates to printing everything on a single line for things like
arrays and dicts.
There's one setting that is proving to be a pain: the disassembly format value.
Currently we don't accept our own default value. I don't know what the problem
is but I managed to work around this by escaping the back ticks.
Repository:
rLLDB LLDB
https://reviews.llvm.org/D52651
Files:
include/lldb/Interpreter/OptionValue.h
lit/Settings/TestExport.test
source/Commands/CommandObjectSettings.cpp
source/Core/Debugger.cpp
source/Interpreter/OptionValueArray.cpp
source/Interpreter/OptionValueDictionary.cpp
source/Interpreter/OptionValueFileSpecLIst.cpp
source/Interpreter/OptionValueFormatEntity.cpp
source/Interpreter/OptionValueLanguage.cpp
source/Interpreter/Property.cpp
Index: source/Interpreter/Property.cpp
===================================================================
--- source/Interpreter/Property.cpp
+++ source/Interpreter/Property.cpp
@@ -233,7 +233,10 @@
uint32_t dump_mask) const {
if (m_value_sp) {
const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription;
+ const bool dump_cmd = dump_mask & OptionValue::eDumpOptionCommand;
const bool transparent = m_value_sp->ValueIsTransparent();
+ if (dump_cmd && !transparent)
+ strm << "settings set ";
if (dump_desc || !transparent) {
if ((dump_mask & OptionValue::eDumpOptionName) && m_name) {
DumpQualifiedName(strm);
Index: source/Interpreter/OptionValueLanguage.cpp
===================================================================
--- source/Interpreter/OptionValueLanguage.cpp
+++ source/Interpreter/OptionValueLanguage.cpp
@@ -28,7 +28,8 @@
if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
strm.PutCString(" = ");
- strm.PutCString(Language::GetNameForLanguageType(m_current_value));
+ if (m_current_value != eLanguageTypeUnknown)
+ strm.PutCString(Language::GetNameForLanguageType(m_current_value));
}
}
Index: source/Interpreter/OptionValueFormatEntity.cpp
===================================================================
--- source/Interpreter/OptionValueFormatEntity.cpp
+++ source/Interpreter/OptionValueFormatEntity.cpp
@@ -47,8 +47,8 @@
strm.Printf("(%s)", GetTypeAsCString());
if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
- strm.PutCString(" = \"");
- strm << m_current_format.c_str() << '"';
+ strm.PutCString(" = ");
+ strm << '"' << m_current_format.c_str() << '"';
}
}
Index: source/Interpreter/OptionValueFileSpecLIst.cpp
===================================================================
--- source/Interpreter/OptionValueFileSpecLIst.cpp
+++ source/Interpreter/OptionValueFileSpecLIst.cpp
@@ -25,16 +25,24 @@
if (dump_mask & eDumpOptionType)
strm.Printf("(%s)", GetTypeAsCString());
if (dump_mask & eDumpOptionValue) {
- if (dump_mask & eDumpOptionType)
- strm.Printf(" =%s", m_current_value.GetSize() > 0 ? "\n" : "");
- strm.IndentMore();
+ const bool one_line = dump_mask & eDumpOptionCommand;
const uint32_t size = m_current_value.GetSize();
+ if (dump_mask & eDumpOptionType)
+ strm.Printf(" =%s",
+ (m_current_value.GetSize() > 0 && !one_line) ? "\n" : "");
+ if (!one_line)
+ strm.IndentMore();
for (uint32_t i = 0; i < size; ++i) {
- strm.Indent();
- strm.Printf("[%u]: ", i);
+ if (!one_line) {
+ strm.Indent();
+ strm.Printf("[%u]: ", i);
+ }
m_current_value.GetFileSpecAtIndex(i).Dump(&strm);
+ if (one_line)
+ strm << ' ';
}
- strm.IndentLess();
+ if (!one_line)
+ strm.IndentLess();
}
}
Index: source/Interpreter/OptionValueDictionary.cpp
===================================================================
--- source/Interpreter/OptionValueDictionary.cpp
+++ source/Interpreter/OptionValueDictionary.cpp
@@ -33,16 +33,23 @@
strm.Printf("(%s)", GetTypeAsCString());
}
if (dump_mask & eDumpOptionValue) {
+ const bool one_line = dump_mask & eDumpOptionCommand;
if (dump_mask & eDumpOptionType)
strm.PutCString(" =");
collection::iterator pos, end = m_values.end();
- strm.IndentMore();
+ if (!one_line)
+ strm.IndentMore();
for (pos = m_values.begin(); pos != end; ++pos) {
OptionValue *option_value = pos->second.get();
- strm.EOL();
+
+ if (one_line)
+ strm << ' ';
+ else
+ strm.EOL();
+
strm.Indent(pos->first.GetCString());
const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
@@ -74,7 +81,8 @@
break;
}
}
- strm.IndentLess();
+ if (!one_line)
+ strm.IndentLess();
}
}
Index: source/Interpreter/OptionValueArray.cpp
===================================================================
--- source/Interpreter/OptionValueArray.cpp
+++ source/Interpreter/OptionValueArray.cpp
@@ -31,13 +31,17 @@
strm.Printf("(%s)", GetTypeAsCString());
}
if (dump_mask & eDumpOptionValue) {
- if (dump_mask & eDumpOptionType)
- strm.Printf(" =%s", (m_values.size() > 0) ? "\n" : "");
- strm.IndentMore();
+ const bool one_line = dump_mask & eDumpOptionCommand;
const uint32_t size = m_values.size();
+ if (dump_mask & eDumpOptionType)
+ strm.Printf(" =%s", (m_values.size() > 0 && !one_line) ? "\n" : "");
+ if (!one_line)
+ strm.IndentMore();
for (uint32_t i = 0; i < size; ++i) {
- strm.Indent();
- strm.Printf("[%u]: ", i);
+ if (!one_line) {
+ strm.Indent();
+ strm.Printf("[%u]: ", i);
+ }
const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
switch (array_element_type) {
default:
@@ -63,10 +67,16 @@
extra_dump_options);
break;
}
- if (i < (size - 1))
- strm.EOL();
+
+ if (!one_line) {
+ if (i < (size - 1))
+ strm.EOL();
+ } else {
+ strm << ' ';
+ }
}
- strm.IndentLess();
+ if (!one_line)
+ strm.IndentLess();
}
}
Index: source/Core/Debugger.cpp
===================================================================
--- source/Core/Debugger.cpp
+++ source/Core/Debugger.cpp
@@ -162,9 +162,9 @@
// 3. print
// address <+offset>:
#define DEFAULT_DISASSEMBLY_FORMAT \
- "{${function.initial-function}{${module.file.basename}`}{${function.name-" \
- "without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${" \
- "function.name-without-args}}:\n}{${current-pc-arrow} " \
+ "{${function.initial-function}{${module.file.basename}\\`}{${function.name-" \
+ "without-args}}:\\n}{${function.changed}\\n{${module.file.basename}\\`}{${" \
+ "function.name-without-args}}:\\n}{${current-pc-arrow} " \
"}${addr-file-or-load}{ " \
"<${function.concrete-only-addr-offset-no-padding}>}: "
Index: source/Commands/CommandObjectSettings.cpp
===================================================================
--- source/Commands/CommandObjectSettings.cpp
+++ source/Commands/CommandObjectSettings.cpp
@@ -185,7 +185,7 @@
return false;
const size_t argc = cmd_args.GetArgumentCount();
- if ((argc < 2) && (!m_options.m_global)) {
+ if ((argc < 1) && (!m_options.m_global)) {
result.AppendError("'settings set' takes more arguments");
result.SetStatus(eReturnStatusFailed);
return false;
@@ -199,6 +199,18 @@
return false;
}
+ // A missing value corresponds to clearing the setting.
+ if (argc == 1) {
+ Status error(m_interpreter.GetDebugger().SetPropertyValue(
+ &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
+ if (error.Fail()) {
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ return result.Succeeded();
+ }
+
// Split the raw command into var_name and value pair.
llvm::StringRef raw_str(command);
std::string var_value_string = raw_str.split(var_name).second.str();
@@ -300,6 +312,63 @@
}
};
+//-------------------------------------------------------------------------
+// CommandObjectSettingsExport -- Export current values
+//-------------------------------------------------------------------------
+
+class CommandObjectSettingsExport : public CommandObjectParsed {
+public:
+ CommandObjectSettingsExport(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "settings export",
+ "Export debugger settings and their current values.", nullptr) {
+ CommandArgumentEntry arg1;
+ CommandArgumentData var_name_arg;
+
+ // Define the first (and only) variant of this arg.
+ var_name_arg.arg_type = eArgTypeFilename;
+ var_name_arg.arg_repetition = eArgRepeatOptional;
+
+ // There is only one variant this argument could be; put it into the
+ // argument entry.
+ arg1.push_back(var_name_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back(arg1);
+ }
+
+ ~CommandObjectSettingsExport() override = default;
+
+ int HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
+ request, nullptr);
+ return request.GetNumberOfMatches();
+ }
+
+protected:
+ bool DoExecute(Args &args, CommandReturnObject &result) override {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ // Open file for dumping the exported settings.
+ const std::string export_path = args.GetArgumentAtIndex(0);
+ const uint32_t options = File::eOpenOptionWrite |
+ File::eOpenOptionTruncate |
+ File::eOpenOptionCanCreate;
+ StreamFile export_file(export_path.c_str(), options);
+
+ // Exporting should not be context sensitive.
+ ExecutionContext clean_ctx;
+
+ m_interpreter.GetDebugger().DumpAllPropertyValues(
+ &clean_ctx, export_file, OptionValue::eDumpGroupExport);
+
+ return result.Succeeded();
+ }
+};
+
//-------------------------------------------------------------------------
// CommandObjectSettingsList -- List settable variables
//-------------------------------------------------------------------------
@@ -987,6 +1056,8 @@
CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
LoadSubCommand("clear",
CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
+ LoadSubCommand("export",
+ CommandObjectSP(new CommandObjectSettingsExport(interpreter)));
}
CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
Index: lit/Settings/TestExport.test
===================================================================
--- /dev/null
+++ lit/Settings/TestExport.test
@@ -0,0 +1,10 @@
+# This tests exporting settings from LLDB. It checks that the settings can be
+# written to file and read again without altering any of the values.
+
+# FIXME: The disassembly-format is problematic because its default value is
+# rejected without escaping the back ticks.
+
+# RUN: %lldb -b -o 'settings set disassembly-format ""' -o 'settings export %t.foo' -o 'command source %t.foo' -o 'settings export %t.bar' -o 'command source %t.bar' 2>&1 | FileCheck %s
+# RUN: diff -w %t.foo %t.bar
+
+# CHECK-NOT: error:
Index: include/lldb/Interpreter/OptionValue.h
===================================================================
--- include/lldb/Interpreter/OptionValue.h
+++ include/lldb/Interpreter/OptionValue.h
@@ -58,9 +58,11 @@
eDumpOptionValue = (1u << 2),
eDumpOptionDescription = (1u << 3),
eDumpOptionRaw = (1u << 4),
+ eDumpOptionCommand = (1u << 5),
eDumpGroupValue = (eDumpOptionName | eDumpOptionType | eDumpOptionValue),
eDumpGroupHelp =
- (eDumpOptionName | eDumpOptionType | eDumpOptionDescription)
+ (eDumpOptionName | eDumpOptionType | eDumpOptionDescription),
+ eDumpGroupExport = (eDumpOptionCommand | eDumpOptionName | eDumpOptionValue)
};
OptionValue()
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits