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().

Link: http://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: Stephen Rothwell <[email protected]>
  • Loading branch information
greghackmann authored and sfrothwell committed May 15, 2019
1 parent e00d543 commit c5b1cc0
Show file tree
Hide file tree
Showing 7 changed files with 616 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 c5b1cc0

Please sign in to comment.