From: Peter O. <obe...@us...> - 2012-07-04 16:06:12
|
Update of /cvsroot/ltp/utils/analysis/lcov/bin In directory vz-cvs-4.sog:/tmp/cvs-serv25641 Modified Files: geninfo Log Message: geninfo: enable auto-detection of gcc-4.7 function record format gcc-4.7 introduced a modified function record format. This format is in use by android toolchains and has also been ported to some pre-4.7 versions of gcc. Introduce a heuristic-based auto-detection to correctly handle .gcno files in these cases. Index: geninfo =================================================================== RCS file: /cvsroot/ltp/utils/analysis/lcov/bin/geninfo,v retrieving revision 1.97 retrieving revision 1.98 diff -C2 -d -r1.97 -r1.98 *** geninfo 8 Jun 2012 14:19:49 -0000 1.97 --- geninfo 4 Jul 2012 16:06:10 -0000 1.98 *************** *** 117,121 **** $COMPAT_FLAG_LIBTOOL => $COMPAT_VALUE_ON, $COMPAT_FLAG_HAMMER => $COMPAT_VALUE_OFF, ! $COMPAT_FLAG_ANDROID_4_4_0 => $COMPAT_VALUE_OFF, ); --- 117,121 ---- $COMPAT_FLAG_LIBTOOL => $COMPAT_VALUE_ON, $COMPAT_FLAG_HAMMER => $COMPAT_VALUE_OFF, ! $COMPAT_FLAG_ANDROID_4_4_0 => $COMPAT_VALUE_AUTO, ); *************** *** 124,127 **** --- 124,128 ---- our %COMPAT_FLAG_AUTO = ( $COMPAT_FLAG_HAMMER => \&compat_hammer_autodetect, + $COMPAT_FLAG_ANDROID_4_4_0 => 1, ); *************** *** 158,162 **** sub graph_error($$); sub graph_expect($); ! sub graph_read(*$;$); sub graph_skip(*$;$); sub sort_uniq(@); --- 159,163 ---- sub graph_error($$); sub graph_expect($); ! sub graph_read(*$;$$); sub graph_skip(*$;$); sub sort_uniq(@); *************** *** 175,183 **** 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 read_gcno_function_record(*$$$$); sub read_gcno($$); sub get_gcov_capabilities(); --- 176,184 ---- 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 read_gcno_function_record(*$$$$$); sub read_gcno($$); sub get_gcov_capabilities(); *************** *** 193,196 **** --- 194,198 ---- sub parse_compat_flags($); sub is_compat($); + sub is_compat_auto($); *************** *** 2316,2339 **** # ! # graph_read(handle, bytes[, description]) # # Read and return the specified number of bytes from handle. Return undef ! # if the number of bytes could not be read. # ! sub graph_read(*$;$) { ! my ($handle, $length, $desc) = @_; my $data; my $result; graph_expect($desc); $result = read($handle, $data, $length); if ($debug) { my $ascii = ""; my $hex = ""; my $i; ! print(STDERR "DEBUG: read($length)=$result: "); for ($i = 0; $i < length($data); $i++) { my $c = substr($data, $i, 1);; --- 2318,2351 ---- # ! # graph_read(handle, bytes[, description, peek]) # # Read and return the specified number of bytes from handle. Return undef ! # if the number of bytes could not be read. If PEEK is non-zero, reset ! # file position after read. # ! sub graph_read(*$;$$) { ! my ($handle, $length, $desc, $peek) = @_; my $data; my $result; + my $pos; graph_expect($desc); + if ($peek) { + $pos = tell($handle); + if ($pos == -1) { + warn("Could not get current file position: $!\n"); + return undef; + } + } $result = read($handle, $data, $length); if ($debug) { + my $op = $peek ? "peek" : "read"; my $ascii = ""; my $hex = ""; my $i; ! print(STDERR "DEBUG: $op($length)=$result: "); for ($i = 0; $i < length($data); $i++) { my $c = substr($data, $i, 1);; *************** *** 2350,2353 **** --- 2362,2371 ---- print(STDERR "\n"); } + if ($peek) { + if (!seek($handle, $pos, 0)) { + warn("Could not set file position: $!\n"); + return undef; + } + } if ($result != $length) { return undef; *************** *** 2900,2928 **** # ! # read_gcno_word(handle[, description]) # # Read and return a word in .gcno format. # ! sub read_gcno_word(*;$) { ! my ($handle, $desc) = @_; ! return graph_read($handle, 4, $desc); } # ! # read_gcno_value(handle, big_endian[, description]) # # Read a word in .gcno format from handle and return its integer value ! # according to the specified endianness. # ! sub read_gcno_value(*$;$) { ! my ($handle, $big_endian, $desc) = @_; my $word; ! $word = read_gcno_word($handle, $desc); return undef if (!defined($word)); if ($big_endian) { --- 2918,2948 ---- # ! # read_gcno_word(handle[, description, peek]) # # Read and return a word in .gcno format. # ! sub read_gcno_word(*;$$) { ! my ($handle, $desc, $peek) = @_; ! return graph_read($handle, 4, $desc, $peek); } # ! # read_gcno_value(handle, big_endian[, description, peek]) # # Read a word in .gcno format from handle and return its integer value ! # according to the specified endianness. If PEEK is non-zero, reset file ! # position after read. # ! sub read_gcno_value(*$;$$) { ! my ($handle, $big_endian, $desc, $peek) = @_; my $word; + my $pos; ! $word = read_gcno_word($handle, $desc, $peek); return undef if (!defined($word)); if ($big_endian) { *************** *** 3008,3012 **** # ! # read_gcno_function_record(handle, graph, base, big_endian) # # Read a gcno format function record from handle and add the relevant data --- 3028,3032 ---- # ! # read_gcno_function_record(handle, graph, base, big_endian, rec_length) # # Read a gcno format function record from handle and add the relevant data *************** *** 3014,3033 **** # ! sub read_gcno_function_record(*$$$$) { ! my ($handle, $bb, $fileorder, $base, $big_endian) = @_; my $filename; my $function; my $lineno; my $lines; graph_expect("function record"); # Skip ident and checksum graph_skip($handle, 8, "function ident and checksum") or return undef; ! if (is_compat($COMPAT_FLAG_ANDROID_4_4_0) || ! ($gcov_version >= $GCOV_VERSION_4_7_0)) { ! # Skip extra checksum added by android 4.4.0 / gcc >= 4.7 ! # toolchains. ! graph_skip($handle, 4, "function extra checksum"); } # Read function name --- 3034,3080 ---- # ! sub read_gcno_function_record(*$$$$$) { ! my ($handle, $bb, $fileorder, $base, $big_endian, $rec_length) = @_; my $filename; my $function; my $lineno; my $lines; + my $is_4_7; graph_expect("function record"); # Skip ident and checksum graph_skip($handle, 8, "function ident and checksum") or return undef; ! # Determine if this is a gcc 4.7 format function record ! if ($gcov_version >= $GCOV_VERSION_4_7_0) { ! $is_4_7 = 1; ! } elsif (is_compat($COMPAT_FLAG_ANDROID_4_4_0)) { ! $is_4_7 = 1; ! } elsif (is_compat_auto($COMPAT_FLAG_ANDROID_4_4_0)) { ! my $strlen = read_gcno_value($handle, $big_endian, undef, 1); ! ! return undef if (!defined($strlen)); ! ! # Heuristic: ! # - pre-gcc 4.7 ! # This is the function name length / 4 which should be ! # less than the remaining record length ! # - gcc 4.7 ! # This is a checksum, likely with high-order bits set, ! # resulting in a large number ! if ($strlen * 4 > $rec_length - 12) { ! if ($debug) { ! print(STDERR "DEBUG: found overlong string ". ! "length - assuming gcc 4.7 format\n"); ! } ! $is_4_7 = 1; ! } elsif ($debug) { ! print(STDERR "DEBUG: found strlen=".($strlen * 4). ! " and rec_length=".($rec_length - 12)."\n"); ! } ! } ! # Skip cfg checksum word in case of gcc 4.7 format function record ! if ($is_4_7) { ! graph_skip($handle, 4, "function cfg checksum"); } # Read function name *************** *** 3117,3121 **** if ($tag == $tag_function) { ($filename, $function) = read_gcno_function_record( ! *HANDLE, $bb, $fileorder, $base, $big_endian); goto incomplete if (!defined($function)); } elsif ($tag == $tag_lines) { --- 3164,3169 ---- if ($tag == $tag_function) { ($filename, $function) = read_gcno_function_record( ! *HANDLE, $bb, $fileorder, $base, $big_endian, ! $length); goto incomplete if (!defined($function)); } elsif ($tag == $tag_lines) { *************** *** 3331,3345 **** "setting '$name' available!\n"); } ! $value = &$autodetect(); ! $compat_value{$flag} = $value; ! $is_autodetect = " (autodetected)"; } if ($specified{$flag}) { if ($value == $COMPAT_VALUE_ON) { info("Enabling compatibility setting ". "'$name'$is_autodetect\n"); ! } else { info("Disabling compatibility setting ". "'$name'$is_autodetect\n"); } } --- 3379,3401 ---- "setting '$name' available!\n"); } ! ! if (ref($autodetect) eq "CODE") { ! $value = &$autodetect(); ! $compat_value{$flag} = $value; ! $is_autodetect = " (auto-detected)"; ! } } + if ($specified{$flag}) { if ($value == $COMPAT_VALUE_ON) { info("Enabling compatibility setting ". "'$name'$is_autodetect\n"); ! } elsif ($value == $COMPAT_VALUE_OFF) { info("Disabling compatibility setting ". "'$name'$is_autodetect\n"); + } else { + info("Using delayed auto-detection for ". + "compatibility setting ". + "'$name'\n"); } } *************** *** 3352,3356 **** $gcov_version_string =~ /mandrake/i && $gcov_version == 0x30302) { ! info("Autodetected compatibility mode for GCC 3.3 (hammer)\n"); return $COMPAT_VALUE_ON; } --- 3408,3412 ---- $gcov_version_string =~ /mandrake/i && $gcov_version == 0x30302) { ! info("Auto-detected compatibility mode for GCC 3.3 (hammer)\n"); return $COMPAT_VALUE_ON; } *************** *** 3371,3372 **** --- 3427,3442 ---- return 0; } + + # + # is_compat_auto(flag) + # + # Return non-zero if compatibility setting for FLAG is set to auto-detect. + # + + sub is_compat_auto($) + { + my ($flag) = @_; + + return 1 if ($compat_value{$flag} == $COMPAT_VALUE_AUTO); + return 0; + } |