[MDEV-26102] dgcov: add support for *.gcda.gcov.json.gz files of gcov 9.1+ Created: 2021-07-07  Updated: 2022-12-13  Resolved: 2022-12-02

Status: Closed
Project: MariaDB Server
Component/s: Scripts & Clients, Tests
Fix Version/s: 10.3.38, 10.4.28, 10.5.19, 10.6.12, 10.7.8, 10.8.7, 10.9.5, 10.10.3

Type: Task Priority: Minor
Reporter: Anel Husakovic Assignee: Anel Husakovic
Resolution: Fixed Votes: 0
Labels: dgcov, foundation

Issue Links:
Relates
relates to MDEV-20787 Script dgcov.pl does not work Closed

 Description   

1. dgcov should be supported with gcc version gcc 4.9.4+ since there is -i option introduced.
2. json format found from here that is introduced with 9.1.0. Looking from all release changes for 9.1.0

The following improvements to the gcov command-line utility have been made.
 
The gcov tool received a new option --use-hotness-colors (-q) that can provide perf-like coloring of hot functions.
The gcov tool has changed its intermediate format to a new JSON format.

and seems that in that version intermediate format was deprecated.
Additional links:
[1] Zulip analysis
[2] Support GCOV intermediate format



 Comments   
Comment by Sergei Golubchik [ 2021-07-17 ]

perl bundles JSON::PP starting from the version v5.13.9. While not the fastest it can hopefully be enough for dgcov purposes and will work without additional dependencies.

Comment by Anel Husakovic [ 2021-07-19 ]

serg can I try to implement this?
JSON::PP is the only thing I should take care of ?

Comment by Sergei Golubchik [ 2021-07-20 ]

of course, you're the assignee

I don't understand the second question. What do you mean to "take care of JSON::PP" ?

Comment by Anel Husakovic [ 2021-07-21 ]

Well I mean, do I need any preprocessing after it? I managed to create the script where locally everything works.
However I have a problem with gcno files which should be generated when compiling - they are not created:

$ gcc --version && gcov --version && g++ --version
gcc (Ubuntu 9.4.0-1ubuntu1~18.04) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
gcov (Ubuntu 9.4.0-1ubuntu1~18.04) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.
 
g++ (Ubuntu 9.4.0-1ubuntu1~18.04) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
$ cmake . -DCMAKE_BUILD_TYPE=Debug -DCONC_WITH_{UNITTEST,SSL}=OFF -DWITH_EMBEDDED_SERVER=OFF -DWITH_UNIT_TESTS=OFF -DPLUGIN_{ARCHIVE,TOKUDB,MROONGA,OQGRAPH,ROCKSDB,CONNECT,PERFSCHEMA,SPIDER,SPHINX}=NO -DWITH_SAFEMALLOC=OFF -DWITH_SSL=bundled -DENABLE_GCOV=ON
 
# Result with empty files

Locally tests:

$ ls
main1.h  main.c  Makefile  test.pl
$ gcc --coverage main.c 
$ ls
a.out  main1.h  main.c  main.gcno  Makefile  test.pl
 
$ gcc --coverage -c main.c 
$ ls
main1.h  main.c  main.gcno  main.o  Makefile  test.pl

Also I found some [regression](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97193) in gcov and I'm not sure is it related.

Comment by Anel Husakovic [ 2021-07-24 ]

Hi Serg,
can you please review 6296c32b10ed2 have problem with write_coverage of created hash cov from function gcov_one_file?

Comment by Sergei Golubchik [ 2021-07-24 ]

Haven't we agreed to use JSON::PP ?

$ perldoc JSON::PP

Comment by Anel Husakovic [ 2021-07-26 ]

Yes and I have used json_pp -f <from-type> -t <to-type> here to pretty (default option -t json -json_opt pretty) the json file.
Other type -t dumper can be used, but not sure, how to use the output of Data::Dumper ($VAR1) on one or multiple files.
Did you mean to use that conversion?

json_pp dumper

Show all

$VAR1 = {
          'files' => [
                       {
                         'lines' => [
                                      {
                                        'line_number' => 3,
                                        'branches' => [],
                                        'unexecuted_block' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' ),
                                        'function_name' => 'main',
                                        'count' => 1
                                      },
                                      {
                                        'count' => 1,
                                        'line_number' => 5,
                                        'unexecuted_block' => $VAR1->{'files'}[0]{'lines'}[0]{'unexecuted_block'},
                                        'branches' => [],
                                        'function_name' => 'main'
                                      },
                                      {
                                        'count' => 1,
                                        'unexecuted_block' => $VAR1->{'files'}[0]{'lines'}[0]{'unexecuted_block'},
                                        'branches' => [],
                                        'line_number' => 6,
                                        'function_name' => 'main'
                                      },
                                      {
                                        'branches' => [],
                                        'unexecuted_block' => $VAR1->{'files'}[0]{'lines'}[0]{'unexecuted_block'},
                                        'line_number' => 7,
                                        'function_name' => 'main',
                                        'count' => 1
                                      }
                                    ],
                         'functions' => [
                                          {
                                            'start_column' => 5,
                                            'demangled_name' => 'main',
                                            'end_column' => 1,
                                            'blocks' => 5,
                                            'start_line' => 3,
                                            'end_line' => 8,
                                            'blocks_executed' => 5,
                                            'name' => 'main',
                                            'execution_count' => 1
                                          }
                                        ],
                         'file' => 'main.c'
                       },
                       {
                         'functions' => [
                                          {
                                            'demangled_name' => 'sum',
                                            'start_column' => 5,
                                            'end_column' => 1,
                                            'blocks' => 2,
                                            'end_line' => 6,
                                            'start_line' => 3,
                                            'execution_count' => 1,
                                            'name' => 'sum',
                                            'blocks_executed' => 2
                                          }
                                        ],
                         'file' => 'main1.h',
                         'lines' => [
                                      {
                                        'function_name' => 'sum',
                                        'line_number' => 3,
                                        'unexecuted_block' => $VAR1->{'files'}[0]{'lines'}[0]{'unexecuted_block'},
                                        'branches' => [],
                                        'count' => 1
                                      },
                                      {
                                        'count' => 1,
                                        'line_number' => 5,
                                        'unexecuted_block' => $VAR1->{'files'}[0]{'lines'}[0]{'unexecuted_block'},
                                        'branches' => [],
                                        'function_name' => 'sum'
                                      }
                                    ]
                       }
                     ],
          'data_file' => 'main.gcda',
          'format_version' => '1',
          'gcc_version' => '9.4.0',
          'current_working_directory' => '/home/anel/mariadb/gcov-analysis/anel-gcc9'
        };

Comment by Anel Husakovic [ 2021-07-26 ]

Sorry, I haven't read perldoc. Reading/testing. Thanks.

Comment by Sergei Golubchik [ 2021-07-26 ]

Why are you even looking at json_pp? Just use JSON::PP module. Like this:

#!/usr/bin/perl -l
 
use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
use JSON::PP;
 
my $js;
gunzip $ARGV[0] => \$js or die "gunzip($ARGV[0]): $GunzipError";
my $obj=decode_json $js;
 
for my $file (@{$obj->{files}}) {
  print "file: $file->{file}";
  for my $fn (@{$file->{functions}}) {
    print "..function: ", $fn->{demangled_name} || $fn-{name};
  }
}

This is a complete demo program, if you run it with a gcda.gcov.json.gz file as an argument, it'll print you all functions in all files in this json file. For example,

$ ./a.pl gen_lex_token.cc.gcda.gcov.json.gz 
file: sql/gen_lex_token.cc
..function: set_token(int, char const*)
..function: set_start_expr_token(int)
..function: compute_tokens()
..function: print_tokens()
..function: main

Comment by Anel Husakovic [ 2021-07-27 ]

Thanks for help serg it helped me a lot.
New patch: 203aa38f9b6606d
Example of the result:

$./mtr --gcov is_check_constraints --record && cat var/last_changes.dgcov
 
*********************
dgcov sql/sql_show.cc
*********************
@@ +6601,7 @@ static int get_check_constraints_record(THD *thd, TABLE_LIST *tables,
         : 6601:      }
         : 6602:#endif
         : 6603:      Virtual_column_info *check= tables->table->check_constraints[i];
       44: 6605:      table->field[0]->store(STRING_WITH_LEN("definition"), system_charset_info);
         : 6606:      table->field[3]->store(check->name.str, check->name.length,
         : 6607:                             system_charset_info);

Comment by Anel Husakovic [ 2021-07-30 ]

Hi Serg,
new patch 85aa3f8cf66per your review .

Comment by Anel Husakovic [ 2022-01-18 ]

Test of patch - with appended commit message (about usage of gcc version <9 and >=9 - noted error in regex - so new patch will be)

  • gcc version < 9 (gcov uses -i format as a file)

    # -DENABLE_GCOV=ON -DCMAKE_\{C_COMPILER=gcc,CXX_COMPILER=g++\}-7
    $ git cherry-pick 25d66172f4a2ba1c8fd25a68032e3d9b782e6adb  # note bb-10.2-anel-MDEV-18284-json_compact commit
    $ cmake --build . -- -j8
    $ ./mtr --gcov func_json
    $ cat var/last_changes.dgcov 
    ****************
    dgcov sql/item.h
    ****************
    @@ +4564,7 @@ class Item_ref :public Item_ident
             : 4564:  {
             : 4565:    return ref ? (*ref)->real_item() : this;
             : 4566:  }
            1: 4567:  bool is_json_type() { return (*ref)->is_json_type(); }
             : 4568:  bool walk(Item_processor processor, bool walk_subquery, void *arg)
             : 4569:  { 
             : 4570:    if (ref && *ref)
    

  • gcov version 9 (gcc version 9 too)

     
    $ sudo update-alternatives --display gcc
    $ sudo update-alternatives --config gcc #(to 9)
    $ gcc --version
    gcc (Ubuntu 9.4.0-1ubuntu1~18.04) 9.4.0
    $ g++ --version
    g++ (Ubuntu 9.4.0-1ubuntu1~18.04) 9.4.0
    # Remove old gcov (symlink to gcov-7)
    $ sudo rm /usr/bin/gcov
    # Make it symlink to gcov-9
    $ sudo ln -s /usr/bin/gcov-9 /usr/bin/gcov
     
    # Remove old files
    $ git clean -dffx
    $ cmake . -DCMAKE_BUILD_TYPE=Debug -DPLUGIN_{ARCHIVE,TOKUDB,MROONGA,OQGRAPH,ROCKSDB,CONNECT,PERFSCHEMA,SPIDER,SPHINX}=NO -DENABLE_GCOV=ON -DCMAKE_\{C_COMPILER=gcc,CXX_COMPILER=g++\}-9
    $ cmake --build . -- -j8
     
    $ git cherry-pick 25d66172f4a2ba1c8fd25a68032e3d9b782e6adb  # note bb-10.2-anel-MDEV-18284-json_compact commit
    $ ./mtr --gcov func_json
    # Example of generated file: ./mysys/CMakeFiles/mysys.dir/list.c.gcda.gcov.json.gz
    $ cat var/last_changes.dgcov 
    ****************
    dgcov sql/item.h
    ****************
    @@ +4564,7 @@ class Item_ref :public Item_ident
             : 4564:  {
             : 4565:    return ref ? (*ref)->real_item() : this;
             : 4566:  }
            1: 4567:  bool is_json_type() { return (*ref)->is_json_type(); }
             : 4568:  bool walk(Item_processor processor, bool walk_subquery, void *arg)
             : 4569:  { 
             : 4570:    if (ref && *ref)
    

Same result as above.

New patch (removed unused line) : 5599795abe1faee79 serg

Generated at Thu Feb 08 09:42:45 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.