-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
010943f
commit f583541
Showing
1 changed file
with
67 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,68 @@ | ||
# libgcov-embedded | ||
Port of libgcov portions to enable a way to generate GCDA files for embedded systems | ||
Working port of `gcov_exit` to use in embedded systems for capturing code coverage. | ||
## Compatibility | ||
- [gnu arm toolchain v5-2016-q3-update](https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q3-update) - **NOTE**: things should work in all versions where the gcov data structures are compatible with those in this version. This means both older and newer versions. | ||
|
||
## How to Generate .gcda Files | ||
### Working Sample Project | ||
It's very easy to get started if you follow [this sample](https://github.com/reeteshranjan/libgcov-embedded-example). | ||
|
||
It is a Blinky project for stm32f4-discovery board made using [gnu arm eclipse](http://gnuarmeclipse.github.io/) with [eclipse cdt neon.1](http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/neon1a). **NOTE**: if you don't have an stm32f4-discovery board, you can use QEMU emulator for this board with gnu arm eclipse. | ||
|
||
Also, this repository includes sample coverage HTML reports generated using the `.gcda` files generated while running the sample project. | ||
### From Scratch | ||
#### Include this software | ||
- Copy the `port` directory or all its subdirectories to your project | ||
- Ensure that these paths are included for finding headers - `port/gcc`, `port/libgcc`, `port/src` | ||
- Ensure that all .c files in `port/gcc`, `port/libgcc` and `port/src` are included in your build | ||
|
||
#### Get the compilation working | ||
- Add this preprocessor directive to your makefiles - `ENABLE_LIBGCOV_PORT=1` | ||
- Add `--coverage` compiler option to your c and/or c++ compiler flags | ||
- Add `--coverage` to your linker flags | ||
- Build with your gnu arm gcc compiler and linker and verify that `.gcno` files are created for each source file in your project. **NOTE**: it would be much smoother if you create a separate directory to store your object and coverage files like done by Eclipse projects. | ||
|
||
#### Hook it in | ||
In your main.c or main.cpp add the following. | ||
``` | ||
#ifdef ENABLE_LIBGCOV_PORT | ||
#include "libgcov-embedded.h" | ||
#endif | ||
``` | ||
In the `main` function, make this as the beginning: | ||
``` | ||
#ifdef ENABLE_LIBGCOV_PORT | ||
static_init(); | ||
#endif | ||
``` | ||
|
||
If you have your own version of `_exit`, comment it out. | ||
|
||
#### Manual .gcda files creation | ||
- Set up a breakpoint at `gcov-io.c:250`. The line has this content `free(gcov_var.gcda_buf);` | ||
- Set a watch expression for this variable `__gcov_var__ported` | ||
- Start your debugging session and do the following each time the above breakpoint hits. It would hit once per source file in your project: | ||
- `__gcov_var__ported.filename` contains the full path of the `.gcda` file to create | ||
- `__gcov_var__ported.gcda_buf` contains the start address of coverage information for corresponding source file | ||
- `__gcov_var__ported.gcda_buf_pos` contains the end address of coverage information for corresponding source file | ||
- On gdb prompt, run `dump binary memory <value of __gcov_var__ported.filename> <hex value of __gcov_var__ported.gcda_buf> <hex value of __gcov_var__ported.gcda_buf_pos>` e.g. `dump binary memory my-proj/Debug/src/main.gcda 0x20006450 0x20006880`. This would create the `.gcda` file. | ||
|
||
## Generate HTML visualization | ||
### For Mac/Linux | ||
- On Mac, install `lcov` using mac ports. On Linux, it should be there or find your Linux flavor specific package. | ||
- Go to your build directory where your object files, `.gcno` files and `.gcda` files are there. | ||
- Run `lcov --capture --output-file main.info --directory . --gcov-tool /usr/local/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-gcov`. **NOTE**: replace the gcov path with your actual system path in case it is installed in a different location. | ||
- Run `genhtml -o html main.info`. It creates HTML visualization inside `html` directory. | ||
|
||
The `index.html` file can be opened in a browser to see graphical visualization per source file. | ||
## Limitations & Caveats | ||
- If the in-memory coverage information is greater than 8K, it would not be generated. **Fix**: Increase the value of the macro `GCOV_GCDA_BUF_SZ` in `port/gcc/gcov-io.c` to suit your application's needs. For the testing so far, this limit has been more than sufficient. | ||
- The port does not support merging of existing `.gcda` data with a new run's collected coverage information. This is difficult for obvious reason that an existing `.gcda` file on the host system cannot be read by the embedded system. **Fix**: None. So only if your application can benefit with a single run's coverage information, this tool is useful. | ||
|
||
## Why this repository? | ||
### Tutorials don't work | ||
Getting code coverage done for stm32f4-discovery using gnu arm toolchain version 5-2016-q3-update (used during October/November 2016) and existing guides like [this](https://mcuoneclipse.com/2014/12/26/code-coverage-for-embedded-target-with-eclipse-gcc-and-gcov/) do not work. | ||
### What's the issue? | ||
When one calls `__gcov_flush` to run the coverage info generation process, it just hangs forever and we can't get to generating `.gcda` files. | ||
### How is the issue taken care of? | ||
This port was created and used in a sample project to see what caused the above hang. It was traced to an undocumented bug (causing 3 such points where code would hang indefinitely) in gcc's gcov portions. The only way to get past this issue was to have our own complete source of `__gcov_flush` (or `gcov_exit`, which I went with) with these bugs fixed, which is what exists in this repository. |