1*08b48e0bSAndroid Build Coastguard Worker #include "config.h"
2*08b48e0bSAndroid Build Coastguard Worker #include "types.h"
3*08b48e0bSAndroid Build Coastguard Worker
4*08b48e0bSAndroid Build Coastguard Worker #if (defined(__AVX512F__) && defined(__AVX512DQ__)) || defined(__AVX2__)
5*08b48e0bSAndroid Build Coastguard Worker #include <immintrin.h>
6*08b48e0bSAndroid Build Coastguard Worker #endif
7*08b48e0bSAndroid Build Coastguard Worker
8*08b48e0bSAndroid Build Coastguard Worker u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end);
9*08b48e0bSAndroid Build Coastguard Worker u64 classify_word(u64 word);
10*08b48e0bSAndroid Build Coastguard Worker
classify_word(u64 word)11*08b48e0bSAndroid Build Coastguard Worker inline u64 classify_word(u64 word) {
12*08b48e0bSAndroid Build Coastguard Worker
13*08b48e0bSAndroid Build Coastguard Worker u16 mem16[4];
14*08b48e0bSAndroid Build Coastguard Worker memcpy(mem16, &word, sizeof(mem16));
15*08b48e0bSAndroid Build Coastguard Worker
16*08b48e0bSAndroid Build Coastguard Worker mem16[0] = count_class_lookup16[mem16[0]];
17*08b48e0bSAndroid Build Coastguard Worker mem16[1] = count_class_lookup16[mem16[1]];
18*08b48e0bSAndroid Build Coastguard Worker mem16[2] = count_class_lookup16[mem16[2]];
19*08b48e0bSAndroid Build Coastguard Worker mem16[3] = count_class_lookup16[mem16[3]];
20*08b48e0bSAndroid Build Coastguard Worker
21*08b48e0bSAndroid Build Coastguard Worker memcpy(&word, mem16, sizeof(mem16));
22*08b48e0bSAndroid Build Coastguard Worker return word;
23*08b48e0bSAndroid Build Coastguard Worker
24*08b48e0bSAndroid Build Coastguard Worker }
25*08b48e0bSAndroid Build Coastguard Worker
simplify_trace(afl_state_t * afl,u8 * bytes)26*08b48e0bSAndroid Build Coastguard Worker void simplify_trace(afl_state_t *afl, u8 *bytes) {
27*08b48e0bSAndroid Build Coastguard Worker
28*08b48e0bSAndroid Build Coastguard Worker u64 *mem = (u64 *)bytes;
29*08b48e0bSAndroid Build Coastguard Worker u32 i = (afl->fsrv.map_size >> 3);
30*08b48e0bSAndroid Build Coastguard Worker
31*08b48e0bSAndroid Build Coastguard Worker while (i--) {
32*08b48e0bSAndroid Build Coastguard Worker
33*08b48e0bSAndroid Build Coastguard Worker /* Optimize for sparse bitmaps. */
34*08b48e0bSAndroid Build Coastguard Worker
35*08b48e0bSAndroid Build Coastguard Worker if (unlikely(*mem)) {
36*08b48e0bSAndroid Build Coastguard Worker
37*08b48e0bSAndroid Build Coastguard Worker u8 *mem8 = (u8 *)mem;
38*08b48e0bSAndroid Build Coastguard Worker
39*08b48e0bSAndroid Build Coastguard Worker mem8[0] = simplify_lookup[mem8[0]];
40*08b48e0bSAndroid Build Coastguard Worker mem8[1] = simplify_lookup[mem8[1]];
41*08b48e0bSAndroid Build Coastguard Worker mem8[2] = simplify_lookup[mem8[2]];
42*08b48e0bSAndroid Build Coastguard Worker mem8[3] = simplify_lookup[mem8[3]];
43*08b48e0bSAndroid Build Coastguard Worker mem8[4] = simplify_lookup[mem8[4]];
44*08b48e0bSAndroid Build Coastguard Worker mem8[5] = simplify_lookup[mem8[5]];
45*08b48e0bSAndroid Build Coastguard Worker mem8[6] = simplify_lookup[mem8[6]];
46*08b48e0bSAndroid Build Coastguard Worker mem8[7] = simplify_lookup[mem8[7]];
47*08b48e0bSAndroid Build Coastguard Worker
48*08b48e0bSAndroid Build Coastguard Worker } else
49*08b48e0bSAndroid Build Coastguard Worker
50*08b48e0bSAndroid Build Coastguard Worker *mem = 0x0101010101010101ULL;
51*08b48e0bSAndroid Build Coastguard Worker
52*08b48e0bSAndroid Build Coastguard Worker mem++;
53*08b48e0bSAndroid Build Coastguard Worker
54*08b48e0bSAndroid Build Coastguard Worker }
55*08b48e0bSAndroid Build Coastguard Worker
56*08b48e0bSAndroid Build Coastguard Worker }
57*08b48e0bSAndroid Build Coastguard Worker
classify_counts(afl_forkserver_t * fsrv)58*08b48e0bSAndroid Build Coastguard Worker inline void classify_counts(afl_forkserver_t *fsrv) {
59*08b48e0bSAndroid Build Coastguard Worker
60*08b48e0bSAndroid Build Coastguard Worker u64 *mem = (u64 *)fsrv->trace_bits;
61*08b48e0bSAndroid Build Coastguard Worker u32 i = (fsrv->map_size >> 3);
62*08b48e0bSAndroid Build Coastguard Worker
63*08b48e0bSAndroid Build Coastguard Worker while (i--) {
64*08b48e0bSAndroid Build Coastguard Worker
65*08b48e0bSAndroid Build Coastguard Worker /* Optimize for sparse bitmaps. */
66*08b48e0bSAndroid Build Coastguard Worker
67*08b48e0bSAndroid Build Coastguard Worker if (unlikely(*mem)) { *mem = classify_word(*mem); }
68*08b48e0bSAndroid Build Coastguard Worker
69*08b48e0bSAndroid Build Coastguard Worker mem++;
70*08b48e0bSAndroid Build Coastguard Worker
71*08b48e0bSAndroid Build Coastguard Worker }
72*08b48e0bSAndroid Build Coastguard Worker
73*08b48e0bSAndroid Build Coastguard Worker }
74*08b48e0bSAndroid Build Coastguard Worker
75*08b48e0bSAndroid Build Coastguard Worker /* Updates the virgin bits, then reflects whether a new count or a new tuple is
76*08b48e0bSAndroid Build Coastguard Worker * seen in ret. */
discover_word(u8 * ret,u64 * current,u64 * virgin)77*08b48e0bSAndroid Build Coastguard Worker inline void discover_word(u8 *ret, u64 *current, u64 *virgin) {
78*08b48e0bSAndroid Build Coastguard Worker
79*08b48e0bSAndroid Build Coastguard Worker /* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap
80*08b48e0bSAndroid Build Coastguard Worker that have not been already cleared from the virgin map - since this will
81*08b48e0bSAndroid Build Coastguard Worker almost always be the case. */
82*08b48e0bSAndroid Build Coastguard Worker
83*08b48e0bSAndroid Build Coastguard Worker if (*current & *virgin) {
84*08b48e0bSAndroid Build Coastguard Worker
85*08b48e0bSAndroid Build Coastguard Worker if (likely(*ret < 2)) {
86*08b48e0bSAndroid Build Coastguard Worker
87*08b48e0bSAndroid Build Coastguard Worker u8 *cur = (u8 *)current;
88*08b48e0bSAndroid Build Coastguard Worker u8 *vir = (u8 *)virgin;
89*08b48e0bSAndroid Build Coastguard Worker
90*08b48e0bSAndroid Build Coastguard Worker /* Looks like we have not found any new bytes yet; see if any non-zero
91*08b48e0bSAndroid Build Coastguard Worker bytes in current[] are pristine in virgin[]. */
92*08b48e0bSAndroid Build Coastguard Worker
93*08b48e0bSAndroid Build Coastguard Worker if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) ||
94*08b48e0bSAndroid Build Coastguard Worker (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) ||
95*08b48e0bSAndroid Build Coastguard Worker (cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) ||
96*08b48e0bSAndroid Build Coastguard Worker (cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff))
97*08b48e0bSAndroid Build Coastguard Worker *ret = 2;
98*08b48e0bSAndroid Build Coastguard Worker else
99*08b48e0bSAndroid Build Coastguard Worker *ret = 1;
100*08b48e0bSAndroid Build Coastguard Worker
101*08b48e0bSAndroid Build Coastguard Worker }
102*08b48e0bSAndroid Build Coastguard Worker
103*08b48e0bSAndroid Build Coastguard Worker *virgin &= ~*current;
104*08b48e0bSAndroid Build Coastguard Worker
105*08b48e0bSAndroid Build Coastguard Worker }
106*08b48e0bSAndroid Build Coastguard Worker
107*08b48e0bSAndroid Build Coastguard Worker }
108*08b48e0bSAndroid Build Coastguard Worker
109*08b48e0bSAndroid Build Coastguard Worker #if defined(__AVX512F__) && defined(__AVX512DQ__)
110*08b48e0bSAndroid Build Coastguard Worker #define PACK_SIZE 64
skim(const u64 * virgin,const u64 * current,const u64 * current_end)111*08b48e0bSAndroid Build Coastguard Worker inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
112*08b48e0bSAndroid Build Coastguard Worker
113*08b48e0bSAndroid Build Coastguard Worker for (; current != current_end; virgin += 8, current += 8) {
114*08b48e0bSAndroid Build Coastguard Worker
115*08b48e0bSAndroid Build Coastguard Worker __m512i value = *(__m512i *)current;
116*08b48e0bSAndroid Build Coastguard Worker __mmask8 mask = _mm512_testn_epi64_mask(value, value);
117*08b48e0bSAndroid Build Coastguard Worker
118*08b48e0bSAndroid Build Coastguard Worker /* All bytes are zero. */
119*08b48e0bSAndroid Build Coastguard Worker if (likely(mask == 0xff)) continue;
120*08b48e0bSAndroid Build Coastguard Worker
121*08b48e0bSAndroid Build Coastguard Worker /* Look for nonzero bytes and check for new bits. */
122*08b48e0bSAndroid Build Coastguard Worker #define UNROLL(x) \
123*08b48e0bSAndroid Build Coastguard Worker if (unlikely(!(mask & (1 << x)) && classify_word(current[x]) & virgin[x])) \
124*08b48e0bSAndroid Build Coastguard Worker return 1
125*08b48e0bSAndroid Build Coastguard Worker UNROLL(0);
126*08b48e0bSAndroid Build Coastguard Worker UNROLL(1);
127*08b48e0bSAndroid Build Coastguard Worker UNROLL(2);
128*08b48e0bSAndroid Build Coastguard Worker UNROLL(3);
129*08b48e0bSAndroid Build Coastguard Worker UNROLL(4);
130*08b48e0bSAndroid Build Coastguard Worker UNROLL(5);
131*08b48e0bSAndroid Build Coastguard Worker UNROLL(6);
132*08b48e0bSAndroid Build Coastguard Worker UNROLL(7);
133*08b48e0bSAndroid Build Coastguard Worker #undef UNROLL
134*08b48e0bSAndroid Build Coastguard Worker
135*08b48e0bSAndroid Build Coastguard Worker }
136*08b48e0bSAndroid Build Coastguard Worker
137*08b48e0bSAndroid Build Coastguard Worker return 0;
138*08b48e0bSAndroid Build Coastguard Worker
139*08b48e0bSAndroid Build Coastguard Worker }
140*08b48e0bSAndroid Build Coastguard Worker
141*08b48e0bSAndroid Build Coastguard Worker #endif
142*08b48e0bSAndroid Build Coastguard Worker
143*08b48e0bSAndroid Build Coastguard Worker #if !defined(PACK_SIZE) && defined(__AVX2__)
144*08b48e0bSAndroid Build Coastguard Worker #define PACK_SIZE 32
skim(const u64 * virgin,const u64 * current,const u64 * current_end)145*08b48e0bSAndroid Build Coastguard Worker inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
146*08b48e0bSAndroid Build Coastguard Worker
147*08b48e0bSAndroid Build Coastguard Worker __m256i zeroes = _mm256_setzero_si256();
148*08b48e0bSAndroid Build Coastguard Worker
149*08b48e0bSAndroid Build Coastguard Worker for (; current < current_end; virgin += 4, current += 4) {
150*08b48e0bSAndroid Build Coastguard Worker
151*08b48e0bSAndroid Build Coastguard Worker __m256i value = *(__m256i *)current;
152*08b48e0bSAndroid Build Coastguard Worker __m256i cmp = _mm256_cmpeq_epi64(value, zeroes);
153*08b48e0bSAndroid Build Coastguard Worker u32 mask = _mm256_movemask_epi8(cmp);
154*08b48e0bSAndroid Build Coastguard Worker
155*08b48e0bSAndroid Build Coastguard Worker /* All bytes are zero. */
156*08b48e0bSAndroid Build Coastguard Worker if (likely(mask == (u32)-1)) continue;
157*08b48e0bSAndroid Build Coastguard Worker
158*08b48e0bSAndroid Build Coastguard Worker /* Look for nonzero bytes and check for new bits. */
159*08b48e0bSAndroid Build Coastguard Worker if (unlikely(!(mask & 0xff) && classify_word(current[0]) & virgin[0]))
160*08b48e0bSAndroid Build Coastguard Worker return 1;
161*08b48e0bSAndroid Build Coastguard Worker if (unlikely(!(mask & 0xff00) && classify_word(current[1]) & virgin[1]))
162*08b48e0bSAndroid Build Coastguard Worker return 1;
163*08b48e0bSAndroid Build Coastguard Worker if (unlikely(!(mask & 0xff0000) && classify_word(current[2]) & virgin[2]))
164*08b48e0bSAndroid Build Coastguard Worker return 1;
165*08b48e0bSAndroid Build Coastguard Worker if (unlikely(!(mask & 0xff000000) && classify_word(current[3]) & virgin[3]))
166*08b48e0bSAndroid Build Coastguard Worker return 1;
167*08b48e0bSAndroid Build Coastguard Worker
168*08b48e0bSAndroid Build Coastguard Worker }
169*08b48e0bSAndroid Build Coastguard Worker
170*08b48e0bSAndroid Build Coastguard Worker return 0;
171*08b48e0bSAndroid Build Coastguard Worker
172*08b48e0bSAndroid Build Coastguard Worker }
173*08b48e0bSAndroid Build Coastguard Worker
174*08b48e0bSAndroid Build Coastguard Worker #endif
175*08b48e0bSAndroid Build Coastguard Worker
176*08b48e0bSAndroid Build Coastguard Worker #if !defined(PACK_SIZE)
177*08b48e0bSAndroid Build Coastguard Worker #define PACK_SIZE 32
skim(const u64 * virgin,const u64 * current,const u64 * current_end)178*08b48e0bSAndroid Build Coastguard Worker inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
179*08b48e0bSAndroid Build Coastguard Worker
180*08b48e0bSAndroid Build Coastguard Worker for (; current < current_end; virgin += 4, current += 4) {
181*08b48e0bSAndroid Build Coastguard Worker
182*08b48e0bSAndroid Build Coastguard Worker if (unlikely(current[0] && classify_word(current[0]) & virgin[0])) return 1;
183*08b48e0bSAndroid Build Coastguard Worker if (unlikely(current[1] && classify_word(current[1]) & virgin[1])) return 1;
184*08b48e0bSAndroid Build Coastguard Worker if (unlikely(current[2] && classify_word(current[2]) & virgin[2])) return 1;
185*08b48e0bSAndroid Build Coastguard Worker if (unlikely(current[3] && classify_word(current[3]) & virgin[3])) return 1;
186*08b48e0bSAndroid Build Coastguard Worker
187*08b48e0bSAndroid Build Coastguard Worker }
188*08b48e0bSAndroid Build Coastguard Worker
189*08b48e0bSAndroid Build Coastguard Worker return 0;
190*08b48e0bSAndroid Build Coastguard Worker
191*08b48e0bSAndroid Build Coastguard Worker }
192*08b48e0bSAndroid Build Coastguard Worker
193*08b48e0bSAndroid Build Coastguard Worker #endif
194*08b48e0bSAndroid Build Coastguard Worker
195