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
|