blob: 7b180635cdb652df89954199e66f19e6eaee6103 [file] [log] [blame]
From e13b2b6f8443da660cafa0679c3b16240843ce9f Mon Sep 17 00:00:00 2001
From: Peter Oberparleiter <oberpar@linux.ibm.com>
Date: Fri, 24 May 2019 17:16:56 +0200
Subject: [PATCH 2/2] geninfo: Add intermediate JSON format support
This change adds support for parsing the output of gcov's intermediate
JSON file format as implemented by GCC version 9.
Note: The way that the intermediate file format support is implemented
in geninfo removes the need to parse .gcno files directly. Since geninfo
does not include support for parsing GCC 9 .gcno files, using the
intermediate format is the only option for geninfo to collect coverage
data generated by GCC version 9.
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
---
bin/geninfo | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 160 insertions(+), 2 deletions(-)
Upstream-Status: Backport
Download URL: https://github.com/linux-test-project/lcov/commit/75fbae1cfc5027f818a0bb865bf6f96fab3202da
diff --git a/bin/geninfo b/bin/geninfo
index 0276666..cceb782 100755
--- a/bin/geninfo
+++ b/bin/geninfo
@@ -59,6 +59,9 @@ use File::Copy qw(copy);
use Getopt::Long;
use Digest::MD5 qw(md5_base64);
use Cwd qw/abs_path/;
+use PerlIO::gzip;
+use JSON qw(decode_json);
+
if( $^O eq "msys" )
{
require File::Spec::Win32;
@@ -474,7 +477,8 @@ if ($rc_intermediate eq "0") {
$intermediate = 1;
} elsif (lc($rc_intermediate) eq "auto") {
# Use intermediate format if supported by gcov
- $intermediate = $gcov_caps->{'intermediate-format'} ? 1 : 0;
+ $intermediate = ($gcov_caps->{'intermediate-format'} ||
+ $gcov_caps->{'json-format'}) ? 1 : 0;
} else {
die("ERROR: invalid value for geninfo_intermediate: ".
"'$rc_intermediate'\n");
@@ -2084,6 +2088,48 @@ sub read_intermediate_text($$)
}
+#
+# read_intermediate_json(gcov_filename, data, basedir_ref)
+#
+# Read gcov intermediate JSON format in GCOV_FILENAME and add the resulting
+# data to DATA in the following format:
+#
+# data: source_filename -> file_data
+# file_data: GCOV JSON data for file
+#
+# Also store the value for current_working_directory to BASEDIR_REF.
+#
+
+sub read_intermediate_json($$$)
+{
+ my ($gcov_filename, $data, $basedir_ref) = @_;
+ my $fd;
+ my $text;
+ my $json;
+
+ open($fd, "<:gzip", $gcov_filename) or
+ die("ERROR: Could not read $gcov_filename: $!\n");
+ local $/;
+ $text = <$fd>;
+ close($fd);
+
+ $json = decode_json($text);
+ if (!defined($json) || !exists($json->{"files"}) ||
+ ref($json->{"files"} ne "ARRAY")) {
+ die("ERROR: Unrecognized JSON output format in ".
+ "$gcov_filename\n");
+ }
+
+ $$basedir_ref = $json->{"current_working_directory"};
+
+ for my $file (@{$json->{"files"}}) {
+ my $filename = $file->{"file"};
+
+ $data->{$filename} = $file;
+ }
+}
+
+
#
# intermediate_text_to_info(fd, data, srcdata)
#
@@ -2173,6 +2219,104 @@ sub intermediate_text_to_info($$$)
}
+#
+# intermediate_json_to_info(fd, data, srcdata)
+#
+# Write DATA in info format to file descriptor FD.
+#
+# data: filename -> file_data:
+# file_data: GCOV JSON data for file
+#
+# srcdata: filename -> [ excl, brexcl, checksums ]
+# excl: lineno -> 1 for all lines for which to exclude all data
+# brexcl: lineno -> 1 for all lines for which to exclude branch data
+# checksums: lineno -> source code checksum
+#
+# Note: To simplify processing, gcov data is not combined here, that is counts
+# that appear multiple times for the same lines/branches are not added.
+# This is done by lcov/genhtml when reading the data files.
+#
+
+sub intermediate_json_to_info($$$)
+{
+ my ($fd, $data, $srcdata) = @_;
+ my $branch_num = 0;
+
+ return if (!%{$data});
+
+ print($fd "TN:$test_name\n");
+ for my $filename (keys(%{$data})) {
+ my ($excl, $brexcl, $checksums);
+ my $file_data = $data->{$filename};
+
+ if (defined($srcdata->{$filename})) {
+ ($excl, $brexcl, $checksums) = @{$srcdata->{$filename}};
+ }
+
+ print($fd "SF:$filename\n");
+
+ # Function data
+ if ($func_coverage) {
+ for my $d (@{$file_data->{"functions"}}) {
+ my $line = $d->{"start_line"};
+ my $count = $d->{"execution_count"};
+ my $name = $d->{"name"};
+
+ next if (!defined($line) || !defined($count) ||
+ !defined($name) || $excl->{$line});
+
+ print($fd "FN:$line,$name\n");
+ print($fd "FNDA:$count,$name\n");
+ }
+ }
+
+ # Line data
+ for my $d (@{$file_data->{"lines"}}) {
+ my $line = $d->{"line_number"};
+ my $count = $d->{"count"};
+ my $c;
+ my $branches = $d->{"branches"};
+ my $unexec = $d->{"unexecuted_block"};
+
+ next if (!defined($line) || !defined($count) ||
+ $excl->{$line});
+
+ if (defined($unexec) && $unexec && $count == 0) {
+ $unexec = 1;
+ } else {
+ $unexec = 0;
+ }
+
+ if ($checksum && exists($checksums->{$line})) {
+ $c = ",".$checksums->{$line};
+ } else {
+ $c = "";
+ }
+ print($fd "DA:$line,$count$c\n");
+
+ $branch_num = 0;
+ # Branch data
+ if ($br_coverage && !$brexcl->{$line}) {
+ for my $b (@$branches) {
+ my $brcount = $b->{"count"};
+
+ if (!defined($brcount) || $unexec) {
+ $brcount = "-";
+ }
+ print($fd "BRDA:$line,0,$branch_num,".
+ "$brcount\n");
+
+ $branch_num++;
+ }
+ }
+
+ }
+
+ print($fd "end_of_record\n");
+ }
+}
+
+
sub get_output_fd($$)
{
my ($outfile, $file) = @_;
@@ -2243,6 +2387,8 @@ sub process_intermediate($$$)
my $srcdata;
my $is_graph = 0;
my ($out, $err, $rc);
+ my $json_basedir;
+ my $json_format;
info("Processing %s\n", abs2rel($file, $dir));
@@ -2296,6 +2442,12 @@ sub process_intermediate($$$)
unlink($gcov_filename);
}
+ for my $gcov_filename (glob("*.gcov.json.gz")) {
+ read_intermediate_json($gcov_filename, \%data, \$json_basedir);
+ unlink($gcov_filename);
+ $json_format = 1;
+ }
+
if (!%data) {
warn("WARNING: GCOV did not produce any data for $file\n");
return;
@@ -2304,6 +2456,8 @@ sub process_intermediate($$$)
# Determine base directory
if (defined($base_directory)) {
$base = $base_directory;
+ } elsif (defined($json_basedir)) {
+ $base = $json_basedir;
} else {
$base = $fdir;
@@ -2331,7 +2485,11 @@ sub process_intermediate($$$)
# Generate output
$fd = get_output_fd($output_filename, $file);
- intermediate_text_to_info($fd, \%data, $srcdata);
+ if ($json_format) {
+ intermediate_json_to_info($fd, \%data, $srcdata);
+ } else {
+ intermediate_text_to_info($fd, \%data, $srcdata);
+ }
close($fd);
chdir($cwd);
--
2.17.1