FFmpeg
tests.c
Go to the documentation of this file.
1 #include "tests.h"
2 
3 #if ARCH_ARM
4 
5 /* Re-use helpers from main checkasm library */
6 #include "src/cpu.h"
7 
8 uint64_t selftest_get_cpu_flags_arm(void)
9 {
10  uint64_t flags = SELFTEST_CPU_FLAG_ARM;
11  if (checkasm_has_vfp())
12  flags |= SELFTEST_CPU_FLAG_VFP;
13  if (checkasm_has_vfpd32())
14  flags |= SELFTEST_CPU_FLAG_VFPD32;
15  return flags;
16 }
17 
18 DEF_NOOP_FUNC(clobber_r0);
19 DEF_NOOP_FUNC(clobber_r1);
20 DEF_NOOP_FUNC(clobber_r2);
21 DEF_NOOP_FUNC(clobber_r3);
22 DEF_NOOP_FUNC(clobber_r4);
23 DEF_NOOP_FUNC(clobber_r5);
24 DEF_NOOP_FUNC(clobber_r6);
25 DEF_NOOP_FUNC(clobber_r7);
26 DEF_NOOP_FUNC(clobber_r8);
27 DEF_NOOP_FUNC(clobber_r9);
28 DEF_NOOP_FUNC(clobber_r10);
29 DEF_NOOP_FUNC(clobber_r11);
30 DEF_NOOP_FUNC(clobber_r12);
31 DEF_NOOP_FUNC(clobber_d0);
32 DEF_NOOP_FUNC(clobber_d1);
33 DEF_NOOP_FUNC(clobber_d2);
34 DEF_NOOP_FUNC(clobber_d3);
35 DEF_NOOP_FUNC(clobber_d4);
36 DEF_NOOP_FUNC(clobber_d5);
37 DEF_NOOP_FUNC(clobber_d6);
38 DEF_NOOP_FUNC(clobber_d7);
39 DEF_NOOP_FUNC(clobber_d8);
40 DEF_NOOP_FUNC(clobber_d9);
41 DEF_NOOP_FUNC(clobber_d10);
42 DEF_NOOP_FUNC(clobber_d11);
43 DEF_NOOP_FUNC(clobber_d12);
44 DEF_NOOP_FUNC(clobber_d13);
45 DEF_NOOP_FUNC(clobber_d14);
46 DEF_NOOP_FUNC(clobber_d15);
47 DEF_NOOP_FUNC(clobber_d16);
48 DEF_NOOP_FUNC(clobber_d17);
49 DEF_NOOP_FUNC(clobber_d18);
50 DEF_NOOP_FUNC(clobber_d19);
51 DEF_NOOP_FUNC(clobber_d20);
52 DEF_NOOP_FUNC(clobber_d21);
53 DEF_NOOP_FUNC(clobber_d22);
54 DEF_NOOP_FUNC(clobber_d23);
55 DEF_NOOP_FUNC(clobber_d24);
56 DEF_NOOP_FUNC(clobber_d25);
57 DEF_NOOP_FUNC(clobber_d26);
58 DEF_NOOP_FUNC(clobber_d27);
59 DEF_NOOP_FUNC(clobber_d28);
60 DEF_NOOP_FUNC(clobber_d29);
61 DEF_NOOP_FUNC(clobber_d30);
62 DEF_NOOP_FUNC(clobber_d31);
63 
64 DEF_NOOP_FUNC(sigill_arm);
65 DEF_NOOP_FUNC(clobber_fpscr_vfp);
66 
67 // A function with 4 parameters in registers and 1 on the stack.
68 typedef void(many_args_func)(int, int, int, int, int);
69 
70 #define DEF_MANY_ARGS_FUNC(NAME) void selftest_##NAME(int, int, int, int, int)
71 #define DEF_MANY_ARGS_GETTER(FLAG, NAME) DEF_GETTER(FLAG, NAME, many_args_func, NULL)
72 
73 DEF_MANY_ARGS_FUNC(clobber_stack_args_arm);
74 DEF_MANY_ARGS_FUNC(clobber_stack_arm);
75 
76 static noop_func *get_clobber_r(int reg)
77 {
78  if (!(checkasm_get_cpu_flags() & SELFTEST_CPU_FLAG_ARM))
79  return NULL;
80 
81  switch (reg) {
82  case 0: return selftest_clobber_r0;
83  case 1: return selftest_clobber_r1;
84  case 2: return selftest_clobber_r2;
85  case 3: return selftest_clobber_r3;
86  case 4: return selftest_clobber_r4;
87  case 5: return selftest_clobber_r5;
88  case 6: return selftest_clobber_r6;
89  case 7: return selftest_clobber_r7;
90  case 8: return selftest_clobber_r8;
91  case 9: return selftest_clobber_r9;
92  case 10: return selftest_clobber_r10;
93  case 11: return selftest_clobber_r11;
94  case 12: return selftest_clobber_r12;
95  case 13: return NULL; /* Shouldn't try to clobber SP */
96  case 14: return NULL; /* Shouldn't try to clobber LR */
97  case 15: return NULL; /* Shouldn't try to clobber PC */
98  default: return NULL;
99  }
100 }
101 
102 static noop_func *get_clobber_d(int reg)
103 {
104  if (!(checkasm_get_cpu_flags() & SELFTEST_CPU_FLAG_VFP))
105  return NULL;
106  if (reg >= 16 && !(checkasm_get_cpu_flags() & SELFTEST_CPU_FLAG_VFPD32))
107  return NULL;
108 
109  switch (reg) {
110  case 0: return selftest_clobber_d0;
111  case 1: return selftest_clobber_d1;
112  case 2: return selftest_clobber_d2;
113  case 3: return selftest_clobber_d3;
114  case 4: return selftest_clobber_d4;
115  case 5: return selftest_clobber_d5;
116  case 6: return selftest_clobber_d6;
117  case 7: return selftest_clobber_d7;
118  case 8: return selftest_clobber_d8;
119  case 9: return selftest_clobber_d9;
120  case 10: return selftest_clobber_d10;
121  case 11: return selftest_clobber_d11;
122  case 12: return selftest_clobber_d12;
123  case 13: return selftest_clobber_d13;
124  case 14: return selftest_clobber_d14;
125  case 15: return selftest_clobber_d15;
126  case 16: return selftest_clobber_d16;
127  case 17: return selftest_clobber_d17;
128  case 18: return selftest_clobber_d18;
129  case 19: return selftest_clobber_d19;
130  case 20: return selftest_clobber_d20;
131  case 21: return selftest_clobber_d21;
132  case 22: return selftest_clobber_d22;
133  case 23: return selftest_clobber_d23;
134  case 24: return selftest_clobber_d24;
135  case 25: return selftest_clobber_d25;
136  case 26: return selftest_clobber_d26;
137  case 27: return selftest_clobber_d27;
138  case 28: return selftest_clobber_d28;
139  case 29: return selftest_clobber_d29;
140  case 30: return selftest_clobber_d30;
141  case 31: return selftest_clobber_d31;
142  default: return NULL;
143  }
144 }
145 
146 DEF_NOOP_GETTER(SELFTEST_CPU_FLAG_ARM, sigill_arm)
147 DEF_NOOP_GETTER(SELFTEST_CPU_FLAG_VFP, clobber_fpscr_vfp)
148 DEF_MANY_ARGS_GETTER(SELFTEST_CPU_FLAG_ARM, clobber_stack_args_arm)
149 DEF_MANY_ARGS_GETTER(SELFTEST_CPU_FLAG_ARM, clobber_stack_arm)
150 
151 static void check_clobber_r(int from, int to)
152 {
153  checkasm_declare(void, int);
154 
155  for (int reg = from; reg < to; reg++) {
156  noop_func *clobber = get_clobber_r(reg);
157  if (!clobber)
158  break;
159 
160  if (checkasm_check_func(clobber, "clobber_r%d", reg)) {
162  }
163  }
164 
165  checkasm_report("clobber_r");
166 }
167 
168 static void check_clobber_d(int from, int to)
169 {
170  checkasm_declare(void, int);
171 
172  for (int reg = from; reg < to; reg++) {
173  noop_func *clobber = get_clobber_d(reg);
174  if (!clobber)
175  break;
176 
177  if (checkasm_check_func(clobber, "clobber_d%d", reg)) {
179  }
180  }
181 
182  checkasm_report("clobber_d");
183 }
184 
185 static void selftest_test_many_args(many_args_func fun, const char *name)
186 {
187  checkasm_declare(void, int, int, int, int, int);
188 
189  if (checkasm_check_func(fun, "%s", name)) {
190  /* don't call unchecked because that one is called without wrapping,
191  * and we try to cloober the stack here. */
192  (void) func_ref;
193  checkasm_call_new(1, 2, 3, 4, 5);
194  }
195 
196  checkasm_report("%s", name);
197 }
198 
199 void selftest_check_arm(void)
200 {
201  check_clobber_r(0, 4);
202  check_clobber_r(12, 13);
203  check_clobber_d(0, 8);
204  check_clobber_d(16, 32);
205  selftest_test_many_args(get_clobber_stack_args_arm(), "clobber_stack_args");
206 
207  if (!checkasm_should_fail(SELFTEST_CPU_FLAG_ARM))
208  return;
209  selftest_test_noop(get_sigill_arm(), "sigill");
210  selftest_test_many_args(get_clobber_stack_arm(), "clobber_stack");
211  selftest_test_noop(get_clobber_fpscr_vfp(), "clobber_fpscr");
212  check_clobber_r(4, 9);
213 #ifndef __APPLE__
214  // In the iOS ABI, r9 is a volatile register, so we don't check if it is
215  // clobbered in the checked_call wrapper.
216  check_clobber_r(9, 10);
217 #endif
218  check_clobber_r(10, 11);
219  check_clobber_d(8, 16);
220 }
221 
222 #endif
flags
const SwsFlags flags[]
Definition: swscale.c:85
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
checkasm_check_func
#define checkasm_check_func(func,...)
Check if a function should be tested and set up function references.
Definition: test.h:77
selftest_check_arm
void selftest_check_arm(void)
selftest_get_cpu_flags_arm
uint64_t selftest_get_cpu_flags_arm(void)
from
const char * from
Definition: jacosubdec.c:64
NULL
#define NULL
Definition: coverity.c:32
func_ref
#define func_ref
Definition: test.h:482
noop_func
void() noop_func(int unused)
Do nothing.
Definition: tests.h:94
to
const char * to
Definition: webvttdec.c:36
cpu.h
checkasm_declare
#define checkasm_declare(ret,...)
Declare a function signature for testing.
Definition: test.h:205
checkasm_report
CHECKASM_API void checkasm_report(const char *name,...) CHECKASM_PRINTF(1
Report test outcome for a named group of functions.
checkasm_get_cpu_flags
CHECKASM_API CheckasmCpu checkasm_get_cpu_flags(void)
Get the current active set of CPU flags.
Definition: checkasm.c:121
tests.h
DEF_NOOP_GETTER
#define DEF_NOOP_GETTER(FLAG, NAME)
Definition: tests.h:98
selftest_test_noop
void selftest_test_noop(noop_func fun, const char *name)
Definition: generic.c:83
DEF_NOOP_FUNC
#define DEF_NOOP_FUNC(NAME)
Definition: tests.h:97
checkasm_should_fail
CHECKASM_API int checkasm_should_fail(CheckasmCpu cpu_flags)
Mark a block of tests as expected to fail.
Definition: checkasm.c:1017
checkasm_call_new
#define checkasm_call_new(...)
Call the implementation being tested with validation.
Definition: test.h:381