Skip to content

Commit

Permalink
clang/gcov: Normalized output
Browse files Browse the repository at this point in the history
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 <wangmingrong1@xiaomi.com>
  • Loading branch information
W-M-R committed Nov 21, 2024
1 parent feb38c4 commit f4dd720
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 48 deletions.
34 changes: 34 additions & 0 deletions libs/libbuiltin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
86 changes: 38 additions & 48 deletions libs/libbuiltin/compiler-rt/coverage.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include <fcntl.h>
#include <nuttx/fs/fs.h>
#include <nuttx/streams.h>

/****************************************************************************
* Pre-processor Definitions
Expand Down Expand Up @@ -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. */

Expand Down Expand Up @@ -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)
{

Check failure on line 278 in libs/libbuiltin/compiler-rt/coverage.c

View workflow job for this annotation

GitHub Actions / check

Blank line follows left brace
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

}

Check failure on line 311 in libs/libbuiltin/compiler-rt/coverage.c

View workflow job for this annotation

GitHub Actions / check

Blank line precedes right brace at line

void __gcov_reset(void)
{

Check failure on line 315 in libs/libbuiltin/compiler-rt/coverage.c

View workflow job for this annotation

GitHub Actions / check

Blank line follows left brace
}

Check failure on line 316 in libs/libbuiltin/compiler-rt/coverage.c

View workflow job for this annotation

GitHub Actions / check

Blank line precedes right brace at line

0 comments on commit f4dd720

Please sign in to comment.