[Lldb-commits] [lldb] 4e9e048 - [lldb/Commands] Add ability to run shell command on the host.

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Fri May 15 13:14:56 PDT 2020


Author: Med Ismail Bennani
Date: 2020-05-15T22:14:39+02:00
New Revision: 4e9e0488ab67c54be57e303ce3085466fbc8e886

URL: https://github.com/llvm/llvm-project/commit/4e9e0488ab67c54be57e303ce3085466fbc8e886
DIFF: https://github.com/llvm/llvm-project/commit/4e9e0488ab67c54be57e303ce3085466fbc8e886.diff

LOG: [lldb/Commands] Add ability to run shell command on the host.

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 at gmail.com>

Added: 
    

Modified: 
    lldb/source/Commands/CommandObjectPlatform.cpp
    lldb/source/Commands/Options.td
    lldb/source/Interpreter/CommandInterpreter.cpp
    lldb/test/API/commands/platform/basic/TestPlatformCommand.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp
index 5a6573307c61..4b19592af75a 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -1567,6 +1567,9 @@ class CommandObjectPlatformShell : public CommandObjectRaw {
       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))
@@ -1574,7 +1577,7 @@ class CommandObjectPlatformShell : public CommandObjectRaw {
               "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");
@@ -1583,9 +1586,13 @@ class CommandObjectPlatformShell : public CommandObjectRaw {
       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)
@@ -1609,6 +1616,7 @@ class CommandObjectPlatformShell : public CommandObjectRaw {
       return true;
     }
 
+    const bool is_alias = !raw_command_line.contains("platform");
     OptionsWithRaw args(raw_command_line);
     const char *expr = args.GetRawPart().c_str();
 
@@ -1616,8 +1624,16 @@ class CommandObjectPlatformShell : public CommandObjectRaw {
       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{};
@@ -1625,7 +1641,7 @@ class CommandObjectPlatformShell : public CommandObjectRaw {
       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) {

diff  --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index addfec53b39c..d6f1e0a3c96d 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -624,6 +624,8 @@ let Command = "platform process attach" in {
 }
 
 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.">;
 }
@@ -703,6 +705,7 @@ let Command = "script add" in {
     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.">;

diff  --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 2cc3d47406b7..df19855b5f8c 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -381,6 +381,16 @@ void CommandInterpreter::Initialize() {
     }
   }
 
+  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);

diff  --git a/lldb/test/API/commands/platform/basic/TestPlatformCommand.py b/lldb/test/API/commands/platform/basic/TestPlatformCommand.py
index 9c16da8ad005..570f9b3f828d 100644
--- a/lldb/test/API/commands/platform/basic/TestPlatformCommand.py
+++ b/lldb/test/API/commands/platform/basic/TestPlatformCommand.py
@@ -18,6 +18,12 @@ class PlatformCommandTestCase(TestBase):
     def test_help_platform(self):
         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",
@@ -55,6 +61,7 @@ def test_shell(self):
             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 /",
@@ -62,19 +69,26 @@ def test_shell(self):
                     "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"])


        


More information about the lldb-commits mailing list