blob: cc0b71ea07a4105d35273d7d3cf4cee84e38b2f4 [file] [log] [blame]
floriandb8bdd22011-10-01 21:07:32 +00001#!/usr/bin/env perl
2
3#---------------------------------------------------------------------
4# Quick and dirty program to filter helgrind's XML output.
5#
6# The script works line-by-line and is generally unaware of XML structure
7# and does not bother with issues of well-formedness.
8#
9# Consists of two parts
10# (1) Global match and replace (see PATTERNS below)
11# (2) Removal of stack frames
12# Stack frames whose associated file name does not match any name in
13# TOOL_FILES or in the list of files given on the command line
14# will be discarded. For a sequence of one or more discarded frames
15# a line <frame>...</frame> will be inserted.
16#
17#---------------------------------------------------------------------
18
19use warnings;
20use strict;
21
22#---------------------------------------------------------------------
23# A list of files specific to the tool at hand. Line numbers in
24# these files will be removed from stack frames matching these files.
25#---------------------------------------------------------------------
26my @tool_files = ( "hg_intercepts.c", "vg_replace_malloc.c" );
27
28# List of patterns and replacement strings.
29# Each pattern must identify a substring which will be replaced.
30my %patterns = (
31 "<pid>(.*)</pid>" => "...",
32 "<ppid>(.*)</ppid>" => "...",
33 "<time>(.*)</time>" => "...",
34 "<obj>(.*)</obj>" => "...",
35 "<dir>(.*)</dir>" => "...",
36 "<exe>(.*)</exe>" => "...",
37 "<tid>(.*)</tid>" => "...",
38 "<unique>(.*)</unique>" => "...",
39 "thread #([0-9]+)" => "x",
40 "0x([0-9a-zA-Z]+)" => "........",
41 "Using Valgrind-([^\\s]*)" => "X.Y.X",
sewardj8eb8bab2015-07-21 14:44:28 +000042 "Copyright \\(C\\) ([0-9]{4}-[0-9]{4}).*" => "XXXX-YYYY",
43 '<fn>pthread_.*(@\*)</fn>' => ""
floriandb8bdd22011-10-01 21:07:32 +000044);
45
46# List of XML sections to be ignored.
47my %ignore_sections = (
48 "<errorcounts>" => "</errorcounts>",
Elliott Hughesa0664b92017-04-18 17:46:52 -070049 "<suppcounts>" => "</suppcounts>",
50 "pthread_create_WRK</fn>" => "<obj>"
51);
52
53# List of XML sections to be quietly ignored.
54my %quiet_ignore_sections = (
55 "pthread_create_WRK</fn>" => "<obj>"
floriandb8bdd22011-10-01 21:07:32 +000056);
57
58
59# If FILE matches any of the FILES return 1
60sub file_matches ($$) {
61 my ($file, $files) = @_;
62 my ($string, $qstring);
63
64 foreach $string (@$files) {
65 $qstring = quotemeta($string);
66 return 1 if ($file =~ /$qstring/);
67 }
68
69 return 0;
70}
71
72
73my $frame_buf = "";
Elliott Hughesa0664b92017-04-18 17:46:52 -070074my ($file, $lineno, $in_frame, $keep_frame, $num_discarded, $ignore_line, $quiet_ignore_line);
floriandb8bdd22011-10-01 21:07:32 +000075
Elliott Hughesa0664b92017-04-18 17:46:52 -070076$in_frame = $keep_frame = $num_discarded = $ignore_line = $quiet_ignore_line = 0;
floriandb8bdd22011-10-01 21:07:32 +000077
78line:
79while (<STDIN>) {
80 my $line = $_;
81 chomp($line);
82
83# Check whether we're ignoring this piece of XML..
84 if ($ignore_line) {
85 foreach my $tag (keys %ignore_sections) {
86 if ($line =~ $ignore_sections{$tag}) {
Elliott Hughesa0664b92017-04-18 17:46:52 -070087 if ($quiet_ignore_line == 0) {
88 print "$tag...$ignore_sections{$tag}\n";
89 }
floriandb8bdd22011-10-01 21:07:32 +000090 $ignore_line = 0;
Elliott Hughesa0664b92017-04-18 17:46:52 -070091 $quiet_ignore_line = 0;
floriandb8bdd22011-10-01 21:07:32 +000092 next line;
93 }
94 }
95 } else {
96 foreach my $tag (keys %ignore_sections) {
97 if ($line =~ $tag) {
98 $ignore_line = 1;
99 }
100 }
Elliott Hughesa0664b92017-04-18 17:46:52 -0700101 # Determine if this section is also in the quiet list.
102 foreach my $tag (keys %quiet_ignore_sections) {
103 if ($line =~ $tag) {
104 $quiet_ignore_line = 1;
105 }
106 }
floriandb8bdd22011-10-01 21:07:32 +0000107 }
108
109 next if ($ignore_line);
110
111# OK. This line is not to be ignored.
112
113# Massage line by applying PATTERNS.
114 foreach my $key (keys %patterns) {
115 if ($line =~ $key) {
sewardj8eb8bab2015-07-21 14:44:28 +0000116 my $matched = quotemeta($1);
117 $line =~ s/$matched/$patterns{$key}/g;
floriandb8bdd22011-10-01 21:07:32 +0000118 }
119 }
120
121# Handle frames
122 if ($in_frame) {
123 if ($line =~ /<\/frame>/) {
124 $frame_buf .= "$line\n";
125# The end of a frame
126 if ($keep_frame) {
127# First: If there were any preceding frames that were discarded
128# print <frame>...</frame>
129 if ($num_discarded) {
130 print " <frame>...</frame>\n";
131 $num_discarded = 0;
132 }
133# Secondly: Write out the frame itself
134 print "$frame_buf";
135 } else {
136# We don't want to write this frame
137 ++$num_discarded;
138 }
139 $in_frame = $keep_frame = 0;
140 $file = "";
141 } elsif ($line =~ /<file>(.*)<\/file>/) {
142 $frame_buf .= "$line\n";
143 $file = $1;
144 if (file_matches($file, \@tool_files) ||
145 file_matches($file, \@ARGV)) {
146 $keep_frame = 1;
147 }
148 } elsif ($line =~ /<line>(.*)<\/line>/) {
149# This code assumes that <file> always precedes <line>
150 $lineno = $1;
151 if (file_matches($file, \@tool_files)) {
152 $line =~ s/$1/.../;
153 }
154 $frame_buf .= "$line\n";
155 } else {
156 $frame_buf .= "$line\n";
157 }
158 } else {
159# not within frame
160 if ($line =~ /<\/stack>/) {
161 print " <frame>...</frame>\n" if ($num_discarded);
162 $num_discarded = 0;
163 }
164 if ($line =~ /<frame>/) {
165 $in_frame = 1;
166 $frame_buf = "$line\n";
167 } else {
168 print "$line\n";
169 }
170 }
171}
172
173exit 0;