[llvm-bugs] [Bug 48798] New: crash after syscall on arm64/AArch64, works with -O2 and GCC

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Jan 19 02:44:05 PST 2021


https://bugs.llvm.org/show_bug.cgi?id=48798

            Bug ID: 48798
           Summary: crash after syscall on arm64/AArch64, works with -O2
                    and GCC
           Product: clang
           Version: 10.0
          Hardware: Other
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
          Assignee: unassignedclangbugs at nondot.org
          Reporter: jarno.rajahalme at gmail.com
                CC: blitzrakete at gmail.com, dgregor at apple.com,
                    erik.pilkington at gmail.com, llvm-bugs at lists.llvm.org,
                    richard-llvm at metafoo.co.uk

Syscalls use the register x8 for the syscall number. The following program,
reduceed from github.com/gperftools/gperftools, crashes when it tries to store
the returned errno code to local my_errno member in a C++ class. The generated
assembly tries to use the syscall number as a memory address, looks like the
fact that x8 was used to pass the syscall number is not properly accounted for
in register allocation. Reproduced below, example run follows after the code.

// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-

#include <sys/wait.h>
#include <errno.h>
#include <syscall.h>

/* Wrap a class around system calls, in order to give us access to
 * a private copy of errno. This only works in C++, but it has the
 * advantage of not needing nested functions, which are a non-standard
 * language extension.
 */
class SysCalls {
public:
  // arm64 inline assembly
  inline pid_t wait4(pid_t p, int* s, int o, struct kernel_rusage* r) {
    register long __x0 __asm__("x0") = (long)p;
    register long __x1 __asm__("x1") = (long)s;
    register long __x2 __asm__("x2") = (long)o;
    register long __x3 __asm__("x3") = (long)r;
    register long __res_x0 __asm__("x0");
    long __res;
    __asm__ __volatile__ ("mov x8, %1\n"
                          "svc 0x0\n"
                          : "=r"(__res_x0)
                          : "i"(__NR_wait4), "r"(__x0), "r"(__x1), "r"(__x2),
"r"(__x3)
                          : "memory");
    __res = __res_x0;
    if ((unsigned long)(__res) >= (unsigned long)(-4095)) {
      my_errno = -(__res);
      __res = -1;
    }
    return (pid_t) (__res);
  }

  inline pid_t waitpid(pid_t pid, int *status, int options){
    return wait4(pid, status, options, 0);
  }

  SysCalls() : my_errno(0) { }
  int my_errno;
};

int main(int argc, char *argv[]) {
  SysCalls sys;

  int status, rc;
  while ((rc = sys.waitpid(1000000, &status, __WALL)) < 0 && sys.my_errno ==
EINTR) {
    /* Keep waiting */
  }
  return sys.my_errno;
}



$ clang++-10 -g -O0 linuxthreads.cc
$ lldb-10 ./a.out 
(lldb) target create "./a.out"
Current executable set to '/home/ubuntu/dev/gperftools/test/a.out' (aarch64).
(lldb) run
Process 12123 launched: '/home/ubuntu/dev/gperftools/test/a.out' (aarch64)
Process 12123 stopped
* thread #1, name = 'a.out', stop reason = signal SIGSEGV: invalid address
(fault address: 0x104)
    frame #0: 0x000000000040073c a.out`SysCalls::wait4(this=0x0000fffffffff33c,
p=1000000, s=0x0000fffffffff338, o=1073741824, r=0x0000000000000000) at
linuxthreads.cc:29:16
   26                             : "memory");
   27       __res = __res_x0;
   28       if ((unsigned long)(__res) >= (unsigned long)(-4095)) {
-> 29         my_errno = -(__res);
   30         __res = -1;
   31       }
   32       return (pid_t) (__res);
(lldb) dis --frame
a.out`SysCalls::wait4:
    0x4006b4 <+0>:   sub    sp, sp, #0x60             ; =0x60 
    0x4006b8 <+4>:   str    x0, [sp, #0x58]
    0x4006bc <+8>:   str    w1, [sp, #0x54]
    0x4006c0 <+12>:  str    x2, [sp, #0x48]
    0x4006c4 <+16>:  str    w3, [sp, #0x44]
    0x4006c8 <+20>:  str    x4, [sp, #0x38]
    0x4006cc <+24>:  ldr    x8, [sp, #0x58]
    0x4006d0 <+28>:  ldrsw  x9, [sp, #0x54]
    0x4006d4 <+32>:  str    x9, [sp, #0x30]
    0x4006d8 <+36>:  ldr    x9, [sp, #0x48]
    0x4006dc <+40>:  str    x9, [sp, #0x28]
    0x4006e0 <+44>:  ldrsw  x9, [sp, #0x44]
    0x4006e4 <+48>:  str    x9, [sp, #0x20]
    0x4006e8 <+52>:  ldr    x9, [sp, #0x38]
    0x4006ec <+56>:  str    x9, [sp, #0x18]
    0x4006f0 <+60>:  ldr    x0, [sp, #0x30]
    0x4006f4 <+64>:  ldr    x1, [sp, #0x28]
    0x4006f8 <+68>:  ldr    x2, [sp, #0x20]
    0x4006fc <+72>:  ldr    x3, [sp, #0x18]
    0x400700 <+76>:  mov    x8, #0x104
    0x400704 <+80>:  svc    #0
    0x400708 <+84>:  str    x0, [sp, #0x10]
    0x40070c <+88>:  ldr    x9, [sp, #0x10]
    0x400710 <+92>:  str    x9, [sp, #0x8]
    0x400714 <+96>:  ldr    x9, [sp, #0x8]
    0x400718 <+100>: adds   x9, x9, #0xfff            ; =0xfff 
    0x40071c <+104>: str    x8, [sp]
    0x400720 <+108>: b.lo   0x40074c                  ; <+152> at
linuxthreads.cc:32:21
    0x400724 <+112>: b      0x400728                  ; <+116> at
linuxthreads.cc:29:20
    0x400728 <+116>: ldr    w8, [sp, #0x8]
    0x40072c <+120>: mov    w9, wzr
    0x400730 <+124>: subs   w8, w9, w8
    0x400734 <+128>: mov    w0, w8
    0x400738 <+132>: ldr    x10, [sp]
->  0x40073c <+136>: str    w0, [x10]
    0x400740 <+140>: mov    x11, #-0x1
    0x400744 <+144>: str    x11, [sp, #0x8]
    0x400748 <+148>: b      0x40074c                  ; <+152> at
linuxthreads.cc:32:21
    0x40074c <+152>: ldr    w0, [sp, #0x8]
    0x400750 <+156>: add    sp, sp, #0x60             ; =0x60 
    0x400754 <+160>: ret    
(lldb) register read x10
     x10 = 0x0000000000000104
(lldb) quit

NOTE: 0x104 (260) is the number of the wait4() syscall on arm64.

$ uname -a
Linux pie 5.4.0-1026-raspi #29-Ubuntu SMP PREEMPT Mon Dec 14 17:01:16 UTC 2020
aarch64 aarch64 aarch64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:        20.04
Codename:       focal

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210119/b5723d71/attachment.html>


More information about the llvm-bugs mailing list