Skip to content

Commit

Permalink
gcov: clang support
Browse files Browse the repository at this point in the history
LLVM uses profiling data that's deliberately similar to GCC, but has a
very different way of exporting that data.  LLVM calls llvm_gcov_init()
once per module, and provides a couple of callbacks that we can use to
ask for more data.

We care about the "writeout" callback, which in turn calls back into
compiler-rt/this module to dump all the gathered coverage data to disk:

   llvm_gcda_start_file()
     llvm_gcda_emit_function()
     llvm_gcda_emit_arcs()
     llvm_gcda_emit_function()
     llvm_gcda_emit_arcs()
     [... repeats for each function ...]
   llvm_gcda_summary_info()
   llvm_gcda_end_file()

This design is much more stateless and unstructured than gcc's, and is
intended to run at process exit.  This forces us to keep some local
state about which module we're dealing with at the moment.  On the other
hand, it also means we don't depend as much on how LLVM represents
profiling data internally.

See LLVM's lib/Transforms/Instrumentation/GCOVProfiling.cpp for more
details on how this works, particularly GCOVProfiler::emitProfileArcs(),
GCOVProfiler::insertCounterWriteout(), and GCOVProfiler::insertFlush().

[[email protected]: coding-style fixes]
Link: http:https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Hackmann <[email protected]>
Signed-off-by: Nick Desaulniers <[email protected]>
Signed-off-by: Tri Vo <[email protected]>
Co-developed-by: Nick Desaulniers <[email protected]>
Co-developed-by: Tri Vo <[email protected]>
Tested-by: Trilok Soni <[email protected]>
Tested-by: Prasad Sodagudi <[email protected]>
Tested-by: Tri Vo <[email protected]>
Tested-by: Daniel Mentz <[email protected]>
Tested-by: Petri Gynther <[email protected]>
Reviewed-by: Peter Oberparleiter <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
greghackmann authored and torvalds committed May 15, 2019
1 parent aa069a2 commit e178a5b
Show file tree
Hide file tree
Showing 7 changed files with 611 additions and 2 deletions.
3 changes: 2 additions & 1 deletion kernel/gcov/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ config GCOV_PROFILE_ALL
choice
prompt "Specify GCOV format"
depends on GCOV_KERNEL
depends on CC_IS_GCC
---help---
The gcov format is usually determined by the GCC version, and the
default is chosen according to your GCC version. However, there are
Expand All @@ -62,7 +63,7 @@ choice

config GCOV_FORMAT_3_4
bool "GCC 3.4 format"
depends on CC_IS_GCC && GCC_VERSION < 40700
depends on GCC_VERSION < 40700
---help---
Select this option to use the format defined by GCC 3.4.

Expand Down
1 change: 1 addition & 0 deletions kernel/gcov/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
obj-y := base.o fs.o
obj-$(CONFIG_GCOV_FORMAT_3_4) += gcc_base.o gcc_3_4.o
obj-$(CONFIG_GCOV_FORMAT_4_7) += gcc_base.o gcc_4_7.o
obj-$(CONFIG_CC_IS_CLANG) += clang.o
2 changes: 1 addition & 1 deletion kernel/gcov/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,

/* Remove entries located in module from linked list. */
while ((info = gcov_info_next(info))) {
if (within_module((unsigned long)info, mod)) {
if (gcov_info_within_module(info, mod)) {
gcov_info_unlink(prev, info);
if (gcov_events_enabled)
gcov_event(GCOV_REMOVE, info);
Expand Down
Loading

0 comments on commit e178a5b

Please sign in to comment.