|
32 | 32 | #include "../kselftest.h"
|
33 | 33 | #include "rseq.h"
|
34 | 34 |
|
35 |
| -static const ptrdiff_t *libc_rseq_offset_p; |
36 |
| -static const unsigned int *libc_rseq_size_p; |
37 |
| -static const unsigned int *libc_rseq_flags_p; |
| 35 | +/* |
| 36 | + * Define weak versions to play nice with binaries that are statically linked |
| 37 | + * against a libc that doesn't support registering its own rseq. |
| 38 | + */ |
| 39 | +__weak ptrdiff_t __rseq_offset; |
| 40 | +__weak unsigned int __rseq_size; |
| 41 | +__weak unsigned int __rseq_flags; |
| 42 | + |
| 43 | +static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset; |
| 44 | +static const unsigned int *libc_rseq_size_p = &__rseq_size; |
| 45 | +static const unsigned int *libc_rseq_flags_p = &__rseq_flags; |
38 | 46 |
|
39 | 47 | /* Offset from the thread pointer to the rseq area. */
|
40 | 48 | ptrdiff_t rseq_offset;
|
@@ -108,9 +116,17 @@ int rseq_unregister_current_thread(void)
|
108 | 116 | static __attribute__((constructor))
|
109 | 117 | void rseq_init(void)
|
110 | 118 | {
|
111 |
| - libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset"); |
112 |
| - libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size"); |
113 |
| - libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags"); |
| 119 | + /* |
| 120 | + * If the libc's registered rseq size isn't already valid, it may be |
| 121 | + * because the binary is dynamically linked and not necessarily due to |
| 122 | + * libc not having registered a restartable sequence. Try to find the |
| 123 | + * symbols if that's the case. |
| 124 | + */ |
| 125 | + if (!*libc_rseq_size_p) { |
| 126 | + libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset"); |
| 127 | + libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size"); |
| 128 | + libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags"); |
| 129 | + } |
114 | 130 | if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
|
115 | 131 | *libc_rseq_size_p != 0) {
|
116 | 132 | /* rseq registration owned by glibc */
|
|
0 commit comments