[PATCH v2 1/2] scripts/code_cov_parse_info: add support for lcov/geninfo >1.14 formats

Jari Tahvanainen <[email protected]>
Newsgroups org.freedesktop.lists.igt-dev
Message-ID <[email protected]>
Add support changes related function coverage data format within .info
files produced by the recent compiler/toolchain versions.

Current assumed/supported .info file is for lcov/geninfo 1.14.
   FN:<line number of function start>,<function name>
   FNDA:<execution count>,<function name>
   FNF:<number of functions found>
   FNH:<number of function hit>

There is change caused by gcc 9 tool chain, requiring lcov/geninfo 2.0.
   https://manpages.ubuntu.com/manpages/noble/man1/geninfo.1.html
   FN:<line number of function start>,[<function end>,]<function name>
   The 'end' line number is optional, and is generated only if the 
   compiler/toolchain version is recent enough to generate the data.

 The format of the function coverage data has changed from LCOV 2.2 onward.
   https://manpages.ubuntu.com/manpages/questing/man1/geninfo.1.html
   First, the leader:
   FNL:<index>,<line number of function start>[,line nbr of function end>]
   Then the aliases of the function; there will be at least one alias.
   All aliases of a particular function share the same index.
   FNA:<index>,<execution count>,<name>
   The now-obsolete function data format is:
   FN:<line number of function start>,[<function end>,]<function name>

v2: fixing name on email for submitter. 

Signed-off-by: Jari Tahvanainen <[email protected]>
Acked-by: Kamil Konieczny <[email protected]>
---
 scripts/code_cov_parse_info | 106 ++++++++++++++++++++++++++++++++++--
 1 file changed, 100 insertions(+), 6 deletions(-)

diff --git a/scripts/code_cov_parse_info b/scripts/code_cov_parse_info
index a3fef1d59..97f325c85 100755
--- a/scripts/code_cov_parse_info
+++ b/scripts/code_cov_parse_info
@@ -37,6 +37,10 @@ my $verbose = 0;
 my $ignore_unused = 0;
 my $skip_func = 0;
 
+my $lcov_version = eval {
+	my $var = `lcov --version|grep -Eo '[0-9]+(\.[0-9]+)'|head -1`;
+	$var;
+};
 my $has_json_support = eval {
 	require Cpanel::JSON::XS;
 	Cpanel::JSON::XS->import(qw(decode_json));
@@ -459,6 +463,7 @@ sub read_info($)
 	my $ignore = 0;
 	my $source = $before_sf;
 	my $func = $before_sf;
+	my $alias = $before_sf;
 	my $cur_test = "";
 	my %cached;
 
@@ -526,13 +531,56 @@ sub read_info($)
 
 		next if ($ignore);
 
+		# Function coverage, the leader
+		# FN:<function index>,<line number of the function start><line number of the function end>
+		# this seems to be format for lcov/geninfo package 2.3
+		if (m/^FNL:(-?\d+),(-?\d+),(-?\d+)/) {
+			my $ln = $2;
+			my $end_ln = $3;
+
+			$func = $1;
+			$has_func = 1;
+
+			if (is_function_excluded($func)) {
+				$skip_func = 1;
+				next;
+			}
+
+			$skip_func = 0;
+
+			$record{files}{$source}{func}{$func}{start_line} = $ln;
+			$record{files}{$source}{func}{$func}{end_line} = $end_ln;
+			$all_func{$func}{$source}->{ln} = $ln;
+			next;
+		}
 		# Function coverage
+		# FN:<line number of function start>,<line number of the function end><function name>
+		# this seems to be format for lcov/geninfo 2.0, obsoleted on 2.3
+		elsif (m/^FN:(-?\d+),(-?\d+),(\w+)/) {
+			my $ln = $1;
+			my $end_ln = $2;
+
+			$func = $3;
+			$has_func = 1;
+
+			if (is_function_excluded($func)) {
+				$skip_func = 1;
+				next;
+			}
+
+			$skip_func = 0;
 
+			$record{files}{$source}{func}{$func}{start_line} = $ln;
+			$record{files}{$source}{func}{$func}{end_line} = $end_ln;
+			$all_func{$func}{$source}->{ln} = $ln;
+			next;
+		}
 		# FN:<line number of function start>,<function name>
 		# Note: /w+ intentionally removes IPA gcc-optimization names, as
 		# this is more related to branch coverage
-		if (m/^FN:(-?\d+),(\w+)/) {
+		elsif (m/^FN:(-?\d+),(\w+)/) {
 			my $ln = $1;
+			my $start_ln = $2;
 
 			$func = $2;
 			$has_func = 1;
@@ -549,11 +597,38 @@ sub read_info($)
 			next;
 		}
 
-		# Parse functions that were actually used
+		# Parse functions that were actually used (package version >2.0)
+		# FNA:<function index>,<execution count><function name>
+		if (m/^FNA:(-?\d+),(-?\d+),(\w+)/) {
+			my $count = $2;
+
+			# Negative gcov results are possible, as reported at:
+			# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67937
+			# Lcov ignores those. So, let's do the same here.
+			next if ($count <= 0);
+
+			$func = $1;
+			$alias = $3;
+			$has_func = 1;
+
+			if (is_function_excluded($alias)) {
+				$skip_func = 1;
+				next;
+			}
+
+			$skip_func = 0;
+			$was_used = 1;
+
+			$record{files}{$source}{func}{$func}{execution_count} += $count;
+			$record{files}{$source}{func}{$func}{alias} = $alias;
+			$used_func{$func}{$source}->{count} += $count;
+			next;
+		}
+		# Parse functions that were actually used (package version <=2.0)
 		# FNDA:<execution count>,<function name>
 		# Note: /w+ intentionally removes IPA gcc-optimization names, as
 		# this is more related to branch coverage
-		if (m/^FNDA:(-?\d+),(\w+)/) {
+		elsif (m/^FNDA:(-?\d+),(\w+)/) {
 			my $count = $1;
 
 			# Negative gcov results are possible, as reported at:
@@ -745,6 +820,7 @@ sub write_info_file($)
 	# Fills $data with the contents to be stored at the file
 	foreach my $source(sort keys %{$record{files}}) {
 		next if (!$used_source{$source});
+		next if is_file_excluded($source);
 
 		if ($source ne $before_sf) {
 			$data .= "SF:$source\n";
@@ -754,11 +830,29 @@ sub write_info_file($)
 			if ($func ne $before_sf) {
 				my $fn;
 				my $fnda;
-
-				if (defined($record{files}{$source}{func}{$func}{start_line})) {
+				#lcov/geninfo 2.3 (>2.0) has additional leader
+				#https://manpages.ubuntu.com/manpages/questing/man1/geninfo.1.html
+				if ($lcov_version>2.0) {
+					$data .= "FNL:$func," . $record{files}{$source}{func}{$func}{start_line} . "," . $record{files}{$source}{func}{$func}{end_line} . "\n";
+				}
+				#lcov/geninfo 2.0 (>1.14) has also end_line defined for FN
+				#https://manpages.ubuntu.com/manpages/noble/man1/geninfo.1.html
+				elsif ($lcov_version==2.0) {
+					$data .= "FN:" . $record{files}{$source}{func}{$func}{start_line} . "," . $record{files}{$source}{func}{$func}{end_line} . ",$func\n";
+				}
+				#lcov/geninfo 1.14
+				elsif (defined($record{files}{$source}{func}{$func}{start_line})) {
 					$data .= "FN:" . $record{files}{$source}{func}{$func}{start_line} . ",$func\n";
 				}
-				if (defined($record{files}{$source}{func}{$func}{execution_count})) {
+				#lcov/geninfo 2.3 (>2.0) has the function covered as FNA line
+				#https://manpages.ubuntu.com/manpages/questing/man1/geninfo.1.html
+				if ($lcov_version>2.0) {
+					if ($record{files}{$source}{func}{$func}{alias}) {
+						$data .= "FNA:$func," . $record{files}{$source}{func}{$func}{execution_count} . "," . $record{files}{$source}{func}{$func}{alias} . "\n";
+					}
+				}
+				#lcov/geninfo 1.14 has the function covered as FNDA line
+				elsif (defined($record{files}{$source}{func}{$func}{execution_count})) {
 					$data .= "FNDA:" . $record{files}{$source}{func}{$func}{execution_count} . ",$func\n";
 				}
 
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.