Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clang/gcov: Enhance clang gcov dump #14877

Merged
merged 2 commits into from
Nov 25, 2024
Merged
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
14 changes: 14 additions & 0 deletions include/gcov.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,20 @@ extern void __gcov_filename_to_gcfn(FAR const char *filename,
FAR void *),
FAR void *arg);

/****************************************************************************
* Name: __gcov_dump_to_memory
*
* Description:
* Dump gcov data directly to memory
*
* Parameters:
* ptr - Memory Address
* size - Memory block size
*
****************************************************************************/

size_t __gcov_dump_to_memory(FAR void *ptr, size_t size);

#undef EXTERN
#ifdef __cplusplus
}
Expand Down
106 changes: 59 additions & 47 deletions libs/libbuiltin/compiler-rt/coverage.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@

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

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define INSTR_PROF_RAW_VERSION 8
#define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version
#define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime

/* Magic number to detect file format and endianness.
Expand Down Expand Up @@ -98,12 +98,6 @@ typedef struct __llvm_profile_header
enum value_kind value_kind_last;
}__llvm_profile_header;

/****************************************************************************
* Private Data
****************************************************************************/

static uint64_t INSTR_PROF_RAW_VERSION_VAR = INSTR_PROF_RAW_VERSION;

/****************************************************************************
* Public Data
****************************************************************************/
Expand Down Expand Up @@ -138,7 +132,7 @@ static uint64_t __llvm_profile_get_magic(void)

static uint64_t __llvm_profile_get_version(void)
{
return __llvm_profile_raw_version;
return INSTR_PROF_RAW_VERSION;
}

static uint64_t __llvm_profile_get_num_counters(const char *begin,
Expand Down Expand Up @@ -225,14 +219,10 @@ 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(FAR struct lib_outstream_s *stream)
{
int fd;
int ret;

/* Header: __llvm_profile_header from InstrProfData.inc */

const char *filename = path;
const char c = '\0';
size_t size = 0;

/* Calculate size of sections. */

Expand Down Expand Up @@ -266,61 +256,83 @@ 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)
{
_NX_SETERRNO(fd);
return;
}

/* Header */

ret = _NX_WRITE(fd, &hdr, sizeof(hdr));
if (ret != sizeof(hdr))
size += sizeof(hdr);
if (sizeof(hdr) != stream->puts(stream, &hdr, sizeof(hdr)))
{
_NX_SETERRNO(ret);
goto exit;
}

/* Data */

ret = _NX_WRITE(fd, data_begin, sizeof(__llvm_profile_data) * num_data);
if (ret != sizeof(__llvm_profile_data) * num_data)
size += sizeof(__llvm_profile_data) * num_data;
if (sizeof(__llvm_profile_data) * num_data !=
stream->puts(stream, data_begin,
sizeof(__llvm_profile_data) * num_data))
{
_NX_SETERRNO(ret);
goto exit;
}

/* Counters */

ret = _NX_WRITE(fd, counters_begin, sizeof(uint64_t) * num_counters);
if (ret != sizeof(uint64_t) * num_counters)
size += sizeof(uint64_t) * num_counters;
if (sizeof(uint64_t) * num_counters !=
stream->puts(stream, counters_begin,
sizeof(uint64_t) * num_counters))
{
_NX_SETERRNO(ret);
goto exit;
}

/* Names */

ret = _NX_WRITE(fd, names_begin, names_size);
if (ret != names_size)
size += names_size;
if (names_size != stream->puts(stream, names_begin, names_size))
{
_NX_SETERRNO(ret);
goto exit;
}

/* Padding */

for (; padding_bytes_after_names != 0; --padding_bytes_after_names)
{
ret = _NX_WRITE(fd, "\0", 1);
if (ret != 1)
size += 1;
if (1 != stream->puts(stream, &c, 1))
{
_NX_SETERRNO(ret);
break;
}
}

exit:

return size;
}

void __gcov_dump(void)
{
struct lib_rawoutstream_s stream;
FAR char *path;
int fd;

path = getenv("GCOV_PREFIX");
if (!path)
{
return;
}

fd = _NX_OPEN(path, O_WRONLY | O_CREAT);
if (fd < 0)
{
_NX_SETERRNO(fd);
return;
}

lib_rawoutstream(&stream, fd);

__llvm_profile_dump(&stream.common);

_NX_CLOSE(fd);
}

size_t __gcov_dump_to_memory(FAR void *ptr, size_t size)
{
struct lib_memoutstream_s stream;

lib_memoutstream(&stream, ptr, size);

return __llvm_profile_dump(&stream.common);
}

void __gcov_reset(void)
{
}
Loading