#include "../kselftest.h"
 #include "rseq.h"
 
-static const ptrdiff_t *libc_rseq_offset_p;
-static const unsigned int *libc_rseq_size_p;
-static const unsigned int *libc_rseq_flags_p;
+/*
+ * Define weak versions to play nice with binaries that are statically linked
+ * against a libc that doesn't support registering its own rseq.
+ */
+__weak ptrdiff_t __rseq_offset;
+__weak unsigned int __rseq_size;
+__weak unsigned int __rseq_flags;
+
+static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset;
+static const unsigned int *libc_rseq_size_p = &__rseq_size;
+static const unsigned int *libc_rseq_flags_p = &__rseq_flags;
 
 /* Offset from the thread pointer to the rseq area. */
 ptrdiff_t rseq_offset;
 static __attribute__((constructor))
 void rseq_init(void)
 {
-       libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
-       libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
-       libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+       /*
+        * If the libc's registered rseq size isn't already valid, it may be
+        * because the binary is dynamically linked and not necessarily due to
+        * libc not having registered a restartable sequence.  Try to find the
+        * symbols if that's the case.
+        */
+       if (!*libc_rseq_size_p) {
+               libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
+               libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
+               libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+       }
        if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
                        *libc_rseq_size_p != 0) {
                /* rseq registration owned by glibc */