[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