Comment 0 for bug 1694644

Revision history for this message
Reetesh Ranjan (reeteshranjan) wrote :

Release version: 5-2016-q3-update
Using binary package
Host: Mac OSX, Windows

All other mandatory details are available in the description below:

I was trying to do code coverage for my embedded project using 5-2016-q3-update and GNU ARM Eclipse (http://gnuarmeclipse.github.io/). I broadly followed the concept of manually breaking into 'gcov_exit' and using 'gdb dump binary' to create the gcda files, as described in https://mcuoneclipse.com/2014/12/26/code-coverage-for-embedded-target-with-eclipse-gcc-and-gcov/. However; gcov_exit hanged infinitely. For a simple project of not more than 25 source files, it would take minutes and won't return. To debug this, I made a copy of respective gcc and libgcc code and tailored it as needed and plugged it into my project so that I could see what the hang is about. It turned out that the 1st instance of these loops "for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)" just won't finish. On debugging it appeared that the list was circular and not a null-terminated one. I cannot figure it out why that is as I studied gcc code, as __gcov_root.list construction through __gcov_init does not seem to create any circular lists. But it appeared to be so, because when I changed the loops to expect a circular list rather than a null-terminated singly linked list, things worked. Also, I manually debugged the functions called by gcov_exit to see that there are exactly as many gcov_info nodes in the __gcov_root.list as the number of source files covered, and the change to expect a circular list made sense. I had to end up changing 3 instances of such loops and then I was able to generated the gcda files.

The ported/tailored version of the minimum gcc/libgcc code has been made available at: https://github.com/reeteshranjan/libgcov-embedded

I saw that the toolchain is based on svn://gcc.gnu.org/svn/gcc/branches/ARM/; and I picked the code from gcc trunk. However; it seems at least from embedded-6-branch onwards that the gcov source is the same as I could see in gcc trunk that time.

I have also attached a patch I made using the embedded-6-branch which clearly shows the for loop changes made.

I also did a sample GNU ARM Eclipse project to use the above, which is available at:
https://github.com/reeteshranjan/libgcov-embedded-example

Steps to reproduce and analyze:
- Setup any embedded project using GNU ARM Eclipse. Follow the steps in https://mcuoneclipse.com/2014/12/26/code-coverage-for-embedded-target-with-eclipse-gcc-and-gcov/ to generate coverage data by breaking into gcov_exit or __gcov_flush (whichever is available). The hang in gcov_exit should be reproducible.
- Now create another project from scratch without using the stub code as described in https://mcuoneclipse.com/2014/12/26/code-coverage-for-embedded-target-with-eclipse-gcc-and-gcov/
- Plugin https://github.com/reeteshranjan/libgcov-embedded using the instructions in README.md provided in this repository into the new project.
- In the port/libgcc/libgcov-driver.c file in the above, search for the loops "for (gi_ptr = list; gi_ptr && !(gi_ptr == list && break_loop_counter); gi_ptr = gi_ptr->next, break_loop_counter++)". These are the changes to expect a circular list and not a null-terminated singly linked list. Change these lines to how they are in original gcc code which is "for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)"
- Follow the README instructions on how to break in gcov-io.c to use gdb instructions to manually create gcda files. You won't hit this breakpoint because of the hang in first of these for loops in 'compute_summary' function (now reproducible as we changed the code to use the original libgcc version)
- Now revert the for loop changes back
- Now the breakpoints should hit once for each source file