xref: /aosp_15_r20/external/AFLplusplus/include/coverage-64.h (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
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