From ac8ffd8b4d947ce73716d8c322bf4b44be465761 Mon Sep 17 00:00:00 2001 From: Saman Dehghan Date: Thu, 18 Sep 2025 08:24:03 -0500 Subject: [PATCH 1/6] Add support for llvm coverage. Right now clang versions 14-19 with profile version 8,9,10 are added. Clean master branch in x86 platform is not linkable with any version of clang. just compilable. Clean master branch in ARM platform is not compilable with any version of clang. Only in clang-19 if we disable this flag `-mgeneral-regs-only`it will succesfuly compile and link. We tested compilability of our patch in above senario and compiled with clang 14-19 in x86 and in ARM it compiled and linked with clang-19 in the described situation. --- xen/common/coverage/llvm.c | 185 +++++++++++++++++++++++++++++++------ xen/include/xen/types.h | 1 + 2 files changed, 159 insertions(+), 27 deletions(-) diff --git a/xen/common/coverage/llvm.c b/xen/common/coverage/llvm.c index 517b2aa8c202..37675eaab603 100644 --- a/xen/common/coverage/llvm.c +++ b/xen/common/coverage/llvm.c @@ -44,51 +44,184 @@ ((uint64_t)'f' << 16) | ((uint64_t)'R' << 8) | ((uint64_t)129) #endif -#define LLVM_PROFILE_VERSION 4 -#define LLVM_PROFILE_NUM_KINDS 2 +/* + * Since Xen uses the llvm code coverage support without the run time library + * __llvm_profile_runtime must be defined according to the docs at: + * + * https://clang.llvm.org/docs/SourceBasedCodeCoverage.html + */ +int __llvm_profile_runtime; + +extern char __start___llvm_prf_data[]; +extern char __stop___llvm_prf_data[]; +extern char __start___llvm_prf_names[]; +extern char __stop___llvm_prf_names[]; +extern char __start___llvm_prf_cnts[]; +extern char __stop___llvm_prf_cnts[]; +extern char __start___llvm_prf_bits[]; +extern char __stop___llvm_prf_bits[]; + +#define START_DATA ((const char *)__start___llvm_prf_data) +#define END_DATA ((const char *)__stop___llvm_prf_data) +#define START_NAMES ((const char *)__start___llvm_prf_names) +#define END_NAMES ((const char *)__stop___llvm_prf_names) +#define START_COUNTERS ((char *)__start___llvm_prf_cnts) +#define END_COUNTERS ((char *)__stop___llvm_prf_cnts) +#define START_BITS ((char *)__start___llvm_prf_bits) +#define STOP_BITS ((char *)__stop___llvm_prf_bits) + +#if __clang_major__ == 19 +#define LLVM_PROFILE_VERSION 10 +#define LLVM_PROFILE_NUM_KINDS 3 struct llvm_profile_data { uint64_t name_ref; uint64_t function_hash; - void *counter; + void *relative_counter; + void *relative_bitmap; void *function; void *values; uint32_t nr_counters; uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS]; + uint32_t numbitmap_bytes; }; struct llvm_profile_header { uint64_t magic; uint64_t version; - uint64_t data_size; - uint64_t counters_size; + uint64_t binary_ids_size; + uint64_t num_data; + uint64_t padding_bytes_before_counters; + uint64_t num_counters; + uint64_t padding_bytes_after_counters; + uint64_t num_bitmap_bytes; + uint64_t padding_bytes_after_bitmap_bytes; uint64_t names_size; uint64_t counters_delta; + uint64_t bitmap_delta; uint64_t names_delta; + uint64_t num_vtables; + uint64_t vnames_size; uint64_t value_kind_last; }; -/* - * Since Xen uses the llvm code coverage support without the run time library - * __llvm_profile_runtime must be defined according to the docs at: - * - * https://clang.llvm.org/docs/SourceBasedCodeCoverage.html - */ -int __llvm_profile_runtime; +struct llvm_profile_header get_header(void) { + return (struct llvm_profile_header) { + .magic = LLVM_PROFILE_MAGIC, + .version = LLVM_PROFILE_VERSION, + .binary_ids_size = 0, + .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), + .padding_bytes_before_counters = 0, + .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - (intptr_t)START_COUNTERS) / sizeof(uint64_t), + .padding_bytes_after_counters = 0, + //.num_bitmap_bytes = ,//TODO + //.padding_bytes_after_bitmap_bytes = 0,//TODO, + .names_size = (END_NAMES - START_NAMES) * sizeof(char), + .counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, + //.bitmap_delta = ,//TODO + .names_delta = (uintptr_t)START_NAMES, + //.num_vtables = ,//TODO + //.vnames_size = ,//TODO + .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, + }; +} + +#elif __clang_major__ == 18 +#define LLVM_PROFILE_VERSION 9 +#define LLVM_PROFILE_NUM_KINDS 2 +struct llvm_profile_data { + uint64_t name_ref; + uint64_t function_hash; + void *relative_counter; + void *relative_bitmap; + void *function; + void *values; + uint32_t nr_counters; + uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS]; + uint32_t numbitmap_bytes; +}; + +struct llvm_profile_header { + uint64_t magic; + uint64_t version; + uint64_t binary_ids_size; + uint64_t num_data; + uint64_t padding_bytes_before_counters; + uint64_t num_counters; + uint64_t padding_bytes_after_counters; + uint64_t num_bitmap_bytes; + uint64_t padding_bytes_after_bitmap_bytes; + uint64_t names_size; + uint64_t counters_delta; + uint64_t bitmap_delta; + uint64_t names_delta; + uint64_t value_kind_last; +}; + +struct llvm_profile_header get_header(void) { + return (struct llvm_profile_header) { + .magic = LLVM_PROFILE_MAGIC, + .version = LLVM_PROFILE_VERSION, + .binary_ids_size = 0, + .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), + .padding_bytes_before_counters = 0, + .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - (intptr_t)START_COUNTERS) / sizeof(uint64_t), + .padding_bytes_after_counters = 0, + //.num_bitmap_bytes = ,//TODO + //.padding_bytes_after_bitmap_bytes = //TODO, + .names_size = (END_NAMES - START_NAMES) * sizeof(char), + .counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, + //.bitmap_delta = ,//TODO + .names_delta = (uintptr_t)START_NAMES, + .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, + }; +} + +#elif __clang_major__ >= 14 && __clang_major__ <= 17 +#define LLVM_PROFILE_VERSION 8 +#define LLVM_PROFILE_NUM_KINDS 2 +struct llvm_profile_data { + uint64_t name_ref; + uint64_t function_hash; + void *relative_counter; + void *function; + void *values; + uint32_t nr_counters; + uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS]; +}; -extern const struct llvm_profile_data __start___llvm_prf_data[]; -extern const struct llvm_profile_data __stop___llvm_prf_data[]; -extern const char __start___llvm_prf_names[]; -extern const char __stop___llvm_prf_names[]; -extern uint64_t __start___llvm_prf_cnts[]; -extern uint64_t __stop___llvm_prf_cnts[]; +struct llvm_profile_header { + uint64_t magic; + uint64_t version; + uint64_t binary_ids_size; + uint64_t data_size; + uint64_t padding_bytes_before_counters; + uint64_t counter_size; + uint64_t padding_bytes_after_counters; + uint64_t names_size; + uint64_t counters_delta; + uint64_t names_delta; + uint64_t value_kind_last; +}; -#define START_DATA ((const void *)__start___llvm_prf_data) -#define END_DATA ((const void *)__stop___llvm_prf_data) -#define START_NAMES ((const void *)__start___llvm_prf_names) -#define END_NAMES ((const void *)__stop___llvm_prf_names) -#define START_COUNTERS ((void *)__start___llvm_prf_cnts) -#define END_COUNTERS ((void *)__stop___llvm_prf_cnts) +struct llvm_profile_header get_header(void) { + return (struct llvm_profile_header) { + .magic = LLVM_PROFILE_MAGIC, + .version = LLVM_PROFILE_VERSION, + .binary_ids_size = 0, + .data_size = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), + .padding_bytes_before_counters = 0, + .counter_size = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - (intptr_t)START_COUNTERS) / sizeof(uint64_t), + .padding_bytes_after_counters = 0, + .names_size = (END_NAMES - START_NAMES) * sizeof(char), + .counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, + .names_delta = (uintptr_t)START_NAMES, + .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, + }; +} +#else +#error "Unsupported Clang version" +#endif static void cf_check reset_counters(void) { @@ -107,10 +240,8 @@ static int cf_check dump( struct llvm_profile_header header = { .magic = LLVM_PROFILE_MAGIC, .version = LLVM_PROFILE_VERSION, - .data_size = (END_DATA - START_DATA) / sizeof(struct llvm_profile_data), - .counters_size = (END_COUNTERS - START_COUNTERS) / sizeof(uint64_t), .names_size = END_NAMES - START_NAMES, - .counters_delta = (uintptr_t)START_COUNTERS, + .counters_delta = (uintptr_t)(START_COUNTERS - START_DATA), .names_delta = (uintptr_t)START_NAMES, .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, }; diff --git a/xen/include/xen/types.h b/xen/include/xen/types.h index 73ddccbbd5dc..799bfe0b95f2 100644 --- a/xen/include/xen/types.h +++ b/xen/include/xen/types.h @@ -18,6 +18,7 @@ typedef signed long ssize_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __UINTPTR_TYPE__ uintptr_t; +typedef __INTPTR_TYPE__ intptr_t; /* * Users of this macro are expected to pass a positive value. From 9b219ad7f26481baf8f0d74247251017b659592d Mon Sep 17 00:00:00 2001 From: Saman Dehghan Date: Fri, 19 Sep 2025 22:12:30 -0500 Subject: [PATCH 2/6] add clang-20, add required initializations. add mcdc flags to makefile --- xen/Rules.mk | 2 +- xen/common/coverage/llvm.c | 49 +++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index 24f447b95734..91f25b7f811e 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -135,7 +135,7 @@ $(filter %.init.o,$(obj-y) $(obj-bin-y) $(extra-y)): CFLAGS-y += -DINIT_SECTIONS non-init-objects = $(filter-out %.init.o, $(obj-y) $(obj-bin-y) $(extra-y)) ifeq ($(CONFIG_CC_IS_CLANG),y) - cov-cflags-$(CONFIG_COVERAGE) := -fprofile-instr-generate -fcoverage-mapping + cov-cflags-$(CONFIG_COVERAGE) := -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc else cov-cflags-$(CONFIG_COVERAGE) := -fprofile-arcs -ftest-coverage cov-cflags-$(CONFIG_CONDITION_COVERAGE) += -fcondition-coverage diff --git a/xen/common/coverage/llvm.c b/xen/common/coverage/llvm.c index 37675eaab603..27855d0607ee 100644 --- a/xen/common/coverage/llvm.c +++ b/xen/common/coverage/llvm.c @@ -58,8 +58,6 @@ extern char __start___llvm_prf_names[]; extern char __stop___llvm_prf_names[]; extern char __start___llvm_prf_cnts[]; extern char __stop___llvm_prf_cnts[]; -extern char __start___llvm_prf_bits[]; -extern char __stop___llvm_prf_bits[]; #define START_DATA ((const char *)__start___llvm_prf_data) #define END_DATA ((const char *)__stop___llvm_prf_data) @@ -67,10 +65,15 @@ extern char __stop___llvm_prf_bits[]; #define END_NAMES ((const char *)__stop___llvm_prf_names) #define START_COUNTERS ((char *)__start___llvm_prf_cnts) #define END_COUNTERS ((char *)__stop___llvm_prf_cnts) + +#if __clang_major__ >= 18 +extern char __start___llvm_prf_bits[]; +extern char __stop___llvm_prf_bits[]; #define START_BITS ((char *)__start___llvm_prf_bits) #define STOP_BITS ((char *)__stop___llvm_prf_bits) +#endif -#if __clang_major__ == 19 +#if __clang_major__ >= 19 #define LLVM_PROFILE_VERSION 10 #define LLVM_PROFILE_NUM_KINDS 3 @@ -105,23 +108,31 @@ struct llvm_profile_header { uint64_t value_kind_last; }; +struct llvm_vtable_profile_data { + uint64_t name_hash; + void* pointer; + uint32_t size; +}; + struct llvm_profile_header get_header(void) { return (struct llvm_profile_header) { .magic = LLVM_PROFILE_MAGIC, .version = LLVM_PROFILE_VERSION, .binary_ids_size = 0, - .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), + .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) + - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), .padding_bytes_before_counters = 0, - .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - (intptr_t)START_COUNTERS) / sizeof(uint64_t), + .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) + - (intptr_t)START_COUNTERS) / sizeof(uint64_t), .padding_bytes_after_counters = 0, - //.num_bitmap_bytes = ,//TODO - //.padding_bytes_after_bitmap_bytes = 0,//TODO, + .num_bitmap_bytes = (uintptr_t)STOP_BITS - (uintptr_t)START_BITS, + .padding_bytes_after_bitmap_bytes = 0, .names_size = (END_NAMES - START_NAMES) * sizeof(char), .counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, - //.bitmap_delta = ,//TODO + .bitmap_delta = (uintptr_t)START_BITS - (uintptr_t)START_DATA, .names_delta = (uintptr_t)START_NAMES, - //.num_vtables = ,//TODO - //.vnames_size = ,//TODO + .num_vtables = 0, + .vnames_size = 0, .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, }; } @@ -163,15 +174,17 @@ struct llvm_profile_header get_header(void) { .magic = LLVM_PROFILE_MAGIC, .version = LLVM_PROFILE_VERSION, .binary_ids_size = 0, - .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), + .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) + - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), .padding_bytes_before_counters = 0, - .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - (intptr_t)START_COUNTERS) / sizeof(uint64_t), + .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) + - (intptr_t)START_COUNTERS) / sizeof(uint64_t), .padding_bytes_after_counters = 0, - //.num_bitmap_bytes = ,//TODO - //.padding_bytes_after_bitmap_bytes = //TODO, + .num_bitmap_bytes = (uintptr_t)STOP_BITS - (uintptr_t)START_BITS, + .padding_bytes_after_bitmap_bytes = 0, .names_size = (END_NAMES - START_NAMES) * sizeof(char), .counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, - //.bitmap_delta = ,//TODO + .bitmap_delta = (uintptr_t)START_BITS - (uintptr_t)START_DATA, .names_delta = (uintptr_t)START_NAMES, .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, }; @@ -209,9 +222,11 @@ struct llvm_profile_header get_header(void) { .magic = LLVM_PROFILE_MAGIC, .version = LLVM_PROFILE_VERSION, .binary_ids_size = 0, - .data_size = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), + .data_size = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) + - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), .padding_bytes_before_counters = 0, - .counter_size = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - (intptr_t)START_COUNTERS) / sizeof(uint64_t), + .counter_size = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) + - (intptr_t)START_COUNTERS) / sizeof(uint64_t), .padding_bytes_after_counters = 0, .names_size = (END_NAMES - START_NAMES) * sizeof(char), .counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, From 9073788dbc82abad28ffd53718895a77d5c2749f Mon Sep 17 00:00:00 2001 From: Saman Dehghan Date: Fri, 19 Sep 2025 22:24:42 -0500 Subject: [PATCH 3/6] condition check on clang version for mcdc support --- xen/Rules.mk | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index 91f25b7f811e..5e6906952209 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -135,7 +135,13 @@ $(filter %.init.o,$(obj-y) $(obj-bin-y) $(extra-y)): CFLAGS-y += -DINIT_SECTIONS non-init-objects = $(filter-out %.init.o, $(obj-y) $(obj-bin-y) $(extra-y)) ifeq ($(CONFIG_CC_IS_CLANG),y) - cov-cflags-$(CONFIG_COVERAGE) := -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc + CLANG_VERSION := $(shell $(CC) -dumpversion | cut -d. -f1) + CLANG_VERSION_GTE_18 := $(shell [ $(CLANG_VERSION) -ge 18 ] && echo y) + ifeq ($(CLANG_VERSION_GTE_18),y) + cov-cflags-$(CONFIG_COVERAGE) := -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc + else + cov-cflags-$(CONFIG_COVERAGE) := -fprofile-instr-generate -fcoverage-mapping + endif else cov-cflags-$(CONFIG_COVERAGE) := -fprofile-arcs -ftest-coverage cov-cflags-$(CONFIG_CONDITION_COVERAGE) += -fcondition-coverage From 935b8569b6a95471da1a577db890bae80b395978 Mon Sep 17 00:00:00 2001 From: Saman Dehghan Date: Sun, 28 Sep 2025 22:46:16 -0500 Subject: [PATCH 4/6] get_header --- xen/common/coverage/llvm.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/xen/common/coverage/llvm.c b/xen/common/coverage/llvm.c index 27855d0607ee..474d11989a83 100644 --- a/xen/common/coverage/llvm.c +++ b/xen/common/coverage/llvm.c @@ -252,14 +252,7 @@ static uint32_t cf_check get_size(void) static int cf_check dump( XEN_GUEST_HANDLE_PARAM(char) buffer, uint32_t *buf_size) { - struct llvm_profile_header header = { - .magic = LLVM_PROFILE_MAGIC, - .version = LLVM_PROFILE_VERSION, - .names_size = END_NAMES - START_NAMES, - .counters_delta = (uintptr_t)(START_COUNTERS - START_DATA), - .names_delta = (uintptr_t)START_NAMES, - .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, - }; + struct llvm_profile_header header = get_header(); unsigned int off = 0; #define APPEND_TO_BUFFER(src, size) \ From 85fcc16038cd72717b1718c623d26e033b8db182 Mon Sep 17 00:00:00 2001 From: Saman Dehghan Date: Tue, 30 Sep 2025 20:52:00 -0500 Subject: [PATCH 5/6] make minimal changes/ remove mcdc --- xen/Rules.mk | 8 +- xen/common/coverage/llvm.c | 205 +++++++++---------------------------- 2 files changed, 51 insertions(+), 162 deletions(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index 5e6906952209..24f447b95734 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -135,13 +135,7 @@ $(filter %.init.o,$(obj-y) $(obj-bin-y) $(extra-y)): CFLAGS-y += -DINIT_SECTIONS non-init-objects = $(filter-out %.init.o, $(obj-y) $(obj-bin-y) $(extra-y)) ifeq ($(CONFIG_CC_IS_CLANG),y) - CLANG_VERSION := $(shell $(CC) -dumpversion | cut -d. -f1) - CLANG_VERSION_GTE_18 := $(shell [ $(CLANG_VERSION) -ge 18 ] && echo y) - ifeq ($(CLANG_VERSION_GTE_18),y) - cov-cflags-$(CONFIG_COVERAGE) := -fprofile-instr-generate -fcoverage-mapping -fcoverage-mcdc - else - cov-cflags-$(CONFIG_COVERAGE) := -fprofile-instr-generate -fcoverage-mapping - endif + cov-cflags-$(CONFIG_COVERAGE) := -fprofile-instr-generate -fcoverage-mapping else cov-cflags-$(CONFIG_COVERAGE) := -fprofile-arcs -ftest-coverage cov-cflags-$(CONFIG_CONDITION_COVERAGE) += -fcondition-coverage diff --git a/xen/common/coverage/llvm.c b/xen/common/coverage/llvm.c index 474d11989a83..24c0643e78b2 100644 --- a/xen/common/coverage/llvm.c +++ b/xen/common/coverage/llvm.c @@ -44,49 +44,33 @@ ((uint64_t)'f' << 16) | ((uint64_t)'R' << 8) | ((uint64_t)129) #endif -/* - * Since Xen uses the llvm code coverage support without the run time library - * __llvm_profile_runtime must be defined according to the docs at: - * - * https://clang.llvm.org/docs/SourceBasedCodeCoverage.html - */ -int __llvm_profile_runtime; - -extern char __start___llvm_prf_data[]; -extern char __stop___llvm_prf_data[]; -extern char __start___llvm_prf_names[]; -extern char __stop___llvm_prf_names[]; -extern char __start___llvm_prf_cnts[]; -extern char __stop___llvm_prf_cnts[]; - -#define START_DATA ((const char *)__start___llvm_prf_data) -#define END_DATA ((const char *)__stop___llvm_prf_data) -#define START_NAMES ((const char *)__start___llvm_prf_names) -#define END_NAMES ((const char *)__stop___llvm_prf_names) -#define START_COUNTERS ((char *)__start___llvm_prf_cnts) -#define END_COUNTERS ((char *)__stop___llvm_prf_cnts) - -#if __clang_major__ >= 18 -extern char __start___llvm_prf_bits[]; -extern char __stop___llvm_prf_bits[]; -#define START_BITS ((char *)__start___llvm_prf_bits) -#define STOP_BITS ((char *)__stop___llvm_prf_bits) -#endif - #if __clang_major__ >= 19 #define LLVM_PROFILE_VERSION 10 #define LLVM_PROFILE_NUM_KINDS 3 +#elif __clang_major__ == 18 +#define LLVM_PROFILE_VERSION 9 +#define LLVM_PROFILE_NUM_KINDS 2 +#elif __clang_major__ >= 14 && __clang_major__ <= 17 +#define LLVM_PROFILE_VERSION 8 +#define LLVM_PROFILE_NUM_KINDS 2 +#else +#error "Unsupported Clang version" +#endif struct llvm_profile_data { uint64_t name_ref; uint64_t function_hash; void *relative_counter; +#if __clang_major__ >= 18 void *relative_bitmap; +#endif void *function; void *values; uint32_t nr_counters; uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS]; +#if __clang_major__ >= 18 uint32_t numbitmap_bytes; +#endif }; struct llvm_profile_header { @@ -100,132 +84,63 @@ struct llvm_profile_header { uint64_t num_bitmap_bytes; uint64_t padding_bytes_after_bitmap_bytes; uint64_t names_size; +#if __clang_major__ >= 18 uint64_t counters_delta; uint64_t bitmap_delta; +#endif uint64_t names_delta; +#if __clang_major__ >= 19 uint64_t num_vtables; uint64_t vnames_size; +#endif uint64_t value_kind_last; }; -struct llvm_vtable_profile_data { - uint64_t name_hash; - void* pointer; - uint32_t size; -}; +/* + * Since Xen uses the llvm code coverage support without the run time library + * __llvm_profile_runtime must be defined according to the docs at: + * + * https://clang.llvm.org/docs/SourceBasedCodeCoverage.html + */ +int __llvm_profile_runtime; -struct llvm_profile_header get_header(void) { - return (struct llvm_profile_header) { - .magic = LLVM_PROFILE_MAGIC, - .version = LLVM_PROFILE_VERSION, - .binary_ids_size = 0, - .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), - .padding_bytes_before_counters = 0, - .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - - (intptr_t)START_COUNTERS) / sizeof(uint64_t), - .padding_bytes_after_counters = 0, - .num_bitmap_bytes = (uintptr_t)STOP_BITS - (uintptr_t)START_BITS, - .padding_bytes_after_bitmap_bytes = 0, - .names_size = (END_NAMES - START_NAMES) * sizeof(char), - .counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, - .bitmap_delta = (uintptr_t)START_BITS - (uintptr_t)START_DATA, - .names_delta = (uintptr_t)START_NAMES, - .num_vtables = 0, - .vnames_size = 0, - .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, - }; -} +extern char __start___llvm_prf_data[]; +extern char __stop___llvm_prf_data[]; +extern char __start___llvm_prf_names[]; +extern char __stop___llvm_prf_names[]; +extern char __start___llvm_prf_cnts[]; +extern char __stop___llvm_prf_cnts[]; -#elif __clang_major__ == 18 -#define LLVM_PROFILE_VERSION 9 -#define LLVM_PROFILE_NUM_KINDS 2 -struct llvm_profile_data { - uint64_t name_ref; - uint64_t function_hash; - void *relative_counter; - void *relative_bitmap; - void *function; - void *values; - uint32_t nr_counters; - uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS]; - uint32_t numbitmap_bytes; -}; +#define START_DATA ((const char *)__start___llvm_prf_data) +#define END_DATA ((const char *)__stop___llvm_prf_data) +#define START_NAMES ((const char *)__start___llvm_prf_names) +#define END_NAMES ((const char *)__stop___llvm_prf_names) +#define START_COUNTERS ((char *)__start___llvm_prf_cnts) +#define END_COUNTERS ((char *)__stop___llvm_prf_cnts) -struct llvm_profile_header { - uint64_t magic; - uint64_t version; - uint64_t binary_ids_size; - uint64_t num_data; - uint64_t padding_bytes_before_counters; - uint64_t num_counters; - uint64_t padding_bytes_after_counters; - uint64_t num_bitmap_bytes; - uint64_t padding_bytes_after_bitmap_bytes; - uint64_t names_size; - uint64_t counters_delta; - uint64_t bitmap_delta; - uint64_t names_delta; - uint64_t value_kind_last; -}; -struct llvm_profile_header get_header(void) { - return (struct llvm_profile_header) { - .magic = LLVM_PROFILE_MAGIC, - .version = LLVM_PROFILE_VERSION, - .binary_ids_size = 0, - .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), - .padding_bytes_before_counters = 0, - .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - - (intptr_t)START_COUNTERS) / sizeof(uint64_t), - .padding_bytes_after_counters = 0, - .num_bitmap_bytes = (uintptr_t)STOP_BITS - (uintptr_t)START_BITS, - .padding_bytes_after_bitmap_bytes = 0, - .names_size = (END_NAMES - START_NAMES) * sizeof(char), - .counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, - .bitmap_delta = (uintptr_t)START_BITS - (uintptr_t)START_DATA, - .names_delta = (uintptr_t)START_NAMES, - .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, - }; +static void cf_check reset_counters(void) +{ + memset(START_COUNTERS, 0, END_COUNTERS - START_COUNTERS); } -#elif __clang_major__ >= 14 && __clang_major__ <= 17 -#define LLVM_PROFILE_VERSION 8 -#define LLVM_PROFILE_NUM_KINDS 2 -struct llvm_profile_data { - uint64_t name_ref; - uint64_t function_hash; - void *relative_counter; - void *function; - void *values; - uint32_t nr_counters; - uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS]; -}; - -struct llvm_profile_header { - uint64_t magic; - uint64_t version; - uint64_t binary_ids_size; - uint64_t data_size; - uint64_t padding_bytes_before_counters; - uint64_t counter_size; - uint64_t padding_bytes_after_counters; - uint64_t names_size; - uint64_t counters_delta; - uint64_t names_delta; - uint64_t value_kind_last; -}; +static uint32_t cf_check get_size(void) +{ + return ROUNDUP(sizeof(struct llvm_profile_header) + END_DATA - START_DATA + + END_COUNTERS - START_COUNTERS + END_NAMES - START_NAMES, 8); +} -struct llvm_profile_header get_header(void) { - return (struct llvm_profile_header) { +static int cf_check dump( + XEN_GUEST_HANDLE_PARAM(char) buffer, uint32_t *buf_size) +{ + struct llvm_profile_header header = { .magic = LLVM_PROFILE_MAGIC, .version = LLVM_PROFILE_VERSION, .binary_ids_size = 0, - .data_size = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) + .num_data = (((intptr_t)END_DATA + sizeof(struct llvm_profile_data) - 1) - (intptr_t)START_DATA) / sizeof(struct llvm_profile_data), .padding_bytes_before_counters = 0, - .counter_size = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) + .num_counters = (((intptr_t)END_COUNTERS + sizeof(uint64_t) - 1) - (intptr_t)START_COUNTERS) / sizeof(uint64_t), .padding_bytes_after_counters = 0, .names_size = (END_NAMES - START_NAMES) * sizeof(char), @@ -233,26 +148,6 @@ struct llvm_profile_header get_header(void) { .names_delta = (uintptr_t)START_NAMES, .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, }; -} -#else -#error "Unsupported Clang version" -#endif - -static void cf_check reset_counters(void) -{ - memset(START_COUNTERS, 0, END_COUNTERS - START_COUNTERS); -} - -static uint32_t cf_check get_size(void) -{ - return ROUNDUP(sizeof(struct llvm_profile_header) + END_DATA - START_DATA + - END_COUNTERS - START_COUNTERS + END_NAMES - START_NAMES, 8); -} - -static int cf_check dump( - XEN_GUEST_HANDLE_PARAM(char) buffer, uint32_t *buf_size) -{ - struct llvm_profile_header header = get_header(); unsigned int off = 0; #define APPEND_TO_BUFFER(src, size) \ From b55862fd2683709e6cfb7169a716acfda60ea7ae Mon Sep 17 00:00:00 2001 From: Saman Dehghan Date: Wed, 1 Oct 2025 10:17:55 -0500 Subject: [PATCH 6/6] Address concerns. --- xen/common/coverage/llvm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/xen/common/coverage/llvm.c b/xen/common/coverage/llvm.c index 24c0643e78b2..f92f10654cf9 100644 --- a/xen/common/coverage/llvm.c +++ b/xen/common/coverage/llvm.c @@ -50,7 +50,7 @@ #elif __clang_major__ == 18 #define LLVM_PROFILE_VERSION 9 #define LLVM_PROFILE_NUM_KINDS 2 -#elif __clang_major__ >= 14 && __clang_major__ <= 17 +#elif __clang_major__ >= 14 #define LLVM_PROFILE_VERSION 8 #define LLVM_PROFILE_NUM_KINDS 2 #else @@ -60,12 +60,12 @@ struct llvm_profile_data { uint64_t name_ref; uint64_t function_hash; - void *relative_counter; + intptr_t *relative_counter; #if __clang_major__ >= 18 - void *relative_bitmap; + intptr_t *relative_bitmap; #endif - void *function; - void *values; + intptr_t *function; + intptr_t *values; uint32_t nr_counters; uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS]; #if __clang_major__ >= 18 @@ -100,7 +100,7 @@ struct llvm_profile_header { * Since Xen uses the llvm code coverage support without the run time library * __llvm_profile_runtime must be defined according to the docs at: * - * https://clang.llvm.org/docs/SourceBasedCodeCoverage.html + * https://clang.llvm.org/docs/SourceBasedCodeCoverage.html */ int __llvm_profile_runtime;