This patch introduces the `(-h|--host)` option to the `platform shell`
command. It allows the user to run shell commands from the host platform
(always available) without putting lldb in the background.
Since the default behaviour of `platform shell` is to run the command of
the selected platform, having such a choice can be quite handy when
debugging remote targets, for instances.
This patch also introduces a `shell` alias, to improve the command
discoverability and make it more convenient to use for the user.
rdar://
62856024
Differential Revision: https://reviews.llvm.org/D79659
Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
const char short_option = (char)GetDefinitions()[option_idx].short_option;
switch (short_option) {
+ case 'h':
+ m_use_host_platform = true;
+ break;
case 't':
uint32_t timeout_sec;
if (option_arg.getAsInteger(10, timeout_sec))
"could not convert \"%s\" to a numeric value.",
option_arg.str().c_str());
else
- timeout = std::chrono::seconds(timeout_sec);
+ m_timeout = std::chrono::seconds(timeout_sec);
break;
default:
llvm_unreachable("Unimplemented option");
return error;
}
- void OptionParsingStarting(ExecutionContext *execution_context) override {}
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_timeout.reset();
+ m_use_host_platform = false;
+ }
- Timeout<std::micro> timeout = std::chrono::seconds(10);
+ Timeout<std::micro> m_timeout = std::chrono::seconds(10);
+ bool m_use_host_platform;
};
CommandObjectPlatformShell(CommandInterpreter &interpreter)
return true;
}
+ const bool is_alias = !raw_command_line.contains("platform");
OptionsWithRaw args(raw_command_line);
const char *expr = args.GetRawPart().c_str();
if (!ParseOptions(args.GetArgs(), result))
return false;
+ if (args.GetRawPart().empty()) {
+ result.GetOutputStream().Printf("%s <shell-command>\n",
+ is_alias ? "shell" : "platform shell");
+ return false;
+ }
+
PlatformSP platform_sp(
- GetDebugger().GetPlatformList().GetSelectedPlatform());
+ m_options.m_use_host_platform
+ ? Platform::GetHostPlatform()
+ : GetDebugger().GetPlatformList().GetSelectedPlatform());
Status error;
if (platform_sp) {
FileSpec working_dir{};
int status = -1;
int signo = -1;
error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo,
- &output, m_options.timeout));
+ &output, m_options.m_timeout));
if (!output.empty())
result.GetOutputStream().PutCString(output);
if (status > 0) {
}
let Command = "platform shell" in {
+ def platform_shell_host : Option<"host", "h">,
+ Desc<"Run the commands on the host shell when enabled.">;
def platform_shell_timeout : Option<"timeout", "t">, Arg<"Value">,
Desc<"Seconds to wait for the remote host to finish running the command.">;
}
Desc<"Set the synchronicity of this command's executions with regard to "
"LLDB event system.">;
}
+
let Command = "source info" in {
def source_info_count : Option<"count", "c">, Arg<"Count">,
Desc<"The number of line entries to display.">;
}
}
+ cmd_obj_sp = GetCommandSPExact("platform shell", false);
+ if (cmd_obj_sp) {
+ CommandAlias *shell_alias = AddAlias("shell", cmd_obj_sp, " --host --");
+ if (shell_alias) {
+ shell_alias->SetHelp("Run a shell command on the host.");
+ shell_alias->SetHelpLong("");
+ shell_alias->SetSyntax("shell <shell-command>");
+ }
+ }
+
cmd_obj_sp = GetCommandSPExact("process kill", false);
if (cmd_obj_sp) {
AddAlias("kill", cmd_obj_sp);
self.runCmd("help platform")
@no_debug_info_test
+ def test_help_platform(self):
+ self.expect("help shell", substrs=["Run a shell command on the host.",
+ "shell <shell-command>"])
+
+
+ @no_debug_info_test
def test_list(self):
self.expect("platform list",
patterns=['^Available platforms:'])
self.expect(
"platform shell dir c:\\", substrs=[
"Windows", "Program Files"])
+ self.expect("shell dir c:\\", substrs=["Windows", "Program Files"])
elif re.match(".*-.*-.*-android", triple):
self.expect(
"platform shell ls /",
"cache",
"dev",
"system"])
+ self.expect("shell ls /",
+ substrs=["cache", "dev", "system"])
else:
self.expect("platform shell ls /", substrs=["dev", "tmp", "usr"])
+ self.expect("shell ls /", substrs=["dev", "tmp", "usr"])
@no_debug_info_test
def test_shell_builtin(self):
""" Test a shell built-in command (echo) """
self.expect("platform shell echo hello lldb",
substrs=["hello lldb"])
+ self.expect("shell echo hello lldb",
+ substrs=["hello lldb"])
+
- # FIXME: re-enable once platform shell -t can specify the desired timeout
@no_debug_info_test
def test_shell_timeout(self):
""" Test a shell built-in command (sleep) that times out """
- self.skipTest("due to taking too long to complete.")
- self.expect("platform shell sleep 15", error=True, substrs=[
+ self.skipTest("Alias with option not supported by the command interpreter.")
+ self.expect("platform shell -t 1 -- sleep 15", error=True, substrs=[
+ "error: timed out waiting for shell command to complete"])
+ self.expect("shell -t 1 -- sleep 3", error=True, substrs=[
"error: timed out waiting for shell command to complete"])