From f4dd720bdafbc17e8f118c04c535590c983367a4 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Thu, 21 Nov 2024 16:28:24 +0800 Subject: [PATCH] clang/gcov: Normalized output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. clang/gcov: Supports data storage for code coverage detection without a file system 2. clang/gcov: supports compatibility with gcc standard gcov Compile "boards/arm/mps/mps3-an547/configs/gcov", find the module that needs code coverage analysis, add the parameter "-fprofile-instr-generate -fcoverage-mapping", run qemu-system-arm -M mps3-an547 -nographic -kernel ./nuttx/nuttx, execute the app that calls __llvm_profile_dump or nsh run "gcov -d /tmp/xxx ", if you set the dump to memory, read the memory in your own way, such as gdb. If you use the default dump to file, please dump the file to the host, and finally use the following command to run: "llvm-profdata merge -sparse default.profraw -o result.profdata" "llvm-cov show -format=html ./nuttx/nuttx -instr-profile=result.profdata -output-dir=./coverage/" Signed-off-by: wangmingrong1 --- libs/libbuiltin/Kconfig | 34 ++++++++++ libs/libbuiltin/compiler-rt/coverage.c | 86 ++++++++++++-------------- 2 files changed, 72 insertions(+), 48 deletions(-) diff --git a/libs/libbuiltin/Kconfig b/libs/libbuiltin/Kconfig index 4d8c581ce4fbe..6a0ad983ffa76 100644 --- a/libs/libbuiltin/Kconfig +++ b/libs/libbuiltin/Kconfig @@ -101,6 +101,40 @@ config COVERAGE_ALL -fcoverage-mapping' parameter to all module. The data can then be printed nsh run "gcov dump -d /xxx/xxx" +choice + prompt "Code coverage data output" + default COVERAGE_DUMP_FILE + ---help--- + Select the code coverage data output method + +config COVERAGE_DUMP_FILE + ---help--- + Save the code coverage results by writing them to a file + +config COVERAGE_DUMP_MEMORY + bool "Dump code coverage data directly to memory" + depends on COVERAGE_MINI + ---help--- + The data output of code coverage detection is written directly + to the memory instead of writing to the file in the standard way. + +endchoice + +if COVERAGE_DUMP_MEMORY + +config COVERAGE_DUMP_MEMORY_ADDR + hex "Dump code coverage data memory address" + ---help--- + The address set will be used to store code coverage data. + Please ensure that the size is large enough. + +config COVERAGE_DUMP_MEMORY_SIZE + int "Dump code coverage data memory size" + ---help--- + The size set will be used to store code coverage data. + Please ensure that the size is large enough. + +endif config PROFILE_ALL bool "Enable gprof call graph for all modules" diff --git a/libs/libbuiltin/compiler-rt/coverage.c b/libs/libbuiltin/compiler-rt/coverage.c index df85b49a0edec..d9e2ae6488622 100644 --- a/libs/libbuiltin/compiler-rt/coverage.c +++ b/libs/libbuiltin/compiler-rt/coverage.c @@ -33,6 +33,7 @@ #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -225,14 +226,9 @@ void __llvm_profile_register_names_function(void *names_start, * llvm-prof. See the clang profiling documentation for details. */ -void __llvm_profile_dump(const char *path) +void __llvm_profile_dump(lib_puts_t puts, void *handle) { - int fd; - int ret; - - /* Header: __llvm_profile_header from InstrProfData.inc */ - - const char *filename = path; + const char c = '\0'; /* Calculate size of sections. */ @@ -266,61 +262,55 @@ void __llvm_profile_dump(const char *path) hdr.names_delta = (uintptr_t)names_begin; hdr.value_kind_last = IPVK_LAST; - fd = _NX_OPEN(filename, O_WRONLY | O_CREAT); - if (fd < 0) + puts(handle, &hdr, sizeof(hdr)); + puts(handle, data_begin, sizeof(__llvm_profile_data) * num_data); + puts(handle, counters_begin, sizeof(uint64_t) * num_counters); + puts(handle, names_begin, names_size); + + for (; padding_bytes_after_names != 0; --padding_bytes_after_names) { - _NX_SETERRNO(fd); - return; + puts(handle, &c, 1); } +} - /* Header */ +void __gcov_dump(void) +{ - ret = _NX_WRITE(fd, &hdr, sizeof(hdr)); - if (ret != sizeof(hdr)) - { - _NX_SETERRNO(ret); - goto exit; - } +#ifdef CONFIG_COVERAGE_DUMP_MEMORY - /* Data */ + struct lib_memoutstream_s stream; - ret = _NX_WRITE(fd, data_begin, sizeof(__llvm_profile_data) * num_data); - if (ret != sizeof(__llvm_profile_data) * num_data) - { - _NX_SETERRNO(ret); - goto exit; - } + lib_memoutstream(&stream, + CONFIG_COVERAGE_DUMP_MEMORY_ADDR, + CONFIG_COVERAGE_DUMP_MEMORY_SIZE); - /* Counters */ + __llvm_profile_dump(stream.puts, &stream); - ret = _NX_WRITE(fd, counters_begin, sizeof(uint64_t) * num_counters); - if (ret != sizeof(uint64_t) * num_counters) - { - _NX_SETERRNO(ret); - goto exit; - } +#elif defined (CONFIG_COVERAGE_DUMP_FILE) - /* Names */ + struct lib_rawoutstream_s stream; + char *path; + int fd; - ret = _NX_WRITE(fd, names_begin, names_size); - if (ret != names_size) + path = getenv("GCOV_PREFIX"); + fd = _NX_OPEN(path, O_WRONLY | O_CREAT); + if (fd < 0) { - _NX_SETERRNO(ret); - goto exit; + _NX_SETERRNO(fd); + return; } - /* Padding */ + lib_rawoutstream(&stream, fd); - for (; padding_bytes_after_names != 0; --padding_bytes_after_names) - { - ret = _NX_WRITE(fd, "\0", 1); - if (ret != 1) - { - _NX_SETERRNO(ret); - break; - } - } + __llvm_profile_dump(stream.common.puts, &stream); -exit: _NX_CLOSE(fd); + +#endif + +} + +void __gcov_reset(void) +{ + }