Skip to content

Commit

Permalink
Introduce lib-embedded-gcov
Browse files Browse the repository at this point in the history
Port of embedded-gcov[1] for Unikraft.

[1] https://github.com/nasa-jpl/embedded-gcov

Signed-off-by: Michalis Pappas <[email protected]>
  • Loading branch information
Michalis Pappas authored and michpappas committed Mar 30, 2023
1 parent c3154a3 commit e17069f
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 1 deletion.
38 changes: 38 additions & 0 deletions Config.uk
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
menuconfig LIBEMBEDDEDGCOV
bool "embedded-gcov"
default n

if LIBEMBEDDEDGCOV
config LIBEMBEDDEDGCOV_PROVIDE_CALL_CONSTRUCTORS
bool "Provide call constructors"
help
In most systems __gcov_init() is called on startup. If you are
running on a non-standard startup environment you can enable this
option, and gcov-embedded will provide __gcov_call_constructors()
that you can run manually. You will also need to define __ctor_list
and __ctor_end.
default n

config LIBEMBEDDEDGCOV_PRINT_STATUS
bool "Print status to console"
help
Print status and error messages to the serial console. If the
coverage data output is set to console, status is always printed
to the console.
default n

config LIBEMBEDDEDGCOV_USE_MALLOC
bool "Use malloc"
depends on LIBUKALLOC
help
Use malloc to get space for coverage data"
default y

choice LIBEMBEDDEDGCOV_OUTPUT
prompt "Coverage data output"
default LIBEMBEDDEDGCOV_OUTPUT_SERIAL_HEXDUMP
config LIBEMBEDDEDGCOV_OUTPUT_SERIAL_HEXDUMP
bool "Console"
endchoice

endif
78 changes: 78 additions & 0 deletions Makefile.uk
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# SPDX-License-Identifier: BSD-3-Clause
#
# embedded-gcov Makefile.uk
#
# Authors: Michalis Pappas <[email protected]>
#
# Copyright (c) 2023, Unikraft GmbH
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
################################################################################
# App registration
################################################################################
$(eval $(call addlib,libembeddedgcov,$(CONFIG_LIBEMBEDDEDGCOV)))

################################################################################
# Sources
################################################################################
LIBEMBEDDEDGCOV_BRANCH = main
LIBEMBEDDEDGCOV_URL = https://github.com/nasa-jpl/embedded-gcov.git
LIBEMBEDDEDGCOV_PATCHDIR = $(LIBEMBEDDEDGCOV_BASE)/patches
$(eval $(call clone,libembeddedgcov,$(LIBEMBEDDEDGCOV_URL),$(LIBEMBEDDEDGCOV_BRANCH)))
$(eval $(call patch,libembeddedgcov,$(LIBEMBEDDEDGCOV_PATCHDIR),$(LIBEMBEDDEDGCOV_BASENAME)))

################################################################################
# Library sources
################################################################################
LIBEMBEDDEDGCOV_SRCS-y += $(LIBEMBEDDEDGCOV_ORIGIN)/code/gcov_public.c
LIBEMBEDDEDGCOV_SRCS-y += $(LIBEMBEDDEDGCOV_ORIGIN)/code/gcov_gcc.c
LIBEMBEDDEDGCOV_SRCS-y += $(LIBEMBEDDEDGCOV_ORIGIN)/code/gcov_printf.c

################################################################################
# Library includes
################################################################################
CINCLUDES-$(CONFIG_LIBEMBEDDEDGCOV) += -I$(LIBEMBEDDEDGCOV_ORIGIN)/code
CXXINCLUDES-$(CONFIG_LIBEMBEDDEDGCOV) += -I$(LIBEMBEDDEDGCOV_ORIGIN)/code

################################################################################
# Library flags
################################################################################

CFLAGS-$(CONFIG_LIBEMBEDDEDGCOV) += -ftest-coverage -fprofile-arcs

ifneq ($(CONFIG_LIBEMBEDDEDGCOV_OUTPUT_BINARY_FILE),)
$(error Binary file output not implemented)
endif
ifneq ($(CONFIG_LIBEMBEDDEDGCOV_OUTPUT_BINARY_MEMORY),)
$(error Memory output not implemented)
endif

LIBEMBEDDEDGCOV_CFLAGS-y += -Dgcov_printf=printf
LIBEMBEDDEDGCOV_CFLAGS-$(CONFIG_LIBEMBEDDEDGCOV_OUTPUT_SERIAL_HEXDUMP) += -DGCOV_OPT_OUTPUT_SERIAL_HEXDUMP
LIBEMBEDDEDGCOV_CFLAGS-$(CONFIG_LIBEMBEDDEDGCOV_PRINT_STATUS) += -DGCOV_OPT_PRINT_STATUS
LIBEMBEDDEDGCOV_CFLAGS-$(CONFIG_LIBEMBEDDEDGCOV_PROVIDE_CALL_CONSTRUCTORS) += -DGCOV_OPT_PROVIDE_CALL_CONSTRUCTORS
LIBEMBEDDEDGCOV_CFLAGS-$(CONFIG_LIBEMBEDDEDGCOV_USE_MALLOC) += -DGCOV_OPT_USE_MALLOC
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,48 @@
# lib-embedded-gcov
Coverage suppport

Unikraft port of [embedded-gcov](https://github.com/nasa-jpl/embedded-gcov).

## Initialization and Termination

Initialization of gcov is done transparently to the application. `lib-embedded-gcov` adds the required GCC options for coverage, and at runtime `__gcov_init()` is automatically call when Unikraft boots via constructors.

To dump the coverage data you need to update the application to manually call `__gcov_exit()`.

## Collecting Coverage Results

embedded-gcov provides three types of output:
- Binary file
- Memory
- Serial console

At this moment `lib-gcov-embedded` supports only serial console output.

### Serial Console Output

To obtain coverage results via the console you need to dump the console output into a file. With QEMU this is possible by configuring the serial device to log all output into a file:
```
-chardev stdio,id=char0,logfile=serial.log,signal=off -serial chardev:char0
```

The console output then needs to be processed into an lcov report. `lib-embedded-gcov` provides the `gcov_process.sh` script for that, which is essentially a wrapper around the tools provided by `embedded-gcov`.

Before executing the script make sure you have the required dependencies installed, that is:
- dox2unix
- lcov

With dependencies installed, execute the script as:
```
lib-embedded-gcov/scripts/gcov_process.sh <build_directory> <console_log>
```

The script will generate an lcov report and provide a link as shown below.
```
...
Writing directory view page.
Overall coverage rate:
lines......: 29.8% (2345 of 7858 lines)
functions..: 36.3% (228 of 628 functions)
lcov report in file:///home/mpp/devel/unikraft_oss/uk_embedded-gcov/app-helloworld/build/libembeddedgcov/origin/results/html/index.html
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
From 51043fb1ad5b99a66749bce2661b388e26b6f90f Mon Sep 17 00:00:00 2001
From: michpappas <[email protected]>
Date: Sat, 21 Jan 2023 18:11:26 +0100
Subject: [PATCH] Disable all user options to allow controlling via KConfig

---
code/gcov_public.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/code/gcov_public.h b/code/gcov_public.h
index 0982c2c..9a32a8c 100644
--- a/code/gcov_public.h
+++ b/code/gcov_public.h
@@ -51,7 +51,7 @@
* If defined, you must also provide defs below
* for GCOV_PRINT_STR and GCOV_PRINT_NUM.
*/
-#define GCOV_OPT_PRINT_STATUS
+//#define GCOV_OPT_PRINT_STATUS

/* Reset watchdog timeout during gcov tree scanning.
* Might be needed if you enable serial output on a slow port,
@@ -95,7 +95,7 @@ extern void *__ctor_end;
* You might NOT want this if you are extremely memory constrained
* (such as in PROM) and do not need this function to take up some bytes.
*/
-#define GCOV_OPT_PROVIDE_CLEAR_COUNTERS
+//#define GCOV_OPT_PROVIDE_CLEAR_COUNTERS

/* Provide small imitation printf function.
* This is only needed if you want serial port outputs and
@@ -104,7 +104,7 @@ extern void *__ctor_end;
* write_bytes() that does the actual serial output in your system.
* See gcov_printf.c
*/
-#define GCOV_OPT_PROVIDE_PRINTF_IMITATION
+//#define GCOV_OPT_PROVIDE_PRINTF_IMITATION

/* select data output method(s) ------------------------------------ */

@@ -122,7 +122,7 @@ extern void *__ctor_end;

/* Modify this output filename if desired */
/* Not used if you do not define GCOV_OPT_OUTPUT_BINARY_FILE */
-#define GCOV_OUTPUT_BINARY_FILENAME "gcov_output.bin"
+//#define GCOV_OUTPUT_BINARY_FILENAME "gcov_output.bin"

/* Modify file headers, data type and functions, if needed */
/* Not used if you do not define GCOV_OPT_OUTPUT_BINARY_FILE */
@@ -164,7 +164,7 @@ typedef FILE * GCOV_FILE_TYPE;
* for GCOV_PRINT_STR and GCOV_PRINT_NUM.
* Can be combined with other GCOV_OPT_OUTPUT_* options.
*/
-#define GCOV_OPT_OUTPUT_SERIAL_HEXDUMP
+//#define GCOV_OPT_OUTPUT_SERIAL_HEXDUMP

/* Function to print a string without newline.
* Not used if you don't define either GCOV_OPT_PRINT_STATUS
--
2.25.1

39 changes: 39 additions & 0 deletions scripts/gcov_process.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash
set -e

if [[ $# -ne 2 ]]; then
echo "Usage: $0 <build_dir> <console_dump>"
exit
fi

if [ -n "${CROSS_COMPILE}" ]; then
GCOV=${CROSS_COMPILE}/gcov
else
GCOV=$(which gcov)
fi

if [ -z "$GCOV" ]; then
echo "$0: Could not find gcov"
exit
fi

BUILD_DIR=$(realpath $1)
CONSOLE_DUMP=$(realpath $2)
GCOV_DIR=${BUILD_DIR}/libembeddedgcov/origin/

cd ${GCOV_DIR}/scripts

rm -rf ../objs/*
rm -rf ../results/*

find $BUILD_DIR -type d -name objs -prune -o -name \*.gcno -exec cp {} ../objs/ \;

lcov --gcov-tool ${CROSS_COMPILE}gcov --capture --initial \
--directory ../objs/ -o ../results/baseline.info

./gcov_convert.sh $CONSOLE_DUMP
./lcov_newcoverage.sh
./lcov_combine_new_base.sh
./genhtml_report.sh

echo -e "\nlcov report in file://$(realpath ../results/html)/index.html\n"

0 comments on commit e17069f

Please sign in to comment.