[Lldb-commits] [lldb] 501eaf8 - [lldb] [gdb-remote] Add fallbacks for vFile:mode and vFile:exists
Michał Górny via lldb-commits
lldb-commits at lists.llvm.org
Fri Sep 10 05:08:45 PDT 2021
Author: Michał Górny
Date: 2021-09-10T14:08:36+02:00
New Revision: 501eaf88770d15de92fa0eb7435f0470a3b93b0a
URL: https://github.com/llvm/llvm-project/commit/501eaf88770d15de92fa0eb7435f0470a3b93b0a
DIFF: https://github.com/llvm/llvm-project/commit/501eaf88770d15de92fa0eb7435f0470a3b93b0a.diff
LOG: [lldb] [gdb-remote] Add fallbacks for vFile:mode and vFile:exists
Add a GDB-compatible fallback to vFile:fstat for vFile:mode, and to
vFile:open for vFile:exists. Note that this is only partial fallback,
as it fails if the file cannot be opened.
Differential Revision: https://reviews.llvm.org/D107811
Added:
Modified:
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 4bcef1f05cdb..588e3faf0187 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -65,7 +65,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true),
m_qSymbol_requests_done(false), m_supports_qModuleInfo(true),
m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true),
- m_supports_vFileSize(true),
+ m_supports_vFileSize(true), m_supports_vFileMode(true),
+ m_supports_vFileExists(true),
m_host_arch(), m_process_arch(), m_os_build(), m_os_kernel(),
m_hostname(), m_gdb_server_name(), m_default_packet_timeout(0),
@@ -3159,37 +3160,50 @@ void GDBRemoteCommunicationClient::AutoCompleteDiskFileOrDirectory(
Status
GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec,
uint32_t &file_permissions) {
- std::string path{file_spec.GetPath(false)};
- Status error;
- lldb_private::StreamString stream;
- stream.PutCString("vFile:mode:");
- stream.PutStringAsRawHex8(path);
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
- PacketResult::Success) {
- if (response.GetChar() != 'F') {
- error.SetErrorStringWithFormat("invalid response to '%s' packet",
+ if (m_supports_vFileMode) {
+ std::string path{file_spec.GetPath(false)};
+ Status error;
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:mode:");
+ stream.PutStringAsRawHex8(path);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) !=
+ PacketResult::Success) {
+ error.SetErrorStringWithFormat("failed to send '%s' packet",
stream.GetData());
- } else {
- const uint32_t mode = response.GetS32(-1, 16);
- if (static_cast<int32_t>(mode) == -1) {
- if (response.GetChar() == ',') {
- int response_errno = response.GetS32(-1, 16);
- if (response_errno > 0)
- error.SetError(response_errno, lldb::eErrorTypePOSIX);
- else
- error.SetErrorToGenericError();
- } else
- error.SetErrorToGenericError();
+ return error;
+ }
+ if (!response.IsUnsupportedResponse()) {
+ if (response.GetChar() != 'F') {
+ error.SetErrorStringWithFormat("invalid response to '%s' packet",
+ stream.GetData());
} else {
- file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ const uint32_t mode = response.GetS32(-1, 16);
+ if (static_cast<int32_t>(mode) == -1) {
+ if (response.GetChar() == ',') {
+ int response_errno = response.GetS32(-1, 16);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ else
+ error.SetErrorToGenericError();
+ } else
+ error.SetErrorToGenericError();
+ } else {
+ file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ }
}
+ return error;
+ } else { // response.IsUnsupportedResponse()
+ m_supports_vFileMode = false;
}
- } else {
- error.SetErrorStringWithFormat("failed to send '%s' packet",
- stream.GetData());
}
- return error;
+
+ // Fallback to fstat.
+ if (llvm::Optional<GDBRemoteFStatData> st = Stat(file_spec)) {
+ file_permissions = st->gdb_st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ return Status();
+ }
+ return Status("fstat failed");
}
uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd,
@@ -3332,21 +3346,33 @@ Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) {
// Extension of host I/O packets to get whether a file exists.
bool GDBRemoteCommunicationClient::GetFileExists(
const lldb_private::FileSpec &file_spec) {
- std::string path(file_spec.GetPath(false));
- lldb_private::StreamString stream;
- stream.PutCString("vFile:exists:");
- stream.PutStringAsRawHex8(path);
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
- PacketResult::Success) {
- if (response.GetChar() != 'F')
- return false;
- if (response.GetChar() != ',')
+ if (m_supports_vFileExists) {
+ std::string path(file_spec.GetPath(false));
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:exists:");
+ stream.PutStringAsRawHex8(path);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) !=
+ PacketResult::Success)
return false;
- bool retcode = (response.GetChar() != '0');
- return retcode;
+ if (!response.IsUnsupportedResponse()) {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ bool retcode = (response.GetChar() != '0');
+ return retcode;
+ } else
+ m_supports_vFileExists = false;
}
- return false;
+
+ // Fallback to open.
+ Status error;
+ lldb::user_id_t fd = OpenFile(file_spec, File::eOpenOptionReadOnly, 0, error);
+ if (fd == UINT64_MAX)
+ return false;
+ CloseFile(fd, error);
+ return true;
}
bool GDBRemoteCommunicationClient::CalculateMD5(
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index f1a78ceeddcd..fde5897f8413 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -587,7 +587,8 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
m_supports_QEnvironment : 1, m_supports_QEnvironmentHexEncoded : 1,
m_supports_qSymbol : 1, m_qSymbol_requests_done : 1,
m_supports_qModuleInfo : 1, m_supports_jThreadsInfo : 1,
- m_supports_jModulesInfo : 1, m_supports_vFileSize : 1;
+ m_supports_jModulesInfo : 1, m_supports_vFileSize : 1,
+ m_supports_vFileMode : 1, m_supports_vFileExists : 1;
/// Current gdb remote protocol process identifier for all other operations
lldb::pid_t m_curr_pid = LLDB_INVALID_PROCESS_ID;
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
index 16ddf6f19e0a..e15838d434ea 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
@@ -116,6 +116,33 @@ def vFile(self, packet):
"vFile:mode:2f736f6d652f66696c652e747874",
])
+ def test_file_permissions_fallback(self):
+ """Test 'platform get-permissions' fallback to fstat"""
+
+ class Responder(MockGDBServerResponder):
+ def vFile(self, packet):
+ if packet.startswith("vFile:open:"):
+ return "F5"
+ elif packet.startswith("vFile:fstat:"):
+ return "F40;" + 8 * "\0" + "\0\0\1\xA4" + 52 * "\0"
+ if packet.startswith("vFile:close:"):
+ return "F0"
+ return ""
+
+ self.server.responder = Responder()
+
+ try:
+ self.match("platform get-permissions /some/file.txt",
+ [r"File permissions of /some/file\.txt \(remote\): 0o0644"])
+ self.assertPacketLogContains([
+ "vFile:mode:2f736f6d652f66696c652e747874",
+ "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000",
+ "vFile:fstat:5",
+ "vFile:close:5",
+ ])
+ finally:
+ self.dbg.GetSelectedPlatform().DisconnectRemote()
+
def test_file_exists(self):
"""Test 'platform file-exists'"""
@@ -145,3 +172,42 @@ def vFile(self, packet):
self.assertPacketLogContains([
"vFile:exists:2f736f6d652f66696c652e747874",
])
+
+ def test_file_exists_fallback(self):
+ """Test 'platform file-exists' fallback to open"""
+
+ class Responder(MockGDBServerResponder):
+ def vFile(self, packet):
+ if packet.startswith("vFile:open:"):
+ return "F5"
+ if packet.startswith("vFile:close:"):
+ return "F0"
+ return ""
+
+ self.server.responder = Responder()
+
+ self.match("platform file-exists /some/file.txt",
+ [r"File /some/file\.txt \(remote\) exists"])
+ self.assertPacketLogContains([
+ "vFile:exists:2f736f6d652f66696c652e747874",
+ "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000",
+ "vFile:close:5",
+ ])
+
+ def test_file_exists_not_fallback(self):
+ """Test 'platform file-exists' fallback to open with non-existing file"""
+
+ class Responder(MockGDBServerResponder):
+ def vFile(self, packet):
+ if packet.startswith("vFile:open:"):
+ return "F-1,2"
+ return ""
+
+ 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",
+ "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000",
+ ])
More information about the lldb-commits
mailing list