diff options
-rw-r--r-- | conf/nonclangable.conf | 1 | ||||
-rw-r--r-- | recipes-devtools/valgrind/valgrind/builtin_setjmp.patch | 125 | ||||
-rw-r--r-- | recipes-devtools/valgrind/valgrind_%.bbappend | 2 |
3 files changed, 127 insertions, 1 deletions
diff --git a/conf/nonclangable.conf b/conf/nonclangable.conf index 0e43036..3f392ff 100644 --- a/conf/nonclangable.conf +++ b/conf/nonclangable.conf | |||
@@ -74,7 +74,6 @@ TOOLCHAIN_pn-syslinux = "gcc" | |||
74 | TOOLCHAIN_pn-systemtap = "gcc" | 74 | TOOLCHAIN_pn-systemtap = "gcc" |
75 | # v4l-utils uses nested functions | 75 | # v4l-utils uses nested functions |
76 | TOOLCHAIN_pn-v4l-utils = "gcc" | 76 | TOOLCHAIN_pn-v4l-utils = "gcc" |
77 | TOOLCHAIN_pn-valgrind = "gcc" | ||
78 | # uses C++ which clang does not like | 77 | # uses C++ which clang does not like |
79 | TOOLCHAIN_pn-wvstreams = "gcc" | 78 | TOOLCHAIN_pn-wvstreams = "gcc" |
80 | TOOLCHAIN_pn-wvdial = "gcc" | 79 | TOOLCHAIN_pn-wvdial = "gcc" |
diff --git a/recipes-devtools/valgrind/valgrind/builtin_setjmp.patch b/recipes-devtools/valgrind/valgrind/builtin_setjmp.patch new file mode 100644 index 0000000..04b198d --- /dev/null +++ b/recipes-devtools/valgrind/valgrind/builtin_setjmp.patch | |||
@@ -0,0 +1,125 @@ | |||
1 | commit cebc9a058d2048e8233ee3eeb510e19b8772909f | ||
2 | Author: Benoit Jacob <benoitjacob@google.com> | ||
3 | Date: Wed May 29 21:15:53 2019 -0400 | ||
4 | |||
5 | Implement VG_MINIMAL_SETJMP in inline assembly on Android/arm64 | ||
6 | because __builtin_setjmp is not implemented in current clang | ||
7 | toolchains in current Android NDK. | ||
8 | |||
9 | diff --git a/include/pub_tool_libcsetjmp.h b/include/pub_tool_libcsetjmp.h | ||
10 | index 681450cef..ccdf295df 100644 | ||
11 | --- a/include/pub_tool_libcsetjmp.h | ||
12 | +++ b/include/pub_tool_libcsetjmp.h | ||
13 | @@ -126,6 +126,111 @@ UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env)); | ||
14 | __attribute__((noreturn)) | ||
15 | void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env)); | ||
16 | |||
17 | +#elif defined __aarch64__ | ||
18 | + | ||
19 | +// __builtin_setjmp is not implemented by the standard C library | ||
20 | +// used on Android in current llvm-based toolchains as of NDK r19. | ||
21 | +// | ||
22 | +// Here is a custom implementation of Valgrind's "minimal" setjmp | ||
23 | +// interface. Per the comment at the top of this file, we only need | ||
24 | +// to save integer registers. | ||
25 | +// | ||
26 | +// Per the Procedure Call Standard for the ARM 64-bit Architecture | ||
27 | +// document, | ||
28 | +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf | ||
29 | +// Section 5.1.1. General-purpose registers: | ||
30 | +// > | ||
31 | +// > A subroutine invocation must preserve the contents of the | ||
32 | +// > registers r19-r29 and SP." | ||
33 | +// | ||
34 | +// We also need to save and restore r30, the link register, i.e. | ||
35 | +// the default destination that a 'ret' instruction branches to. | ||
36 | +// | ||
37 | +// Note that this document is phrased in terms of 'r' registers | ||
38 | +// (e.g. "r30") because it aims to be agnostic as to A64 vs A32 | ||
39 | +// instruction sets, but here we are targeting the A64 instruction | ||
40 | +// set, so we are dealing with 'x' registers. | ||
41 | + | ||
42 | + | ||
43 | +#define VG_MINIMAL_JMP_BUF(_name) UWord _name [13] | ||
44 | + | ||
45 | +__attribute__((returns_twice)) | ||
46 | +inline UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env)) | ||
47 | +{ | ||
48 | + asm volatile( | ||
49 | + // x9 is the first of the regular temporary registers | ||
50 | + // per the above-mentioned Procedule Call Standard document. | ||
51 | + // Use it as temporary to hold the value of SP, since str does | ||
52 | + // not accept SP as operand. | ||
53 | + " mov x9, sp \n" | ||
54 | + // Store the general-purpose registers that we need to save | ||
55 | + // per the above discussion. | ||
56 | + // Note that x30 is the link register. | ||
57 | + " stp x19, x20, [%[_env], 0] \n" | ||
58 | + " stp x21, x22, [%[_env], 0x10] \n" | ||
59 | + " stp x23, x24, [%[_env], 0x20] \n" | ||
60 | + " stp x25, x26, [%[_env], 0x30] \n" | ||
61 | + " stp x27, x28, [%[_env], 0x40] \n" | ||
62 | + " stp x29, x30, [%[_env], 0x50] \n" | ||
63 | + // Store the value of SP. | ||
64 | + " str x9, [%[_env], 0x60] \n" | ||
65 | + : | ||
66 | + // No outputs | ||
67 | + : | ||
68 | + // Inputs | ||
69 | + [_env]"r"(_env) | ||
70 | + : | ||
71 | + // Clobbers. | ||
72 | + // We have used x9 as a temporary | ||
73 | + "x9", | ||
74 | + // We have written to memory locations | ||
75 | + "memory"); | ||
76 | + | ||
77 | + // Direct invokation of setjmp always returns 0. | ||
78 | + // The pseudo returning of the value 1 as a return from longjmp | ||
79 | + // is implemented in longjmp. | ||
80 | + return 0; | ||
81 | +} | ||
82 | + | ||
83 | +__attribute__((noreturn)) | ||
84 | +inline void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env)) | ||
85 | +{ | ||
86 | + asm volatile( | ||
87 | + // Loads to match the stores in the above setjmp implementation. | ||
88 | + " ldp x19, x20, [%[_env], 0] \n" | ||
89 | + " ldp x21, x22, [%[_env], 0x10] \n" | ||
90 | + " ldp x23, x24, [%[_env], 0x20] \n" | ||
91 | + " ldp x25, x26, [%[_env], 0x30] \n" | ||
92 | + " ldp x27, x28, [%[_env], 0x40] \n" | ||
93 | + " ldp x29, x30, [%[_env], 0x50] \n" | ||
94 | + " ldr x9, [%[_env], 0x60] \n" | ||
95 | + " mov sp, x9 \n" | ||
96 | + // return as setjmp for the second time, returning 1. | ||
97 | + // Since we have loaded the link register x30 from the saved buffer | ||
98 | + // that was set by the above setjmp implementation, the 'ret' instruction | ||
99 | + // here is going to return to where setjmp was called. | ||
100 | + // Per the setjmp/longjmp contract, that pseudo second returning | ||
101 | + // of setjmp should return the value 1. | ||
102 | + // x0 is holds the integer return value. | ||
103 | + " mov x0, 1 \n" | ||
104 | + " ret \n" | ||
105 | + : | ||
106 | + // No outputs | ||
107 | + : | ||
108 | + // Inputs | ||
109 | + [_env]"r"(_env) | ||
110 | + : | ||
111 | + // Clobbers. | ||
112 | + // We have used x9 as a temporary | ||
113 | + "x9"); | ||
114 | + | ||
115 | + // This statement is unreachable because the above asm statement | ||
116 | + // unconditionally does a 'ret' instruction. The purpose of this | ||
117 | + // statement is to silence clang warnings about this function returning | ||
118 | + // while having the 'noreturn' attribute. | ||
119 | + __builtin_unreachable(); | ||
120 | +} | ||
121 | + | ||
122 | #else | ||
123 | |||
124 | /* The default implementation. */ | ||
125 | |||
diff --git a/recipes-devtools/valgrind/valgrind_%.bbappend b/recipes-devtools/valgrind/valgrind_%.bbappend new file mode 100644 index 0000000..def33ce --- /dev/null +++ b/recipes-devtools/valgrind/valgrind_%.bbappend | |||
@@ -0,0 +1,2 @@ | |||
1 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
2 | SRC_URI_append = " file://builtin_setjmp.patch" | ||