From abbea9398616742c0a7ece792acc054d89b6349c Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Wed, 20 Nov 2024 19:09:29 +0800 Subject: [PATCH] clang/gcov: Supports saving data by dumping it directly into memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supports data storage for code coverage detection without a file system 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, 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 | 11 ++++++ libs/libbuiltin/compiler-rt/coverage.c | 47 +++++++++++++++++++++----- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/libs/libbuiltin/Kconfig b/libs/libbuiltin/Kconfig index 4d8c581ce4fbe..ad6002d97727b 100644 --- a/libs/libbuiltin/Kconfig +++ b/libs/libbuiltin/Kconfig @@ -101,6 +101,17 @@ config COVERAGE_ALL -fcoverage-mapping' parameter to all module. The data can then be printed nsh run "gcov dump -d /xxx/xxx" +config COVERAGE_DUMP_MEMORY + bool "Dump code coverage data directly to memory" + depends on COVERAGE_MINI + default n + +if COVERAGE_DUMP_MEMORY + +config COVERAGE_DUMP_MEMORY_ADDR + hex "Dump code coverage data memory address" + +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..86df2b0f177e9 100644 --- a/libs/libbuiltin/compiler-rt/coverage.c +++ b/libs/libbuiltin/compiler-rt/coverage.c @@ -225,15 +225,8 @@ 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) +size_t __llvm_profile_dump(const char *path) { - int fd; - int ret; - - /* Header: __llvm_profile_header from InstrProfData.inc */ - - const char *filename = path; - /* Calculate size of sections. */ const __llvm_profile_data *data_begin = __llvm_profile_begin_data(); @@ -266,11 +259,18 @@ void __llvm_profile_dump(const char *path) hdr.names_delta = (uintptr_t)names_begin; hdr.value_kind_last = IPVK_LAST; +#ifndef CONFIG_COVERAGE_DUMP_MEMORY + + int fd; + int ret; + + const char *filename = path; + fd = _NX_OPEN(filename, O_WRONLY | O_CREAT); if (fd < 0) { _NX_SETERRNO(fd); - return; + return -ENOENT; } /* Header */ @@ -323,4 +323,33 @@ void __llvm_profile_dump(const char *path) exit: _NX_CLOSE(fd); + + return ret; +#else + + UNUSED(path); + char *p = (char *)CONFIG_COVERAGE_DUMP_MEMORY_ADDR; + + memcpy(p, &hdr, sizeof(hdr)); + p += sizeof(hdr); + + memcpy(p, data_begin, sizeof(__llvm_profile_data) * num_data); + p += sizeof(__llvm_profile_data) * num_data; + + memcpy(p, counters_begin, sizeof(uint64_t) * num_counters); + p += sizeof(uint64_t) * num_counters; + + memcpy(p, names_begin, names_size); + p += names_size; + + /* Padding */ + + for (; padding_bytes_after_names != 0; --padding_bytes_after_names) + { + *p++ = '\0'; + } + + return (uintptr_t)p - CONFIG_COVERAGE_DUMP_MEMORY_ADDR; + +#endif }