1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4
5 #include <libunwind.h>
6
7 static int verbose;
8 static int nerrors;
9
10 #define panic(args...) \
11 do { printf (args); ++nerrors; } while (0)
12
13 // Assembly routine which sets up the stack for the test then calls another one
14 // which clobbers the stack, and which in turn calls recover_register below
15 extern int64_t DW_CFA_expression_testcase(int64_t regnum, int64_t height);
16
17 // recover_register is called by the assembly routines. It returns the value of
18 // a register at a specified height from the inner-most frame. The return value
19 // is propagated back through the assembly routines to the testcase.
recover_register(int64_t regnum,int64_t height)20 extern int64_t recover_register(int64_t regnum, int64_t height)
21 {
22 // Initialize cursor to current frame
23 int rc, i;
24 unw_cursor_t cursor;
25 unw_context_t context;
26 unw_getcontext(&context);
27 unw_init_local(&cursor, &context);
28 // Unwind frames until required height from inner-most frame (i.e. this one)
29 for (i = 0; i < height; ++i)
30 {
31 rc = unw_step(&cursor);
32 if (rc < 0)
33 panic("%s: unw_step failed on step %d with return code %d", __FUNCTION__, i, rc);
34 else if (rc == 0)
35 panic("%s: unw_step failed to reach the end of the stack", __FUNCTION__);
36 unw_word_t pc;
37 rc = unw_get_reg(&cursor, UNW_REG_IP, &pc);
38 if (rc < 0 || pc == 0)
39 panic("%s: unw_get_reg failed to locate the program counter", __FUNCTION__);
40 }
41 // We're now at the required height, extract register
42 uint64_t value;
43 if ((rc = unw_get_reg(&cursor, (unw_regnum_t) regnum, &value)) != 0)
44 panic("%s: unw_get_reg failed to retrieve register %lu", __FUNCTION__, regnum);
45 return value;
46 }
47
48 int
main(int argc,char ** argv)49 main (int argc, char **argv)
50 {
51 if (argc > 1)
52 verbose = 1;
53
54 if (DW_CFA_expression_testcase(12, 1) != 0)
55 panic("r12 should be clobbered at height 1 (DW_CFA_expression_inner)");
56 if (DW_CFA_expression_testcase(12, 2) != 111222333)
57 panic("r12 should be restored at height 2 (DW_CFA_expression_testcase)");
58
59 if (nerrors > 0)
60 {
61 fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
62 exit (-1);
63 }
64
65 if (verbose)
66 printf ("SUCCESS.\n");
67 return 0;
68 }
69