mgorny updated this revision to Diff 371674.
mgorny marked an inline comment as done.
mgorny added a comment.
Use fancy endian-magic types ;-).
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D107840/new/
https://reviews.llvm.org/D107840
Files:
lldb/include/lldb/Utility/StringExtractorGDBRemote.h
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
lldb/source/Utility/StringExtractorGDBRemote.cpp
lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py
Index: lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py
===================================================================
--- lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py
+++ lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py
@@ -9,7 +9,38 @@
from gdbremote_testcase import GdbRemoteTestCaseBase
import binascii
+import os
import stat
+import struct
+import typing
+
+
+class GDBStat(typing.NamedTuple):
+ st_dev: int
+ st_ino: int
+ st_mode: int
+ st_nlink: int
+ st_uid: int
+ st_gid: int
+ st_rdev: int
+ st_size: int
+ st_blksize: int
+ st_blocks: int
+ st_atime: int
+ st_mtime: int
+ st_ctime: int
+
+
+def uint32_or_zero(x):
+ return x if x < 2**32 else 0
+
+
+def uint32_or_max(x):
+ return x if x < 2**32 else 2**32 - 1
+
+
+def uint32_trunc(x):
+ return x & (2**32 - 1)
class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase):
@@ -178,6 +209,70 @@
True)
self.expect_gdbremote_sequence()
+ @skipIfWindows
+ @add_test_categories(["llgs"])
+ def test_platform_file_fstat(self):
+ server = self.connect_to_debug_monitor()
+ self.assertIsNotNone(server)
+
+ with tempfile.NamedTemporaryFile() as temp_file:
+ temp_file.write(b"some test data for stat")
+ temp_file.flush()
+
+ self.do_handshake()
+ self.test_sequence.add_log_lines(
+ ["read packet: $vFile:open:%s,0,0#00" % (
+ binascii.b2a_hex(temp_file.name.encode()).decode(),),
+ {"direction": "send",
+ "regex": r"^\$F([0-9a-fA-F]+)#[0-9a-fA-F]{2}$",
+ "capture": {1: "fd"}}],
+ True)
+
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+ fd = int(context["fd"], 16)
+
+ self.reset_test_sequence()
+ self.test_sequence.add_log_lines(
+ ["read packet: $vFile:fstat:%x#00" % (fd,),
+ {"direction": "send",
+ "regex": r"^\$F([0-9a-fA-F]+);(.*)#[0-9a-fA-F]{2}$",
+ "capture": {1: "size", 2: "data"}}],
+ True)
+ context = self.expect_gdbremote_sequence()
+ self.assertEqual(int(context["size"], 16), 64)
+ # NB: we're using .encode() as a hack because the test suite
+ # is wrongly using (unicode) str instead of bytes
+ gdb_stat = GDBStat(
+ *struct.unpack(">IIIIIIIQQQIII",
+ self.decode_gdbremote_binary(context["data"])
+ .encode("iso-8859-1")))
+ sys_stat = os.fstat(temp_file.fileno())
+
+ self.assertEqual(gdb_stat.st_dev, uint32_or_zero(sys_stat.st_dev))
+ self.assertEqual(gdb_stat.st_ino, uint32_or_zero(sys_stat.st_ino))
+ self.assertEqual(gdb_stat.st_mode, uint32_trunc(sys_stat.st_mode))
+ self.assertEqual(gdb_stat.st_nlink, uint32_or_max(sys_stat.st_nlink))
+ self.assertEqual(gdb_stat.st_uid, uint32_or_zero(sys_stat.st_uid))
+ self.assertEqual(gdb_stat.st_gid, uint32_or_zero(sys_stat.st_gid))
+ self.assertEqual(gdb_stat.st_rdev, uint32_or_zero(sys_stat.st_rdev))
+ self.assertEqual(gdb_stat.st_size, sys_stat.st_size)
+ self.assertEqual(gdb_stat.st_blksize, sys_stat.st_blksize)
+ self.assertEqual(gdb_stat.st_blocks, sys_stat.st_blocks)
+ self.assertEqual(gdb_stat.st_atime,
+ uint32_or_zero(int(sys_stat.st_atime)))
+ self.assertEqual(gdb_stat.st_mtime,
+ uint32_or_zero(int(sys_stat.st_mtime)))
+ self.assertEqual(gdb_stat.st_ctime,
+ uint32_or_zero(int(sys_stat.st_ctime)))
+
+ self.reset_test_sequence()
+ self.test_sequence.add_log_lines(
+ ["read packet: $vFile:close:%x#00" % (fd,),
+ "send packet: $F0#00"],
+ True)
+ self.expect_gdbremote_sequence()
+
def expect_error(self):
self.test_sequence.add_log_lines(
[{"direction": "send",
Index: lldb/source/Utility/StringExtractorGDBRemote.cpp
===================================================================
--- lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -339,6 +339,8 @@
return eServerPacketType_vFile_size;
else if (PACKET_STARTS_WITH("vFile:exists"))
return eServerPacketType_vFile_exists;
+ else if (PACKET_STARTS_WITH("vFile:fstat"))
+ return eServerPacketType_vFile_fstat;
else if (PACKET_STARTS_WITH("vFile:stat"))
return eServerPacketType_vFile_stat;
else if (PACKET_STARTS_WITH("vFile:mode"))
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
@@ -71,6 +71,8 @@
PacketResult Handle_vFile_unlink(StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_FStat(StringExtractorGDBRemote &packet);
+
PacketResult Handle_vFile_Stat(StringExtractorGDBRemote &packet);
PacketResult Handle_vFile_MD5(StringExtractorGDBRemote &packet);
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -29,6 +29,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Platform.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/DataEncoder.h"
#include "lldb/Utility/GDBRemote.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
@@ -156,6 +157,9 @@
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_vFile_size,
&GDBRemoteCommunicationServerCommon::Handle_vFile_Size);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_fstat,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_FStat);
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_vFile_stat,
&GDBRemoteCommunicationServerCommon::Handle_vFile_Stat);
@@ -755,6 +759,46 @@
return SendErrorResponse(24);
}
+template <typename T, typename U>
+void fill_clamp(T &dest, U src, typename T::value_type fallback) {
+ dest = dest <= std::numeric_limits<typename T::value_type>::max() ? src
+ : fallback;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerCommon::Handle_vFile_FStat(
+ StringExtractorGDBRemote &packet) {
+ StreamGDBRemote response;
+ packet.SetFilePos(::strlen("vFile:fstat:"));
+ int fd = packet.GetS32(-1, 16);
+
+ struct stat file_stats;
+ if (::fstat(fd, &file_stats) == -1) {
+ const int save_errno = errno;
+ response.Printf("F-1,%x", save_errno);
+ return SendPacketNoLock(response.GetString());
+ }
+
+ GDBRemoteFStatData data;
+ fill_clamp(data.gdb_st_dev, file_stats.st_dev, 0);
+ fill_clamp(data.gdb_st_ino, file_stats.st_ino, 0);
+ data.gdb_st_mode = file_stats.st_mode;
+ fill_clamp(data.gdb_st_nlink, file_stats.st_nlink, UINT32_MAX);
+ fill_clamp(data.gdb_st_uid, file_stats.st_uid, 0);
+ fill_clamp(data.gdb_st_gid, file_stats.st_gid, 0);
+ fill_clamp(data.gdb_st_rdev, file_stats.st_rdev, 0);
+ data.gdb_st_size = file_stats.st_size;
+ data.gdb_st_blksize = file_stats.st_blksize;
+ data.gdb_st_blocks = file_stats.st_blocks;
+ fill_clamp(data.gdb_st_atime, file_stats.st_atime, 0);
+ fill_clamp(data.gdb_st_mtime, file_stats.st_mtime, 0);
+ fill_clamp(data.gdb_st_ctime, file_stats.st_ctime, 0);
+
+ response.Printf("F%zx;", sizeof(data));
+ response.PutEscapedBytes(&data, sizeof(data));
+ return SendPacketNoLock(response.GetString());
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_vFile_Stat(
StringExtractorGDBRemote &packet) {
Index: lldb/include/lldb/Utility/StringExtractorGDBRemote.h
===================================================================
--- lldb/include/lldb/Utility/StringExtractorGDBRemote.h
+++ lldb/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -88,6 +88,7 @@
eServerPacketType_vFile_mode,
eServerPacketType_vFile_exists,
eServerPacketType_vFile_md5,
+ eServerPacketType_vFile_fstat,
eServerPacketType_vFile_stat,
eServerPacketType_vFile_symlink,
eServerPacketType_vFile_unlink,
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits