[compiler-rt] [sanitizer_common][PowerPC64] Fix internal_clone() error handling (PR #99908)

Ilya Leoshkevich via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 24 02:11:44 PDT 2024


================
@@ -1630,13 +1630,22 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
       "sc\n\t"
 
       /* Return to parent */
+      "0:\n\t"
+      "neg %0,3\n\t"
+      "b 2f\n\t"
       "1:\n\t"
-      "mr %0, 3\n\t"
+      "mr %0,3\n\t"
+      "2:\n\t"
+
       : "=r"(res)
       : "0"(-1), "i"(EINVAL), "i"(__NR_clone), "i"(__NR_exit), "r"(__fn),
         "r"(__cstack), "r"(__flags), "r"(__arg), "r"(__ptidptr), "r"(__newtls),
         "r"(__ctidptr), "i"(FRAME_SIZE), "i"(FRAME_TOC_SAVE_OFFSET)
       : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
+  if ((uptr)res >= (uptr)-4095) {
----------------
iii-i wrote:

This is because powerpc64 is special. Most of the platforms check for syscall errors by looking at the return value alone. In `man 2 syscall` they have `-` in the `Error` column, but powerpc64 has `cr0.SO`. Looking at what qemu-user is doing there (`linux-user/ppc/cpu_loop.c`, it's a bit more readable than the Linux kernel):

```
            if (ret > (target_ulong)(-515)) {
                env->crf[0] |= 0x1;
                ret = -ret;
            }
```

This means that on success we have `cr0.SO=0` and `r3=pid`, and on error we have `cr0.SO=1` and `r3=errno` (non-negated!).

https://github.com/llvm/llvm-project/pull/99908


More information about the llvm-commits mailing list