source: tags/arb-6.0-rc1/SOURCE_TOOLS/valgrind2grep

Last change on this file was 11401, checked in by westram, 10 years ago
  • reintegrates 'tree' into 'trunk':
    • consensus trees:
      • support for merging partial trees ("worked" before, but results were crap; implements #65)
      • generated trees are automatically re-rooted and -ordered
      • always list source trees in consensus-tree-comment; show info about partial trees
      • fixed progress bar
    • made GBT_TREE a base class of other tree classes (implements #31)
    • save tree properties in properties (not in DB)
    • new functions 'Remove zombies/marked from ALL trees'
    • tree load/save: layout fixes
    • unit tests
      • added tests for basic tree modifications (PARSIMONY)
    • performance:
      • compute_tree updates tree information in one traversal
      • tree generators are now capable to generate any type of tree (w/o needing to copy it once)
    • bugfixes:
      • NNI (of marked species) was also always performed for colored species
      • centered beautify-order is stable now
      • improved 'search optimal root'
  • adds:
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 13.8 KB
Line 
1#!/usr/bin/perl
2
3use warnings;
4use strict;
5use IO::Handle;
6
7# -------------------------------------------------------------------- customize here
8
9# top source directory
10my $topdir = "$ENV{ARBHOME}";
11my $toplen = length($topdir);
12
13# list containing paths of all source files (generated by arb_valgrind)
14my $sourcelist = "$topdir/SOURCE_TOOLS/valgrind2grep.lst";
15
16# prefix to write before hidden caller-lines
17# (-> emacs will not jump to them automatically, you have to remove the prefix first)
18my $unmark_callers  = "(hide) ";
19
20# prefix to write before filtered lines
21my $unmark_filtered = "(filt) ";
22
23# prefix to write before other non-error lines
24my $unmark_rest     = "(note) ";
25
26sub check_ignore_external($\$$) {
27  my ($text,$ignore_r,$reason) = @_;
28  if (not defined $$ignore_r) {
29    # if you encounter errors/warnings in foreign libraries you wont be able to fix them.
30    # To ignore them add a search expression here.
31    # Please add current date as well, to make it easier to find outdated expressions.
32
33    if ($reason =~ 'loss record') { # memory leaks
34      # Xtoolkit leaks / ARB leaks which we wont fix for motif - retry after gtk merge
35
36      if ($reason =~ 'still reachable' or $reason =~ 'possibly lost') { # reachable memory leaks
37
38        if ($text =~ /\b(XLoadQueryFont)\b.*libXt/) { $$ignore_r = $&; return; } # 29/05/2010
39        if ($text =~ /\b(XRebindKeysym)\b.*libXt/) { $$ignore_r = $&; return; } # 29/05/2010
40        if ($text =~ /\b(XmGetPixmap)\b.*libXm/) { $$ignore_r = $&; return; } # 29/05/2010
41        if ($text =~ /\b(XtOpenApplication)\b.*libXt/) { $$ignore_r = $&; return; } # 29/05/2010
42        if ($text =~ /\b(XtRealizeWidget)\b.*libXt/) { $$ignore_r = $&; return; } # 29/05/2010
43        if ($text =~ /\b(XtVaCreateManagedWidget)\b.*libXt/) { $$ignore_r = $&; return; } # 29/05/2010
44        if ($text =~ /\b(XtVaCreatePopupShell)\b.*libXt/) { $$ignore_r = $&; return; } # 29/05/2010
45        if ($text =~ /\b(XtVaSetValues)\b.*libXt/) { $$ignore_r = $&; return; } # 29/05/2010
46        if ($text =~ /\b(XtVaCreateWidget)\b.*libXt/) { $$ignore_r = $&; return; } # 03/12/2013
47        if ($text =~ /\b(XtParseTranslationTable)\b.*libXt/) { $$ignore_r = $&; return; } # 03/12/2013
48        if ($text =~ /\b(XtAugmentTranslations)\b.*libXt/) { $$ignore_r = $&; return; } # 03/12/2013
49        if ($text =~ /\b(XQueryColor|XGetGeometry|XAllocNamedColor)\b.*libX11/) { $$ignore_r = $&; return; } # 04/12/2013
50      }
51    }
52    else { # illegal memory access (in fact everything else -- @@@ need condition here)
53      # X11 bugs:
54      if ($text =~ /\b(_X11TransWrite)\b.*libX11/) { $$ignore_r = $&; return; } # 24/11/2005
55      if ($text =~ /\b(_XSend)\b.*libX11/) { $$ignore_r = $&; return; } # 16/05/2009
56      # Xtoolkit bugs:
57      if ($text =~ /\b(_XtGet(Sub)?[rR]esources)\b.*libXt/) { $$ignore_r = $&; return; } # 24/11/2005
58      if ($text =~ /\b(XtOpenApplication)\b.*libXt/) { $$ignore_r = $&; return; } # 13/06/2009
59      # motif bugs:
60      if ($text =~ /\b(XmRenderTableCopy)\b.*libXm/) { $$ignore_r = $&; return; } # 09/02/2009
61      if ($text =~ /\b(XmRenderTableFree)\b.*libXm/) { $$ignore_r = $&; return; } # 09/02/2009
62      if ($text =~ /\b(XmIsMotifWMRunning)\b.*libXm/) { $$ignore_r = $&; return; } # 13/06/2009
63      if ($text =~ /\b(XmGetPixmap)\b.*libXm/) { $$ignore_r = $&; return; } # 22/04/2010
64    }
65  }
66}
67
68sub check_ignore_internal($\$$) {
69  my ($text,$ignore_r,$reason) = @_;
70  if (not defined $$ignore_r) {
71    # defines ignored leaks/errors occurring in internal libraries (wontfixes)
72    # To ignore them add a search expression here.
73    # Please add current date as well, to make it easier to find outdated expressions.
74
75    # print "check_ignore_internal: reason='$reason'\n";
76
77    if ($reason =~ 'loss record') { # memory leaks
78      if ($reason =~ 'still reachable' or $reason =~ 'possibly lost') { # reachable memory leaks
79        # things broken in ARB motif (wontfix; remove these exclusions after gtk merge)
80        if ($text =~ /\b(aw_create_shell)\b/) { $$ignore_r = $&; return; } # 03/12/2013
81        if ($text =~ /\b(AW_window::(load_xfig|insert_option_internal))\b/) { $$ignore_r = $&; return; } # 04/12/2013
82        if ($text =~ /\b(gbmGetMemImpl)\b/) { $$ignore_r = $&; return; } # 04/12/2013 -- not all blocks of internal mem.management were freed (set MEMORY_TEST 1 in gb_memory.h to find leakers)
83      }
84      elsif ($reason =~ 'definitely lost') { # unreachable memory leaks
85        if ($text =~ /\b(awt_create_selection_list_on_(trees|alignments))\b/) { $$ignore_r = $&; return; } # 03/12/2013
86        if ($text =~ /\b(AW_window::(create_toggle|create_option_menu))\b/) { $$ignore_r = $&; return; } # 03/12/2013
87        if ($text =~ /\b(AW_root::create_colormap)\b/) { $$ignore_r = $&; return; } # 03/12/2013
88      }
89      if ($text =~ /\b(AW_manage_GC)\b/) { $$ignore_r = $&; return; } # 04/12/2013
90    }
91    elsif ($reason =~ 'file descriptor') { # open file descriptors
92      if ($text =~ /\b(aw_initstatus)\b/) { $$ignore_r = $&; return; } # 03/12/2013
93    }
94    # else { # illegal memory access
95    # }
96  }
97}
98
99
100
101sub is_boring($) {
102  my ($text) = @_;
103  if ($text =~ /provoke_core_dump/) { return 1; }
104  return 0;
105}
106
107my $debug = 0;
108
109# --------------------------------------------------------------- customize till here
110
111# get args:
112
113my $args = scalar(@ARGV);
114
115if ($args<2 or $args>3) { die "Usage: valgrind2grep <callers> <filter> [--suppress-common]\n"; }
116my $callers = $ARGV[0];
117my $filter  = $ARGV[1];
118
119my $suppress_common = 0;
120if ($args==3) {
121  my $a = $ARGV[2];
122  if ($a eq '--suppress-common') { $suppress_common=1; }
123  else { die "Unknown argument '$a'"; }
124}
125
126# use unbuffered I/O (otherwise pipe waits for valgrind to terminate???)
127
128my $in = new IO::Handle;
129$in->fdopen(fileno(STDIN),"r") || die "can't open STDIN";
130
131my $out = new IO::Handle;
132$out->fdopen(fileno(STDOUT),"w") || die "can't open STDOUT";
133
134# read list of source files:
135
136open(SOURCELIST,"<$sourcelist") || die "can't open $sourcelist";
137
138my %fileIndex = ();
139
140sub addFileIndex($$) {
141  my ($key,$val) = @_;
142  if (not exists $fileIndex{$key}) {
143    my @array = ();
144    $fileIndex{$key} = \@array;
145  }
146  my $array_r = $fileIndex{$key};
147  push @$array_r, $val;
148}
149
150foreach (<SOURCELIST>) {
151  chomp;
152  addFileIndex($_,$_);
153  if (/\/([^\/]+)\/([^\/]+)$/) {
154    my $last_dir = $1;
155    my $fname    = $2;
156
157    addFileIndex($fname,$_);
158    addFileIndex($last_dir.'/'.$fname,$_);
159  }
160  elsif (/\/([^\/]+)$/) {
161    my $fname = $1;
162    addFileIndex($fname,$_);
163  }
164  else {
165    die "invalid entry in $sourcelist ('$_')"
166  }
167}
168
169close(SOURCELIST);
170
171sub parentDir($) {
172  my ($dirOrFile) = @_;
173  if ($dirOrFile =~ /\/[^\/]+$/o) { return $`; }
174  return undef;
175}
176
177sub makeTargetAbsolute($$) {
178  my ($abslink,$reltarget) = @_;
179  my $absdir = parentDir($abslink);
180  if (defined $absdir) {
181    while ($reltarget =~ /^\.\.\//o) {
182      $reltarget = $';
183      my $absparent = parentDir($absdir);
184      if (defined $absparent) {
185        $absdir = $absparent;
186      }
187      else {
188        die "Can't detect parent dir of '$absdir'";
189      }
190    }
191
192    my $result = $absdir.'/'.$reltarget;
193    return $result;
194  }
195  else {
196    die "Can't detect parent dir of '$abslink'";
197  }
198}
199
200# make entries unique
201foreach (keys %fileIndex) {
202  my $array_r = $fileIndex{$_};
203  my %unique = map { $_ => 1; } @$array_r;
204
205  my $changed = 1;
206  while ($changed==1) {
207    $changed = 0;
208    my @del = ();
209    my @add = ();
210    foreach (keys %unique) {
211      my $target = undef;
212      eval { $target = readlink($_); };
213      if ($@) {                 # a link with invalid target?
214        push @del, $_;
215        $out->print("Remove invalid link '$_' (Reason: $!)\n");
216      }
217      elsif (defined $target) { # a link with valid target
218        $target = makeTargetAbsolute($_,$target);
219        push @del, $_;
220        push @add, $target;
221        # $out->print("Replace link '$_'\n   by target '$target'\n");
222        # $out->print("Target '$target' exists:".(-e $target ? 'yes' : 'no')."\n");
223      }
224      # else not a link
225    }
226    if (scalar(@del)) { foreach (@del) { delete $unique{$_}; } $changed=1; }
227    if (scalar(@add)) { foreach (@add) { $unique{$_} = 1; } $changed=1; }
228  }
229  @$array_r = keys %unique;
230}
231
232
233$out->print("Settings: Showing $callers caller(s).\n");
234$out->print("          Filtering with '$filter'.\n");
235
236sub avoid_location($) {         # invalidate everything emacs could missinterpret as error-location (i.e. '(file:lineno)')
237  ($_) = @_;
238  s/([(].*)(:)(.*[)])/$1_$2_$3/ig;
239  $_;
240}
241
242my $reg_topdir = qr/^$topdir\//o;
243
244sub shorten_location($) {
245  my ($locline) = @_;
246  if ($locline =~ /^([^:]+):([0-9]+):/o) {
247    my ($loc,$line,$msg) = ($1,$2,$');
248    if ($loc =~ $reg_topdir) {
249      $loc = $';
250    }
251    $locline = $loc.':'.$line.':'.$msg;
252  }
253  $locline;
254}
255
256my $entered=0;
257
258sub entering() {
259  if ($entered==0) {
260    $out->print('vake[2]: Entering directory `'.$topdir."\'\n");
261    $entered = 1;
262  }
263}
264sub leaving() {
265  if ($entered==1) {
266    $out->print('vake[2]: Leaving directory `'.$topdir."\'\n");
267    $entered = 0;
268  }
269}
270
271sub hideMessages($\@) {
272  my ($hidePrefix,$outstack_r) = @_;
273  $hidePrefix = "($hidePrefix) ";
274  @$outstack_r = map { $hidePrefix.$_; } @$outstack_r;
275}
276
277# variables:
278
279my $i;
280my $called_from       = "called from";
281my $reason            = 'no reason yet';
282my $non_caller_reason = 'no reason yet';
283my $caller_count      = 0;       # counts callers
284my $filtered          = 0;       # filter current error
285my $ignore            = undef;
286my $last_ignore       = '';
287my $ignore_curr_line  = 0;
288
289# the filter loop:
290
291my @outstack = ();
292
293while (not $in->eof) {
294  # read one line:
295  $_ = $in->getline;
296
297  # convert error messages to grep format:
298  if (/^([=\-0-9]+[ ]+)(.*)$/) {
299    my $prefix  = $1;
300    my $content = $2;
301
302    if ($content =~ /^([ab][ty].*)([(][^()]+[)])$/) { # looks like an valgrind error
303      $content = $1;
304      my $location = $2;
305
306      if ($location =~ /[(](.*):(.*)[)]/) { # seems to have a valid '(file:line)' location at eol
307        my ($file,$line) = ($1,$2);
308        if ($filtered == 1) {
309          $_ = $unmark_filtered.' '.&avoid_location($_);
310        }
311        else {
312          my $array_r = $fileIndex{$file};
313          if (defined $array_r) {
314            my @lines = ();
315            if (scalar(@$array_r)>1) {
316              push @lines, $unmark_rest."Multiple occurrences of '$file' - not sure which location is the correct one\n";
317            }
318
319            if ($reason eq $called_from) { # its a caller
320              $caller_count++;
321            }
322            else {
323              $caller_count = 0;
324            }
325
326            foreach my $replace (@$array_r) {
327              if (not -f $replace) {
328                $_ = "$sourcelist:1: might be outdated ($replace does not exist)\n";
329              }
330              else {
331                $_ = "$replace:$line: $reason ($content)\n";
332                if ($caller_count > $callers) {
333                  $_ = $unmark_callers.$_;
334                }             # hide this caller
335              }
336              push @lines, $_;
337            }
338
339            $reason = $called_from;
340            $_ = join '', @lines;
341          }
342          else {                # location in unavailable file (i.e. in library)
343            $_ = $unmark_rest.$prefix.$reason." $content (in unavailable file $file line $line)\n";
344          }
345          if ($reason ne $called_from) { $non_caller_reason = $reason; }
346          if ($suppress_common==1) {
347            check_ignore_internal($_, $ignore, $non_caller_reason);
348          }
349        }
350      }
351      else {                    # valgrind error w/o location
352        $non_caller_reason = $reason;
353        $_=$unmark_rest.' '.$_;
354        if ($suppress_common==1) { check_ignore_external($_, $ignore, $reason); }
355      }
356    }
357    else {                      # no location found
358      if ($content =~ /^TRANSLATE: / or
359          $content =~ /^Reading syms from/ or
360          $content =~ /unhandled CFI instruction/ or # happens since gcc 5.4.2
361          $content =~ /object doesn.t have a/) {
362        $ignore_curr_line = 1;
363      }
364      elsif ($content =~ /^[ ]*$/) {
365        if (defined $ignore) { hideMessages('ign2', @outstack); }
366        foreach my $line (@outstack) { $out->print($line); } @outstack = ();
367        $out->flush;
368
369        $ignore = undef;
370        $_      = '(    ) '.$_;
371      }
372      else {
373        $reason = $content;
374        $_='(    ) '.$_;
375
376        # should that reason be filtered ?
377        if ($reason =~ /alloc\'d/) { # an allocator message (applies to last message) -> so never filter
378          $reason = "ORIGIN: $reason";
379          # keep $ignore like before
380        }
381        else {
382          if ($reason =~ /$filter/i) { $filtered = 0; }
383          else { $filtered = 1; }
384
385          if ($filtered == 1) { $ignore = undef; }
386        }
387        if ($filtered==0) { $non_caller_reason = $reason; }
388      }
389    }
390  }
391
392  my $boring = 0;
393  if ($ignore_curr_line==0) {
394    $boring = $ignore_curr_line = is_boring($_);
395  }
396
397  # print out line
398  if ($ignore_curr_line==0) {
399    if (not defined $ignore) {
400      entering();
401      push @outstack, shorten_location($_);
402      $last_ignore = '';
403    }
404    else { # defined ignore
405      # print "last_ignore='$last_ignore' ignore='$ignore'\n";
406      if ($ignore ne $last_ignore) {
407        hideMessages('ign3', @outstack);
408        foreach my $line (@outstack) { $out->print($line); } @outstack = ();
409
410        s/^\(note\)[ ]*//;
411        $out->print("(igno) '$ignore' ".$_);
412        $out->print("(skip) further messages suppressed\n");
413        $out->flush;
414        $last_ignore = $ignore;
415      }
416      else {
417        if ($debug==1) {
418          $out->print("(comm) ".$_);
419          $out->flush;
420        }
421      }
422    }
423  }
424  else {
425    if ($boring) {
426      $out->print("(BORE) ".$_);
427      $out->flush();
428    }
429    elsif ($debug==1) {
430      $out->print("(SUPP) ".$_);
431      $out->flush();
432    }
433    $ignore_curr_line = 0;
434  }
435}
436
437if (defined $ignore) { hideMessages('ign4', @outstack); }
438foreach my $line (@outstack) { $out->print($line); } @outstack = ();
439leaving();
440$out->flush;
441
442$in->close;
443$out->close;
444
Note: See TracBrowser for help on using the repository browser.