sim-se: Implement statx system call for Linux x86-64 (#887)
Implement the statx Linux-specific system call for x86-64. statx is used by LLVM's libc. Change-Id: Ic000a36a5e5c1399996f520fa357b9354c73c864
This commit is contained in:
@@ -119,6 +119,49 @@ class X86Linux64 : public X86Linux, public OpenFlagTable<X86Linux64>
|
||||
int64_t unused0[3];
|
||||
};
|
||||
|
||||
struct tgt_statx
|
||||
{
|
||||
/* 0x00 */
|
||||
uint32_t stx_mask;
|
||||
uint32_t stx_blksize;
|
||||
uint64_t stx_attributes;
|
||||
/* 0x10 */
|
||||
uint32_t stx_nlink;
|
||||
uint32_t stx_uid;
|
||||
uint32_t stx_gid;
|
||||
uint16_t stx_mode;
|
||||
uint16_t stx_spare0;
|
||||
/* 0x20 */
|
||||
uint64_t stx_ino;
|
||||
uint64_t stx_size;
|
||||
uint64_t stx_blocks;
|
||||
uint64_t stx_attributes_mask;
|
||||
/* 0x40 */
|
||||
uint64_t stx_atimeX;
|
||||
uint32_t stx_atime_nsec;
|
||||
int32_t stx_atime_reserved;
|
||||
uint64_t stx_btimeX;
|
||||
uint32_t stx_btime_nsec;
|
||||
int32_t stx_btime_reserved;
|
||||
uint64_t stx_ctimeX;
|
||||
uint32_t stx_ctime_nsec;
|
||||
int32_t stx_ctime_reserved;
|
||||
uint64_t stx_mtimeX;
|
||||
uint32_t stx_mtime_nsec;
|
||||
int32_t stx_mtime_reserved;
|
||||
/* 0x80 */
|
||||
uint32_t stx_rdev_major;
|
||||
uint32_t stx_rdev_minor;
|
||||
uint32_t stx_dev_major;
|
||||
uint32_t stx_dev_minor;
|
||||
/* 0x90 */
|
||||
uint64_t stx_mnt_id;
|
||||
uint64_t stx_spare2;
|
||||
/* 0xa0 */
|
||||
uint64_t stx_spare3[12];
|
||||
/* 0x100 */
|
||||
};
|
||||
|
||||
struct tgt_fsid
|
||||
{
|
||||
long val[2];
|
||||
|
||||
@@ -375,7 +375,7 @@ SyscallDescTable<EmuLinux::SyscallABI64> EmuLinux::syscallDescs64 = {
|
||||
{ 329, "pkey_mprotect" },
|
||||
{ 330, "pkey_alloc" },
|
||||
{ 331, "pkey_free" },
|
||||
{ 332, "statx" },
|
||||
{ 332, "statx", statxFunc<X86Linux64> },
|
||||
{ 333, "io_pgetevents" },
|
||||
{ 334, "rseq", ignoreFunc },
|
||||
{ 424, "pidfd_send_signal" },
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
/// application on the host machine.
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/kdev_t.h>
|
||||
#include <sched.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/statfs.h>
|
||||
@@ -677,6 +678,73 @@ copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename OS, typename TgtStatPtr, typename HostStatPtr>
|
||||
void
|
||||
copyOutStatxBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY = false)
|
||||
{
|
||||
constexpr ByteOrder bo = OS::byteOrder;
|
||||
|
||||
if (fakeTTY) {
|
||||
tgt->stx_dev_major = MAJOR(0xA);
|
||||
tgt->stx_dev_minor = MINOR(0xA);
|
||||
} else {
|
||||
tgt->stx_dev_major = host->stx_dev_major;
|
||||
tgt->stx_dev_minor = host->stx_dev_minor;
|
||||
}
|
||||
tgt->stx_dev_major = htog(tgt->stx_dev_major, bo);
|
||||
tgt->stx_dev_minor = htog(tgt->stx_dev_minor, bo);
|
||||
tgt->stx_ino = host->stx_ino;
|
||||
tgt->stx_ino = htog(tgt->stx_ino, bo);
|
||||
tgt->stx_mode = host->stx_mode;
|
||||
if (fakeTTY) {
|
||||
// Claim to be character device.
|
||||
tgt->stx_mode &= ~S_IFMT;
|
||||
tgt->stx_mode |= S_IFCHR;
|
||||
}
|
||||
tgt->stx_mode = htog(tgt->stx_mode, bo);
|
||||
tgt->stx_nlink = host->stx_nlink;
|
||||
tgt->stx_nlink = htog(tgt->stx_nlink, bo);
|
||||
tgt->stx_uid = host->stx_uid;
|
||||
tgt->stx_uid = htog(tgt->stx_uid, bo);
|
||||
tgt->stx_gid = host->stx_gid;
|
||||
tgt->stx_gid = htog(tgt->stx_gid, bo);
|
||||
if (fakeTTY) {
|
||||
tgt->stx_rdev_major = MAJOR(0x880d);
|
||||
tgt->stx_rdev_minor = MINOR(0x880d);
|
||||
} else {
|
||||
tgt->stx_rdev_major = host->stx_rdev_major;
|
||||
tgt->stx_rdev_minor = host->stx_rdev_minor;
|
||||
}
|
||||
tgt->stx_rdev_major = htog(tgt->stx_rdev_major, bo);
|
||||
tgt->stx_rdev_minor = htog(tgt->stx_rdev_minor, bo);
|
||||
tgt->stx_size = host->stx_size;
|
||||
tgt->stx_size = htog(tgt->stx_size, bo);
|
||||
#define statx_copy_time(out, in) \
|
||||
out##X = in.tv_sec; \
|
||||
out##X = htog(out##X, bo); \
|
||||
out##_nsec = in.tv_sec; \
|
||||
out##_nsec = htog(out##_nsec, bo);
|
||||
statx_copy_time(tgt->stx_atime, host->stx_atime);
|
||||
statx_copy_time(tgt->stx_btime, host->stx_btime);
|
||||
statx_copy_time(tgt->stx_ctime, host->stx_ctime);
|
||||
statx_copy_time(tgt->stx_mtime, host->stx_mtime);
|
||||
#undef statx_copy_time
|
||||
// Force the block size to be 8KB. This helps to ensure buffered io works
|
||||
// consistently across different hosts.
|
||||
tgt->stx_blksize = 0x2000;
|
||||
tgt->stx_blksize = htog(tgt->stx_blksize, bo);
|
||||
tgt->stx_blocks = host->stx_blocks;
|
||||
tgt->stx_blocks = htog(tgt->stx_blocks, bo);
|
||||
tgt->stx_mask = host->stx_mask;
|
||||
tgt->stx_mask = htog(tgt->stx_mask, bo);
|
||||
tgt->stx_attributes = host->stx_attributes;
|
||||
tgt->stx_attributes = htog(tgt->stx_attributes, bo);
|
||||
tgt->stx_attributes_mask = host->stx_attributes_mask;
|
||||
tgt->stx_attributes_mask = htog(tgt->stx_attributes_mask, bo);
|
||||
tgt->stx_mnt_id = host->stx_mnt_id;
|
||||
tgt->stx_mnt_id = htog(tgt->stx_mnt_id, bo);
|
||||
}
|
||||
|
||||
/// Target ioctl() handler. For the most part, programs call ioctl()
|
||||
/// only to find out if their stdout is a tty, to determine whether to
|
||||
/// do line or block buffering. We always claim that output fds are
|
||||
@@ -1456,6 +1524,46 @@ stat64Func(SyscallDesc *desc, ThreadContext *tc,
|
||||
return fstatat64Func<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_stat);
|
||||
}
|
||||
|
||||
/// Target statx() handler.
|
||||
template <class OS>
|
||||
SyscallReturn
|
||||
statxFunc(SyscallDesc *desc, ThreadContext *tc,
|
||||
int dirfd, VPtr<> pathname, int flags,
|
||||
unsigned int mask, VPtr<typename OS::tgt_statx> tgt_statx)
|
||||
{
|
||||
std::string path;
|
||||
|
||||
if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
|
||||
return -EFAULT;
|
||||
|
||||
if (path.empty() && !(flags & OS::TGT_AT_EMPTY_PATH))
|
||||
return -ENOENT;
|
||||
flags = flags & ~OS::TGT_AT_EMPTY_PATH;
|
||||
|
||||
warn_if(flags != 0, "statx: Flag bits %#x not supported.", flags);
|
||||
|
||||
// Modifying path from the directory descriptor
|
||||
if (auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
auto p = tc->getProcessPtr();
|
||||
|
||||
// Adjust path for cwd and redirection
|
||||
path = p->checkPathRedirect(path);
|
||||
|
||||
struct statx host_buf;
|
||||
std::memset(&host_buf, 0, sizeof host_buf);
|
||||
int result = statx(AT_FDCWD, path.c_str(), flags, mask, &host_buf);
|
||||
|
||||
if (result < 0)
|
||||
return -errno;
|
||||
|
||||
copyOutStatxBuf<OS>(tgt_statx, &host_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Target fstat64() handler.
|
||||
template <class OS>
|
||||
SyscallReturn
|
||||
|
||||
Reference in New Issue
Block a user