Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/zephyr/debug/gcov.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#ifdef CONFIG_COVERAGE_GCOV
void gcov_coverage_dump(void);
void gcov_coverage_semihost(void);
void gcov_static_init(void);
#else
static inline void gcov_coverage_dump(void) { }
Expand Down
2 changes: 1 addition & 1 deletion kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ if DYNAMIC_THREAD

config DYNAMIC_THREAD_STACK_SIZE
int "Size of each pre-allocated thread stack"
default 4096 if X86
default 4096 if X86 || COVERAGE_GCOV
default 1024 if !X86 && !64BIT
default 2048 if !X86 && 64BIT
help
Expand Down
2 changes: 2 additions & 0 deletions kernel/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3)
#ifdef CONFIG_COVERAGE_DUMP
/* Dump coverage data once the main() has exited. */
gcov_coverage_dump();
#elif defined(CONFIG_COVERAGE_SEMIHOST)
gcov_coverage_semihost();
#endif /* CONFIG_COVERAGE_DUMP */
} /* LCOV_EXCL_LINE ... because we just dumped final coverage data */

Expand Down
2 changes: 2 additions & 0 deletions lib/os/reboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ FUNC_NORETURN void sys_reboot(int type)
{
#ifdef CONFIG_COVERAGE_DUMP
gcov_coverage_dump();
#elif defined(CONFIG_COVERAGE_SEMIHOST)
gcov_coverage_semihost();
#endif /* CONFIG_COVERAGE_DUMP */

(void)irq_lock();
Expand Down
94 changes: 3 additions & 91 deletions subsys/testsuite/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -24,97 +24,6 @@ config TEST_EXTRA_STACK_SIZE
Additional stack for tests on some platform where default is not
enough.

config HAS_COVERAGE_SUPPORT
bool
help
The code coverage report generation is only available on boards
with enough spare RAM to buffer the coverage data, or on boards
based on the POSIX ARCH.

config COVERAGE
bool "Create coverage data"
depends on HAS_COVERAGE_SUPPORT
help
This option will build your application with the -coverage option
which will generate data that can be used to create coverage reports.
For more information see
https://docs.zephyrproject.org/latest/guides/coverage.html

choice
prompt "Coverage mode"
default COVERAGE_NATIVE_GCOV if NATIVE_BUILD
default COVERAGE_GCOV if !NATIVE_BUILD
depends on COVERAGE

config COVERAGE_NATIVE_GCOV
bool "Host compiler gcov based code coverage"
depends on NATIVE_BUILD
help
Build natively with the compiler standard `--coverage` options,
that is with gcov/GCC-compatible coverage

config COVERAGE_NATIVE_SOURCE
bool "Host compiler source based code coverage"
depends on NATIVE_BUILD
depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "llvm"
help
Build natively with the compiler source based coverage options.
Today this is only supported with LLVM

config COVERAGE_GCOV
bool "Create Coverage data from hardware platform"
depends on !NATIVE_BUILD
help
This option will select the custom gcov library. The reports will
be available over serial. This serial dump can be passed to
gen_gcov_files.py which creates the required .gcda files. These
can be read by gcov utility. For more details see gcovr.com .

endchoice

if COVERAGE_GCOV

config COVERAGE_GCOV_HEAP_SIZE
int "Size of heap allocated for gcov coverage data dump"
depends on COVERAGE_GCOV
default 32768 if X86 || SOC_SERIES_MPS2
default 16384
help
This option configures the heap size allocated for gcov coverage
data to be dumped over serial. If the value is 0, no buffer will be used,
data will be dumped directly over serial.

choice COVERAGE_DUMP_METHOD
prompt "Method to dump coverage data"
default COVERAGE_DUMP

config COVERAGE_DUMP
bool "Dump coverage data to console on exit"
help
Dump collected coverage information to console on exit.

endchoice

config COVERAGE_DUMP_PATH_EXCLUDE
string "Exclude files matching this pattern from the coverage data"
default ""
help
Filenames are matched against the pattern using the POSIX fnmatch
function. Filenames are based on their path in the build folder, not the
original source tree. The empty string "" disables the pattern
matching.

endif # COVERAGE_GCOV

config FORCE_COVERAGE
bool "Force coverage"
select HAS_COVERAGE_SUPPORT
help
Regardless of platform support, it will enable coverage data production.
If the platform does not support coverage by default, setting this config
does not guarantee that coverage data will be gathered.
Application may not fit memory or crash at runtime.

config TEST_USERSPACE
bool "Indicate that this test exercises user mode"
help
Expand Down Expand Up @@ -217,3 +126,6 @@ config TEST_BUSY_SIM
with random intervals and random busy looping in the interrupt.

endmenu


rsource "Kconfig.coverage"
99 changes: 99 additions & 0 deletions subsys/testsuite/Kconfig.coverage
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright The Zephyr Project Contributors
#
menu "Coverage"

config HAS_COVERAGE_SUPPORT
bool
help
The code coverage report generation is only available on boards
with enough spare RAM to buffer the coverage data, or on boards
based on the POSIX ARCH.

config COVERAGE
bool "Create coverage data"
depends on HAS_COVERAGE_SUPPORT
help
This option will build your application with the -coverage option
which will generate data that can be used to create coverage reports.
For more information see
https://docs.zephyrproject.org/latest/guides/coverage.html

choice
prompt "Coverage mode"
default COVERAGE_NATIVE_GCOV if NATIVE_BUILD
default COVERAGE_GCOV if !NATIVE_BUILD
depends on COVERAGE

config COVERAGE_NATIVE_GCOV
bool "Host compiler gcov based code coverage"
depends on NATIVE_BUILD
help
Build natively with the compiler standard `--coverage` options,
that is with gcov/GCC-compatible coverage

config COVERAGE_NATIVE_SOURCE
bool "Host compiler source based code coverage"
depends on NATIVE_BUILD
depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "llvm"
help
Build natively with the compiler source based coverage options.
Today this is only supported with LLVM

config COVERAGE_GCOV
bool "Create Coverage data from hardware platform"
depends on !NATIVE_BUILD
help
This option will select the custom gcov library. The reports will
be available over serial. This serial dump can be passed to
gen_gcov_files.py which creates the required .gcda files. These
can be read by gcov utility. For more details see gcovr.com .

endchoice

config COVERAGE_GCOV_HEAP_SIZE
int "Size of heap allocated for gcov coverage data dump"
depends on COVERAGE_GCOV
default 32768 if X86 || SOC_SERIES_MPS2
default 16384
help
This option configures the heap size allocated for gcov coverage
data to be dumped over serial. If the value is 0, no buffer will be used,
data will be dumped directly over serial.

choice COVERAGE_DUMP_METHOD
prompt "Method to dump coverage data"
default COVERAGE_DUMP

config COVERAGE_DUMP
bool "Dump coverage data to console on exit"
help
Dump collected coverage information to console on exit.

config COVERAGE_SEMIHOST
bool "Use semihosting to write coverage data"
depends on SEMIHOST
help
Use semihosting to write coverage data to a file on the host.

endchoice

config FORCE_COVERAGE
bool "Force coverage"
select HAS_COVERAGE_SUPPORT
help
Regardless of platform support, it will enable coverage data production.
If the platform does not support coverage by default, setting this config
does not guarantee that coverage data will be gathered.
Application may not fit memory or crash at runtime.

config COVERAGE_DUMP_PATH_EXCLUDE
string "Exclude files matching this pattern from the coverage data"
default ""
help
Filenames are matched against the pattern using the POSIX fnmatch
function. Filenames are based on their path in the build folder, not the
original source tree. The empty string "" disables the pattern
matching.

endmenu
87 changes: 81 additions & 6 deletions subsys/testsuite/coverage/coverage.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <string.h>
#include <fnmatch.h>
#include "coverage.h"
#include <zephyr/arch/common/semihost.h>
#include <sys/types.h>

K_HEAP_DEFINE(gcov_heap, CONFIG_COVERAGE_GCOV_HEAP_SIZE);

Expand Down Expand Up @@ -280,6 +282,7 @@ void gcov_reset_all_counts(void)
#endif
}

#ifdef CONFIG_COVERAGE_DUMP
void dump_on_console_start(const char *filename)
{
printk("\n%c", FILE_START_INDICATOR);
Expand All @@ -298,6 +301,7 @@ void dump_on_console_data(char *ptr, size_t len)
}
}


/**
* Retrieves gcov coverage data and sends it over the given interface.
*/
Expand All @@ -309,11 +313,11 @@ void gcov_coverage_dump(void)
struct gcov_info *gcov_list_first = gcov_info_head;
struct gcov_info *gcov_list = gcov_info_head;

if (!k_is_in_isr()) {
#ifdef CONFIG_MULTITHREADING
if (!k_is_in_isr()) {
k_sched_lock();
#endif
}
#endif
printk("\nGCOV_COVERAGE_DUMP_START");
while (gcov_list) {
if ((strlen(CONFIG_COVERAGE_DUMP_PATH_EXCLUDE) > 0) &&
Expand All @@ -327,13 +331,15 @@ void gcov_coverage_dump(void)

buffer = k_heap_alloc(&gcov_heap, size, K_NO_WAIT);
if (CONFIG_COVERAGE_GCOV_HEAP_SIZE > 0 && !buffer) {
printk("No Mem available to continue dump\n");
printk("No memory available to continue dump\n");
k_heap_free(&gcov_heap, buffer);
goto coverage_dump_end;
}

written_size = gcov_populate_buffer(buffer, gcov_list);
if (written_size != size) {
printk("Write Error on buff\n");
printk("Write Error on buffer\n");
k_heap_free(&gcov_heap, buffer);
goto coverage_dump_end;
}

Expand All @@ -348,14 +354,83 @@ void gcov_coverage_dump(void)
}
coverage_dump_end:
printk("\nGCOV_COVERAGE_DUMP_END\n");
if (!k_is_in_isr()) {
#ifdef CONFIG_MULTITHREADING
if (!k_is_in_isr()) {
k_sched_unlock();
#endif
}
#endif
return;
}

#elif CONFIG_COVERAGE_SEMIHOST
/**
* Retrieves gcov coverage data and sends it over the given interface.
*/
void gcov_coverage_semihost(void)
{
uint8_t *buffer;
size_t size;
size_t written_size;
struct gcov_info *gcov_list_first = gcov_info_head;
struct gcov_info *gcov_list = gcov_info_head;

#ifdef CONFIG_MULTITHREADING
if (!k_is_in_isr()) {
k_sched_lock();
}
#endif
while (gcov_list) {

int fd = semihost_open(gcov_list->filename, SEMIHOST_OPEN_WB);

if (fd < 0) {
printk("Failed to open file: %s\n", gcov_list->filename);
goto coverage_dump_end;
}

size = gcov_calculate_buff_size(gcov_list);

buffer = k_heap_alloc(&gcov_heap, size, K_NO_WAIT);
if (CONFIG_COVERAGE_GCOV_HEAP_SIZE > 0 && !buffer) {
printk("No memory available to continue dump\n");
semihost_close(fd);
k_heap_free(&gcov_heap, buffer);
goto coverage_dump_end;
}

written_size = gcov_populate_buffer(buffer, gcov_list);
if (written_size != size) {
printk("Write Error on buffer\n");
semihost_close(fd);
k_heap_free(&gcov_heap, buffer);
goto coverage_dump_end;
}

int ret = semihost_write(fd, (const void *)buffer, size);

if (ret < 0) {
printk("Failed to write data to file: %s\n", gcov_list->filename);
semihost_close(fd);
k_heap_free(&gcov_heap, buffer);
goto coverage_dump_end;
}

k_heap_free(&gcov_heap, buffer);
gcov_list = gcov_list->next;
if (gcov_list_first == gcov_list) {
semihost_close(fd);
goto coverage_dump_end;
}
}
coverage_dump_end:
#ifdef CONFIG_MULTITHREADING
if (!k_is_in_isr()) {
k_sched_unlock();
}
#endif
}
#endif

struct gcov_info *gcov_get_list_head(void)
{
/* Locking someway before getting this is recommended. */
Expand Down
2 changes: 1 addition & 1 deletion tests/arch/arm/arm_interrupt/src/arm_interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ static volatile int expected_reason = -1;
static volatile int run_esf_validation;
static volatile int esf_validation_rv;
static volatile uint32_t expected_msp;
static K_THREAD_STACK_DEFINE(esf_collection_stack, 2048);
static K_THREAD_STACK_DEFINE(esf_collection_stack, 2048 + CONFIG_TEST_EXTRA_STACK_SIZE);
static struct k_thread esf_collection_thread;
#define MAIN_PRIORITY 7
#define PRIORITY 5
Expand Down
Loading
Loading