Skip to content
Permalink
Browse files
gcov: fail build on gcov_info size mismatch
gcov kernel profiling works by emulating parts of GCC's libgcov in the
kernel, including a definition of struct gcov_info used by profiling
code to handle coverage data. The original definition of this data type
is not available outside of GCC's source tree, and when it changes with
new GCC versions the result may be hard-to-debug kernel failures [1].

This patch adds a compile-time check to ensure that the kernel's version
of struct gcov_info has the same length as the one used by GCC as
determined by looking at GCC's assembler output. This check should help
reduce the number of run-time failures when using gcov kernel support
with new GCC versions that include updates to struct gcov_info.

Tested with various GCC versions between 4.9 and 10, and also Clang 11.

[1] https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1891288

Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
  • Loading branch information
oberpar authored and intel-lab-lkp committed Mar 11, 2021
1 parent a74e6a0 commit 01c5ab69a25e3cdfeff9cccf0f1fae26b583cc39
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
@@ -1,6 +1,15 @@
# SPDX-License-Identifier: GPL-2.0
ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'

ifeq ($(CONFIG_CC_IS_GCC),y)
GCOV_INFO_SIZE := $(shell $(srctree)/$(src)/geninfosize.sh)
ifneq ($(GCOV_INFO_SIZE),)
ccflags-y += -DGCC_GCOV_INFO_SIZE=$(GCOV_INFO_SIZE)
else
$(error Could not determine size of GCC's struct gcov_info)
endif
endif

obj-y := base.o fs.o
obj-$(CONFIG_CC_IS_GCC) += gcc_base.o gcc_4_7.o
obj-$(CONFIG_CC_IS_CLANG) += clang.o
@@ -94,6 +94,9 @@ struct gcov_info {
struct gcov_fn_info **functions;
};

_Static_assert(sizeof(struct gcov_info) == GCC_GCOV_INFO_SIZE,
"struct gcov_info must be updated");

/**
* gcov_info_filename - return info filename
* @info: profiling data set
@@ -0,0 +1,19 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Determine size of GCC's internal struct gcov_info. CC must be set correctly.
#
# Note: GCC adds an instance of its built-in version of struct gcov_info under
# the label .LPBX0 to assembler output when compiling with --coverage
#

echo "void fn(void) {}" | $CC -S --coverage -x c - -o - | \
while read a b c ; do
# .size .LPBX0, 112
if [ "$a" = ".size" -a "$b" = ".LPBX0," ] ; then
echo "$c"
break
fi
done

exit 0

0 comments on commit 01c5ab6

Please sign in to comment.