diff mbox series

[1/2] gcov: re-fix clang-11+ support

Message ID 20210407185456.41943-2-ndesaulniers@google.com
State New
Headers show
Series [1/2] gcov: re-fix clang-11+ support | expand

Commit Message

Nick Desaulniers April 7, 2021, 6:54 p.m. UTC
LLVM changed the expected function signature for
llvm_gcda_emit_function() in the clang-11 release.  Users of clang-11 or
newer may have noticed their kernels producing invalid coverage
information:

$ llvm-cov gcov -a -c -u -f -b <input>.gcda -- gcno=<input>.gcno
1 <func>: checksum mismatch, \
  (<lineno chksum A>, <cfg chksum B>) != (<lineno chksum A>, <cfg chksum C>)
2 Invalid .gcda File!
...

Fix up the function signatures so calling this function interprets its
parameters correctly and computes the correct cfg checksum. In
particular, in clang-11, the additional checksum is no longer optional.

Link: https://reviews.llvm.org/rG25544ce2df0daa4304c07e64b9c8b0f7df60c11d
Cc: stable@vger.kernel.org #5.4+
Reported-by: Prasad Sodagudi <psodagud@quicinc.com>
Tested-by: Prasad Sodagudi <psodagud@quicinc.com>

Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>

---
 kernel/gcov/clang.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

-- 
2.31.1.295.g9ea45b61b8-goog

Comments

Nathan Chancellor April 7, 2021, 7:51 p.m. UTC | #1
On Wed, Apr 07, 2021 at 11:54:55AM -0700, Nick Desaulniers wrote:
> LLVM changed the expected function signature for

> llvm_gcda_emit_function() in the clang-11 release.  Users of clang-11 or

> newer may have noticed their kernels producing invalid coverage

> information:

> 

> $ llvm-cov gcov -a -c -u -f -b <input>.gcda -- gcno=<input>.gcno

> 1 <func>: checksum mismatch, \

>   (<lineno chksum A>, <cfg chksum B>) != (<lineno chksum A>, <cfg chksum C>)

> 2 Invalid .gcda File!

> ...

> 

> Fix up the function signatures so calling this function interprets its

> parameters correctly and computes the correct cfg checksum. In

> particular, in clang-11, the additional checksum is no longer optional.

> 

> Link: https://reviews.llvm.org/rG25544ce2df0daa4304c07e64b9c8b0f7df60c11d

> Cc: stable@vger.kernel.org #5.4+

> Reported-by: Prasad Sodagudi <psodagud@quicinc.com>

> Tested-by: Prasad Sodagudi <psodagud@quicinc.com>

> Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>


Reviewed-by: Nathan Chancellor <nathan@kernel.org>


> ---

>  kernel/gcov/clang.c | 38 +++++++++++++++++++++++++++++++++-----

>  1 file changed, 33 insertions(+), 5 deletions(-)

> 

> diff --git a/kernel/gcov/clang.c b/kernel/gcov/clang.c

> index d41f5ecda9db..1747204541bf 100644

> --- a/kernel/gcov/clang.c

> +++ b/kernel/gcov/clang.c

> @@ -69,7 +69,9 @@ struct gcov_fn_info {

>  

>  	u32 ident;

>  	u32 checksum;

> +#if CONFIG_CLANG_VERSION < 110000

>  	u8 use_extra_checksum;

> +#endif

>  	u32 cfg_checksum;

>  

>  	u32 num_counters;

> @@ -111,6 +113,7 @@ void llvm_gcda_start_file(const char *orig_filename, u32 version, u32 checksum)

>  }

>  EXPORT_SYMBOL(llvm_gcda_start_file);

>  

> +#if CONFIG_CLANG_VERSION < 110000

>  void llvm_gcda_emit_function(u32 ident, u32 func_checksum,

>  		u8 use_extra_checksum, u32 cfg_checksum)

>  {

> @@ -126,6 +129,21 @@ void llvm_gcda_emit_function(u32 ident, u32 func_checksum,

>  	info->cfg_checksum = cfg_checksum;

>  	list_add_tail(&info->head, &current_info->functions);

>  }

> +#else

> +void llvm_gcda_emit_function(u32 ident, u32 func_checksum, u32 cfg_checksum)

> +{

> +	struct gcov_fn_info *info = kzalloc(sizeof(*info), GFP_KERNEL);

> +

> +	if (!info)

> +		return;

> +

> +	INIT_LIST_HEAD(&info->head);

> +	info->ident = ident;

> +	info->checksum = func_checksum;

> +	info->cfg_checksum = cfg_checksum;

> +	list_add_tail(&info->head, &current_info->functions);

> +}

> +#endif

>  EXPORT_SYMBOL(llvm_gcda_emit_function);

>  

>  void llvm_gcda_emit_arcs(u32 num_counters, u64 *counters)

> @@ -256,11 +274,16 @@ int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)

>  		!list_is_last(&fn_ptr2->head, &info2->functions)) {

>  		if (fn_ptr1->checksum != fn_ptr2->checksum)

>  			return false;

> +#if CONFIG_CLANG_VERSION < 110000

>  		if (fn_ptr1->use_extra_checksum != fn_ptr2->use_extra_checksum)

>  			return false;

>  		if (fn_ptr1->use_extra_checksum &&

>  			fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)

>  			return false;

> +#else

> +		if (fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)

> +			return false;

> +#endif

>  		fn_ptr1 = list_next_entry(fn_ptr1, head);

>  		fn_ptr2 = list_next_entry(fn_ptr2, head);

>  	}

> @@ -378,17 +401,22 @@ size_t convert_to_gcda(char *buffer, struct gcov_info *info)

>  

>  	list_for_each_entry(fi_ptr, &info->functions, head) {

>  		u32 i;

> -		u32 len = 2;

> -

> -		if (fi_ptr->use_extra_checksum)

> -			len++;

>  

>  		pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION);

> -		pos += store_gcov_u32(buffer, pos, len);

> +#if CONFIG_CLANG_VERSION < 110000

> +		pos += store_gcov_u32(buffer, pos,

> +			fi_ptr->use_extra_checksum ? 3 : 2);

> +#else

> +		pos += store_gcov_u32(buffer, pos, 3);

> +#endif

>  		pos += store_gcov_u32(buffer, pos, fi_ptr->ident);

>  		pos += store_gcov_u32(buffer, pos, fi_ptr->checksum);

> +#if CONFIG_CLANG_VERSION < 110000

>  		if (fi_ptr->use_extra_checksum)

>  			pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);

> +#else

> +		pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);

> +#endif

>  

>  		pos += store_gcov_u32(buffer, pos, GCOV_TAG_COUNTER_BASE);

>  		pos += store_gcov_u32(buffer, pos, fi_ptr->num_counters * 2);

> -- 

> 2.31.1.295.g9ea45b61b8-goog

>
Andrew Morton April 7, 2021, 9:21 p.m. UTC | #2
On Wed,  7 Apr 2021 11:54:55 -0700 Nick Desaulniers <ndesaulniers@google.com> wrote:

> LLVM changed the expected function signature for

> llvm_gcda_emit_function() in the clang-11 release.  Users of clang-11 or

> newer may have noticed their kernels producing invalid coverage

> information:

> 

> $ llvm-cov gcov -a -c -u -f -b <input>.gcda -- gcno=<input>.gcno

> 1 <func>: checksum mismatch, \

>   (<lineno chksum A>, <cfg chksum B>) != (<lineno chksum A>, <cfg chksum C>)

> 2 Invalid .gcda File!

> ...

> 

> Fix up the function signatures so calling this function interprets its

> parameters correctly and computes the correct cfg checksum. In

> particular, in clang-11, the additional checksum is no longer optional.


Which tree is this against?  I'm seeing quite a lot of rejects against
Linus's current.
Nick Desaulniers April 7, 2021, 9:28 p.m. UTC | #3
On Wed, Apr 7, 2021 at 2:21 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>

> On Wed,  7 Apr 2021 11:54:55 -0700 Nick Desaulniers <ndesaulniers@google.com> wrote:

>

> > LLVM changed the expected function signature for

> > llvm_gcda_emit_function() in the clang-11 release.  Users of clang-11 or

> > newer may have noticed their kernels producing invalid coverage

> > information:

> >

> > $ llvm-cov gcov -a -c -u -f -b <input>.gcda -- gcno=<input>.gcno

> > 1 <func>: checksum mismatch, \

> >   (<lineno chksum A>, <cfg chksum B>) != (<lineno chksum A>, <cfg chksum C>)

> > 2 Invalid .gcda File!

> > ...

> >

> > Fix up the function signatures so calling this function interprets its

> > parameters correctly and computes the correct cfg checksum. In

> > particular, in clang-11, the additional checksum is no longer optional.

>

> Which tree is this against?  I'm seeing quite a lot of rejects against

> Linus's current.


Today's linux-next; the only recent changes to this single source file
since my last patches were:

commit b3c4e66c908b ("gcov: combine common code")
commit 17d0508a080d ("gcov: use kvmalloc()")

both have your sign off, so I assume those are in your tree?

-- 
Thanks,
~Nick Desaulniers
Andrew Morton April 7, 2021, 10:26 p.m. UTC | #4
On Wed, 7 Apr 2021 14:28:21 -0700 Nick Desaulniers <ndesaulniers@google.com> wrote:

> On Wed, Apr 7, 2021 at 2:21 PM Andrew Morton <akpm@linux-foundation.org> wrote:

> >

> > On Wed,  7 Apr 2021 11:54:55 -0700 Nick Desaulniers <ndesaulniers@google.com> wrote:

> >

> > > LLVM changed the expected function signature for

> > > llvm_gcda_emit_function() in the clang-11 release.  Users of clang-11 or

> > > newer may have noticed their kernels producing invalid coverage

> > > information:

> > >

> > > $ llvm-cov gcov -a -c -u -f -b <input>.gcda -- gcno=<input>.gcno

> > > 1 <func>: checksum mismatch, \

> > >   (<lineno chksum A>, <cfg chksum B>) != (<lineno chksum A>, <cfg chksum C>)

> > > 2 Invalid .gcda File!

> > > ...

> > >

> > > Fix up the function signatures so calling this function interprets its

> > > parameters correctly and computes the correct cfg checksum. In

> > > particular, in clang-11, the additional checksum is no longer optional.

> >

> > Which tree is this against?  I'm seeing quite a lot of rejects against

> > Linus's current.

> 

> Today's linux-next; the only recent changes to this single source file

> since my last patches were:

> 

> commit b3c4e66c908b ("gcov: combine common code")

> commit 17d0508a080d ("gcov: use kvmalloc()")

> 

> both have your sign off, so I assume those are in your tree?


Yes, I presently have

gcov-clang-drop-support-for-clang-10-and-older.patch
gcov-combine-common-code.patch
gcov-simplify-buffer-allocation.patch
gcov-use-kvmalloc.patch

But this patch ("gcov: re-fix clang-11+ support") has cc:stable, so it
should be against Linus's tree, to give the -stable trees something
more mergeable.
diff mbox series

Patch

diff --git a/kernel/gcov/clang.c b/kernel/gcov/clang.c
index d41f5ecda9db..1747204541bf 100644
--- a/kernel/gcov/clang.c
+++ b/kernel/gcov/clang.c
@@ -69,7 +69,9 @@  struct gcov_fn_info {
 
 	u32 ident;
 	u32 checksum;
+#if CONFIG_CLANG_VERSION < 110000
 	u8 use_extra_checksum;
+#endif
 	u32 cfg_checksum;
 
 	u32 num_counters;
@@ -111,6 +113,7 @@  void llvm_gcda_start_file(const char *orig_filename, u32 version, u32 checksum)
 }
 EXPORT_SYMBOL(llvm_gcda_start_file);
 
+#if CONFIG_CLANG_VERSION < 110000
 void llvm_gcda_emit_function(u32 ident, u32 func_checksum,
 		u8 use_extra_checksum, u32 cfg_checksum)
 {
@@ -126,6 +129,21 @@  void llvm_gcda_emit_function(u32 ident, u32 func_checksum,
 	info->cfg_checksum = cfg_checksum;
 	list_add_tail(&info->head, &current_info->functions);
 }
+#else
+void llvm_gcda_emit_function(u32 ident, u32 func_checksum, u32 cfg_checksum)
+{
+	struct gcov_fn_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+	if (!info)
+		return;
+
+	INIT_LIST_HEAD(&info->head);
+	info->ident = ident;
+	info->checksum = func_checksum;
+	info->cfg_checksum = cfg_checksum;
+	list_add_tail(&info->head, &current_info->functions);
+}
+#endif
 EXPORT_SYMBOL(llvm_gcda_emit_function);
 
 void llvm_gcda_emit_arcs(u32 num_counters, u64 *counters)
@@ -256,11 +274,16 @@  int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)
 		!list_is_last(&fn_ptr2->head, &info2->functions)) {
 		if (fn_ptr1->checksum != fn_ptr2->checksum)
 			return false;
+#if CONFIG_CLANG_VERSION < 110000
 		if (fn_ptr1->use_extra_checksum != fn_ptr2->use_extra_checksum)
 			return false;
 		if (fn_ptr1->use_extra_checksum &&
 			fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)
 			return false;
+#else
+		if (fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)
+			return false;
+#endif
 		fn_ptr1 = list_next_entry(fn_ptr1, head);
 		fn_ptr2 = list_next_entry(fn_ptr2, head);
 	}
@@ -378,17 +401,22 @@  size_t convert_to_gcda(char *buffer, struct gcov_info *info)
 
 	list_for_each_entry(fi_ptr, &info->functions, head) {
 		u32 i;
-		u32 len = 2;
-
-		if (fi_ptr->use_extra_checksum)
-			len++;
 
 		pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION);
-		pos += store_gcov_u32(buffer, pos, len);
+#if CONFIG_CLANG_VERSION < 110000
+		pos += store_gcov_u32(buffer, pos,
+			fi_ptr->use_extra_checksum ? 3 : 2);
+#else
+		pos += store_gcov_u32(buffer, pos, 3);
+#endif
 		pos += store_gcov_u32(buffer, pos, fi_ptr->ident);
 		pos += store_gcov_u32(buffer, pos, fi_ptr->checksum);
+#if CONFIG_CLANG_VERSION < 110000
 		if (fi_ptr->use_extra_checksum)
 			pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);
+#else
+		pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);
+#endif
 
 		pos += store_gcov_u32(buffer, pos, GCOV_TAG_COUNTER_BASE);
 		pos += store_gcov_u32(buffer, pos, fi_ptr->num_counters * 2);