[Lldb-commits] [lldb] dbb0c14 - [lldb] Add new commands and tests for getting file perms & exists
Michał Górny via lldb-commits
lldb-commits at lists.llvm.org
Fri Sep 10 05:08:43 PDT 2021
Author: Michał Górny
Date: 2021-09-10T14:08:36+02:00
New Revision: dbb0c14d2729d135d9d6bb2d0e858e128129da08
URL: https://github.com/llvm/llvm-project/commit/dbb0c14d2729d135d9d6bb2d0e858e128129da08
DIFF: https://github.com/llvm/llvm-project/commit/dbb0c14d2729d135d9d6bb2d0e858e128129da08.diff
LOG: [lldb] Add new commands and tests for getting file perms & exists
Add two new commands 'platform get-file-permissions' and 'platform
file-exists' for the respective bits of LLDB protocol. Add tests for
them. Fix error handling in GetFilePermissions().
Differential Revision: https://reviews.llvm.org/D107809
Added:
Modified:
lldb/source/Commands/CommandObjectPlatform.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py
Removed:
################################################################################
diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp
index 0274605f2e329..7760eba290d4b 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -926,6 +926,141 @@ class CommandObjectPlatformGetSize : public CommandObjectParsed {
}
};
+// "platform get-permissions remote-file-path"
+class CommandObjectPlatformGetPermissions : public CommandObjectParsed {
+public:
+ CommandObjectPlatformGetPermissions(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "platform get-permissions",
+ "Get the file permission bits from the remote end.",
+ "platform get-permissions <remote-file-spec>", 0) {
+ SetHelpLong(
+ R"(Examples:
+
+(lldb) platform get-permissions /the/remote/file/path
+
+ Get the file permissions from the remote end with path /the/remote/file/path.)");
+
+ CommandArgumentEntry arg1;
+ CommandArgumentData file_arg_remote;
+
+ // Define the first (and only) variant of this arg.
+ file_arg_remote.arg_type = eArgTypeFilename;
+ file_arg_remote.arg_repetition = eArgRepeatPlain;
+ // There is only one variant this argument could be; put it into the
+ // argument entry.
+ arg1.push_back(file_arg_remote);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back(arg1);
+ }
+
+ ~CommandObjectPlatformGetPermissions() override = default;
+
+ void
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ if (request.GetCursorIndex() != 0)
+ return;
+
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), CommandCompletions::eRemoteDiskFileCompletion,
+ request, nullptr);
+ }
+
+ bool DoExecute(Args &args, CommandReturnObject &result) override {
+ // If the number of arguments is incorrect, issue an error message.
+ if (args.GetArgumentCount() != 1) {
+ result.AppendError("required argument missing; specify the source file "
+ "path as the only argument");
+ return false;
+ }
+
+ PlatformSP platform_sp(
+ GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp) {
+ std::string remote_file_path(args.GetArgumentAtIndex(0));
+ uint32_t permissions;
+ Status error = platform_sp->GetFilePermissions(FileSpec(remote_file_path),
+ permissions);
+ if (error.Success()) {
+ result.AppendMessageWithFormat(
+ "File permissions of %s (remote): 0o%04" PRIo32 "\n",
+ remote_file_path.c_str(), permissions);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ } else
+ result.AppendError(error.AsCString());
+ } else {
+ result.AppendError("no platform currently selected\n");
+ }
+ return result.Succeeded();
+ }
+};
+
+// "platform file-exists remote-file-path"
+class CommandObjectPlatformFileExists : public CommandObjectParsed {
+public:
+ CommandObjectPlatformFileExists(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "platform file-exists",
+ "Check if the file exists on the remote end.",
+ "platform file-exists <remote-file-spec>", 0) {
+ SetHelpLong(
+ R"(Examples:
+
+(lldb) platform file-exists /the/remote/file/path
+
+ Check if /the/remote/file/path exists on the remote end.)");
+
+ CommandArgumentEntry arg1;
+ CommandArgumentData file_arg_remote;
+
+ // Define the first (and only) variant of this arg.
+ file_arg_remote.arg_type = eArgTypeFilename;
+ file_arg_remote.arg_repetition = eArgRepeatPlain;
+ // There is only one variant this argument could be; put it into the
+ // argument entry.
+ arg1.push_back(file_arg_remote);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back(arg1);
+ }
+
+ ~CommandObjectPlatformFileExists() override = default;
+
+ void
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ if (request.GetCursorIndex() != 0)
+ return;
+
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), CommandCompletions::eRemoteDiskFileCompletion,
+ request, nullptr);
+ }
+
+ bool DoExecute(Args &args, CommandReturnObject &result) override {
+ // If the number of arguments is incorrect, issue an error message.
+ if (args.GetArgumentCount() != 1) {
+ result.AppendError("required argument missing; specify the source file "
+ "path as the only argument");
+ return false;
+ }
+
+ PlatformSP platform_sp(
+ GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp) {
+ std::string remote_file_path(args.GetArgumentAtIndex(0));
+ bool exists = platform_sp->GetFileExists(FileSpec(remote_file_path));
+ result.AppendMessageWithFormat(
+ "File %s (remote) %s\n",
+ remote_file_path.c_str(), exists ? "exists" : "does not exist");
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ } else {
+ result.AppendError("no platform currently selected\n");
+ }
+ return result.Succeeded();
+ }
+};
+
// "platform put-file"
class CommandObjectPlatformPutFile : public CommandObjectParsed {
public:
@@ -1759,8 +1894,12 @@ CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
LoadSubCommand("file",
CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
+ LoadSubCommand("file-exists",
+ CommandObjectSP(new CommandObjectPlatformFileExists(interpreter)));
LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
interpreter)));
+ LoadSubCommand("get-permissions",
+ CommandObjectSP(new CommandObjectPlatformGetPermissions(interpreter)));
LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
interpreter)));
LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 410937483dcd1..248fd57ba909b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -661,9 +661,10 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Mode(
std::error_code ec;
const uint32_t mode = FileSystem::Instance().GetPermissions(file_spec, ec);
StreamString response;
- response.Printf("F%x", mode);
- if (mode == 0 || ec)
- response.Printf(",%x", (int)Status(ec).GetError());
+ if (mode != llvm::sys::fs::perms_not_known)
+ response.Printf("F%x", mode);
+ else
+ response.Printf("F-1,%x", (int)Status(ec).GetError());
return SendPacketNoLock(response.GetString());
}
return SendErrorResponse(23);
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
index d5475986bb57d..16ddf6f19e0af 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
@@ -100,3 +100,48 @@ def vFile(self, packet):
"vFile:fstat:5",
"vFile:close:5",
])
+
+ def test_file_permissions(self):
+ """Test 'platform get-permissions'"""
+
+ class Responder(MockGDBServerResponder):
+ def vFile(self, packet):
+ return "F1a4"
+
+ self.server.responder = Responder()
+
+ self.match("platform get-permissions /some/file.txt",
+ [r"File permissions of /some/file\.txt \(remote\): 0o0644"])
+ self.assertPacketLogContains([
+ "vFile:mode:2f736f6d652f66696c652e747874",
+ ])
+
+ def test_file_exists(self):
+ """Test 'platform file-exists'"""
+
+ class Responder(MockGDBServerResponder):
+ def vFile(self, packet):
+ return "F,1"
+
+ self.server.responder = Responder()
+
+ self.match("platform file-exists /some/file.txt",
+ [r"File /some/file\.txt \(remote\) exists"])
+ self.assertPacketLogContains([
+ "vFile:exists:2f736f6d652f66696c652e747874",
+ ])
+
+ def test_file_exists_not(self):
+ """Test 'platform file-exists' with non-existing file"""
+
+ class Responder(MockGDBServerResponder):
+ def vFile(self, packet):
+ return "F,0"
+
+ self.server.responder = Responder()
+
+ self.match("platform file-exists /some/file.txt",
+ [r"File /some/file\.txt \(remote\) does not exist"])
+ self.assertPacketLogContains([
+ "vFile:exists:2f736f6d652f66696c652e747874",
+ ])
diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py b/lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py
index 63658f8dec765..af017632b444c 100644
--- a/lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py
+++ b/lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py
@@ -176,6 +176,23 @@ def test_platform_file_mode(self):
context = self.expect_gdbremote_sequence()
self.assertEqual(int(context["mode"], 16), test_mode)
+ @skipIfWindows
+ @add_test_categories(["llgs"])
+ def test_platform_file_mode_fail(self):
+ server = self.connect_to_debug_monitor()
+ self.assertIsNotNone(server)
+
+ temp_path = self.getBuildArtifact("nonexist")
+
+ self.do_handshake()
+ self.test_sequence.add_log_lines(
+ ["read packet: $vFile:mode:%s#00" % (
+ binascii.b2a_hex(temp_path.encode()).decode(),),
+ {"direction": "send",
+ "regex": r"^\$F-1,0*2+#[0-9a-fA-F]{2}$"}],
+ True)
+ self.expect_gdbremote_sequence()
+
@skipIfWindows
@add_test_categories(["llgs"])
def test_platform_file_exists(self):
More information about the lldb-commits
mailing list