Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sanitizer_common] Fix internal_*stat on Linux/sparc64 #101236

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 34 additions & 7 deletions compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@
// For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat'
// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To
// access stat from asm/stat.h, without conflicting with definition in
// sys/stat.h, we use this trick.
# if SANITIZER_MIPS64
// sys/stat.h, we use this trick. sparc64 is similar, using
// syscall(__NR_stat64) and struct kernel_stat64.
# if SANITIZER_LINUX && (SANITIZER_MIPS64 || SANITIZER_SPARC64)
# include <asm/unistd.h>
# include <sys/types.h>
# define stat kernel_stat
# if SANITIZER_SPARC64
# define stat64 kernel_stat64
# endif
# if SANITIZER_GO
# undef st_atime
# undef st_mtime
Expand All @@ -48,6 +52,7 @@
# endif
# include <asm/stat.h>
# undef stat
# undef stat64
# endif

# include <dlfcn.h>
Expand Down Expand Up @@ -285,8 +290,7 @@ uptr internal_ftruncate(fd_t fd, uptr size) {
return res;
}

# if (!SANITIZER_LINUX_USES_64BIT_SYSCALLS || SANITIZER_SPARC) && \
SANITIZER_LINUX
# if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && SANITIZER_LINUX
static void stat64_to_stat(struct stat64 *in, struct stat *out) {
internal_memset(out, 0, sizeof(*out));
out->st_dev = in->st_dev;
Expand Down Expand Up @@ -327,7 +331,12 @@ static void statx_to_stat(struct statx *in, struct stat *out) {
}
# endif

# if SANITIZER_MIPS64
# if SANITIZER_MIPS64 || SANITIZER_SPARC64
# if SANITIZER_MIPS64
typedef struct kernel_stat kstat_t;
# else
typedef struct kernel_stat64 kstat_t;
# endif
// Undefine compatibility macros from <sys/stat.h>
// so that they would not clash with the kernel_stat
// st_[a|m|c]time fields
Expand All @@ -345,7 +354,7 @@ static void statx_to_stat(struct statx *in, struct stat *out) {
# undef st_mtime_nsec
# undef st_ctime_nsec
# endif
static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
static void kernel_stat_to_stat(kstat_t *in, struct stat *out) {
internal_memset(out, 0, sizeof(*out));
out->st_dev = in->st_dev;
out->st_ino = in->st_ino;
Expand Down Expand Up @@ -391,6 +400,12 @@ uptr internal_stat(const char *path, void *buf) {
!SANITIZER_SPARC
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
0);
# elif SANITIZER_SPARC64
kstat_t buf64;
int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
(uptr)&buf64, 0);
kernel_stat_to_stat(&buf64, (struct stat *)buf);
return res;
# else
struct stat64 buf64;
int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
Expand Down Expand Up @@ -423,6 +438,12 @@ uptr internal_lstat(const char *path, void *buf) {
!SANITIZER_SPARC
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
AT_SYMLINK_NOFOLLOW);
# elif SANITIZER_SPARC64
kstat_t buf64;
int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
(uptr)&buf64, AT_SYMLINK_NOFOLLOW);
kernel_stat_to_stat(&buf64, (struct stat *)buf);
return res;
# else
struct stat64 buf64;
int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
Expand All @@ -442,10 +463,16 @@ uptr internal_fstat(fd_t fd, void *buf) {
# if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
# if SANITIZER_MIPS64
// For mips64, fstat syscall fills buffer in the format of kernel_stat
struct kernel_stat kbuf;
kstat_t kbuf;
int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);
kernel_stat_to_stat(&kbuf, (struct stat *)buf);
return res;
# elif SANITIZER_LINUX && SANITIZER_SPARC64
// For sparc64, fstat64 syscall fills buffer in the format of kernel_stat64
kstat_t kbuf;
int res = internal_syscall(SYSCALL(fstat64), fd, &kbuf);
kernel_stat_to_stat(&kbuf, (struct stat *)buf);
return res;
# elif SANITIZER_LINUX && defined(__loongarch__)
struct statx bufx;
int res = internal_syscall(SYSCALL(statx), fd, "", AT_EMPTY_PATH,
Expand Down
Loading