chh updated this revision to Diff 152957.
chh edited the summary of this revision.

https://reviews.llvm.org/D45454

Files:
  lib/profile/GCDAProfiling.c
  test/profile/Inputs/instrprof-dlopen-dlclose-main.c


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;
Index: lib/profile/GCDAProfiling.c
===================================================================
--- lib/profile/GCDAProfiling.c
+++ lib/profile/GCDAProfiling.c
@@ -527,16 +527,28 @@
   }
 }
 
+// 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) {
     curr->fn();
     curr = curr->next;
   }
 }
 
+// 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;
Index: lib/profile/GCDAProfiling.c
===================================================================
--- lib/profile/GCDAProfiling.c
+++ lib/profile/GCDAProfiling.c
@@ -527,16 +527,28 @@
   }
 }
 
+// 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) {
     curr->fn();
     curr = curr->next;
   }
 }
 
+// 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) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to