diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2013-05-08 14:43:49 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2013-05-08 14:43:49 +0000 |
commit | 9578a3ecfc35a264ede1135033398e2a77a6cad6 (patch) | |
tree | 5e4cb064cb5c58ec85e5a9705ae92226b18bddd3 /lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc | |
parent | 33280bba681b7bb683be01749aaba70dc06ffb6c (diff) | |
download | compiler-rt-9578a3ecfc35a264ede1135033398e2a77a6cad6.tar.gz compiler-rt-9578a3ecfc35a264ede1135033398e2a77a6cad6.tar.bz2 compiler-rt-9578a3ecfc35a264ede1135033398e2a77a6cad6.tar.xz |
[nolibc] Change internal syscall API to remove reliance on libc's errno.
This change moves to a model where the error value of a system call is
potentially contained in the return value itself rather than being
implicit in errno. The helper function internal_iserror can be used
to extract the error value from a return value. On platforms other
than Linux/x86_64 this still uses errno, but other platforms are free
to port their error handling to this new model.
Differential Revision: http://llvm-reviews.chandlerc.com/D756
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@181436 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc b/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc new file mode 100644 index 00000000..e084b84a --- /dev/null +++ b/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc @@ -0,0 +1,87 @@ +//===-- sanitizer_syscall_linux_x86_64.inc ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementations of internal_syscall and internal_iserror for Linux/x86_64. +// +//===----------------------------------------------------------------------===// + +static uptr internal_syscall(u64 nr) { + u64 retval; + asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11"); + return retval; +} + +template <typename T1> +static uptr internal_syscall(u64 nr, T1 arg1) { + u64 retval; + asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1) : + "rcx", "r11"); + return retval; +} + +template <typename T1, typename T2> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2) { + u64 retval; + asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2) : "rcx", "r11"); + return retval; +} + +template <typename T1, typename T2, typename T3> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3) { + u64 retval; + asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2), "d"((u64)arg3) : "rcx", "r11"); + return retval; +} + +template <typename T1, typename T2, typename T3, typename T4> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { + u64 retval; + asm volatile("mov %5, %%r10;" + "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4) : + "rcx", "r11", "r10"); + return retval; +} + +template <typename T1, typename T2, typename T3, typename T4, typename T5> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, + T5 arg5) { + u64 retval; + asm volatile("mov %5, %%r10;" + "mov %6, %%r8;" + "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5) : + "rcx", "r11", "r10", "r8"); + return retval; +} + +template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, + T5 arg5, T6 arg6) { + u64 retval; + asm volatile("mov %5, %%r10;" + "mov %6, %%r8;" + "mov %7, %%r9;" + "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5), + "r"((u64)arg6) : "rcx", "r11", "r10", "r8", "r9"); + return retval; +} + +bool internal_iserror(uptr retval, int *rverrno) { + if (retval >= (uptr)-4095) { + if (rverrno) + *rverrno = -retval; + return true; + } + return false; +} |