[llvm-bugs] [Bug 38104] New: LLD's termination code does not allow code coverage analysis to work properly.

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Jul 9 07:30:21 PDT 2018


            Bug ID: 38104
           Summary: LLD's termination code does not allow code coverage
                    analysis to work properly.
           Product: lld
           Version: unspecified
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: ELF
          Assignee: unassignedbugs at nondot.org
          Reporter: grimar at accesssoftek.com
                CC: llvm-bugs at lists.llvm.org

Created attachment 20542
  --> https://bugs.llvm.org/attachment.cgi?id=20542&action=edit

I am not sure we can call it a bug of LLD, though it seems at least something
worth to document. (And maybe to improve somehow).

Currently, LLD uses _exit for error() and fatal() calls:

That does not allow to test code coverage properly sometimes.

Imagine the following code:

#include <stdlib.h>
#include <unistd.h>

__attribute__((noreturn)) void fatal() {

int main() {
  return 0;

If we compile and run it as
clang++ test.c --coverage -fPIC -std=c++11 -fprofile-arcs -ftest-coverage -o
We'll see the .gcno and .gcda created and will be able to generate the coverage
~/LLVM/build/bin/llvm-cov gcov test.gcda

But if we change "exit" to "_exit", then no .gcda file is created after running
the app.
That happens because _exit does not do enough cleaning, buffers flushing etc.

The same happens with LLD. If I change "_exit" to "exit" at a mentioned line,
it allows obtaining the correct reports about code coverage.

There is a problem about race conditions though. When using exit() LLD hangs
running the tests when multithreading is enabled. I was able to catch
and debug it (reproduces on invalid-cie-length.s test case for me).
Screenshot attached shows how 2 threads are stuck in destructors and waiting
for something.

The issue happens in the following code:
At line 103 we call the Task() functor. Here Task() calls fatal() inside, which
is "noreturn" and
calls _exit originally. After changing _exit() to exit(), the code starts to
execute static destructors
and we stuck because of that in the ~ThreadPoolExecutor which waits for ~Latch
because line 105 ("Done.dec();") is never executed.

The case above happens because we call fatal() in the parrallel_foreach thread.
That particular fatal() is coming from EhFrame parser:
It should be possible to workaround that race condition if we will use error()
instead of fatal(), which usually does not exit immediately.
It might be enough for building coverage report purposes.

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20180709/69bbe90c/attachment-0001.html>

More information about the llvm-bugs mailing list