This will make the behavior of __gcov_flush match the GCC behavior.
I would like to rename gcov_flush to llvm_gcov_flush (in case of programs linking to libraries built with different compilers), but I guess we can't for compatibility reasons.
Differential D48538
Make __gcov_flush flush counters for all shared libraries marco-c on Jun 25 2018, 3:26 AM. Authored by
Details This will make the behavior of __gcov_flush match the GCC behavior. I would like to rename gcov_flush to llvm_gcov_flush (in case of programs linking to libraries built with different compilers), but I guess we can't for compatibility reasons.
Diff Detail Event TimelineComment Actions This change will cause each dynamic library to dump modules (gcda files) from other dynamic objects as well -- leading to wrong profile count merged.
Comment Actions I'm using two lists, one for the current dynamic object, one shared between all. We could make the shared one a list of lists, but I feel it would make the code more complex, with no large benefit (if you disagree, I can update the patch). A question, why do we need both a writeout function and a flush function? Wouldn't it be OK to just always use flush? When we call writeout, we are atexit, so it doesn't really matter if we clear or not the counters after the writeout, or does it?
Comment Actions I've merged all the shared / __gcov_flush tests into a single file and made the test a little more involved by adding a "bar" function in the main file.
Comment Actions I've taken another approach which looks simpler to me. Instead of having two lists, I only have a shared list and I use a static variable's address as an identifier for a dynamic object. I've also added another test (which would have failed with the previous iteration of the patch) which dlopens three libraries. I will file follow-up bugs for things that don't look right in the llvm-cov output which are not regressions from this patch:
Regarding removing writeout and only always using __gcov_flush, do you see any disadvantage if we do that? Regarding llvm_gcov_flush that was recently added, should I remove it since we can now unhide __gcov_flush? Comment Actions
Sorry, what I meant is that we could remove llvm_gcov_writeout and only keep llvm_gcov_flush (they are defined in lib/Transforms/Instrumentation/GCOVProfiling.cpp and passed to llvm_gcov_init). We currently have writeout functions and flush functions, where the difference is just that the flush function is also resetting the counters to 0.
Should we make llvm_gcov_flush hidden and gcov_flush unhidden then? gcov_flush unhidden would be for compatibility with GCC. Comment Actions If you are going to hide llvm_gcov_flush(), you might as well delete it and break our implementation that way. We are only going to try to use llvm_gcov_flush() temporarily to restore some missing functionality. When __gcov_flush() becomes available again, we will switch back to it for simplicity. Comment Actions LGTM ( watch out any potential breakages)
Comment Actions
Yeah, definitely a separate thing, I'll do it and submit it in another revision.
OK, I'll remove it then. Before landing, I will "stress test" this patch on our CI to make sure everything is still working as before. Comment Actions
I've filed https://bugs.llvm.org/show_bug.cgi?id=38067. It's unrelated to the presence of shared libraries.
I've filed https://bugs.llvm.org/show_bug.cgi?id=38065, this one too is unrelated to the presence of shared libraries. I've also filed https://bugs.llvm.org/show_bug.cgi?id=38066, about wrong line hit counts when exceptions are enabled. I've tested the patch on our CI and it was working correctly. I'll land it shortly. Comment Actions It looks like this causes build bot failures on s390x-linux. Three of the new tests fail: /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/projects/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c.gcov:11:15: error: expected string not found in input // CHECK-NEXT: 1: 6: dlerror(); ^ instrprof-dlopen-dlclose-main.c.gcov:11:1: note: scanning from here 4294967296: 6: dlerror(); This looks suspiciously like an endian problem somewhere, we get 4294967296 == 0x1_0000_0000 instead of 0x0_0000_0001 ... |
this loop is still wrong.
Also it is possible to simply the code by removing the if-then-else: