1From e13b2b6f8443da660cafa0679c3b16240843ce9f Mon Sep 17 00:00:00 2001 2From: Peter Oberparleiter <oberpar@linux.ibm.com> 3Date: Fri, 24 May 2019 17:16:56 +0200 4Subject: [PATCH 2/2] geninfo: Add intermediate JSON format support 5 6This change adds support for parsing the output of gcov's intermediate 7JSON file format as implemented by GCC version 9. 8 9Note: The way that the intermediate file format support is implemented 10in geninfo removes the need to parse .gcno files directly. Since geninfo 11does not include support for parsing GCC 9 .gcno files, using the 12intermediate format is the only option for geninfo to collect coverage 13data generated by GCC version 9. 14 15Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com> 16--- 17 bin/geninfo | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++- 18 1 file changed, 160 insertions(+), 2 deletions(-) 19 20Upstream-Status: Backport 21Download URL: https://github.com/linux-test-project/lcov/commit/75fbae1cfc5027f818a0bb865bf6f96fab3202da 22 23diff --git a/bin/geninfo b/bin/geninfo 24index 0276666..cceb782 100755 25--- a/bin/geninfo 26+++ b/bin/geninfo 27@@ -59,6 +59,9 @@ use File::Copy qw(copy); 28 use Getopt::Long; 29 use Digest::MD5 qw(md5_base64); 30 use Cwd qw/abs_path/; 31+use PerlIO::gzip; 32+use JSON qw(decode_json); 33+ 34 if( $^O eq "msys" ) 35 { 36 require File::Spec::Win32; 37@@ -474,7 +477,8 @@ if ($rc_intermediate eq "0") { 38 $intermediate = 1; 39 } elsif (lc($rc_intermediate) eq "auto") { 40 # Use intermediate format if supported by gcov 41- $intermediate = $gcov_caps->{'intermediate-format'} ? 1 : 0; 42+ $intermediate = ($gcov_caps->{'intermediate-format'} || 43+ $gcov_caps->{'json-format'}) ? 1 : 0; 44 } else { 45 die("ERROR: invalid value for geninfo_intermediate: ". 46 "'$rc_intermediate'\n"); 47@@ -2084,6 +2088,48 @@ sub read_intermediate_text($$) 48 } 49 50 51+# 52+# read_intermediate_json(gcov_filename, data, basedir_ref) 53+# 54+# Read gcov intermediate JSON format in GCOV_FILENAME and add the resulting 55+# data to DATA in the following format: 56+# 57+# data: source_filename -> file_data 58+# file_data: GCOV JSON data for file 59+# 60+# Also store the value for current_working_directory to BASEDIR_REF. 61+# 62+ 63+sub read_intermediate_json($$$) 64+{ 65+ my ($gcov_filename, $data, $basedir_ref) = @_; 66+ my $fd; 67+ my $text; 68+ my $json; 69+ 70+ open($fd, "<:gzip", $gcov_filename) or 71+ die("ERROR: Could not read $gcov_filename: $!\n"); 72+ local $/; 73+ $text = <$fd>; 74+ close($fd); 75+ 76+ $json = decode_json($text); 77+ if (!defined($json) || !exists($json->{"files"}) || 78+ ref($json->{"files"} ne "ARRAY")) { 79+ die("ERROR: Unrecognized JSON output format in ". 80+ "$gcov_filename\n"); 81+ } 82+ 83+ $$basedir_ref = $json->{"current_working_directory"}; 84+ 85+ for my $file (@{$json->{"files"}}) { 86+ my $filename = $file->{"file"}; 87+ 88+ $data->{$filename} = $file; 89+ } 90+} 91+ 92+ 93 # 94 # intermediate_text_to_info(fd, data, srcdata) 95 # 96@@ -2173,6 +2219,104 @@ sub intermediate_text_to_info($$$) 97 } 98 99 100+# 101+# intermediate_json_to_info(fd, data, srcdata) 102+# 103+# Write DATA in info format to file descriptor FD. 104+# 105+# data: filename -> file_data: 106+# file_data: GCOV JSON data for file 107+# 108+# srcdata: filename -> [ excl, brexcl, checksums ] 109+# excl: lineno -> 1 for all lines for which to exclude all data 110+# brexcl: lineno -> 1 for all lines for which to exclude branch data 111+# checksums: lineno -> source code checksum 112+# 113+# Note: To simplify processing, gcov data is not combined here, that is counts 114+# that appear multiple times for the same lines/branches are not added. 115+# This is done by lcov/genhtml when reading the data files. 116+# 117+ 118+sub intermediate_json_to_info($$$) 119+{ 120+ my ($fd, $data, $srcdata) = @_; 121+ my $branch_num = 0; 122+ 123+ return if (!%{$data}); 124+ 125+ print($fd "TN:$test_name\n"); 126+ for my $filename (keys(%{$data})) { 127+ my ($excl, $brexcl, $checksums); 128+ my $file_data = $data->{$filename}; 129+ 130+ if (defined($srcdata->{$filename})) { 131+ ($excl, $brexcl, $checksums) = @{$srcdata->{$filename}}; 132+ } 133+ 134+ print($fd "SF:$filename\n"); 135+ 136+ # Function data 137+ if ($func_coverage) { 138+ for my $d (@{$file_data->{"functions"}}) { 139+ my $line = $d->{"start_line"}; 140+ my $count = $d->{"execution_count"}; 141+ my $name = $d->{"name"}; 142+ 143+ next if (!defined($line) || !defined($count) || 144+ !defined($name) || $excl->{$line}); 145+ 146+ print($fd "FN:$line,$name\n"); 147+ print($fd "FNDA:$count,$name\n"); 148+ } 149+ } 150+ 151+ # Line data 152+ for my $d (@{$file_data->{"lines"}}) { 153+ my $line = $d->{"line_number"}; 154+ my $count = $d->{"count"}; 155+ my $c; 156+ my $branches = $d->{"branches"}; 157+ my $unexec = $d->{"unexecuted_block"}; 158+ 159+ next if (!defined($line) || !defined($count) || 160+ $excl->{$line}); 161+ 162+ if (defined($unexec) && $unexec && $count == 0) { 163+ $unexec = 1; 164+ } else { 165+ $unexec = 0; 166+ } 167+ 168+ if ($checksum && exists($checksums->{$line})) { 169+ $c = ",".$checksums->{$line}; 170+ } else { 171+ $c = ""; 172+ } 173+ print($fd "DA:$line,$count$c\n"); 174+ 175+ $branch_num = 0; 176+ # Branch data 177+ if ($br_coverage && !$brexcl->{$line}) { 178+ for my $b (@$branches) { 179+ my $brcount = $b->{"count"}; 180+ 181+ if (!defined($brcount) || $unexec) { 182+ $brcount = "-"; 183+ } 184+ print($fd "BRDA:$line,0,$branch_num,". 185+ "$brcount\n"); 186+ 187+ $branch_num++; 188+ } 189+ } 190+ 191+ } 192+ 193+ print($fd "end_of_record\n"); 194+ } 195+} 196+ 197+ 198 sub get_output_fd($$) 199 { 200 my ($outfile, $file) = @_; 201@@ -2243,6 +2387,8 @@ sub process_intermediate($$$) 202 my $srcdata; 203 my $is_graph = 0; 204 my ($out, $err, $rc); 205+ my $json_basedir; 206+ my $json_format; 207 208 info("Processing %s\n", abs2rel($file, $dir)); 209 210@@ -2296,6 +2442,12 @@ sub process_intermediate($$$) 211 unlink($gcov_filename); 212 } 213 214+ for my $gcov_filename (glob("*.gcov.json.gz")) { 215+ read_intermediate_json($gcov_filename, \%data, \$json_basedir); 216+ unlink($gcov_filename); 217+ $json_format = 1; 218+ } 219+ 220 if (!%data) { 221 warn("WARNING: GCOV did not produce any data for $file\n"); 222 return; 223@@ -2304,6 +2456,8 @@ sub process_intermediate($$$) 224 # Determine base directory 225 if (defined($base_directory)) { 226 $base = $base_directory; 227+ } elsif (defined($json_basedir)) { 228+ $base = $json_basedir; 229 } else { 230 $base = $fdir; 231 232@@ -2331,7 +2485,11 @@ sub process_intermediate($$$) 233 234 # Generate output 235 $fd = get_output_fd($output_filename, $file); 236- intermediate_text_to_info($fd, \%data, $srcdata); 237+ if ($json_format) { 238+ intermediate_json_to_info($fd, \%data, $srcdata); 239+ } else { 240+ intermediate_text_to_info($fd, \%data, $srcdata); 241+ } 242 close($fd); 243 244 chdir($cwd); 245-- 2462.17.1 247 248