}
}
+ lldb::SBStructuredData GetSetting(const char *setting = nullptr);
+
SBError
SetInputString (const char* data);
void Clear();
+ /// Getting a specific setting value into SBStructuredData format.
+ /// Client can specify empty string or null to get all settings.
+ ///
+ /// Example usages:
+ /// lldb::SBStructuredData settings = debugger.GetSetting();
+ /// lldb::SBStructuredData settings = debugger.GetSetting(nullptr);
+ /// lldb::SBStructuredData settings = debugger.GetSetting("");
+ /// lldb::SBStructuredData settings = debugger.GetSetting("target.arg0");
+ /// lldb::SBStructuredData settings = debugger.GetSetting("target");
+ ///
+ /// \param[out] setting
+ /// Property setting path to retrieve values. e.g "target.source-map"
+ ///
+ lldb::SBStructuredData GetSetting(const char *setting = nullptr);
+
void SetAsync(bool b);
bool GetAsync();
virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx,
Stream &strm, llvm::StringRef property_path,
- uint32_t dump_mask);
+ uint32_t dump_mask, bool is_json = false);
virtual void DumpAllPropertyValues(const ExecutionContext *exe_ctx,
- Stream &strm, uint32_t dump_mask);
+ Stream &strm, uint32_t dump_mask,
+ bool is_json = false);
virtual void DumpAllDescriptions(CommandInterpreter &interpreter,
Stream &strm) const;
#include "lldb/lldb-defines.h"
#include "lldb/lldb-private-enumerations.h"
#include "lldb/lldb-private-interfaces.h"
+#include "llvm/Support/JSON.h"
namespace lldb_private {
virtual void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) = 0;
+ // TODO: make this function pure virtual after implementing it in all
+ // child classes.
+ virtual llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) {
+ // Return nullptr which will create a llvm::json::Value() that is a NULL
+ // value. No setting should ever really have a NULL value in JSON. This
+ // indicates an error occurred and if/when we add a FromJSON() it will know
+ // to fail if someone tries to set it with a NULL JSON value.
+ return nullptr;
+ }
+
virtual Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign);
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override {
+ return m_current_value;
+ }
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override {
+ return m_current_value;
+ }
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override {
+ return m_current_value.GetPath();
+ }
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
+
ConstString GetName() const override { return m_name; }
virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx,
Stream &strm, llvm::StringRef property_path,
- uint32_t dump_mask);
+ uint32_t dump_mask, bool is_json = false);
virtual void DumpAllDescriptions(CommandInterpreter &interpreter,
Stream &strm) const;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override {
+ return m_regex.GetText();
+ }
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override {
+ return m_current_value;
+ }
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override {
+ return m_current_value;
+ }
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
bool IsCurrentValueEmpty() const { return m_current_value.empty(); }
bool IsDefaultValueEmpty() const { return m_default_value.empty(); }
-
+
void SetValidator(ValidatorCallback validator, void *baton = nullptr) {
m_validator = validator;
m_validator_baton = baton;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override {
+ return m_current_value;
+ }
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) override;
+ llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override {
+ return m_uuid.GetAsString();
+ }
+
Status
SetValueFromString(llvm::StringRef value,
VarSetOperationType op = eVarSetOperationAssign) override;
#ifndef LLDB_TARGET_PATHMAPPINGLIST_H
#define LLDB_TARGET_PATHMAPPINGLIST_H
-#include <map>
-#include <vector>
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
+#include "llvm/Support/JSON.h"
+#include <map>
+#include <vector>
namespace lldb_private {
// By default, dump all pairs.
void Dump(Stream *s, int pair_index = -1);
+ llvm::json::Value ToJSON();
+
bool IsEmpty() const { return m_pairs.empty(); }
size_t GetSize() const { return m_pairs.size(); }
return error;
}
+lldb::SBStructuredData SBDebugger::GetSetting(const char *setting) {
+ LLDB_INSTRUMENT_VA(this, setting);
+
+ SBStructuredData data;
+ if (!m_opaque_sp)
+ return data;
+
+ StreamString json_strm;
+ ExecutionContext exe_ctx(
+ m_opaque_sp->GetCommandInterpreter().GetExecutionContext());
+ if (setting && strlen(setting) > 0)
+ m_opaque_sp->DumpPropertyValue(&exe_ctx, json_strm, setting,
+ /*dump_mask*/ 0,
+ /*is_json*/ true);
+ else
+ m_opaque_sp->DumpAllPropertyValues(&exe_ctx, json_strm, /*dump_mask*/ 0,
+ /*is_json*/ true);
+
+ data.m_impl_up->SetObjectSP(
+ StructuredData::ParseJSON(json_strm.GetString().str()));
+ return data;
+}
+
FILE *SBDebugger::GetInputFileHandle() {
LLDB_INSTRUMENT_VA(this);
if (m_opaque_sp) {
}
void Properties::DumpAllPropertyValues(const ExecutionContext *exe_ctx,
- Stream &strm, uint32_t dump_mask) {
+ Stream &strm, uint32_t dump_mask,
+ bool is_json) {
OptionValuePropertiesSP properties_sp(GetValueProperties());
- if (properties_sp)
- return properties_sp->DumpValue(exe_ctx, strm, dump_mask);
+ if (!properties_sp)
+ return;
+
+ if (is_json) {
+ llvm::json::Value json = properties_sp->ToJSON(exe_ctx);
+ strm.Printf("%s", llvm::formatv("{0:2}", json).str().c_str());
+ } else
+ properties_sp->DumpValue(exe_ctx, strm, dump_mask);
}
void Properties::DumpAllDescriptions(CommandInterpreter &interpreter,
Status Properties::DumpPropertyValue(const ExecutionContext *exe_ctx,
Stream &strm,
llvm::StringRef property_path,
- uint32_t dump_mask) {
+ uint32_t dump_mask, bool is_json) {
OptionValuePropertiesSP properties_sp(GetValueProperties());
if (properties_sp) {
return properties_sp->DumpPropertyValue(exe_ctx, strm, property_path,
- dump_mask);
+ dump_mask, is_json);
}
Status error;
error.SetErrorString("empty property list");
}
}
+llvm::json::Value OptionValueArray::ToJSON(const ExecutionContext *exe_ctx) {
+ llvm::json::Array json_array;
+ const uint32_t size = m_values.size();
+ for (uint32_t i = 0; i < size; ++i)
+ json_array.emplace_back(m_values[i]->ToJSON(exe_ctx));
+ return json_array;
+}
+
Status OptionValueArray::SetValueFromString(llvm::StringRef value,
VarSetOperationType op) {
Args args(value.str());
}
}
+llvm::json::Value
+OptionValueDictionary::ToJSON(const ExecutionContext *exe_ctx) {
+ llvm::json::Object dict;
+ for (const auto &value : m_values) {
+ dict.try_emplace(value.first.GetCString(), value.second->ToJSON(exe_ctx));
+ }
+ return dict;
+}
+
size_t OptionValueDictionary::GetArgs(Args &args) const {
args.Clear();
collection::const_iterator pos, end = m_values.end();
}
}
+llvm::json::Value OptionValueFormat::ToJSON(const ExecutionContext *exe_ctx) {
+ return FormatManager::GetFormatAsCString(m_current_value);
+}
+
Status OptionValueFormat::SetValueFromString(llvm::StringRef value,
VarSetOperationType op) {
Status error;
}
}
+llvm::json::Value
+OptionValueFormatEntity::ToJSON(const ExecutionContext *exe_ctx) {
+ std::string escaped;
+ EscapeBackticks(m_current_format, escaped);
+ return escaped;
+}
+
Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str,
VarSetOperationType op) {
Status error;
}
}
+llvm::json::Value OptionValueLanguage::ToJSON(const ExecutionContext *exe_ctx) {
+ return Language::GetNameForLanguageType(m_current_value);
+}
+
Status OptionValueLanguage::SetValueFromString(llvm::StringRef value,
VarSetOperationType op) {
Status error;
}
}
+llvm::json::Value
+OptionValuePathMappings::ToJSON(const ExecutionContext *exe_ctx) {
+ return m_path_mappings.ToJSON();
+}
+
Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value,
VarSetOperationType op) {
Status error;
}
}
+llvm::json::Value
+OptionValueProperties::ToJSON(const ExecutionContext *exe_ctx) {
+ llvm::json::Object json_properties;
+ const size_t num_properties = m_properties.size();
+ for (size_t i = 0; i < num_properties; ++i) {
+ const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
+ if (property) {
+ OptionValue *option_value = property->GetValue().get();
+ assert(option_value);
+ json_properties.try_emplace(property->GetName(),
+ option_value->ToJSON(exe_ctx));
+ }
+ }
+ return json_properties;
+}
+
Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
Stream &strm,
llvm::StringRef property_path,
- uint32_t dump_mask) {
+ uint32_t dump_mask, bool is_json) {
Status error;
const bool will_modify = false;
lldb::OptionValueSP value_sp(
if (dump_mask & ~eDumpOptionName)
strm.PutChar(' ');
}
- value_sp->DumpValue(exe_ctx, strm, dump_mask);
+ if (is_json) {
+ strm.Printf("%s", llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx)).str().c_str());
+ } else
+ value_sp->DumpValue(exe_ctx, strm, dump_mask);
}
return error;
}
}
}
+llvm::json::Value PathMappingList::ToJSON() {
+ llvm::json::Array entries;
+ for (const auto &pair : m_pairs) {
+ llvm::json::Array entry{pair.first.GetStringRef().str(),
+ pair.second.GetStringRef().str()};
+ entries.emplace_back(std::move(entry));
+ }
+ return entries;
+}
+
void PathMappingList::Clear(bool notify) {
if (!m_pairs.empty())
++m_mod_id;
"""
-
+import json
import os
import re
import lldb
self.assertEqual(launch_info.GetArgumentAtIndex(0), "A")
self.assertEqual(launch_info.GetArgumentAtIndex(1), "B")
self.assertEqual(launch_info.GetArgumentAtIndex(2), "C")
-
+
self.expect(
'target show-launch-environment',
substrs=["MY_ENV_VAR=YES"])
# A known option should fail if its argument is invalid.
self.expect("settings set auto-confirm bogus", error=True)
+
+ def get_setting_json(self, setting_path = None):
+ settings_data = self.dbg.GetSetting(setting_path)
+ stream = lldb.SBStream()
+ settings_data.GetAsJSON(stream)
+ return json.loads(stream.GetData())
+
+ def verify_setting_value_json(self, setting_path, setting_value):
+ self.runCmd("settings set %s %s" % (setting_path, setting_value))
+ settings_json = self.get_setting_json(setting_path)
+ self.assertEqual(settings_json, setting_value)
+
+ def test_settings_api(self):
+ """
+ Test that ensures SBDebugger::GetSetting() APIs
+ can correctly fetch settings.
+ """
+
+ # Test basic values and embedding special JSON escaping characters.
+ self.runCmd("settings set auto-confirm true")
+ self.runCmd("settings set tab-size 2")
+ arg_value = "hello \"world\""
+ self.runCmd('settings set target.arg0 %s' % arg_value)
+
+ settings_json = self.get_setting_json()
+ self.assertEqual(settings_json["auto-confirm"], True)
+ self.assertEqual(settings_json["tab-size"], 2)
+ self.assertEqual(settings_json["target"]["arg0"], arg_value)
+
+ settings_data = self.get_setting_json("target.arg0")
+ self.assertEqual(settings_data, arg_value)
+
+ # Test OptionValueFileSpec
+ self.verify_setting_value_json("platform.module-cache-directory", self.get_process_working_directory())
+
+ # Test OptionValueArray
+ setting_path = "target.run-args"
+ setting_value = ["value1", "value2", "value3"]
+ self.runCmd("settings set %s %s" % (setting_path, " ".join(setting_value)))
+ settings_json = self.get_setting_json(setting_path)
+ self.assertEqual(settings_json, setting_value)
+
+ # Test OptionValueFormatEntity
+ setting_value = """thread #${thread.index}{, name = \\'${thread.name}\\
+ '}{, queue = ${ansi.fg.green}\\'${thread.queue}\\'${ansi.normal}}{,
+ activity = ${ansi.fg.green}\\'${thread.info.activity.name}\\'${ansi.normal}}
+ {, ${thread.info.trace_messages} messages}{, stop reason = ${ansi.fg.red}$
+ {thread.stop-reason}${ansi.normal}}{\\\\nReturn value: ${thread.return-value}}
+ {\\\\nCompleted expression: ${thread.completed-expression}}\\\\n"""
+ self.verify_setting_value_json("thread-stop-format", setting_value)
+
+ # Test OptionValueRegex
+ self.verify_setting_value_json("target.process.thread.step-avoid-regexp", "^std::")
+
+ # Test OptionValueLanguage
+ self.verify_setting_value_json("repl-lang", "c++")
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
+import json
import os
class TestTargetSourceMap(TestBase):
@no_debug_info_test
+ def test_source_map_via_setting_api(self):
+ """
+ Test that ensures SBDebugger::GetSetting("target.source-map") API
+ can correctly fetch source mapping entries.
+ """
+ # Set the target soure map to map "./" to the current test directory
+ src_dir = self.getSourceDir()
+
+ source_map_setting_path = "target.source-map"
+ initial_source_map = self.dbg.GetSetting(source_map_setting_path)
+ self.assertEquals(initial_source_map.GetSize(), 0,
+ "Initial source map should be empty")
+
+ src_dir = self.getSourceDir()
+ self.runCmd('settings set %s . "%s"' % (source_map_setting_path, src_dir))
+
+ source_map = self.dbg.GetSetting(source_map_setting_path)
+ self.assertEquals(source_map.GetSize(), 1,
+ "source map should be have one appended entry")
+
+ stream = lldb.SBStream()
+ source_map.GetAsJSON(stream)
+ serialized_source_map = json.loads(stream.GetData())
+
+ self.assertEquals(len(serialized_source_map[0]), 2,
+ "source map entry should have two parts")
+ self.assertEquals(serialized_source_map[0][0], ".",
+ "source map entry's first part does not match")
+ self.assertEquals(serialized_source_map[0][1], src_dir,
+ "source map entry's second part does not match")
+
+
+ @no_debug_info_test
def test_source_map(self):
"""Test target.source-map' functionality."""