Projects
Mega:24.03:SP1:Everything
valgrind
_service:tar_scm:Add-AArch64-clang-longjmp-supp...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:Add-AArch64-clang-longjmp-support.patch of Package valgrind
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. */ --
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2