Skip to content

Commit 7a03bbc

Browse files
add support for the vFile:fstat packet
## Purpose Add support for lldb's `vFile:fstat` packet to ds2 debug and platform sessions. Fixes #135. ## Overview * Add `fstat` method to the `File` class and implement it for POSIX. Leave the Windows implementation unimplemented (as is the rest of `File`) * Call the new `File::fstat` method when is `vFile:fstat` packet is received. ## Problem Details Several of the lldb tests rely on `vFile:fstat` to fetch files from the device, and these tests fail against ds2 because it is not implemented. The `vFile:fstat` packet isn't documented. The implementation is based on the expectation of the lldb test case `TestGdbRemotePlatformFile.TestGdbRemotePlatformFile.test_platform_file_fstat_llgs`, which now passes with this change. ## Validation Once this PR and a some additionalchanges are merged, most of the `TestGdbRemotePlatformFile` tests succeed with ds2 running on Android and Linux and can be enabled in CI. They do not all pass with this PR alone. Co-authored-by: Saleem Abdulrasool <[email protected]>
1 parent b5622cb commit 7a03bbc

File tree

9 files changed

+80
-0
lines changed

9 files changed

+80
-0
lines changed

Headers/DebugServer2/GDBRemote/DummySessionDelegateImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ class DummySessionDelegateImpl : public SessionDelegate {
247247
uint64_t &size) override;
248248
ErrorCode onFileGetMode(Session &session, std::string const &path,
249249
uint32_t &mode) const override;
250+
ErrorCode onFileFstat(Session &session, int fd,
251+
ByteVector &buffer) const override;
250252

251253
ErrorCode onQueryProcessList(Session &session, ProcessInfoMatch const &match,
252254
bool first, ProcessInfo &info) const override;

Headers/DebugServer2/GDBRemote/Mixins/FileOperationsMixin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ template <typename T> class FileOperationsMixin : public T {
4949
uint64_t &size) override;
5050
ErrorCode onFileGetMode(Session &session, std::string const &path,
5151
uint32_t &mode) const override;
52+
ErrorCode onFileFstat(Session &session, int fd, ByteVector &buffer) const override;
5253
ErrorCode onFileRemove(Session &session, std::string const &path) override;
5354

5455
protected:

Headers/DebugServer2/GDBRemote/SessionDelegate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ class SessionDelegate {
274274
uint64_t &size) = 0;
275275
virtual ErrorCode onFileGetMode(Session &session, std::string const &path,
276276
uint32_t &mode) const = 0;
277+
virtual ErrorCode onFileFstat(Session &session, int fd,
278+
ByteVector &buffer) const = 0;
277279

278280
virtual ErrorCode onQueryProcessList(Session &session,
279281
ProcessInfoMatch const &match,

Headers/DebugServer2/Host/File.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class File {
4747
public:
4848
ErrorCode pread(ByteVector &buf, uint64_t &count, uint64_t offset);
4949
ErrorCode pwrite(ByteVector const &buf, uint64_t &count, uint64_t offset);
50+
ErrorCode fstat(ByteVector &buffer) const;
5051

5152
public:
5253
bool valid() const { return (_fd >= 0); }

Sources/GDBRemote/DummySessionDelegateImpl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ DUMMY_IMPL_EMPTY(onFileGetSize, Session &, std::string const &, uint64_t &)
295295

296296
DUMMY_IMPL_EMPTY_CONST(onFileGetMode, Session &, std::string const &, uint32_t&)
297297

298+
DUMMY_IMPL_EMPTY_CONST(onFileFstat, Session &, int, ByteVector &)
299+
298300
DUMMY_IMPL_EMPTY_CONST(onQueryProcessList, Session &, ProcessInfoMatch const &,
299301
bool, ProcessInfo &)
300302

Sources/GDBRemote/Mixins/FileOperationsMixin.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@ ErrorCode FileOperationsMixin<T>::onFileGetMode(Session &session,
101101
return Host::File::fileMode(path, mode);
102102
}
103103

104+
template <typename T>
105+
ErrorCode FileOperationsMixin<T>::onFileFstat(Session &session, int fd,
106+
ByteVector &buffer) const {
107+
auto it = _openFiles.find(fd);
108+
if (it == _openFiles.end())
109+
return kErrorInvalidHandle;
110+
111+
return it->second.fstat(buffer);
112+
}
113+
104114
template <typename T>
105115
ErrorCode FileOperationsMixin<T>::onFileRemove(Session &session,
106116
std::string const &path) {

Sources/GDBRemote/Session.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3114,6 +3114,20 @@ void Session::Handle_vFile(ProtocolInterpreter::Handler const &,
31143114
} else {
31153115
ss << std::hex << mode;
31163116
}
3117+
} else if (op == "fstat") {
3118+
ByteVector buffer;
3119+
int fd = std::strtol(&args[op_end], nullptr, 16);
3120+
ErrorCode error = _delegate->onFileFstat(*this, fd, buffer);
3121+
// Response is F, followed by the the size of the stat data (base 16),
3122+
// a semicolon, followed by the stat result in the binary-escaped-data
3123+
// encoding or F-1,errno with the errno if an error occurs, base 16
3124+
ss << 'F';
3125+
if (error != kSuccess) {
3126+
ss << -1 << ',' << std::hex << error;
3127+
} else {
3128+
ss << std::hex << buffer.size() << ';' << Escape(buffer);
3129+
escaped = true;
3130+
}
31173131
} else {
31183132
sendError(kErrorUnsupported);
31193133
return;

Sources/Host/POSIX/File.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616
#include <sys/stat.h>
1717
#include <unistd.h>
1818

19+
#if defined(OS_LINUX)
20+
#include <endian.h>
21+
#elif defined(OS_FREEBSD)
22+
#include <sys/_endian.h>
23+
#elif defined(OS_DARWIN)
24+
#include <libkern/OSByteOrder.h>
25+
#define htobe32(x) OSSwapHostToBigInt32(x)
26+
#define htobe64(x) OSSwapHostToBigInt64(x)
27+
#endif
28+
1929
namespace ds2 {
2030
namespace Host {
2131

@@ -118,6 +128,40 @@ ErrorCode File::pwrite(ByteVector const &buf, uint64_t &count,
118128
return _lastError = kSuccess;
119129
}
120130

131+
// lldb expects stat data is returned as a packed buffer with total size of 64
132+
// bytes. The field order is the same as the POSIX defined stat struct. All
133+
// fields are encoded as 4-byte, big-endian unsigned integers except for
134+
// st_size, st_blksize, and st_blocks which are all 8-byte, big-endian unsigned
135+
// integers.
136+
ErrorCode File::fstat(ByteVector &buffer) const {
137+
struct stat s;
138+
if (::fstat(_fd, &s) < 0)
139+
return Platform::TranslateError();
140+
141+
const auto appendInteger = [&buffer](auto value) -> void {
142+
buffer.insert(buffer.end(),
143+
reinterpret_cast<uint8_t*>(&value),
144+
reinterpret_cast<uint8_t*>(&value) + sizeof(value));
145+
};
146+
147+
appendInteger(htobe32(static_cast<uint32_t>(s.st_dev)));
148+
appendInteger(htobe32(static_cast<uint32_t>(s.st_ino)));
149+
appendInteger(htobe32(static_cast<uint32_t>(s.st_mode)));
150+
appendInteger(htobe32(static_cast<uint32_t>(s.st_nlink)));
151+
appendInteger(htobe32(static_cast<uint32_t>(s.st_uid)));
152+
appendInteger(htobe32(static_cast<uint32_t>(s.st_gid)));
153+
appendInteger(htobe32(static_cast<uint32_t>(s.st_rdev)));
154+
appendInteger(htobe64(static_cast<uint64_t>(s.st_size)));
155+
appendInteger(htobe64(static_cast<uint64_t>(s.st_blksize)));
156+
appendInteger(htobe64(static_cast<uint64_t>(s.st_blocks)));
157+
appendInteger(htobe32(static_cast<uint32_t>(s.st_atime)));
158+
appendInteger(htobe32(static_cast<uint32_t>(s.st_mtime)));
159+
appendInteger(htobe32(static_cast<uint32_t>(s.st_ctime)));
160+
DS2ASSERT(buffer.size() == 64);
161+
162+
return kSuccess;
163+
}
164+
121165
ErrorCode File::chmod(std::string const &path, uint32_t mode) {
122166
if (::chmod(path.c_str(), mode) < 0) {
123167
return Platform::TranslateError();

Sources/Host/Windows/File.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ ErrorCode File::pwrite(ByteVector const &buf, uint64_t &count,
2929
return kErrorUnsupported;
3030
}
3131

32+
ErrorCode File::fstat(ByteVector &buffer) const {
33+
return kErrorUnsupported;
34+
}
35+
3236
ErrorCode File::chmod(std::string const &path, uint32_t mode) {
3337
return kErrorUnsupported;
3438
}

0 commit comments

Comments
 (0)