aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp41
1 files changed, 34 insertions, 7 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 3f30bfed..b768b8e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -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_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
@@ -48,6 +52,7 @@
# endif
# include <asm/stat.h>
# undef stat
+# undef stat64
# endif
# include <dlfcn.h>
@@ -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;
@@ -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
@@ -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;
@@ -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,
@@ -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,
@@ -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,