1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2012, Richard Lowe.
14  */
15 
16 #include <stdio.h>
17 #include <sys/types.h>
18 #include <saveargs.h>
19 
20 #define	DEF_TEST(name)		\
21     extern uint8_t name[];	\
22     extern int name##_end
23 
24 #define	SIZE_OF(name) ((caddr_t)&name##_end - (caddr_t)&name)
25 
26 #define	TEST_GOOD(name, argc)					\
27 	if (saveargs_has_args(name, SIZE_OF(name), argc, 0) ==	\
28 	    SAVEARGS_TRAD_ARGS)					\
29 		printf("Pass: %s\n", #name);			\
30 	else							\
31 		printf("FAIL: %s\n", #name);
32 
33 #define	TEST_GOOD_STRUCT(name, argc)				\
34 	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) ==	\
35 	    SAVEARGS_STRUCT_ARGS)				\
36 		printf("Pass: %s\n", #name);			\
37 	else							\
38 		printf("FAIL: %s\n", #name);
39 
40 /*
41  * GCC deals with structures differently, so TRAD args is actually correct for
42  * this
43  */
44 #define	TEST_GOOD_GSTRUCT(name, argc)				\
45 	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) ==	\
46 	    SAVEARGS_TRAD_ARGS)					\
47 		printf("Pass: %s\n", #name);			\
48 	else							\
49 		printf("FAIL: %s\n", #name);
50 
51 #define	TEST_BAD(name, argc)					\
52 	if (saveargs_has_args(name, SIZE_OF(name), argc, 0) == 	\
53 		SAVEARGS_NO_ARGS)				\
54 		printf("Pass: %s\n", #name);			\
55 	else							\
56 		printf("FAIL: %s\n", #name);
57 
58 #define	TEST_BAD_STRUCT(name, argc)				\
59 	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == 	\
60 		SAVEARGS_NO_ARGS)				\
61 		printf("Pass: %s\n", #name);			\
62 	else							\
63 		printf("FAIL: %s\n", #name);
64 
65 #define	TEST_BAD_GSTRUCT(name, argc)				\
66 	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == 	\
67 		SAVEARGS_NO_ARGS)				\
68 		printf("Pass: %s\n", #name);			\
69 	else							\
70 		printf("FAIL: %s\n", #name);
71 
72 DEF_TEST(gcc_mov_align);
73 DEF_TEST(gcc_mov_basic);
74 DEF_TEST(gcc_mov_noorder);
75 DEF_TEST(gcc_mov_struct_noorder);
76 DEF_TEST(gcc_mov_big_struct_ret);
77 DEF_TEST(gcc_mov_big_struct_ret_and_spill);
78 DEF_TEST(gcc_mov_small_struct_ret);
79 DEF_TEST(gcc_mov_small_struct_ret_and_spill);
80 DEF_TEST(gcc_mov_stack_spill);
81 
82 DEF_TEST(gcc_push_align);
83 DEF_TEST(gcc_push_basic);
84 DEF_TEST(gcc_push_noorder);
85 DEF_TEST(gcc_push_struct_noorder);
86 DEF_TEST(gcc_push_big_struct_ret);
87 DEF_TEST(gcc_push_big_struct_ret_and_spill);
88 DEF_TEST(gcc_push_small_struct_ret);
89 DEF_TEST(gcc_push_small_struct_ret_and_spill);
90 DEF_TEST(gcc_push_stack_spill);
91 
92 DEF_TEST(ss_mov_align);
93 DEF_TEST(ss_mov_basic);
94 DEF_TEST(ss_mov_big_struct_ret);
95 DEF_TEST(ss_mov_big_struct_ret_and_spill);
96 DEF_TEST(ss_mov_small_struct_ret);
97 DEF_TEST(ss_mov_small_struct_ret_and_spill);
98 DEF_TEST(ss_mov_stack_spill);
99 
100 DEF_TEST(dtrace_instrumented);
101 DEF_TEST(kmem_alloc);
102 DEF_TEST(uts_kill);
103 DEF_TEST(av1394_ic_bitreverse);
104 
105 DEF_TEST(small_struct_ret_w_float);
106 DEF_TEST(big_struct_ret_w_float);
107 
108 DEF_TEST(interleaved_argument_saves);
109 DEF_TEST(jmp_table);
110 
111 /*
112  * Functions which should not match
113  *
114  * no_fp			-- valid save-args sequence with no saved FP
115  * big_struct_arg_by_value	-- function with big struct passed by value
116  * small_struct_arg_by_value	-- function with small struct passed by value
117  */
118 DEF_TEST(no_fp);
119 DEF_TEST(big_struct_arg_by_value);
120 DEF_TEST(small_struct_arg_by_value);
121 
122 int
main(int argc,char ** argv)123 main(int argc, char **argv)
124 {
125 	TEST_GOOD(kmem_alloc, 2);
126 	TEST_GOOD(uts_kill, 2);
127 	TEST_GOOD(av1394_ic_bitreverse, 1);
128 	TEST_GOOD(dtrace_instrumented, 4);
129 	TEST_GOOD_GSTRUCT(big_struct_ret_w_float, 1);
130 	TEST_BAD(no_fp, 5);
131 
132 	TEST_GOOD(gcc_mov_align, 5);
133 	TEST_GOOD(gcc_push_align, 5);
134 	TEST_GOOD(ss_mov_align, 5);
135 
136 	TEST_GOOD(gcc_mov_basic, 4);
137 	TEST_GOOD(gcc_push_basic, 4);
138 	TEST_GOOD(ss_mov_basic, 4);
139 
140 	TEST_GOOD(gcc_mov_noorder, 4);
141 	TEST_GOOD(gcc_push_noorder, 4);
142 
143 	TEST_GOOD_GSTRUCT(gcc_mov_big_struct_ret, 4);
144 	TEST_GOOD_GSTRUCT(gcc_push_big_struct_ret, 4);
145 	TEST_GOOD_STRUCT(ss_mov_big_struct_ret, 4);
146 
147 	TEST_GOOD_GSTRUCT(gcc_mov_struct_noorder, 4);
148 	TEST_GOOD_GSTRUCT(gcc_push_struct_noorder, 4);
149 
150 	TEST_GOOD_GSTRUCT(gcc_mov_big_struct_ret_and_spill, 8);
151 	TEST_GOOD_GSTRUCT(gcc_push_big_struct_ret_and_spill, 8);
152 	TEST_GOOD_STRUCT(ss_mov_big_struct_ret_and_spill, 8);
153 
154 	TEST_GOOD(gcc_mov_small_struct_ret, 4);
155 	TEST_GOOD(gcc_push_small_struct_ret, 4);
156 	TEST_GOOD(ss_mov_small_struct_ret, 4);
157 
158 	TEST_GOOD(gcc_mov_small_struct_ret_and_spill, 8);
159 	TEST_GOOD(gcc_push_small_struct_ret_and_spill, 8);
160 	TEST_GOOD(ss_mov_small_struct_ret_and_spill, 8);
161 
162 	TEST_GOOD(gcc_mov_stack_spill, 8);
163 	TEST_GOOD(gcc_push_stack_spill, 8);
164 	TEST_GOOD(ss_mov_stack_spill, 8);
165 
166 	TEST_BAD(big_struct_arg_by_value, 2);
167 	TEST_BAD(small_struct_arg_by_value, 2);
168 
169 	TEST_BAD(small_struct_ret_w_float, 1);
170 
171 	TEST_GOOD(interleaved_argument_saves, 4);
172 	TEST_BAD(jmp_table, 1);
173 
174 	return (0);
175 }
176