mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 19:44:38 +08:00
[gcov] Move llvm_writeout_files from atexit to a static destructor
atexit registered functions run earlier so `__attribute__((destructor))` annotated functions cannot be tracked. Set a priority of 100 (compatible with GCC 7 onwards) to track destructors and destructors whose priorities are greater than 100. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=7970 Reviewed By: calixte, marco-c Differential Revision: https://reviews.llvm.org/D82253
This commit is contained in:
@@ -628,8 +628,14 @@ void llvm_writeout_files(void) {
|
||||
}
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
void llvm_delete_writeout_function_list(void) {
|
||||
#ifndef _WIN32
|
||||
// __attribute__((destructor)) and destructors whose priorities are greater than
|
||||
// 100 run before this function and can thus be tracked. The priority is
|
||||
// compatible with GCC 7 onwards.
|
||||
__attribute__((destructor(100)))
|
||||
#endif
|
||||
static void llvm_writeout_and_clear(void) {
|
||||
llvm_writeout_files();
|
||||
fn_list_remove(&writeout_fn_list);
|
||||
}
|
||||
|
||||
@@ -710,8 +716,9 @@ void llvm_gcov_init(fn_ptr wfn, fn_ptr ffn, fn_ptr rfn) {
|
||||
/* Make sure we write out the data and delete the data structures. */
|
||||
atexit(llvm_delete_reset_function_list);
|
||||
atexit(llvm_delete_flush_function_list);
|
||||
atexit(llvm_delete_writeout_function_list);
|
||||
atexit(llvm_writeout_files);
|
||||
#ifdef _WIN32
|
||||
atexit(llvm_writeout_and_clear);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
33
compiler-rt/test/profile/Posix/gcov-destructor.c
Normal file
33
compiler-rt/test/profile/Posix/gcov-destructor.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/// Test that destructors and destructors whose priorities are greater than 100 are tracked.
|
||||
// RUN: mkdir -p %t.dir && cd %t.dir
|
||||
// RUN: %clang --coverage %s -o %t
|
||||
// RUN: rm -f gcov-destructor.gcda && %run %t
|
||||
// RUN: llvm-cov gcov -t gcov-destructor.gcda | FileCheck %s
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
void before_exec() {} // CHECK: 1: [[#@LINE]]:void before_exec
|
||||
void after_exec() {} // CHECK-NEXT: 1: [[#@LINE]]:void after_exec
|
||||
|
||||
__attribute__((constructor)) // CHECK: -: [[#@LINE]]:__attribute__
|
||||
void constructor() {} // CHECK-NEXT: 1: [[#@LINE]]:
|
||||
|
||||
/// Runs before __llvm_gcov_writeout.
|
||||
__attribute__((destructor)) // CHECK: -: [[#@LINE]]:__attribute__
|
||||
void destructor() {} // CHECK-NEXT: 1: [[#@LINE]]:
|
||||
|
||||
__attribute__((destructor(101))) // CHECK: -: [[#@LINE]]:__attribute__
|
||||
void destructor_101() {} // CHECK-NEXT: 1: [[#@LINE]]:
|
||||
|
||||
/// Runs after __llvm_gcov_writeout.
|
||||
__attribute__((destructor(99))) // CHECK: -: [[#@LINE]]:__attribute__
|
||||
void destructor_99() {} // CHECK-NEXT: #####: [[#@LINE]]:
|
||||
|
||||
int main() {
|
||||
before_exec();
|
||||
// Implicit writeout.
|
||||
execl("/not_exist", "not_exist", (char *)0);
|
||||
// Still tracked.
|
||||
after_exec();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user