mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 19:07:53 +08:00
[lldb/Commands] Add command options for ScriptedProcess to ProcessLaunch
This patch adds a new command options to the CommandObjectProcessLaunch for scripted processes. Among the options, the user need to specify the class name managing the scripted process. The user can also use a key-value dictionary holding arbitrary data that will be passed to the managing class. This patch also adds getters and setters to `SBLaunchInfo` for the class name managing the scripted process and the dictionary. rdar://65508855 Differential Review: https://reviews.llvm.org/D95710 Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
This commit is contained in:
@@ -135,6 +135,16 @@ public:
|
||||
|
||||
void
|
||||
SetDetachOnError(bool enable);
|
||||
|
||||
const char *
|
||||
GetScriptedProcessClassName() const;
|
||||
|
||||
void SetScriptedProcessClassName(const char *class_name);
|
||||
|
||||
lldb::SBStructuredData
|
||||
GetScriptedProcessDictionary() const;
|
||||
|
||||
void SetScriptedProcessDictionary(lldb::SBStructuredData dict);
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
@@ -171,6 +171,14 @@ public:
|
||||
|
||||
void SetDetachOnError(bool enable);
|
||||
|
||||
const char *GetScriptedProcessClassName() const;
|
||||
|
||||
void SetScriptedProcessClassName(const char *class_name);
|
||||
|
||||
lldb::SBStructuredData GetScriptedProcessDictionary() const;
|
||||
|
||||
void SetScriptedProcessDictionary(lldb::SBStructuredData dict);
|
||||
|
||||
protected:
|
||||
friend class SBPlatform;
|
||||
friend class SBTarget;
|
||||
|
||||
@@ -72,6 +72,7 @@ protected:
|
||||
friend class SBFunction;
|
||||
friend class SBInstruction;
|
||||
friend class SBInstructionList;
|
||||
friend class SBLaunchInfo;
|
||||
friend class SBLineEntry;
|
||||
friend class SBMemoryRegionInfo;
|
||||
friend class SBModule;
|
||||
|
||||
@@ -88,6 +88,7 @@ public:
|
||||
size_t GetStringValue(char *dst, size_t dst_len) const;
|
||||
|
||||
protected:
|
||||
friend class SBLaunchInfo;
|
||||
friend class SBTraceOptions;
|
||||
friend class SBDebugger;
|
||||
friend class SBTarget;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "lldb/Host/PseudoTerminal.h"
|
||||
#include "lldb/Utility/FileSpec.h"
|
||||
#include "lldb/Utility/ProcessInfo.h"
|
||||
#include "lldb/Utility/StructuredData.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
@@ -146,6 +147,28 @@ public:
|
||||
return m_flags.Test(lldb::eLaunchFlagDetachOnError);
|
||||
}
|
||||
|
||||
bool IsScriptedProcess() const {
|
||||
return !m_scripted_process_class_name.empty();
|
||||
}
|
||||
|
||||
std::string GetScriptedProcessClassName() const {
|
||||
return m_scripted_process_class_name;
|
||||
}
|
||||
|
||||
void SetScriptedProcessClassName(std::string name) {
|
||||
m_scripted_process_class_name = name;
|
||||
}
|
||||
|
||||
lldb_private::StructuredData::DictionarySP
|
||||
GetScriptedProcessDictionarySP() const {
|
||||
return m_scripted_process_dictionary_sp;
|
||||
}
|
||||
|
||||
void SetScriptedProcessDictionarySP(
|
||||
lldb_private::StructuredData::DictionarySP dictionary_sp) {
|
||||
m_scripted_process_dictionary_sp = dictionary_sp;
|
||||
}
|
||||
|
||||
protected:
|
||||
FileSpec m_working_dir;
|
||||
std::string m_plugin_name;
|
||||
@@ -161,6 +184,11 @@ protected:
|
||||
// meaning to the upper levels of lldb.
|
||||
lldb::ListenerSP m_listener_sp;
|
||||
lldb::ListenerSP m_hijack_listener_sp;
|
||||
std::string m_scripted_process_class_name; // The name of the class that will
|
||||
// manage a scripted process.
|
||||
StructuredData::DictionarySP
|
||||
m_scripted_process_dictionary_sp; // A dictionary that holds key/value
|
||||
// pairs passed to the scripted process.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
#include "SBReproducerPrivate.h"
|
||||
|
||||
#include "lldb/API/SBEnvironment.h"
|
||||
#include "lldb/API/SBError.h"
|
||||
#include "lldb/API/SBFileSpec.h"
|
||||
#include "lldb/API/SBListener.h"
|
||||
#include "lldb/API/SBStream.h"
|
||||
#include "lldb/API/SBStructuredData.h"
|
||||
#include "lldb/Core/StructuredDataImpl.h"
|
||||
#include "lldb/Host/ProcessLaunchInfo.h"
|
||||
|
||||
using namespace lldb;
|
||||
@@ -343,6 +347,53 @@ bool SBLaunchInfo::GetDetachOnError() const {
|
||||
return m_opaque_sp->GetDetachOnError();
|
||||
}
|
||||
|
||||
const char *SBLaunchInfo::GetScriptedProcessClassName() const {
|
||||
LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBLaunchInfo,
|
||||
GetScriptedProcessClassName);
|
||||
|
||||
// Constify this string so that it is saved in the string pool. Otherwise it
|
||||
// would be freed when this function goes out of scope.
|
||||
ConstString class_name(m_opaque_sp->GetScriptedProcessClassName().c_str());
|
||||
return class_name.AsCString();
|
||||
}
|
||||
|
||||
void SBLaunchInfo::SetScriptedProcessClassName(const char *class_name) {
|
||||
LLDB_RECORD_METHOD(void, SBLaunchInfo, SetScriptedProcessClassName,
|
||||
(const char *), class_name);
|
||||
|
||||
m_opaque_sp->SetScriptedProcessClassName(class_name);
|
||||
}
|
||||
|
||||
lldb::SBStructuredData SBLaunchInfo::GetScriptedProcessDictionary() const {
|
||||
LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBStructuredData, SBLaunchInfo,
|
||||
GetScriptedProcessDictionary);
|
||||
|
||||
lldb_private::StructuredData::DictionarySP dict_sp =
|
||||
m_opaque_sp->GetScriptedProcessDictionarySP();
|
||||
|
||||
SBStructuredData data;
|
||||
data.m_impl_up->SetObjectSP(dict_sp);
|
||||
|
||||
return LLDB_RECORD_RESULT(data);
|
||||
}
|
||||
|
||||
void SBLaunchInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
|
||||
LLDB_RECORD_METHOD(void, SBLaunchInfo, SetScriptedProcessDictionary,
|
||||
(lldb::SBStructuredData), dict);
|
||||
|
||||
SBStream stream;
|
||||
SBError error = dict.GetAsJSON(stream);
|
||||
|
||||
if (error.Fail())
|
||||
return;
|
||||
|
||||
StructuredData::DictionarySP dict_sp;
|
||||
llvm::json::OStream s(stream.ref().AsRawOstream());
|
||||
dict_sp->Serialize(s);
|
||||
|
||||
m_opaque_sp->SetScriptedProcessDictionarySP(dict_sp);
|
||||
}
|
||||
|
||||
namespace lldb_private {
|
||||
namespace repro {
|
||||
|
||||
@@ -403,6 +454,14 @@ void RegisterMethods<SBLaunchInfo>(Registry &R) {
|
||||
());
|
||||
LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetDetachOnError, (bool));
|
||||
LLDB_REGISTER_METHOD_CONST(bool, SBLaunchInfo, GetDetachOnError, ());
|
||||
LLDB_REGISTER_METHOD_CONST(const char *, SBLaunchInfo,
|
||||
GetScriptedProcessClassName, ());
|
||||
LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetScriptedProcessClassName,
|
||||
(const char *));
|
||||
LLDB_REGISTER_METHOD_CONST(lldb::SBStructuredData, SBLaunchInfo,
|
||||
GetScriptedProcessDictionary, ());
|
||||
LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetScriptedProcessDictionary,
|
||||
(lldb::SBStructuredData));
|
||||
LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetEnvironment,
|
||||
(const lldb::SBEnvironment &, bool));
|
||||
LLDB_REGISTER_METHOD(lldb::SBEnvironment, SBLaunchInfo, GetEnvironment, ());
|
||||
|
||||
@@ -1009,11 +1009,14 @@ public:
|
||||
"Launch a new process on a remote platform.",
|
||||
"platform process launch program",
|
||||
eCommandRequiresTarget | eCommandTryTargetAPILock),
|
||||
m_options() {}
|
||||
m_options(), m_all_options() {
|
||||
m_all_options.Append(&m_options);
|
||||
m_all_options.Finalize();
|
||||
}
|
||||
|
||||
~CommandObjectPlatformProcessLaunch() override = default;
|
||||
|
||||
Options *GetOptions() override { return &m_options; }
|
||||
Options *GetOptions() override { return &m_all_options; }
|
||||
|
||||
protected:
|
||||
bool DoExecute(Args &args, CommandReturnObject &result) override {
|
||||
@@ -1085,6 +1088,7 @@ protected:
|
||||
}
|
||||
|
||||
CommandOptionsProcessLaunch m_options;
|
||||
OptionGroupOptions m_all_options;
|
||||
};
|
||||
|
||||
// "platform process list"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
#include "lldb/Interpreter/CommandReturnObject.h"
|
||||
#include "lldb/Interpreter/OptionArgParser.h"
|
||||
#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
|
||||
#include "lldb/Interpreter/Options.h"
|
||||
#include "lldb/Target/Platform.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
@@ -108,7 +109,14 @@ public:
|
||||
interpreter, "process launch",
|
||||
"Launch the executable in the debugger.", nullptr,
|
||||
eCommandRequiresTarget, "restart"),
|
||||
m_options() {
|
||||
m_options(),
|
||||
m_class_options("scripted process", true, 'C', 'k', 'v', 0),
|
||||
m_all_options() {
|
||||
m_all_options.Append(&m_options);
|
||||
m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
|
||||
LLDB_OPT_SET_ALL);
|
||||
m_all_options.Finalize();
|
||||
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData run_args_arg;
|
||||
|
||||
@@ -135,7 +143,7 @@ public:
|
||||
request, nullptr);
|
||||
}
|
||||
|
||||
Options *GetOptions() override { return &m_options; }
|
||||
Options *GetOptions() override { return &m_all_options; }
|
||||
|
||||
const char *GetRepeatCommand(Args ¤t_command_args,
|
||||
uint32_t index) override {
|
||||
@@ -180,6 +188,15 @@ protected:
|
||||
disable_aslr = target->GetDisableASLR();
|
||||
}
|
||||
|
||||
if (!m_class_options.GetName().empty()) {
|
||||
m_options.launch_info.SetProcessPluginName("ScriptedProcess");
|
||||
m_options.launch_info.SetScriptedProcessClassName(
|
||||
m_class_options.GetName());
|
||||
m_options.launch_info.SetScriptedProcessDictionarySP(
|
||||
m_class_options.GetStructuredData());
|
||||
target->SetProcessLaunchInfo(m_options.launch_info);
|
||||
}
|
||||
|
||||
if (disable_aslr)
|
||||
m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
|
||||
else
|
||||
@@ -253,6 +270,8 @@ protected:
|
||||
}
|
||||
|
||||
CommandOptionsProcessLaunch m_options;
|
||||
OptionGroupPythonClassWithDict m_class_options;
|
||||
OptionGroupOptions m_all_options;
|
||||
};
|
||||
|
||||
#define LLDB_OPTIONS_process_attach
|
||||
|
||||
@@ -30,7 +30,7 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
|
||||
uint32_t option_idx, llvm::StringRef option_arg,
|
||||
ExecutionContext *execution_context) {
|
||||
Status error;
|
||||
const int short_option = m_getopt_table[option_idx].val;
|
||||
const int short_option = g_process_launch_options[option_idx].short_option;
|
||||
|
||||
switch (short_option) {
|
||||
case 's': // Stop at program entry point
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===-- CommandOptionsProcessLaunch.h -------------------------------------===//
|
||||
//===-- CommandOptionsProcessLaunch.h ---------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -16,9 +16,9 @@ namespace lldb_private {
|
||||
|
||||
// CommandOptionsProcessLaunch
|
||||
|
||||
class CommandOptionsProcessLaunch : public lldb_private::Options {
|
||||
class CommandOptionsProcessLaunch : public lldb_private::OptionGroup {
|
||||
public:
|
||||
CommandOptionsProcessLaunch() : lldb_private::Options() {
|
||||
CommandOptionsProcessLaunch() : lldb_private::OptionGroup() {
|
||||
// Keep default values of all options in one place: OptionParsingStarting
|
||||
// ()
|
||||
OptionParsingStarting(nullptr);
|
||||
|
||||
@@ -32,7 +32,8 @@ ProcessLaunchInfo::ProcessLaunchInfo()
|
||||
: ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0),
|
||||
m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0),
|
||||
m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr),
|
||||
m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() {}
|
||||
m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp(),
|
||||
m_scripted_process_class_name(), m_scripted_process_dictionary_sp() {}
|
||||
|
||||
ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
|
||||
const FileSpec &stdout_file_spec,
|
||||
@@ -42,7 +43,8 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
|
||||
: ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
|
||||
m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0),
|
||||
m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr),
|
||||
m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() {
|
||||
m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp(),
|
||||
m_scripted_process_class_name(), m_scripted_process_dictionary_sp() {
|
||||
if (stdin_file_spec) {
|
||||
FileAction file_action;
|
||||
const bool read = true;
|
||||
@@ -171,6 +173,8 @@ void ProcessLaunchInfo::Clear() {
|
||||
m_resume_count = 0;
|
||||
m_listener_sp.reset();
|
||||
m_hijack_listener_sp.reset();
|
||||
m_scripted_process_class_name.clear();
|
||||
m_scripted_process_dictionary_sp.reset();
|
||||
}
|
||||
|
||||
void ProcessLaunchInfo::SetMonitorProcessCallback(
|
||||
|
||||
@@ -2925,6 +2925,28 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
|
||||
|
||||
launch_info.GetFlags().Set(eLaunchFlagDebug);
|
||||
|
||||
if (launch_info.IsScriptedProcess()) {
|
||||
TargetPropertiesSP properties_sp = GetGlobalProperties();
|
||||
|
||||
if (!properties_sp) {
|
||||
LLDB_LOGF(log, "Target::%s Couldn't fetch target global properties.",
|
||||
__FUNCTION__);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Only copy scripted process launch options.
|
||||
ProcessLaunchInfo &default_launch_info =
|
||||
const_cast<ProcessLaunchInfo &>(properties_sp->GetProcessLaunchInfo());
|
||||
|
||||
default_launch_info.SetProcessPluginName("ScriptedProcess");
|
||||
default_launch_info.SetScriptedProcessClassName(
|
||||
launch_info.GetScriptedProcessClassName());
|
||||
default_launch_info.SetScriptedProcessDictionarySP(
|
||||
launch_info.GetScriptedProcessDictionarySP());
|
||||
|
||||
SetProcessLaunchInfo(launch_info);
|
||||
}
|
||||
|
||||
// Get the value of synchronous execution here. If you wait till after you
|
||||
// have started to run, then you could have hit a breakpoint, whose command
|
||||
// might switch the value, and then you'll pick up that incorrect value.
|
||||
|
||||
Reference in New Issue
Block a user