]> git.saurik.com Git - apple/libpthread.git/blobdiff - tests/stack.c
libpthread-330.201.1.tar.gz
[apple/libpthread.git] / tests / stack.c
diff --git a/tests/stack.c b/tests/stack.c
new file mode 100644 (file)
index 0000000..f910b28
--- /dev/null
@@ -0,0 +1,82 @@
+#include <signal.h>
+#include <pthread/stack_np.h>
+
+#include "darwintest_defaults.h"
+#include <darwintest_utils.h>
+
+#if defined(__arm64__)
+#define call_chkstk(value) \
+               __asm__ volatile("orr x9, xzr, %0\t\n" \
+                               "bl _thread_chkstk_darwin" : : "i"(value) : "x9")
+#define TRAPSIG SIGTRAP
+#elif defined(__x86_64__)
+#define call_chkstk(value) \
+               __asm__ volatile("movq %0, %%rax\t\n" \
+                               "callq _thread_chkstk_darwin" : : "i"(value) : "rax")
+#define TRAPSIG SIGILL
+#elif defined(__i386__)
+#define call_chkstk(value) \
+               __asm__ volatile("movl %0, %%eax\t\n" \
+                               "calll _thread_chkstk_darwin" : : "i"(value) : "eax")
+#define TRAPSIG SIGILL
+#endif
+
+static void
+got_signal(int signo __unused)
+{
+       T_PASS("calling with 1 << 24 crashed");
+       T_END;
+}
+
+T_DECL(chkstk, "chkstk",
+               T_META_ALL_VALID_ARCHS(YES), T_META_CHECK_LEAKS(NO))
+{
+#if defined(__arm__)
+       T_SKIP("not on armv7");
+#else
+
+       call_chkstk(1 << 8);
+       T_PASS("calling with 1 << 8");
+
+       call_chkstk(1 << 16);
+       T_PASS("calling with 1 << 16");
+
+       signal(TRAPSIG, got_signal);
+
+       call_chkstk(1 << 24);
+       T_FAIL("should have crashed");
+#endif
+}
+
+struct frame {
+       uintptr_t frame;
+       uintptr_t ret;
+};
+
+OS_NOINLINE OS_NOT_TAIL_CALLED
+static void
+do_stack_frame_decode_test(struct frame frames[], size_t n, size_t count)
+{
+       if (n < count) {
+               frames[n].frame = (uintptr_t)__builtin_frame_address(1);
+               frames[n].ret = (uintptr_t)__builtin_return_address(0);
+               do_stack_frame_decode_test(frames, n + 1, count);
+       } else {
+               uintptr_t frame = (uintptr_t)__builtin_frame_address(1);
+               uintptr_t ret;
+               while (count-- > 0) {
+                       frame = pthread_stack_frame_decode_np(frame, &ret);
+                       T_EXPECT_EQ(frames[count].frame, frame, "Frame %zd", count);
+                       T_EXPECT_EQ(frames[count].ret, ret, "Retaddr %zd", count);
+               }
+       }
+}
+
+T_DECL(pthread_stack_frame_decode_np, "pthread_stack_frame_decode_np",
+               T_META_ALL_VALID_ARCHS(YES), T_META_CHECK_LEAKS(NO))
+{
+       struct frame frames[10];
+       frames[0].frame = (uintptr_t)__builtin_frame_address(1);
+       frames[0].ret = (uintptr_t)__builtin_return_address(0);
+       do_stack_frame_decode_test(frames, 1, 10);
+}