[Lldb-commits] [lldb] 82507f1 - [LLDB][GUI] Add Process Launch form
Greg Clayton via lldb-commits
lldb-commits at lists.llvm.org
Wed Aug 18 15:43:39 PDT 2021
Author: Omar Emara
Date: 2021-08-18T15:43:30-07:00
New Revision: 82507f1798768280cf5d5aab95caaafbc7fe6f47
URL: https://github.com/llvm/llvm-project/commit/82507f1798768280cf5d5aab95caaafbc7fe6f47
DIFF: https://github.com/llvm/llvm-project/commit/82507f1798768280cf5d5aab95caaafbc7fe6f47.diff
LOG: [LLDB][GUI] Add Process Launch form
This patch adds a process launch form. Additionally, a LazyBoolean field
was implemented and numerous utility methods were added to various
fields to get the launch form working.
Differential Revision: https://reviews.llvm.org/D107869
Added:
Modified:
lldb/include/lldb/Target/Target.h
lldb/source/Core/IOHandlerCursesGUI.cpp
lldb/source/Target/Target.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index ac8d002b09a12..fc9dd97515aa9 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -122,7 +122,16 @@ class TargetProperties : public Properties {
void SetRunArguments(const Args &args);
+ // Get the whole environment including the platform inherited environment and
+ // the target specific environment, excluding the unset environment variables.
Environment GetEnvironment() const;
+ // Get the platform inherited environment, excluding the unset environment
+ // variables.
+ Environment GetInheritedEnvironment() const;
+ // Get the target specific environment only, without the platform inherited
+ // environment.
+ Environment GetTargetEnvironment() const;
+ // Set the target specific environment.
void SetEnvironment(Environment env);
bool GetSkipPrologue() const;
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index 6e68c1d757c09..791e5edde250e 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -1259,6 +1259,14 @@ class TextFieldDelegate : public FieldDelegate {
const std::string &GetText() { return m_content; }
+ void SetText(const char *text) {
+ if (text == nullptr) {
+ m_content.clear();
+ return;
+ }
+ m_content = text;
+ }
+
protected:
std::string m_label;
bool m_required;
@@ -1618,6 +1626,33 @@ class ProcessPluginFieldDelegate : public ChoicesFieldDelegate {
}
};
+class LazyBooleanFieldDelegate : public ChoicesFieldDelegate {
+public:
+ LazyBooleanFieldDelegate(const char *label, const char *calculate_label)
+ : ChoicesFieldDelegate(label, 3, GetPossibleOptions(calculate_label)) {}
+
+ static constexpr const char *kNo = "No";
+ static constexpr const char *kYes = "Yes";
+
+ std::vector<std::string> GetPossibleOptions(const char *calculate_label) {
+ std::vector<std::string> options;
+ options.push_back(calculate_label);
+ options.push_back(kYes);
+ options.push_back(kNo);
+ return options;
+ }
+
+ LazyBool GetLazyBoolean() {
+ std::string choice = GetChoiceContent();
+ if (choice == kNo)
+ return eLazyBoolNo;
+ else if (choice == kYes)
+ return eLazyBoolYes;
+ else
+ return eLazyBoolCalculate;
+ }
+};
+
template <class T> class ListFieldDelegate : public FieldDelegate {
public:
ListFieldDelegate(const char *label, T default_field)
@@ -1908,6 +1943,29 @@ template <class T> class ListFieldDelegate : public FieldDelegate {
SelectionType m_selection_type;
};
+class ArgumentsFieldDelegate : public ListFieldDelegate<TextFieldDelegate> {
+public:
+ ArgumentsFieldDelegate()
+ : ListFieldDelegate("Arguments",
+ TextFieldDelegate("Argument", "", false)) {}
+
+ Args GetArguments() {
+ Args arguments;
+ for (int i = 0; i < GetNumberOfFields(); i++) {
+ arguments.AppendArgument(GetField(i).GetText());
+ }
+ return arguments;
+ }
+
+ void AddArguments(const Args &arguments) {
+ for (size_t i = 0; i < arguments.GetArgumentCount(); i++) {
+ AddNewField();
+ TextFieldDelegate &field = GetField(GetNumberOfFields() - 1);
+ field.SetText(arguments.GetArgumentAtIndex(i));
+ }
+ }
+};
+
template <class KeyFieldDelegateType, class ValueFieldDelegateType>
class MappingFieldDelegate : public FieldDelegate {
public:
@@ -2068,14 +2126,36 @@ class EnvironmentVariableFieldDelegate
const std::string &GetName() { return GetKeyField().GetName(); }
const std::string &GetValue() { return GetValueField().GetText(); }
+
+ void SetName(const char *name) { return GetKeyField().SetText(name); }
+
+ void SetValue(const char *value) { return GetValueField().SetText(value); }
};
class EnvironmentVariableListFieldDelegate
: public ListFieldDelegate<EnvironmentVariableFieldDelegate> {
public:
- EnvironmentVariableListFieldDelegate()
- : ListFieldDelegate("Environment Variables",
- EnvironmentVariableFieldDelegate()) {}
+ EnvironmentVariableListFieldDelegate(const char *label)
+ : ListFieldDelegate(label, EnvironmentVariableFieldDelegate()) {}
+
+ Environment GetEnvironment() {
+ Environment environment;
+ for (int i = 0; i < GetNumberOfFields(); i++) {
+ environment.insert(
+ std::make_pair(GetField(i).GetName(), GetField(i).GetValue()));
+ }
+ return environment;
+ }
+
+ void AddEnvironmentVariables(const Environment &environment) {
+ for (auto &variable : environment) {
+ AddNewField();
+ EnvironmentVariableFieldDelegate &field =
+ GetField(GetNumberOfFields() - 1);
+ field.SetName(variable.getKey().str().c_str());
+ field.SetValue(variable.getValue().c_str());
+ }
+ }
};
class FormAction {
@@ -2200,6 +2280,14 @@ class FormDelegate {
return delegate;
}
+ LazyBooleanFieldDelegate *AddLazyBooleanField(const char *label,
+ const char *calculate_label) {
+ LazyBooleanFieldDelegate *delegate =
+ new LazyBooleanFieldDelegate(label, calculate_label);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
ChoicesFieldDelegate *AddChoicesField(const char *label, int height,
std::vector<std::string> choices) {
ChoicesFieldDelegate *delegate =
@@ -2229,6 +2317,12 @@ class FormDelegate {
return delegate;
}
+ ArgumentsFieldDelegate *AddArgumentsField() {
+ ArgumentsFieldDelegate *delegate = new ArgumentsFieldDelegate();
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
template <class K, class V>
MappingFieldDelegate<K, V> *AddMappingField(K key_field, V value_field) {
MappingFieldDelegate<K, V> *delegate =
@@ -2252,9 +2346,10 @@ class FormDelegate {
return delegate;
}
- EnvironmentVariableListFieldDelegate *AddEnvironmentVariableListField() {
+ EnvironmentVariableListFieldDelegate *
+ AddEnvironmentVariableListField(const char *label) {
EnvironmentVariableListFieldDelegate *delegate =
- new EnvironmentVariableListFieldDelegate();
+ new EnvironmentVariableListFieldDelegate(label);
m_fields.push_back(FieldDelegateUP(delegate));
return delegate;
}
@@ -3030,6 +3125,396 @@ class TargetCreateFormDelegate : public FormDelegate {
ChoicesFieldDelegate *m_load_dependent_files_field;
};
+class ProcessLaunchFormDelegate : public FormDelegate {
+public:
+ ProcessLaunchFormDelegate(Debugger &debugger, WindowSP main_window_sp)
+ : m_debugger(debugger), m_main_window_sp(main_window_sp) {
+
+ m_arguments_field = AddArgumentsField();
+ SetArgumentsFieldDefaultValue();
+ m_target_environment_field =
+ AddEnvironmentVariableListField("Target Environment Variables");
+ SetTargetEnvironmentFieldDefaultValue();
+ m_working_directory_field = AddDirectoryField(
+ "Working Directory", GetDefaultWorkingDirectory().c_str(), true, false);
+
+ m_show_advanced_field = AddBooleanField("Show advanced settings.", false);
+
+ m_stop_at_entry_field = AddBooleanField("Stop at entry point.", false);
+ m_detach_on_error_field =
+ AddBooleanField("Detach on error.", GetDefaultDetachOnError());
+ m_disable_aslr_field =
+ AddBooleanField("Disable ASLR", GetDefaultDisableASLR());
+ m_plugin_field = AddProcessPluginField();
+ m_arch_field = AddArchField("Architecture", "", false);
+ m_shell_field = AddFileField("Shell", "", true, false);
+ m_expand_shell_arguments_field =
+ AddBooleanField("Expand shell arguments.", false);
+
+ m_disable_standard_io_field =
+ AddBooleanField("Disable Standard IO", GetDefaultDisableStandardIO());
+ m_standard_output_field =
+ AddFileField("Standard Output File", "", /*need_to_exist=*/false,
+ /*required=*/false);
+ m_standard_error_field =
+ AddFileField("Standard Error File", "", /*need_to_exist=*/false,
+ /*required=*/false);
+ m_standard_input_field =
+ AddFileField("Standard Input File", "", /*need_to_exist=*/false,
+ /*required=*/false);
+
+ m_show_inherited_environment_field =
+ AddBooleanField("Show inherited environment variables.", false);
+ m_inherited_environment_field =
+ AddEnvironmentVariableListField("Inherited Environment Variables");
+ SetInheritedEnvironmentFieldDefaultValue();
+
+ AddAction("Launch", [this](Window &window) { Launch(window); });
+ }
+
+ std::string GetName() override { return "Launch Process"; }
+
+ void UpdateFieldsVisibility() override {
+ if (m_show_advanced_field->GetBoolean()) {
+ m_stop_at_entry_field->FieldDelegateShow();
+ m_detach_on_error_field->FieldDelegateShow();
+ m_disable_aslr_field->FieldDelegateShow();
+ m_plugin_field->FieldDelegateShow();
+ m_arch_field->FieldDelegateShow();
+ m_shell_field->FieldDelegateShow();
+ m_expand_shell_arguments_field->FieldDelegateShow();
+ m_disable_standard_io_field->FieldDelegateShow();
+ if (m_disable_standard_io_field->GetBoolean()) {
+ m_standard_input_field->FieldDelegateHide();
+ m_standard_output_field->FieldDelegateHide();
+ m_standard_error_field->FieldDelegateHide();
+ } else {
+ m_standard_input_field->FieldDelegateShow();
+ m_standard_output_field->FieldDelegateShow();
+ m_standard_error_field->FieldDelegateShow();
+ }
+ m_show_inherited_environment_field->FieldDelegateShow();
+ if (m_show_inherited_environment_field->GetBoolean())
+ m_inherited_environment_field->FieldDelegateShow();
+ else
+ m_inherited_environment_field->FieldDelegateHide();
+ } else {
+ m_stop_at_entry_field->FieldDelegateHide();
+ m_detach_on_error_field->FieldDelegateHide();
+ m_disable_aslr_field->FieldDelegateHide();
+ m_plugin_field->FieldDelegateHide();
+ m_arch_field->FieldDelegateHide();
+ m_shell_field->FieldDelegateHide();
+ m_expand_shell_arguments_field->FieldDelegateHide();
+ m_disable_standard_io_field->FieldDelegateHide();
+ m_standard_input_field->FieldDelegateHide();
+ m_standard_output_field->FieldDelegateHide();
+ m_standard_error_field->FieldDelegateHide();
+ m_show_inherited_environment_field->FieldDelegateHide();
+ m_inherited_environment_field->FieldDelegateHide();
+ }
+ }
+
+ // Methods for setting the default value of the fields.
+
+ void SetArgumentsFieldDefaultValue() {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ if (target == nullptr)
+ return;
+
+ const Args &target_arguments =
+ target->GetProcessLaunchInfo().GetArguments();
+ m_arguments_field->AddArguments(target_arguments);
+ }
+
+ void SetTargetEnvironmentFieldDefaultValue() {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ if (target == nullptr)
+ return;
+
+ const Environment &target_environment = target->GetTargetEnvironment();
+ m_target_environment_field->AddEnvironmentVariables(target_environment);
+ }
+
+ void SetInheritedEnvironmentFieldDefaultValue() {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ if (target == nullptr)
+ return;
+
+ const Environment &inherited_environment =
+ target->GetInheritedEnvironment();
+ m_inherited_environment_field->AddEnvironmentVariables(
+ inherited_environment);
+ }
+
+ std::string GetDefaultWorkingDirectory() {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ if (target == nullptr)
+ return "";
+
+ PlatformSP platform = target->GetPlatform();
+ return platform->GetWorkingDirectory().GetPath();
+ }
+
+ bool GetDefaultDisableASLR() {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ if (target == nullptr)
+ return false;
+
+ return target->GetDisableASLR();
+ }
+
+ bool GetDefaultDisableStandardIO() {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ if (target == nullptr)
+ return true;
+
+ return target->GetDisableSTDIO();
+ }
+
+ bool GetDefaultDetachOnError() {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ if (target == nullptr)
+ return true;
+
+ return target->GetDetachOnError();
+ }
+
+ // Methods for getting the necessary information and setting them to the
+ // ProcessLaunchInfo.
+
+ void GetExecutableSettings(ProcessLaunchInfo &launch_info) {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ ModuleSP executable_module = target->GetExecutableModule();
+ llvm::StringRef target_settings_argv0 = target->GetArg0();
+
+ if (!target_settings_argv0.empty()) {
+ launch_info.GetArguments().AppendArgument(target_settings_argv0);
+ launch_info.SetExecutableFile(executable_module->GetPlatformFileSpec(),
+ false);
+ return;
+ }
+
+ launch_info.SetExecutableFile(executable_module->GetPlatformFileSpec(),
+ true);
+ }
+
+ void GetArguments(ProcessLaunchInfo &launch_info) {
+ TargetSP target = m_debugger.GetSelectedTarget();
+ Args arguments = m_arguments_field->GetArguments();
+ launch_info.GetArguments().AppendArguments(arguments);
+ }
+
+ void GetEnvironment(ProcessLaunchInfo &launch_info) {
+ Environment target_environment =
+ m_target_environment_field->GetEnvironment();
+ Environment inherited_environment =
+ m_inherited_environment_field->GetEnvironment();
+ launch_info.GetEnvironment().insert(target_environment.begin(),
+ target_environment.end());
+ launch_info.GetEnvironment().insert(inherited_environment.begin(),
+ inherited_environment.end());
+ }
+
+ void GetWorkingDirectory(ProcessLaunchInfo &launch_info) {
+ if (m_working_directory_field->IsSpecified())
+ launch_info.SetWorkingDirectory(
+ m_working_directory_field->GetResolvedFileSpec());
+ }
+
+ void GetStopAtEntry(ProcessLaunchInfo &launch_info) {
+ if (m_stop_at_entry_field->GetBoolean())
+ launch_info.GetFlags().Set(eLaunchFlagStopAtEntry);
+ else
+ launch_info.GetFlags().Clear(eLaunchFlagStopAtEntry);
+ }
+
+ void GetDetachOnError(ProcessLaunchInfo &launch_info) {
+ if (m_detach_on_error_field->GetBoolean())
+ launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
+ else
+ launch_info.GetFlags().Clear(eLaunchFlagDetachOnError);
+ }
+
+ void GetDisableASLR(ProcessLaunchInfo &launch_info) {
+ if (m_disable_aslr_field->GetBoolean())
+ launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
+ else
+ launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
+ }
+
+ void GetPlugin(ProcessLaunchInfo &launch_info) {
+ launch_info.SetProcessPluginName(m_plugin_field->GetPluginName());
+ }
+
+ void GetArch(ProcessLaunchInfo &launch_info) {
+ if (!m_arch_field->IsSpecified())
+ return;
+
+ TargetSP target_sp = m_debugger.GetSelectedTarget();
+ PlatformSP platform_sp =
+ target_sp ? target_sp->GetPlatform() : PlatformSP();
+ launch_info.GetArchitecture() = Platform::GetAugmentedArchSpec(
+ platform_sp.get(), m_arch_field->GetArchString());
+ }
+
+ void GetShell(ProcessLaunchInfo &launch_info) {
+ if (!m_shell_field->IsSpecified())
+ return;
+
+ launch_info.SetShell(m_shell_field->GetResolvedFileSpec());
+ launch_info.SetShellExpandArguments(
+ m_expand_shell_arguments_field->GetBoolean());
+ }
+
+ void GetStandardIO(ProcessLaunchInfo &launch_info) {
+ if (m_disable_standard_io_field->GetBoolean()) {
+ launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
+ return;
+ }
+
+ FileAction action;
+ if (m_standard_input_field->IsSpecified()) {
+ action.Open(STDIN_FILENO, m_standard_input_field->GetFileSpec(), true,
+ false);
+ launch_info.AppendFileAction(action);
+ }
+ if (m_standard_output_field->IsSpecified()) {
+ action.Open(STDOUT_FILENO, m_standard_output_field->GetFileSpec(), false,
+ true);
+ launch_info.AppendFileAction(action);
+ }
+ if (m_standard_error_field->IsSpecified()) {
+ action.Open(STDERR_FILENO, m_standard_error_field->GetFileSpec(), false,
+ true);
+ launch_info.AppendFileAction(action);
+ }
+ }
+
+ void GetInheritTCC(ProcessLaunchInfo &launch_info) {
+ if (m_debugger.GetSelectedTarget()->GetInheritTCC())
+ launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);
+ }
+
+ ProcessLaunchInfo GetLaunchInfo() {
+ ProcessLaunchInfo launch_info;
+
+ GetExecutableSettings(launch_info);
+ GetArguments(launch_info);
+ GetEnvironment(launch_info);
+ GetWorkingDirectory(launch_info);
+ GetStopAtEntry(launch_info);
+ GetDetachOnError(launch_info);
+ GetDisableASLR(launch_info);
+ GetPlugin(launch_info);
+ GetArch(launch_info);
+ GetShell(launch_info);
+ GetStandardIO(launch_info);
+ GetInheritTCC(launch_info);
+
+ return launch_info;
+ }
+
+ bool StopRunningProcess() {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+
+ if (!exe_ctx.HasProcessScope())
+ return false;
+
+ Process *process = exe_ctx.GetProcessPtr();
+ if (!(process && process->IsAlive()))
+ return false;
+
+ FormDelegateSP form_delegate_sp =
+ FormDelegateSP(new DetachOrKillProcessFormDelegate(process));
+ Rect bounds = m_main_window_sp->GetCenteredRect(85, 8);
+ WindowSP form_window_sp = m_main_window_sp->CreateSubWindow(
+ form_delegate_sp->GetName().c_str(), bounds, true);
+ WindowDelegateSP window_delegate_sp =
+ WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
+ form_window_sp->SetDelegate(window_delegate_sp);
+
+ return true;
+ }
+
+ Target *GetTarget() {
+ Target *target = m_debugger.GetSelectedTarget().get();
+
+ if (target == nullptr) {
+ SetError("No target exists!");
+ return nullptr;
+ }
+
+ ModuleSP exe_module_sp = target->GetExecutableModule();
+
+ if (exe_module_sp == nullptr) {
+ SetError("No executable in target!");
+ return nullptr;
+ }
+
+ return target;
+ }
+
+ void Launch(Window &window) {
+ ClearError();
+
+ bool all_fields_are_valid = CheckFieldsValidity();
+ if (!all_fields_are_valid)
+ return;
+
+ bool process_is_running = StopRunningProcess();
+ if (process_is_running)
+ return;
+
+ Target *target = GetTarget();
+ if (HasError())
+ return;
+
+ StreamString stream;
+ ProcessLaunchInfo launch_info = GetLaunchInfo();
+ Status status = target->Launch(launch_info, &stream);
+
+ if (status.Fail()) {
+ SetError(status.AsCString());
+ return;
+ }
+
+ ProcessSP process_sp(target->GetProcessSP());
+ if (!process_sp) {
+ SetError("Launched successfully but target has no process!");
+ return;
+ }
+
+ window.GetParent()->RemoveSubWindow(&window);
+ }
+
+protected:
+ Debugger &m_debugger;
+ WindowSP m_main_window_sp;
+
+ ArgumentsFieldDelegate *m_arguments_field;
+ EnvironmentVariableListFieldDelegate *m_target_environment_field;
+ DirectoryFieldDelegate *m_working_directory_field;
+
+ BooleanFieldDelegate *m_show_advanced_field;
+
+ BooleanFieldDelegate *m_stop_at_entry_field;
+ BooleanFieldDelegate *m_detach_on_error_field;
+ BooleanFieldDelegate *m_disable_aslr_field;
+ ProcessPluginFieldDelegate *m_plugin_field;
+ ArchFieldDelegate *m_arch_field;
+ FileFieldDelegate *m_shell_field;
+ BooleanFieldDelegate *m_expand_shell_arguments_field;
+ BooleanFieldDelegate *m_disable_standard_io_field;
+ FileFieldDelegate *m_standard_input_field;
+ FileFieldDelegate *m_standard_output_field;
+ FileFieldDelegate *m_standard_error_field;
+
+ BooleanFieldDelegate *m_show_inherited_environment_field;
+ EnvironmentVariableListFieldDelegate *m_inherited_environment_field;
+};
+
class MenuDelegate {
public:
virtual ~MenuDelegate() = default;
@@ -5612,6 +6097,18 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate {
form_window_sp->SetDelegate(window_delegate_sp);
return MenuActionResult::Handled;
}
+ case eMenuID_ProcessLaunch: {
+ WindowSP main_window_sp = m_app.GetMainWindow();
+ FormDelegateSP form_delegate_sp = FormDelegateSP(
+ new ProcessLaunchFormDelegate(m_debugger, main_window_sp));
+ Rect bounds = main_window_sp->GetCenteredRect(80, 22);
+ WindowSP form_window_sp = main_window_sp->CreateSubWindow(
+ form_delegate_sp->GetName().c_str(), bounds, true);
+ WindowDelegateSP window_delegate_sp =
+ WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
+ form_window_sp->SetDelegate(window_delegate_sp);
+ return MenuActionResult::Handled;
+ }
case eMenuID_ProcessContinue: {
ExecutionContext exe_ctx =
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index d21935cb6f344..159928981c921 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3985,6 +3985,45 @@ Environment TargetProperties::GetEnvironment() const {
return ComputeEnvironment();
}
+Environment TargetProperties::GetInheritedEnvironment() const {
+ Environment environment;
+
+ if (m_target == nullptr)
+ return environment;
+
+ if (!m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, ePropertyInheritEnv,
+ g_target_properties[ePropertyInheritEnv].default_uint_value != 0))
+ return environment;
+
+ PlatformSP platform_sp = m_target->GetPlatform();
+ if (platform_sp == nullptr)
+ return environment;
+
+ Environment platform_environment = platform_sp->GetEnvironment();
+ for (const auto &KV : platform_environment)
+ environment[KV.first()] = KV.second;
+
+ Args property_unset_environment;
+ m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyUnsetEnvVars,
+ property_unset_environment);
+ for (const auto &var : property_unset_environment)
+ environment.erase(var.ref());
+
+ return environment;
+}
+
+Environment TargetProperties::GetTargetEnvironment() const {
+ Args property_environment;
+ m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyEnvVars,
+ property_environment);
+ Environment environment;
+ for (const auto &KV : Environment(property_environment))
+ environment[KV.first()] = KV.second;
+
+ return environment;
+}
+
void TargetProperties::SetEnvironment(Environment env) {
// TODO: Get rid of the Args intermediate step
const uint32_t idx = ePropertyEnvVars;
More information about the lldb-commits
mailing list