summaryrefslogtreecommitdiff
path: root/src/third_party/unwind/dist/tests/Ltest-init-local-signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/unwind/dist/tests/Ltest-init-local-signal.c')
-rw-r--r--src/third_party/unwind/dist/tests/Ltest-init-local-signal.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/third_party/unwind/dist/tests/Ltest-init-local-signal.c b/src/third_party/unwind/dist/tests/Ltest-init-local-signal.c
new file mode 100644
index 00000000000..4bde218f3bb
--- /dev/null
+++ b/src/third_party/unwind/dist/tests/Ltest-init-local-signal.c
@@ -0,0 +1,60 @@
+#include "libunwind.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <stdlib.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <assert.h>
+
+int stepper(unw_cursor_t* c) {
+ int steps = 0;
+ int ret = 1;
+ while (ret) {
+
+ ret = unw_step(c);
+ if (!ret) {
+ break;
+ }
+ steps++;
+ }
+ return steps;
+}
+
+/* Verify that we can step from both ucontext, and from getcontext()
+ * roughly the same. This tests that the IP from ucontext is used
+ * correctly (see impl of unw_init_local2) */
+void handler(int num, siginfo_t* info, void* ucontext) {
+ unw_cursor_t c;
+ unw_context_t context;
+ unw_getcontext(&context);
+ int ret = unw_init_local2(&c, ucontext, UNW_INIT_SIGNAL_FRAME);
+ assert(!ret);
+ int ucontext_steps = stepper(&c);
+
+ ret = unw_init_local(&c, &context);
+ (void)ret;
+ assert(!ret);
+ int getcontext_steps = stepper(&c);
+ if (ucontext_steps == getcontext_steps - 2) {
+ exit(0);
+ }
+ printf("unw_getcontext steps was %i, ucontext steps was %i, should be %i\n",
+ getcontext_steps, ucontext_steps, getcontext_steps - 2);
+ exit(-1);
+}
+
+int foo(volatile int* f);
+
+int main(){
+ struct sigaction a;
+ memset(&a, 0, sizeof(struct sigaction));
+ a.sa_sigaction = &handler;
+ a.sa_flags = SA_SIGINFO;
+ sigaction(SIGSEGV, &a, NULL);
+
+ foo(NULL);
+ return 0;
+}