From a7e40821c3e37f405eb12effee3b1db6f1587317 Mon Sep 17 00:00:00 2001 From: liyunfei Date: Tue, 29 Aug 2023 19:59:58 +0800 Subject: [PATCH] Add clang compile support on AArch64 --- Add-AArch64-clang-longjmp-support.patch | 117 ++++++++++++++++++++++++ valgrind.spec | 12 ++- 2 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 Add-AArch64-clang-longjmp-support.patch diff --git a/Add-AArch64-clang-longjmp-support.patch b/Add-AArch64-clang-longjmp-support.patch new file mode 100644 index 0000000..c39f9c1 --- /dev/null +++ b/Add-AArch64-clang-longjmp-support.patch @@ -0,0 +1,117 @@ +diff --git a/include/pub_tool_libcsetjmp.h b/include/pub_tool_libcsetjmp.h +index 681450cef..ccdf295df 100644 +--- a/include/pub_tool_libcsetjmp.h ++++ b/include/pub_tool_libcsetjmp.h +@@ -126,6 +126,111 @@ UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env)); + __attribute__((noreturn)) + void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env)); + ++#elif defined __aarch64__ && defined __clang__ ++ ++// __builtin_setjmp is not implemented by the standard C library ++// used on Android in current llvm-based toolchains as of NDK r19. ++// ++// Here is a custom implementation of Valgrind's "minimal" setjmp ++// interface. Per the comment at the top of this file, we only need ++// to save integer registers. ++// ++// Per the Procedure Call Standard for the ARM 64-bit Architecture ++// document, ++// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf ++// Section 5.1.1. General-purpose registers: ++// > ++// > A subroutine invocation must preserve the contents of the ++// > registers r19-r29 and SP." ++// ++// We also need to save and restore r30, the link register, i.e. ++// the default destination that a 'ret' instruction branches to. ++// ++// Note that this document is phrased in terms of 'r' registers ++// (e.g. "r30") because it aims to be agnostic as to A64 vs A32 ++// instruction sets, but here we are targeting the A64 instruction ++// set, so we are dealing with 'x' registers. ++ ++ ++#define VG_MINIMAL_JMP_BUF(_name) UWord _name [13] ++ ++__attribute__((returns_twice)) ++inline UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env)) ++{ ++ asm volatile( ++ // x9 is the first of the regular temporary registers ++ // per the above-mentioned Procedule Call Standard document. ++ // Use it as temporary to hold the value of SP, since str does ++ // not accept SP as operand. ++ " mov x9, sp \n" ++ // Store the general-purpose registers that we need to save ++ // per the above discussion. ++ // Note that x30 is the link register. ++ " stp x19, x20, [%[_env], 0] \n" ++ " stp x21, x22, [%[_env], 0x10] \n" ++ " stp x23, x24, [%[_env], 0x20] \n" ++ " stp x25, x26, [%[_env], 0x30] \n" ++ " stp x27, x28, [%[_env], 0x40] \n" ++ " stp x29, x30, [%[_env], 0x50] \n" ++ // Store the value of SP. ++ " str x9, [%[_env], 0x60] \n" ++ : ++ // No outputs ++ : ++ // Inputs ++ [_env]"r"(_env) ++ : ++ // Clobbers. ++ // We have used x9 as a temporary ++ "x9", ++ // We have written to memory locations ++ "memory"); ++ ++ // Direct invokation of setjmp always returns 0. ++ // The pseudo returning of the value 1 as a return from longjmp ++ // is implemented in longjmp. ++ return 0; ++} ++ ++__attribute__((noreturn)) ++inline void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env)) ++{ ++ asm volatile( ++ // Loads to match the stores in the above setjmp implementation. ++ " ldp x19, x20, [%[_env], 0] \n" ++ " ldp x21, x22, [%[_env], 0x10] \n" ++ " ldp x23, x24, [%[_env], 0x20] \n" ++ " ldp x25, x26, [%[_env], 0x30] \n" ++ " ldp x27, x28, [%[_env], 0x40] \n" ++ " ldp x29, x30, [%[_env], 0x50] \n" ++ " ldr x9, [%[_env], 0x60] \n" ++ " mov sp, x9 \n" ++ // return as setjmp for the second time, returning 1. ++ // Since we have loaded the link register x30 from the saved buffer ++ // that was set by the above setjmp implementation, the 'ret' instruction ++ // here is going to return to where setjmp was called. ++ // Per the setjmp/longjmp contract, that pseudo second returning ++ // of setjmp should return the value 1. ++ // x0 is holds the integer return value. ++ " mov x0, 1 \n" ++ " ret \n" ++ : ++ // No outputs ++ : ++ // Inputs ++ [_env]"r"(_env) ++ : ++ // Clobbers. ++ // We have used x9 as a temporary ++ "x9"); ++ ++ // This statement is unreachable because the above asm statement ++ // unconditionally does a 'ret' instruction. The purpose of this ++ // statement is to silence clang warnings about this function returning ++ // while having the 'noreturn' attribute. ++ __builtin_unreachable(); ++} ++ + #else + + /* The default implementation. */ + -- \ No newline at end of file diff --git a/valgrind.spec b/valgrind.spec index 481eae7..6fbd1da 100644 --- a/valgrind.spec +++ b/valgrind.spec @@ -17,7 +17,7 @@ Name: valgrind Version: 3.16.0 -Release: 6 +Release: 7 Epoch: 1 Summary: An instrumentation framework for building dynamic analysis tools License: GPLv2+ @@ -31,6 +31,9 @@ Patch4: backport-Generate-a-ENOSYS-sys_ni_syscall-for-clone3-on-all-linu Patch5: valgrind-Implement-linux-rseq-syscall-as-ENOSYS.patch Patch6: Add-LOONGARCH64-Linux-support.patch Patch7: valgrind-Sync-LoongArch-with-glibc-2.36.patch +%if "%{toolchain}" == "clang" +Patch8: Add-AArch64-clang-longjmp-support.patch +%endif BuildRequires: glibc glibc-devel gdb procps gcc-c++ perl(Getopt::Long) @@ -52,12 +55,12 @@ This files contains the development files for %{name}. %autosetup -n %{name}-%{version} -p1 %build -CC=gcc +CC=%{__cc} %ifarch x86_64 mkdir -p shared/libgcc/32 ar r shared/libgcc/32/libgcc_s.a ar r shared/libgcc/libgcc_s_32.a -CC="gcc -B `pwd`/shared/libgcc/" +CC="%{__cc} -B `pwd`/shared/libgcc/" %endif %undefine _hardened_build @@ -108,6 +111,9 @@ popd %{_mandir}/man1/* %changelog +* Tue Aug 29 2023 liyunfei - 1:3.16.0-7 +- Add clang compile support on AArch64 + * Tue Jan 03 2023 chenfeiyang - 1:3.16.0-6 - Sync LoongArch with glibc 2.36 -- Gitee