diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -23,7 +23,7 @@ endif() set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64} - ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) + ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}) set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} ${RISCV32} ${RISCV64} ${VE}) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -697,7 +697,8 @@ kModuleArchARMV7S, kModuleArchARMV7K, kModuleArchARM64, - kModuleArchRISCV64 + kModuleArchRISCV64, + kModuleArchHexagon }; // Sorts and removes duplicates from the container. @@ -764,6 +765,8 @@ return "arm64"; case kModuleArchRISCV64: return "riscv64"; + case kModuleArchHexagon: + return "hexagon"; } CHECK(0 && "Invalid module arch"); return ""; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h @@ -180,7 +180,7 @@ #if SANITIZER_FREEBSD || SANITIZER_NETBSD || \ SANITIZER_MAC || \ (SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)) || \ - (SANITIZER_LINUX && defined(__x86_64__)) + (SANITIZER_LINUX && (defined(__x86_64__) || defined(__hexagon__))) typedef u64 OFF_T; #else typedef uptr OFF_T; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -158,6 +158,8 @@ #include "sanitizer_syscall_linux_aarch64.inc" #elif SANITIZER_LINUX && defined(__arm__) #include "sanitizer_syscall_linux_arm.inc" +#elif SANITIZER_LINUX && defined(__hexagon__) +#include "sanitizer_syscall_linux_hexagon.inc" #else #include "sanitizer_syscall_generic.inc" #endif @@ -2097,6 +2099,11 @@ *pc = ucontext->uc_mcontext.__gregs[REG_PC]; *bp = ucontext->uc_mcontext.__gregs[REG_S0]; *sp = ucontext->uc_mcontext.__gregs[REG_SP]; +#elif defined(__hexagon__) + ucontext_t *ucontext = (ucontext_t *)context; + *pc = ucontext->uc_mcontext.pc; + *bp = ucontext->uc_mcontext.r30; + *sp = ucontext->uc_mcontext.r29; #else # error "Unsupported arch" #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -281,7 +281,7 @@ // mandated by the upstream linux community for all new ports. Other ports // may still use legacy syscalls. #ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS -# if (defined(__aarch64__) || defined(__riscv)) && SANITIZER_LINUX +# if (defined(__aarch64__) || defined(__riscv) || defined(__hexagon__)) && SANITIZER_LINUX # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1 # else # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp @@ -28,7 +28,7 @@ // are not defined anywhere in userspace headers. Fake them. This seems to work // fine with newer headers, too. #include -#if defined(__x86_64__) || defined(__mips__) +#if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__) #include #else #define ino_t __kernel_ino_t @@ -65,7 +65,8 @@ #if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\ && !defined(__mips__) && !defined(__s390__)\ - && !defined(__sparc__) && !defined(__riscv) + && !defined(__sparc__) && !defined(__riscv) \ + && !defined(__hexagon__) COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat)); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -102,6 +102,9 @@ #elif SANITIZER_RISCV64 const unsigned struct_kernel_stat_sz = 128; const unsigned struct_kernel_stat64_sz = 0; // RISCV64 does not use stat64 +#elif defined(__hexagon__) +const unsigned struct_kernel_stat_sz = 128; +const unsigned struct_kernel_stat64_sz = 0; #endif struct __sanitizer_perf_event_attr { unsigned type; @@ -367,7 +370,7 @@ char **gr_mem; }; -#if defined(__x86_64__) && !defined(_LP64) +#if (defined(__x86_64__) && !defined(_LP64)) || defined(__hexagon__) typedef long long __sanitizer_time_t; #else typedef long __sanitizer_time_t; @@ -475,7 +478,7 @@ unsigned short d_reclen; // more fields that we don't care about }; -#elif SANITIZER_ANDROID || defined(__x86_64__) +#elif SANITIZER_ANDROID || defined(__x86_64__) || defined(__hexagon__) struct __sanitizer_dirent { unsigned long long d_ino; unsigned long long d_off; @@ -512,7 +515,7 @@ #if SANITIZER_LINUX #if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \ - defined(__mips__) + defined(__mips__) || defined(__hexagon__) typedef unsigned __sanitizer___kernel_uid_t; typedef unsigned __sanitizer___kernel_gid_t; #else diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -92,6 +92,7 @@ # include # include #if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \ + defined(__hexagon__) || \ SANITIZER_RISCV64 # include # ifdef __arm__ @@ -243,7 +244,8 @@ defined(__x86_64__) || SANITIZER_RISCV64 #define SIZEOF_STRUCT_USTAT 32 #elif defined(__arm__) || defined(__i386__) || defined(__mips__) \ - || defined(__powerpc__) || defined(__s390__) || defined(__sparc__) + || defined(__powerpc__) || defined(__s390__) || defined(__sparc__) \ + || defined(__hexagon__) #define SIZEOF_STRUCT_USTAT 20 #else #error Unknown size of struct ustat diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp @@ -22,7 +22,8 @@ uptr StackTrace::GetNextInstructionPc(uptr pc) { #if defined(__sparc__) || defined(__mips__) return pc + 8; -#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__) +#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__) \ + || defined(__hexagon__) return pc + 4; #elif SANITIZER_RISCV64 // Current check order is 4 -> 2 -> 6 -> 8 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc @@ -0,0 +1,131 @@ +//===-- sanitizer_syscall_linux_hexagon.inc ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implementations of internal_syscall and internal_iserror for Linux/hexagon. +// +//===----------------------------------------------------------------------===// + +#define SYSCALL(name) __NR_ ## name + +#define __internal_syscall_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __internal_syscall_LL_O(x) 0, __SYSCALL_LL_E((x)) + +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "trap0(#1)" \ + : "=r"(r0) : __VA_ARGS__ : "memory"); \ + return r0; \ + } while (0) + +#define __internal_syscall0(n) \ + (__internal_syscall)(n) + +static uptr __internal_syscall(long n) +{ + register long r6 __asm__("r6") = n; + register long r0 __asm__("r0"); + __asm_syscall("r"(r6)); +} + +#define __internal_syscall1(n, a1) \ + (__internal_syscall)(n, (long)(a1)) + +static uptr __internal_syscall(long n, long a) +{ + register long r6 __asm__("r6") = n; + register long r0 __asm__("r0") = a; + __asm_syscall("r"(r6), "0"(r0)); +} + +#define __internal_syscall2(n, a1, a2) \ + (__internal_syscall)(n, (long)(a1), (long)(a2)) + +static uptr __internal_syscall(long n, long a, long b) +{ + register long r6 __asm__("r6") = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + __asm_syscall("r"(r6), "0"(r0), "r"(r1)); +} + +#define __internal_syscall3(n, a1, a2, a3) \ + (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3)) + +static uptr __internal_syscall(long n, long a, long b, long c) +{ + register long r6 __asm__("r6") = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2)); +} + +#define __internal_syscall4(n, a1, a2, a3, a4) \ + (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4)) + +static uptr __internal_syscall(long n, long a, long b, long c, long d) +{ + register long r6 __asm__("r6") = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3)); +} + +#define __internal_syscall5(n, a1, a2, a3, a4, a5) \ + (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \ + (long)(a5)) + +static uptr __internal_syscall(long n, long a, long b, long c, long d, long e) +{ + register long r6 __asm__("r6") = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + register long r4 __asm__("r4") = e; + __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)); +} + +#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \ + (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \ + (long)(a5), (long)(a6)) + +static uptr __internal_syscall(long n, long a, long b, long c, long d, long e, + long f) +{ + register long r6 __asm__("r6") = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + register long r4 __asm__("r4") = e; + register long r5 __asm__("r5") = f; + __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)); +} + +#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n +#define __SYSCALL_NARGS(...) \ + __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, ) +#define __SYSCALL_CONCAT_X(a, b) a##b +#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b) +#define __SYSCALL_DISP(b, ...) \ + __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) + +#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__) + +bool internal_iserror(uptr retval, int *rverrno) { + if (retval == (uptr)-1) { + if (rverrno) + *rverrno = errno; + return true; + } + return false; +}