Clang具有内置的(标记为实验性)方法,用于添加简单的代码覆盖率计数器。只需使用-fsanitize-coverage=inline-8bit-counters
进行编译。
不幸的是,计数器可以包装,有时很不幸地归零,这使它们不是很值得信赖。我想将其更改为饱和计数器,但是我对LLVM不太熟悉。
当前,如果未在x86-64上进行优化而进行编译,则检测方式如下:
mov al, [counter]
add al, 1
mov [counter], al
或者通过优化,它可以获取
add byte ptr [counter], 1
我想要的是这样的东西:
add byte ptr [counter], 1
sbb byte ptr [counter], 0
或者至少这就是我写的方式。还是单个加载和存储速度更快?
mov al, [counter]
add al, 1
sbb al, 0
mov [counter], al
不幸的是,我不太了解LLVM,并且不确定如何将其转换为LLVM工具。
问题:
*似乎我需要以某种方式告诉它用标志减去,但是如何引用标志?
*还是存在固有的饱和添加?
*还是我必须以某种方式将条件集设置为0xff,并希望它足够聪明以进行优化而无需添加条件跳转?
我觉得我对LLVM甚至还没有正确的“心态”,而这些问题是毫无根据的。因此,如果我的问题本身是“错误的”,我将不胜感激。
作为参考,这是当前LLVM仪器的外观。
https://github.com/llvm-mirror/llvm/blob/master/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
if (Options.Inline8bitCounters) {
auto CounterPtr = IRB.CreateGEP(
Function8bitCounterArray,
{ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});
auto Load = IRB.CreateLoad(CounterPtr);
auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1));
auto Store = IRB.CreateStore(Inc, CounterPtr);
SetNoSanitizeMetadata(Load);
SetNoSanitizeMetadata(Store);
}
答案 0 :(得分:2)
替换行
auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1));
使用
CallInst *AddOv = IRB.CreateBinaryIntrinsic(Intrinsic::uadd_with_overflow,
Load, ConstantInt::get(Int8Ty, 1));
Value *SumWithOverflowBit = AddOv;
auto Inc = IRB.CreateSub(
IRB.CreateExtractValue(SumWithOverflowBit, 0), /* sum */
IRB.CreateZExt( /* convert from one bit type to 8 bits type */
IRB.CreateExtractValue(SumWithOverflowBit, 1) /* overflow */
, Int8Ty));
SetNoSanitizeMetadata(AddOv);
应该可以解决问题。
答案 1 :(得分:1)
LLVM IR没有标志,甚至没有变量。您想要的可能是在商店之前添加一个比较和一个选择。 Compare Load
against 255,然后是select
either Load
or Inc
depending on the comparison,最后将select
的结果存储在CreateStore中。