From: Peter O. <obe...@us...> - 2012-10-09 13:58:24
|
Update of /cvsroot/ltp/utils/analysis/lcov/bin In directory vz-cvs-4.sog:/tmp/cvs-serv1952/bin Modified Files: geninfo Log Message: geninfo: add automatic detection of base directory Add a heuristic to automatically determine the base directory when collecting coverage data. This heuristic should cover many, if not most cases of build systems moving files around during compilation (e.g. libtool, automake, etc.). The heuristic can be enabled or disabled using the configuration file directory 'geninfo_auto_base'. Index: geninfo =================================================================== RCS file: /cvsroot/ltp/utils/analysis/lcov/bin/geninfo,v retrieving revision 1.114 retrieving revision 1.115 diff -C2 -d -r1.114 -r1.115 *** geninfo 8 Oct 2012 15:03:23 -0000 1.114 --- geninfo 9 Oct 2012 13:58:22 -0000 1.115 *************** *** 53,57 **** use File::Basename; use File::Spec::Functions qw /abs2rel catdir file_name_is_absolute splitdir ! splitpath/; use Getopt::Long; use Digest::MD5 qw(md5_base64); --- 53,57 ---- use File::Basename; use File::Spec::Functions qw /abs2rel catdir file_name_is_absolute splitdir ! splitpath catpath/; use Getopt::Long; use Digest::MD5 qw(md5_base64); *************** *** 178,194 **** sub read_bb_value(*;$); sub read_bb_string(*$); ! sub read_bb($$); sub read_bbg_word(*;$); sub read_bbg_value(*;$); sub read_bbg_string(*); ! sub read_bbg_lines_record(*$$$$$$); ! sub read_bbg($$); sub read_gcno_word(*;$$); sub read_gcno_value(*$;$$); sub read_gcno_string(*$); ! sub read_gcno_lines_record(*$$$$$$$); sub determine_gcno_split_crc($$$); ! sub read_gcno_function_record(*$$$$$); ! sub read_gcno($$); sub get_gcov_capabilities(); sub get_overall_line($$$$); --- 178,194 ---- sub read_bb_value(*;$); sub read_bb_string(*$); ! sub read_bb($); sub read_bbg_word(*;$); sub read_bbg_value(*;$); sub read_bbg_string(*); ! sub read_bbg_lines_record(*$$$$$); ! sub read_bbg($); sub read_gcno_word(*;$$); sub read_gcno_value(*$;$$); sub read_gcno_string(*$); ! sub read_gcno_lines_record(*$$$$$$); sub determine_gcno_split_crc($$$); ! sub read_gcno_function_record(*$$$$); ! sub read_gcno($); sub get_gcov_capabilities(); sub get_overall_line($$$$); *************** *** 249,252 **** --- 249,253 ---- our $func_coverage = 1; our $br_coverage = 0; + our $rc_auto_base = 1; our $cwd = `pwd`; *************** *** 300,303 **** --- 301,305 ---- "geninfo_compat" => \$opt_compat, "geninfo_adjust_src_path" => \$rc_adjust_src_path, + "geninfo_auto_base" => \$rc_auto_base, "lcov_function_coverage" => \$func_coverage, "lcov_branch_coverage" => \$br_coverage, *************** *** 936,951 **** if (is_compat($COMPAT_MODE_HAMMER)) { ! ($instr, $graph) = read_bbg($bb_filename, $base_dir); } else { ! ($instr, $graph) = read_bb($bb_filename, $base_dir); } } else { ! ($instr, $graph) = read_gcno($bb_filename, $base_dir); } # Set $object_dir to real location of object files. This may differ # from $da_dir if the graph file is just a link to the "real" object --- 938,960 ---- if (is_compat($COMPAT_MODE_HAMMER)) { ! ($instr, $graph) = read_bbg($bb_filename); } else { ! ($instr, $graph) = read_bb($bb_filename); } } else { ! ($instr, $graph) = read_gcno($bb_filename); } + # Try to find base directory automatically if requested by user + if ($rc_auto_base) { + $base_dir = find_base_from_graph($base_dir, $instr, $graph); + } + + ($instr, $graph) = adjust_graph_filenames($base_dir, $instr, $graph); + # Set $object_dir to real location of object files. This may differ # from $da_dir if the graph file is just a link to the "real" object *************** *** 976,979 **** --- 985,989 ---- # Change to directory containing data files and apply GCOV + debug("chdir($base_dir)\n"); chdir($base_dir); *************** *** 2222,2237 **** if (is_compat($COMPAT_MODE_HAMMER)) { ! ($instr, $graph) = read_bbg($graph_filename, $base_dir); } else { ! ($instr, $graph) = read_bb($graph_filename, $base_dir); } } else { ! ($instr, $graph) = read_gcno($graph_filename, $base_dir); } if (!$no_markers) { # Apply exclusion marker data to graph file data --- 2232,2254 ---- if (is_compat($COMPAT_MODE_HAMMER)) { ! ($instr, $graph) = read_bbg($graph_filename); } else { ! ($instr, $graph) = read_bb($graph_filename); } } else { ! ($instr, $graph) = read_gcno($graph_filename); } + # Try to find base directory automatically if requested by user + if ($rc_auto_base) { + $base_dir = find_base_from_graph($base_dir, $instr, $graph); + } + + ($instr, $graph) = adjust_graph_filenames($base_dir, $instr, $graph); + if (!$no_markers) { # Apply exclusion marker data to graph file data *************** *** 2480,2501 **** # ! # adjust_graph_filenames(instr, graph) # ! # Apply geninfo_adjust_src_path setting to graph file data. # ! sub adjust_graph_filenames($$) { ! my ($instr, $graph) = @_; ! return ($instr, $graph) if (!defined($adjust_src_pattern)); foreach my $filename (keys(%{$instr})) { my $old_filename = $filename; ! next if ($filename !~ ! s/$adjust_src_pattern/$adjust_src_replace/g); ! $instr->{$filename} = delete($instr->{$old_filename}); } --- 2497,2604 ---- # ! # parent_dir(dir) # ! # Return parent directory for DIR. DIR must not contain relative path ! # components. # ! sub parent_dir($) { ! my ($dir) = @_; ! my ($v, $d, $f) = splitpath($dir, 1); ! my @dirs = splitdir($d); ! pop(@dirs); ! ! return catpath($v, catdir(@dirs), $f); ! } ! ! # ! # find_base_from_graph(base_dir, instr, graph) ! # ! # Try to determine the base directory of the graph file specified by INSTR ! # and GRAPH. The base directory is the base for all relative filenames in ! # the graph file. It is defined by the current working directory at time ! # of compiling the source file. ! # ! # This function implements a heuristic which relies on the following ! # assumptions: ! # - all files used for compilation are still present at their location ! # - the base directory is either BASE_DIR or one of its parent directories ! # - files by the same name are not present in multiple parent directories ! # ! ! sub find_base_from_graph($$$) ! { ! my ($base_dir, $instr, $graph) = @_; ! my $old_base; ! my $best_miss; ! my $best_base; ! my %rel_files; ! ! # Determine list of relative paths ! foreach my $filename (keys(%{$instr}), keys(%{$graph})) { ! next if (file_name_is_absolute($filename)); ! ! $rel_files{$filename} = 1; ! } ! ! # Early exit if there are no relative paths ! return $base_dir if (!%rel_files); ! ! do { ! my $miss = 0; ! ! foreach my $filename (keys(%rel_files)) { ! if (!-e solve_relative_path($base_dir, $filename)) { ! $miss++; ! } ! } ! ! debug("base_dir=$base_dir miss=$miss\n"); ! ! # Exit if we find an exact match with no misses ! return $base_dir if ($miss == 0); ! ! # No exact match, aim for the one with the least source file ! # misses ! if (!defined($best_base) || $miss < $best_miss) { ! $best_base = $base_dir; ! $best_miss = $miss; ! } ! ! # Repeat until there's no more parent directory ! $old_base = $base_dir; ! $base_dir = parent_dir($base_dir); ! } while ($old_base ne $base_dir); ! ! return $best_base; ! } ! ! # ! # adjust_graph_filenames(base_dir, instr, graph) ! # ! # Make relative paths in INSTR and GRAPH absolute and apply ! # geninfo_adjust_src_path setting to graph file data. ! # ! ! sub adjust_graph_filenames($$$) ! { ! my ($base_dir, $instr, $graph) = @_; foreach my $filename (keys(%{$instr})) { my $old_filename = $filename; ! # Convert to absolute canonical form ! $filename = solve_relative_path($base_dir, $filename); ! # Apply adjustment ! if (defined($adjust_src_pattern)) { ! $filename =~ s/$adjust_src_pattern/$adjust_src_replace/g; ! } ! ! if ($filename ne $old_filename) { ! $instr->{$filename} = delete($instr->{$old_filename}); ! } } *************** *** 2503,2510 **** my $old_filename = $filename; ! next if ($filename !~ ! s/$adjust_src_pattern/$adjust_src_replace/g); ! $graph->{$filename} = delete($graph->{$old_filename}); } --- 2606,2621 ---- my $old_filename = $filename; ! # Make absolute ! # Convert to absolute canonical form ! $filename = solve_relative_path($base_dir, $filename); ! # Apply adjustment ! if (defined($adjust_src_pattern)) { ! $filename =~ s/$adjust_src_pattern/$adjust_src_replace/g; ! } ! ! if ($filename ne $old_filename) { ! $graph->{$filename} = delete($graph->{$old_filename}); ! } } *************** *** 2741,2745 **** # ! # read_bb(filename, base_dir) # # Read the contents of the specified .bb file and return (instr, graph), where: --- 2852,2856 ---- # ! # read_bb(filename) # # Read the contents of the specified .bb file and return (instr, graph), where: *************** *** 2752,2763 **** # line_data : [ line1, line2, ... ] # ! # Relative filenames are converted to absolute form using base_dir as ! # base directory. See the gcov info pages of gcc 2.95 for a description of ! # the .bb file format. # ! sub read_bb($$) { ! my ($bb_filename, $base) = @_; my $minus_one = 0x80000001; my $minus_two = 0x80000002; --- 2863,2872 ---- # line_data : [ line1, line2, ... ] # ! # See the gcov info pages of gcc 2.95 for a description of the .bb file format. # ! sub read_bb($) { ! my ($bb_filename) = @_; my $minus_one = 0x80000001; my $minus_two = 0x80000002; *************** *** 2781,2788 **** $filename = read_bb_string(*HANDLE, $minus_one); goto incomplete if (!defined($filename)); - if ($filename ne "") { - $filename = solve_relative_path($base, - $filename); - } } elsif ($value == $minus_two) { # Function name --- 2890,2893 ---- *************** *** 2805,2809 **** graph_cleanup($graph); ! return adjust_graph_filenames($instr, $graph); open_error: --- 2910,2914 ---- graph_cleanup($graph); ! return ($instr, $graph); open_error: *************** *** 2875,2879 **** # # read_bbg_lines_record(handle, bbg_filename, bb, fileorder, filename, ! # function, base) # # Read a bbg format lines record from handle and add the relevant data to --- 2980,2984 ---- # # read_bbg_lines_record(handle, bbg_filename, bb, fileorder, filename, ! # function) # # Read a bbg format lines record from handle and add the relevant data to *************** *** 2881,2888 **** # ! sub read_bbg_lines_record(*$$$$$$) { ! my ($handle, $bbg_filename, $bb, $fileorder, $filename, $function, ! $base) = @_; my $string; my $lineno; --- 2986,2992 ---- # ! sub read_bbg_lines_record(*$$$$$) { ! my ($handle, $bbg_filename, $bb, $fileorder, $filename, $function) = @_; my $string; my $lineno; *************** *** 2904,2908 **** return $filename; } ! $filename = solve_relative_path($base, $string); if (!exists($bb->{$function}->{$filename})) { $bb->{$function}->{$filename} = []; --- 3008,3012 ---- return $filename; } ! $filename = $string; if (!exists($bb->{$function}->{$filename})) { $bb->{$function}->{$filename} = []; *************** *** 2922,2926 **** # ! # read_bbg(filename, base_dir) # # Read the contents of the specified .bbg file and return the following mapping: --- 3026,3030 ---- # ! # read_bbg(filename) # # Read the contents of the specified .bbg file and return the following mapping: *************** *** 2929,2940 **** # line_data: [ line1, line2, ... ] # ! # Relative filenames are converted to absolute form using base_dir as ! # base directory. See the gcov-io.h file in the SLES 9 gcc 3.3.3 source code ! # for a description of the .bbg format. # ! sub read_bbg($$) { ! my ($bbg_filename, $base) = @_; my $file_magic = 0x67626267; my $tag_function = 0x01000000; --- 3033,3043 ---- # line_data: [ line1, line2, ... ] # ! # See the gcov-io.h file in the SLES 9 gcc 3.3.3 source code for a description ! # of the .bbg format. # ! sub read_bbg($) { ! my ($bbg_filename) = @_; my $file_magic = 0x67626267; my $tag_function = 0x01000000; *************** *** 2983,2987 **** $filename = read_bbg_lines_record(HANDLE, $bbg_filename, $bb, $fileorder, $filename, ! $function, $base); goto incomplete if (!defined($filename)); } else { --- 3086,3090 ---- $filename = read_bbg_lines_record(HANDLE, $bbg_filename, $bb, $fileorder, $filename, ! $function); goto incomplete if (!defined($filename)); } else { *************** *** 2995,2999 **** graph_cleanup($graph); ! return adjust_graph_filenames($instr, $graph); open_error: --- 3098,3102 ---- graph_cleanup($graph); ! return ($instr, $graph); open_error: *************** *** 3074,3078 **** # # read_gcno_lines_record(handle, gcno_filename, bb, fileorder, filename, ! # function, base, big_endian) # # Read a gcno format lines record from handle and add the relevant data to --- 3177,3181 ---- # # read_gcno_lines_record(handle, gcno_filename, bb, fileorder, filename, ! # function, big_endian) # # Read a gcno format lines record from handle and add the relevant data to *************** *** 3080,3087 **** # ! sub read_gcno_lines_record(*$$$$$$$) { my ($handle, $gcno_filename, $bb, $fileorder, $filename, $function, ! $base, $big_endian) = @_; my $string; my $lineno; --- 3183,3190 ---- # ! sub read_gcno_lines_record(*$$$$$$) { my ($handle, $gcno_filename, $bb, $fileorder, $filename, $function, ! $big_endian) = @_; my $string; my $lineno; *************** *** 3103,3107 **** return $filename; } ! $filename = solve_relative_path($base, $string); if (!exists($bb->{$function}->{$filename})) { $bb->{$function}->{$filename} = []; --- 3206,3210 ---- return $filename; } ! $filename = $string; if (!exists($bb->{$function}->{$filename})) { $bb->{$function}->{$filename} = []; *************** *** 3167,3171 **** # ! # read_gcno_function_record(handle, graph, base, big_endian, rec_length) # # Read a gcno format function record from handle and add the relevant data --- 3270,3274 ---- # ! # read_gcno_function_record(handle, graph, big_endian, rec_length) # # Read a gcno format function record from handle and add the relevant data *************** *** 3173,3179 **** # ! sub read_gcno_function_record(*$$$$$) { ! my ($handle, $bb, $fileorder, $base, $big_endian, $rec_length) = @_; my $filename; my $function; --- 3276,3282 ---- # ! sub read_gcno_function_record(*$$$$) { ! my ($handle, $bb, $fileorder, $big_endian, $rec_length) = @_; my $filename; my $function; *************** *** 3200,3204 **** $filename = read_gcno_string($handle, $big_endian); return undef if (!defined($filename)); - $filename = solve_relative_path($base, $filename); # Read first line number $lineno = read_gcno_value($handle, $big_endian, "initial line number"); --- 3303,3306 ---- *************** *** 3212,3216 **** # ! # read_gcno(filename, base_dir) # # Read the contents of the specified .gcno file and return the following --- 3314,3318 ---- # ! # read_gcno(filename) # # Read the contents of the specified .gcno file and return the following *************** *** 3220,3231 **** # line_data: [ line1, line2, ... ] # ! # Relative filenames are converted to absolute form using base_dir as ! # base directory. See the gcov-io.h file in the gcc 3.3 source code ! # for a description of the .gcno format. # ! sub read_gcno($$) { ! my ($gcno_filename, $base) = @_; my $file_magic = 0x67636e6f; my $tag_function = 0x01000000; --- 3322,3332 ---- # line_data: [ line1, line2, ... ] # ! # See the gcov-io.h file in the gcc 3.3 source code for a description of ! # the .gcno format. # ! sub read_gcno($) { ! my ($gcno_filename) = @_; my $file_magic = 0x67636e6f; my $tag_function = 0x01000000; *************** *** 3278,3282 **** if ($tag == $tag_function) { ($filename, $function) = read_gcno_function_record( ! *HANDLE, $bb, $fileorder, $base, $big_endian, $length); goto incomplete if (!defined($function)); --- 3379,3383 ---- if ($tag == $tag_function) { ($filename, $function) = read_gcno_function_record( ! *HANDLE, $bb, $fileorder, $big_endian, $length); goto incomplete if (!defined($function)); *************** *** 3285,3289 **** $filename = read_gcno_lines_record(*HANDLE, $gcno_filename, $bb, $fileorder, ! $filename, $function, $base, $big_endian); goto incomplete if (!defined($filename)); --- 3386,3390 ---- $filename = read_gcno_lines_record(*HANDLE, $gcno_filename, $bb, $fileorder, ! $filename, $function, $big_endian); goto incomplete if (!defined($filename)); *************** *** 3306,3310 **** graph_cleanup($graph); ! return adjust_graph_filenames($instr, $graph); open_error: --- 3407,3411 ---- graph_cleanup($graph); ! return ($instr, $graph); open_error: |