@@ -740,6 +740,12 @@ all: vmlinux
CFLAGS_LLVM_COV := -fprofile-instr-generate -fcoverage-mapping
export CFLAGS_LLVM_COV
+CFLAGS_LLVM_COV_MCDC := -fcoverage-mcdc
+ifdef CONFIG_LLVM_COV_KERNEL_MCDC_MAX_CONDITIONS
+CFLAGS_LLVM_COV_MCDC += -Xclang -fmcdc-max-conditions=$(CONFIG_LLVM_COV_KERNEL_MCDC_MAX_CONDITIONS)
+endif
+export CFLAGS_LLVM_COV_MCDC
+
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage
ifdef CONFIG_CC_IS_GCC
CFLAGS_GCOV += -fno-tree-loop-im
@@ -26,4 +26,40 @@ config LLVM_COV_KERNEL
Note that the debugfs filesystem has to be mounted to access the raw
profile.
+config LLVM_COV_KERNEL_MCDC
+ bool "Enable measuring modified condition/decision coverage (MC/DC)"
+ depends on LLVM_COV_KERNEL
+ depends on CLANG_VERSION >= 180000
+ help
+ This option enables modified condition/decision coverage (MC/DC)
+ code coverage instrumentation.
+
+ If unsure, say N.
+
+ This will add Clang's Source-based Code Coverage MC/DC
+ instrumentation to your kernel. As of LLVM 19, certain expressions
+ are still not covered, and will produce build warnings when they are
+ encountered.
+
+ "[...] if a boolean expression is embedded in the nest of another
+ boolean expression but separated by a non-logical operator, this is
+ also not supported. For example, in
+ x = (a && b && c && func(d && f)), the d && f case starts a new
+ boolean expression that is separated from the other conditions by the
+ operator func(). When this is encountered, a warning will be
+ generated and the boolean expression will not be instrumented."
+
+ https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#mc-dc-instrumentation
+
+config LLVM_COV_KERNEL_MCDC_MAX_CONDITIONS
+ int "Maximum number of conditions in a decision to instrument"
+ range 6 32767
+ depends on LLVM_COV_KERNEL_MCDC
+ depends on CLANG_VERSION >= 190000
+ default "6"
+ help
+ This value is passed to "-fmcdc-max-conditions" flag of Clang cc1.
+ Expressions whose number of conditions is greater than this value will
+ produce warnings and will not be instrumented.
+
endmenu
@@ -168,6 +168,17 @@ _c_flags += $(if $(patsubst n%,, \
$(CFLAGS_LLVM_COV))
endif
+#
+# Flag that turns on modified condition/decision coverage (MC/DC) measurement
+# with Clang's Source-based Code Coverage. Enable the flag for a file or
+# directory depending on variables LLVM_COV_PROFILE_obj.o and LLVM_COV_PROFILE.
+#
+ifeq ($(CONFIG_LLVM_COV_KERNEL_MCDC),y)
+_c_flags += $(if $(patsubst n%,, \
+ $(LLVM_COV_PROFILE_$(basetarget).o)$(LLVM_COV_PROFILE)y), \
+ $(CFLAGS_LLVM_COV_MCDC))
+endif
+
#
# Enable address sanitizer flags for kernel except some files or directories
# we don't want to check (depends on variables KASAN_SANITIZE_obj.o, KASAN_SANITIZE)