-
Notifications
You must be signed in to change notification settings - Fork 12.4k
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 #101012
[sanitizer_common] Fix internal_*stat on Linux/sparc64 #101012
Conversation
``` SanitizerCommon-Unit :: ./Sanitizer-sparcv9-Test/SanitizerCommon/FileOps ``` `FAIL`s on 64-bit Linux/sparc64: ``` projects/compiler-rt/lib/sanitizer_common/tests/./Sanitizer-sparcv9-Test --gtest_filter=SanitizerCommon.FileOps -- compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cpp:144: Failure Expected equality of these values: len1 + len2 Which is: 10 fsize Which is: 1721875535 ``` The issue is similar to the mips64 case: the Linux/sparc64 `*stat` syscalls take a `struct kernel_stat64 *` arg. Also the syscalls actually used differ. This patch handles this, adopting the mips64 code to avoid too much duplication. Tested on `sparc64-unknown-linux-gnu` and `x86_64-pc-linux-gnu`.
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Rainer Orth (rorth) Changes
The issue is similar to the mips64 case: the Linux/sparc64 This patch handles this, adopting the mips64 code to avoid too much duplication. Tested on Full diff: https://github.com/llvm/llvm-project/pull/101012.diff 1 Files Affected:
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 2ea61b1cb424c..eab12d4ca430f 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,
|
/cherry-pick fcd6bd5 |
``` SanitizerCommon-Unit :: ./Sanitizer-sparcv9-Test/SanitizerCommon/FileOps ``` `FAIL`s on 64-bit Linux/sparc64: ``` projects/compiler-rt/lib/sanitizer_common/tests/./Sanitizer-sparcv9-Test --gtest_filter=SanitizerCommon.FileOps -- compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cpp:144: Failure Expected equality of these values: len1 + len2 Which is: 10 fsize Which is: 1721875535 ``` The issue is similar to the mips64 case: the Linux/sparc64 `*stat` syscalls take a `struct kernel_stat64 *` arg. Also the syscalls actually used differ. This patch handles this, adopting the mips64 code to avoid too much duplication. Tested on `sparc64-unknown-linux-gnu` and `x86_64-pc-linux-gnu`. (cherry picked from commit fcd6bd5)
/pull-request #101143 |
It turns out I messed up: that patch broke the Solaris/sparcv9 build because the section messing with Linux headers to |
/cherry-pick 16e9bb9 |
If this patch gets backported to the 19.x branch, the followup is necessary, too. |
Failed to cherry-pick: 16e9bb9 https://github.com/llvm/llvm-project/actions/runs/10158600153 Please manually backport the fix and push it to your github fork. Once this is done, please create a pull request |
``` SanitizerCommon-Unit :: ./Sanitizer-sparcv9-Test/SanitizerCommon/FileOps ``` `FAIL`s on 64-bit Linux/sparc64: ``` projects/compiler-rt/lib/sanitizer_common/tests/./Sanitizer-sparcv9-Test --gtest_filter=SanitizerCommon.FileOps -- compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cpp:144: Failure Expected equality of these values: len1 + len2 Which is: 10 fsize Which is: 1721875535 ``` The issue is similar to the mips64 case: the Linux/sparc64 `*stat` syscalls take a `struct kernel_stat64 *` arg. Also the syscalls actually used differ. This patch handles this, adopting the mips64 code to avoid too much duplication. Tested on `sparc64-unknown-linux-gnu` and `x86_64-pc-linux-gnu`. (cherry picked from commit fcd6bd5)
Done: PR #101236. |
``` SanitizerCommon-Unit :: ./Sanitizer-sparcv9-Test/SanitizerCommon/FileOps ``` `FAIL`s on 64-bit Linux/sparc64: ``` projects/compiler-rt/lib/sanitizer_common/tests/./Sanitizer-sparcv9-Test --gtest_filter=SanitizerCommon.FileOps -- compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cpp:144: Failure Expected equality of these values: len1 + len2 Which is: 10 fsize Which is: 1721875535 ``` The issue is similar to the mips64 case: the Linux/sparc64 `*stat` syscalls take a `struct kernel_stat64 *` arg. Also the syscalls actually used differ. This patch handles this, adopting the mips64 code to avoid too much duplication. Tested on `sparc64-unknown-linux-gnu` and `x86_64-pc-linux-gnu`.
``` SanitizerCommon-Unit :: ./Sanitizer-sparcv9-Test/SanitizerCommon/FileOps ``` `FAIL`s on 64-bit Linux/sparc64: ``` projects/compiler-rt/lib/sanitizer_common/tests/./Sanitizer-sparcv9-Test --gtest_filter=SanitizerCommon.FileOps -- compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cpp:144: Failure Expected equality of these values: len1 + len2 Which is: 10 fsize Which is: 1721875535 ``` The issue is similar to the mips64 case: the Linux/sparc64 `*stat` syscalls take a `struct kernel_stat64 *` arg. Also the syscalls actually used differ. This patch handles this, adopting the mips64 code to avoid too much duplication. Tested on `sparc64-unknown-linux-gnu` and `x86_64-pc-linux-gnu`. (cherry picked from commit fcd6bd5)
FAIL
s on 64-bit Linux/sparc64:The issue is similar to the mips64 case: the Linux/sparc64
*stat
syscalls take astruct kernel_stat64 *
arg. Also the syscalls actually used differ.This patch handles this, adopting the mips64 code to avoid too much duplication.
Tested on
sparc64-unknown-linux-gnu
andx86_64-pc-linux-gnu
.