[compiler-rt] c5a6ad8 - [Sanitizer][RISCV] Fix internal_clone
Luís Marques via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 8 14:30:22 PST 2021
Author: Luís Marques
Date: 2021-03-08T22:29:59Z
New Revision: c5a6ad86b066a6f159b687d181d947cb43aab70b
URL: https://github.com/llvm/llvm-project/commit/c5a6ad86b066a6f159b687d181d947cb43aab70b
DIFF: https://github.com/llvm/llvm-project/commit/c5a6ad86b066a6f159b687d181d947cb43aab70b.diff
LOG: [Sanitizer][RISCV] Fix internal_clone
A RISC-V implementation of `internal_clone` was introduced in D87573, as
part of the RISC-V ASan patch set by @EccoTheDolphin. That function was
never used/tested until I ported LSan for RISC-V, as part of D92403. That
port revealed problems in the original implementation, so I provided a fix
in D92403. Unfortunately, my choice of replacing the assembly with regular
C++ code wasn't correct. The clone syscall arguments specify a separate
stack, so non-inlined calls, spills, etc. aren't going to work. This wasn't
a problem in practice for optimized builds of Compiler-RT, but it breaks
for debug builds. This patch fixes the original problem while keeping the
assembly.
Differential Revision: https://reviews.llvm.org/D96954
Added:
Modified:
compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 9d4fd06ed37e..25c0751c9a38 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -1338,17 +1338,41 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
int *parent_tidptr, void *newtls, int *child_tidptr) {
if (!fn || !child_stack)
return -EINVAL;
+
CHECK_EQ(0, (uptr)child_stack % 16);
- child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
- ((unsigned long long *)child_stack)[0] = (uptr)fn;
- ((unsigned long long *)child_stack)[1] = (uptr)arg;
- int tid = internal_syscall(SYSCALL(clone), (unsigned long)flags, child_stack,
- parent_tidptr, newtls, child_tidptr);
- if (tid != 0)
- return tid;
- fn(arg);
- internal_syscall(SYSCALL(exit), 0);
+ register int res __asm__("a0");
+ register int __flags __asm__("a0") = flags;
+ register void *__stack __asm__("a1") = child_stack;
+ register int *__ptid __asm__("a2") = parent_tidptr;
+ register void *__tls __asm__("a3") = newtls;
+ register int *__ctid __asm__("a4") = child_tidptr;
+ register int (*__fn)(void *) __asm__("a5") = fn;
+ register void *__arg __asm__("a6") = arg;
+ register int nr_clone __asm__("a7") = __NR_clone;
+
+ __asm__ __volatile__(
+ "ecall\n"
+
+ /* if (a0 != 0)
+ * return a0;
+ */
+ "bnez a0, 1f\n"
+
+ // In the child, now. Call "fn(arg)".
+ "mv a0, a6\n"
+ "jalr a5\n"
+
+ // Call _exit(a0).
+ "addi a7, zero, %9\n"
+ "ecall\n"
+ "1:\n"
+
+ : "=r"(res)
+ : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__tls), "r"(__ctid),
+ "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit)
+ : "memory");
+ return res;
}
#elif defined(__aarch64__)
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
More information about the llvm-commits
mailing list