Index: lib/profile/CMakeLists.txt =================================================================== --- lib/profile/CMakeLists.txt +++ lib/profile/CMakeLists.txt @@ -1,3 +1,4 @@ +include_directories(..) CHECK_CXX_SOURCE_COMPILES(" #ifdef _MSC_VER @@ -50,6 +51,7 @@ set(PROFILE_SOURCES GCDAProfiling.c + GCDAProfilingInterceptors.cc InstrProfiling.c InstrProfilingValue.c InstrProfilingBuffer.c @@ -65,6 +67,7 @@ InstrProfilingUtil.c) set(PROFILE_HEADERS + GCDAProfiling.h InstrProfData.inc InstrProfiling.h InstrProfilingInternal.h @@ -110,6 +113,7 @@ STATIC OS ${PROFILE_SUPPORTED_OS} ARCHS ${PROFILE_SUPPORTED_ARCH} + OBJECT_LIBS RTInterception CFLAGS ${EXTRA_FLAGS} SOURCES ${PROFILE_SOURCES} ADDITIONAL_HEADERS ${PROFILE_HEADERS} @@ -118,6 +122,7 @@ add_compiler_rt_runtime(clang_rt.profile STATIC ARCHS ${PROFILE_SUPPORTED_ARCH} + OBJECT_LIBS RTInterception CFLAGS ${EXTRA_FLAGS} SOURCES ${PROFILE_SOURCES} ADDITIONAL_HEADERS ${PROFILE_HEADERS} Index: lib/profile/GCDAProfiling.h =================================================================== --- lib/profile/GCDAProfiling.h +++ lib/profile/GCDAProfiling.h @@ -0,0 +1,16 @@ +/*===- GCDAProfiling.h ----------------------------------------------------===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#ifndef PROFILE_INSTRPROFILING_GCDAPROFILING_H +#define PROFILE_INSTRPROFILING_GCDAPROFILING_H + +void gcov_initialize_interceptors(); +void __gcov_flush(); + +#endif /* PROFILE_INSTRPROFILING_GCDAPROFILING_H */ Index: lib/profile/GCDAProfiling.c =================================================================== --- lib/profile/GCDAProfiling.c +++ lib/profile/GCDAProfiling.c @@ -26,6 +26,7 @@ #include #include +#include "GCDAProfiling.h" #if defined(_WIN32) #include "WindowsMMap.h" #else @@ -587,6 +588,8 @@ void llvm_gcov_init(fn_ptr wfn, fn_ptr ffn) { static int atexit_ran = 0; + gcov_initialize_interceptors(); + if (wfn) llvm_register_writeout_function(wfn); Index: lib/profile/GCDAProfilingInterceptors.cc =================================================================== --- lib/profile/GCDAProfilingInterceptors.cc +++ lib/profile/GCDAProfilingInterceptors.cc @@ -0,0 +1,33 @@ +//===-- GCDAProfilingInterceptors.c ---------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "interception/interception.h" +extern "C" { +#include "GCDAProfiling.h" +} + +#include + +// Before forking, we should flush the counters so that the execution so far is +// not counted twice. +INTERCEPTOR(int, fork, void) { + __gcov_flush(); + return REAL(fork)(); +} + +extern "C" void gcov_initialize_interceptors() { + static int inited = 0; + if (inited != 0) { + fprintf(stderr, "llvmgcda: Interceptors already initialized\n"); + } + + INTERCEPT_FUNCTION(fork); + + inited = 1; +} Index: test/profile/Inputs/instrprof-gcov-fork.c =================================================================== --- test/profile/Inputs/instrprof-gcov-fork.c +++ test/profile/Inputs/instrprof-gcov-fork.c @@ -0,0 +1,15 @@ +#include + +void func1() {} +void func2() {} + +int main(void) +{ + func1(); + + fork(); + + func2(); + + return 0; +} Index: test/profile/Inputs/instrprof-gcov-fork.c.gcov =================================================================== --- test/profile/Inputs/instrprof-gcov-fork.c.gcov +++ test/profile/Inputs/instrprof-gcov-fork.c.gcov @@ -0,0 +1,23 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-gcov-fork.c +// CHECK-NEXT: -: 0:Graph:instrprof-gcov-fork.gcno +// CHECK-NEXT: -: 0:Data:instrprof-gcov-fork.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:#include +// CHECK-NEXT: -: 2: +// CHECK-NEXT:function func1 called 1 returned 100% blocks executed 100% +// CHECK-NEXT: 2: 3:void func1() {} +// CHECK-NEXT:function func2 called 2 returned 100% blocks executed 100% +// CHECK-NEXT: 4: 4:void func2() {} +// CHECK-NEXT: -: 5: +// CHECK-NEXT:function main called 1 returned 100% blocks executed 100% +// CHECK-NEXT: -: 6:int main(void) +// CHECK-NEXT: -: 7:{ +// CHECK-NEXT: 1: 8: func1(); +// CHECK-NEXT: -: 9: +// CHECK-NEXT: 1: 10: fork(); +// CHECK-NEXT: -: 11: +// CHECK-NEXT: 1: 12: func2(); +// CHECK-NEXT: -: 13: +// CHECK-NEXT: 1: 14: return 0; +// CHECK-NEXT: -: 15:} Index: test/profile/Posix/instrprof-gcov-fork.test =================================================================== --- test/profile/Posix/instrprof-gcov-fork.test +++ test/profile/Posix/instrprof-gcov-fork.test @@ -0,0 +1,10 @@ +RUN: mkdir -p %t.d +RUN: cd %t.d + +RUN: %clang --coverage -o %t %S/../Inputs/instrprof-gcov-fork.c +RUN: test -f instrprof-gcov-fork.gcno + +RUN: rm -f instrprof-gcov-fork.gcda +RUN: %run %t +RUN: llvm-cov gcov -b -c instrprof-gcov-fork.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-fork.c.gcov %S/../Inputs/instrprof-gcov-fork.c.gcov