Index: lib/profile/GCDAProfiling.c =================================================================== --- lib/profile/GCDAProfiling.c +++ lib/profile/GCDAProfiling.c @@ -527,8 +527,10 @@ } } +// llvm_gcov_flush is like __gcov_flush, but invisible outside a .so file. +// It should be used inside a .so file to flush its own profile data. COMPILER_RT_VISIBILITY -void __gcov_flush() { +void llvm_gcov_flush() { struct flush_fn_node *curr = flush_fn_head; while (curr) { @@ -537,6 +539,16 @@ } } +// Keep __gcov_flush visible to be compatible with old gcov users +// who call dlsym to find and call __gcov_flush in .so files. +// In that use case, the expected bahavior is to flush profile data +// for each .so file. +// When called directly inside a .so file, the unified __gcov_flush +// would flush the main program profile data. +void __gcov_flush() { + llvm_gcov_flush(); +} + COMPILER_RT_VISIBILITY void llvm_delete_flush_function_list(void) { while (flush_fn_head) { Index: test/profile/Inputs/instrprof-dlopen-dlclose-main.c =================================================================== --- test/profile/Inputs/instrprof-dlopen-dlclose-main.c +++ test/profile/Inputs/instrprof-dlopen-dlclose-main.c @@ -16,6 +16,31 @@ return EXIT_FAILURE; } + void (*llvm_flush)() = (void (*)())dlsym(f1_handle, "llvm_gcov_flush"); + if (llvm_flush != NULL) { + fprintf(stderr, "llvm_gcov_flush should not be visible in func.shared'\n"); + return EXIT_FAILURE; + } + + void (*f1_flush)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); + if (f1_flush == NULL) { + fprintf(stderr, "unable to find __gcov_flush in func.shared'\n"); + return EXIT_FAILURE; + } + f1_flush(); + + void (*f2_flush)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); + if (f2_flush == NULL) { + fprintf(stderr, "unable to find __gcov_flush in func2.shared'\n"); + return EXIT_FAILURE; + } + f2_flush(); + + if (f1_flush == f2_flush) { + fprintf(stderr, "Same __gcov_flush found in func.shared and func2.shared\n"); + return EXIT_FAILURE; + } + if (dlclose(f2_handle) != 0) { fprintf(stderr, "unable to close 'func2.shared': %s\n", dlerror()); return EXIT_FAILURE;