Skip to content

Commit 6ab3990

Browse files
committed
[lldb] Add scripted process launch/attach option to {,platform }process commands
This patch does several things: First, it refactors the `CommandObject{,Platform}ProcessObject` command option class into a separate `CommandOptionsProcessAttach` option group. This will make sure both the `platform process attach` and `process attach` command options will always stay in sync without having with duplicate them each time. But more importantly, making this class an `OptionGroup` allows us to combine with a `OptionGroupPythonClassWithDict` to add support for the scripted process managing class name and user-provided dictionary options. This patch also improves feature parity between `ProcessLaunchInfo` and `ProcessAttachInfo` with regard to ScriptedProcesses, by exposing the various getters and setters necessary to use them through the SBAPI. This is foundation work for adding support to "attach" to a process from the scripted platform. Differential Revision: https://reviews.llvm.org/D139945 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent 84a9005 commit 6ab3990

File tree

9 files changed

+264
-131
lines changed

9 files changed

+264
-131
lines changed

lldb/include/lldb/API/SBAttachInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,14 @@ class LLDB_API SBAttachInfo {
164164
/// allows a different listener to be used to listen for process events.
165165
void SetListener(SBListener &listener);
166166

167+
const char *GetScriptedProcessClassName() const;
168+
169+
void SetScriptedProcessClassName(const char *class_name);
170+
171+
lldb::SBStructuredData GetScriptedProcessDictionary() const;
172+
173+
void SetScriptedProcessDictionary(lldb::SBStructuredData dict);
174+
167175
protected:
168176
friend class SBTarget;
169177

lldb/include/lldb/API/SBStructuredData.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class SBStructuredData {
9090
size_t GetStringValue(char *dst, size_t dst_len) const;
9191

9292
protected:
93+
friend class SBAttachInfo;
9394
friend class SBLaunchInfo;
9495
friend class SBDebugger;
9596
friend class SBTarget;

lldb/include/lldb/Target/Process.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,28 @@ class ProcessAttachInfo : public ProcessInstanceInfo {
196196

197197
lldb::ListenerSP GetListenerForProcess(Debugger &debugger);
198198

199+
bool IsScriptedProcess() const {
200+
return !m_scripted_process_class_name.empty();
201+
}
202+
203+
std::string GetScriptedProcessClassName() const {
204+
return m_scripted_process_class_name;
205+
}
206+
207+
void SetScriptedProcessClassName(std::string name) {
208+
m_scripted_process_class_name = name;
209+
}
210+
211+
lldb_private::StructuredData::DictionarySP
212+
GetScriptedProcessDictionarySP() const {
213+
return m_scripted_process_dictionary_sp;
214+
}
215+
216+
void SetScriptedProcessDictionarySP(
217+
lldb_private::StructuredData::DictionarySP dictionary_sp) {
218+
m_scripted_process_dictionary_sp = dictionary_sp;
219+
}
220+
199221
protected:
200222
lldb::ListenerSP m_listener_sp;
201223
lldb::ListenerSP m_hijack_listener_sp;
@@ -213,6 +235,11 @@ class ProcessAttachInfo : public ProcessInstanceInfo {
213235
false; // Use an async attach where we start the attach and return
214236
// immediately (used by GUI programs with --waitfor so they can
215237
// call SBProcess::Stop() to cancel attach)
238+
std::string m_scripted_process_class_name; // The name of the class that will
239+
// manage a scripted process.
240+
StructuredData::DictionarySP
241+
m_scripted_process_dictionary_sp; // A dictionary that holds key/value
242+
// pairs passed to the scripted process.
216243
};
217244

218245
// This class tracks the Modification state of the process. Things that can

lldb/source/API/SBAttachInfo.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "Utils.h"
1111
#include "lldb/API/SBFileSpec.h"
1212
#include "lldb/API/SBListener.h"
13+
#include "lldb/API/SBStructuredData.h"
1314
#include "lldb/Target/Process.h"
1415
#include "lldb/Utility/Instrumentation.h"
1516

@@ -251,3 +252,48 @@ void SBAttachInfo::SetListener(SBListener &listener) {
251252

252253
m_opaque_sp->SetListener(listener.GetSP());
253254
}
255+
256+
const char *SBAttachInfo::GetScriptedProcessClassName() const {
257+
LLDB_INSTRUMENT_VA(this);
258+
259+
// Constify this string so that it is saved in the string pool. Otherwise it
260+
// would be freed when this function goes out of scope.
261+
ConstString class_name(m_opaque_sp->GetScriptedProcessClassName().c_str());
262+
return class_name.AsCString();
263+
}
264+
265+
void SBAttachInfo::SetScriptedProcessClassName(const char *class_name) {
266+
LLDB_INSTRUMENT_VA(this, class_name);
267+
268+
m_opaque_sp->SetScriptedProcessClassName(class_name);
269+
}
270+
271+
lldb::SBStructuredData SBAttachInfo::GetScriptedProcessDictionary() const {
272+
LLDB_INSTRUMENT_VA(this);
273+
274+
lldb_private::StructuredData::DictionarySP dict_sp =
275+
m_opaque_sp->GetScriptedProcessDictionarySP();
276+
277+
SBStructuredData data;
278+
data.m_impl_up->SetObjectSP(dict_sp);
279+
280+
return data;
281+
}
282+
283+
void SBAttachInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
284+
LLDB_INSTRUMENT_VA(this, dict);
285+
if (!dict.IsValid() || !dict.m_impl_up)
286+
return;
287+
288+
StructuredData::ObjectSP obj_sp = dict.m_impl_up->GetObjectSP();
289+
290+
if (!obj_sp)
291+
return;
292+
293+
StructuredData::DictionarySP dict_sp =
294+
std::make_shared<StructuredData::Dictionary>(obj_sp);
295+
if (!dict_sp || dict_sp->GetType() == lldb::eStructuredDataTypeInvalid)
296+
return;
297+
298+
m_opaque_sp->SetScriptedProcessDictionarySP(dict_sp);
299+
}

lldb/source/Commands/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ add_lldb_library(lldbCommands
4444
CommandObjectWatchpoint.cpp
4545
CommandObjectWatchpointCommand.cpp
4646
CommandOptionArgumentTable.cpp
47+
CommandOptionsProcessAttach.cpp
4748
CommandOptionsProcessLaunch.cpp
4849

4950
${Healtcheck_SOURCES}

lldb/source/Commands/CommandObjectPlatform.cpp

Lines changed: 37 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "CommandObjectPlatform.h"
10+
#include "CommandOptionsProcessAttach.h"
1011
#include "CommandOptionsProcessLaunch.h"
1112
#include "lldb/Core/Debugger.h"
1213
#include "lldb/Core/Module.h"
@@ -18,6 +19,8 @@
1819
#include "lldb/Interpreter/CommandReturnObject.h"
1920
#include "lldb/Interpreter/OptionGroupFile.h"
2021
#include "lldb/Interpreter/OptionGroupPlatform.h"
22+
#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
23+
#include "lldb/Interpreter/ScriptedMetadata.h"
2124
#include "lldb/Target/ExecutionContext.h"
2225
#include "lldb/Target/Platform.h"
2326
#include "lldb/Target/Process.h"
@@ -1143,8 +1146,11 @@ class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
11431146
: CommandObjectParsed(interpreter, "platform process launch",
11441147
"Launch a new process on a remote platform.",
11451148
"platform process launch program",
1146-
eCommandRequiresTarget | eCommandTryTargetAPILock) {
1149+
eCommandRequiresTarget | eCommandTryTargetAPILock),
1150+
m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
11471151
m_all_options.Append(&m_options);
1152+
m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
1153+
LLDB_OPT_SET_ALL);
11481154
m_all_options.Finalize();
11491155
CommandArgumentData run_arg_arg{eArgTypeRunArgs, eArgRepeatStar};
11501156
m_arguments.push_back({run_arg_arg});
@@ -1179,6 +1185,15 @@ class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
11791185
m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
11801186
}
11811187

1188+
if (!m_class_options.GetName().empty()) {
1189+
m_options.launch_info.SetProcessPluginName("ScriptedProcess");
1190+
m_options.launch_info.SetScriptedProcessClassName(
1191+
m_class_options.GetName());
1192+
m_options.launch_info.SetScriptedProcessDictionarySP(
1193+
m_class_options.GetStructuredData());
1194+
target->SetProcessLaunchInfo(m_options.launch_info);
1195+
}
1196+
11821197
if (argc > 0) {
11831198
if (m_options.launch_info.GetExecutableFile()) {
11841199
// We already have an executable file, so we will use this and all
@@ -1222,6 +1237,7 @@ class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
12221237
}
12231238

12241239
CommandOptionsProcessLaunch m_options;
1240+
OptionGroupPythonClassWithDict m_class_options;
12251241
OptionGroupOptions m_all_options;
12261242
};
12271243

@@ -1571,78 +1587,32 @@ class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
15711587

15721588
class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
15731589
public:
1574-
class CommandOptions : public Options {
1575-
public:
1576-
CommandOptions() {
1577-
// Keep default values of all options in one place: OptionParsingStarting
1578-
// ()
1579-
OptionParsingStarting(nullptr);
1580-
}
1581-
1582-
~CommandOptions() override = default;
1583-
1584-
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1585-
ExecutionContext *execution_context) override {
1586-
Status error;
1587-
char short_option = (char)m_getopt_table[option_idx].val;
1588-
switch (short_option) {
1589-
case 'p': {
1590-
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
1591-
if (option_arg.getAsInteger(0, pid)) {
1592-
error.SetErrorStringWithFormat("invalid process ID '%s'",
1593-
option_arg.str().c_str());
1594-
} else {
1595-
attach_info.SetProcessID(pid);
1596-
}
1597-
} break;
1598-
1599-
case 'P':
1600-
attach_info.SetProcessPluginName(option_arg);
1601-
break;
1602-
1603-
case 'n':
1604-
attach_info.GetExecutableFile().SetFile(option_arg,
1605-
FileSpec::Style::native);
1606-
break;
1607-
1608-
case 'w':
1609-
attach_info.SetWaitForLaunch(true);
1610-
break;
1611-
1612-
default:
1613-
llvm_unreachable("Unimplemented option");
1614-
}
1615-
return error;
1616-
}
1617-
1618-
void OptionParsingStarting(ExecutionContext *execution_context) override {
1619-
attach_info.Clear();
1620-
}
1621-
1622-
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1623-
return llvm::makeArrayRef(g_platform_process_attach_options);
1624-
}
1625-
1626-
// Options table: Required for subclasses of Options.
1627-
1628-
static OptionDefinition g_option_table[];
1629-
1630-
// Instance variables to hold the values for command options.
1631-
1632-
ProcessAttachInfo attach_info;
1633-
};
1634-
16351590
CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
16361591
: CommandObjectParsed(interpreter, "platform process attach",
16371592
"Attach to a process.",
1638-
"platform process attach <cmd-options>") {}
1593+
"platform process attach <cmd-options>"),
1594+
m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
1595+
m_all_options.Append(&m_options);
1596+
m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
1597+
LLDB_OPT_SET_ALL);
1598+
m_all_options.Finalize();
1599+
}
16391600

16401601
~CommandObjectPlatformProcessAttach() override = default;
16411602

16421603
bool DoExecute(Args &command, CommandReturnObject &result) override {
16431604
PlatformSP platform_sp(
16441605
GetDebugger().GetPlatformList().GetSelectedPlatform());
16451606
if (platform_sp) {
1607+
1608+
if (!m_class_options.GetName().empty()) {
1609+
m_options.attach_info.SetProcessPluginName("ScriptedProcess");
1610+
m_options.attach_info.SetScriptedProcessClassName(
1611+
m_class_options.GetName());
1612+
m_options.attach_info.SetScriptedProcessDictionarySP(
1613+
m_class_options.GetStructuredData());
1614+
}
1615+
16461616
Status err;
16471617
ProcessSP remote_process_sp = platform_sp->Attach(
16481618
m_options.attach_info, GetDebugger(), nullptr, err);
@@ -1658,10 +1628,12 @@ class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
16581628
return result.Succeeded();
16591629
}
16601630

1661-
Options *GetOptions() override { return &m_options; }
1631+
Options *GetOptions() override { return &m_all_options; }
16621632

16631633
protected:
1664-
CommandOptions m_options;
1634+
CommandOptionsProcessAttach m_options;
1635+
OptionGroupPythonClassWithDict m_class_options;
1636+
OptionGroupOptions m_all_options;
16651637
};
16661638

16671639
class CommandObjectPlatformProcess : public CommandObjectMultiword {

0 commit comments

Comments
 (0)