先简单总结下run_target中和覆盖率计算相关的代码(去除我不关注的内容,如dump,no_forkserver等):
static u8 run_target(char** argv, u32 timeout) {
/* After this memset, trace_bits[] are effectively volatile, so we
must prevent any earlier operations from venturing into that
territory. */
memset(trace_bits, 0, MAP_SIZE);
MEM_BARRIER();
// 执行二进制程序。。。
// 等待程序终止。。。
/* Any subsequent operations on trace_bits must not be moved by the
compiler below this point. Past this location, trace_bits[] behave
very normally and do not have to be treated as volatile. */
MEM_BARRIER();
#ifdef WORD_SIZE_64
classify_counts((u64*)trace_bits);
#else
classify_counts((u32*)trace_bits);
#endif /* ^WORD_SIZE_64 */
return FAULT_NONE;
把其他内容删减后,对共享内存的操作就几句话。
memset,给trace_bits全部置0。
MEM_BARRIER(),内存屏障,暂时不去了解
classify_counts((u64*)trace_bits);每次处理8个字节,一共65536个字节需要处理
classify_count函数如下:
static inline void classify_counts(u64* mem) {
u32 i = MAP_SIZE >> 3;
while (i--) {
/* Optimize for sparse bitmaps. */
if (unlikely(*mem)) {
u16* mem16 = (u16*)mem;
mem16[0] = count_class_lookup16[mem16[0]];
mem16[1] = count_class_lookup16[mem16[1]];
mem16[2] = count_class_lookup16[mem16[2]];
mem16[3] = count_class_lookup16[mem16[3]];
}
mem++;
}
}
i = 65536 / 8 = 8192,while循环8192次
u16* mem16 = (u16*)mem; 把u64指针转化为u16指针
static u16 count_class_lookup16[65536];
EXP_ST void init_count_class16(void) {
u32 b1, b2;
for (b1 = 0; b1 < 256; b1++)
for (b2 = 0; b2 < 256; b2++)
count_class_lookup16[(b1 << 8) + b2] =
(count_class_lookup8[b1] << 8) |
count_class_lookup8[b2];
}
static const u8 count_class_lookup8[256] = {
[0] = 0,
[1] = 1,
[2] = 2,
[3] = 4,
[4 ... 7] = 8,
[8 ... 15] = 16,
[16 ... 31] = 32,
[32 ... 127] = 64,
[128 ... 255] = 128
};
感觉大概意思就是,对trace_bit的数据进行一些形式化处理,但是基本上不改变值。
run_target中间没有其他地方对trace_bits的具体赋值,应该是在二进制程序插桩中直接修改了trace_bits,暂时先不去深入了解