[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