]> git.vpit.fr Git - perl/modules/Test-Valgrind.git/commitdiff
Z-demangle symbol names in suppressions
authorVincent Pit <vince@profvince.com>
Thu, 5 Nov 2009 18:13:43 +0000 (19:13 +0100)
committerVincent Pit <vince@profvince.com>
Thu, 5 Nov 2009 18:13:43 +0000 (19:13 +0100)
lib/Test/Valgrind/Parser/Suppressions/Text.pm
lib/Test/Valgrind/Suppressions.pm
t/81-suppressions-demangle.t [new file with mode: 0644]

index b738ea03617fbaa63a0951a844eaef2ce81a324d..c8e6e9f73ee604c734b34a9059392159a317554a 100644 (file)
@@ -60,7 +60,14 @@ sub parse {
    $s  = '';            # Reset the state
    $in = 0;
   } elsif ($in) {       # We're inside a suppresion block
-   $s .= "$_\n";        # Append the current line to the state
+   if (/^fun\s*:\s*(.*)/) {
+    # Sometimes valgrind seems to forget to Z-demangle the symbol names.
+    # Make sure it's done and append the result to the state.
+    my $sym = $1;
+    $s .= 'fun:' . Test::Valgrind::Suppressions->maybe_z_demangle($sym) . "\n";
+   } else {
+    $s .= "$_\n";
+   }
   }
  }
 
index 3af3a9847631fb3025c7857709b2f4a0ff77287e..dc1878280c3619fca6cc0b2366d017fbd9a90f2f 100644 (file)
@@ -111,6 +111,54 @@ sub strip_tail {
  $supp;
 }
 
+=head2 C<maybe_z_demangle $symbol>
+
+If C<$symbol> is Z-encoded as described in C<valgrind>'s F<include/pub_tool_redir.h>, extract and decode its function name part.
+Otherwise, C<$symbol> is returned as is.
+
+This routine follows C<valgrind>'s F<coregrind/m_demangle/demangle.c:maybe_Z_demangle>.
+
+=cut
+
+my %z_escapes = (
+ a => '*',
+ c => ':',
+ d => '.',
+ h => '-',
+ p => '+',
+ s => ' ',
+ u => '_',
+ A => '@',
+ D => '$',
+ L => '(',
+ R => ')',
+ Z => 'Z',
+);
+
+sub maybe_z_demangle {
+ my ($self, $sym) = @_;
+
+ $sym =~ s/^_vg[rwn]Z([ZU])_// or return $sym;
+
+ my $fn_is_encoded = $1 eq 'Z';
+
+ $sym =~ /^VG_Z_/ and $self->_croak('Symbol with a "VG_Z_" prefix is invalid');
+ $sym =~ s/^[^_]*_//
+                   or $self->_croak('Symbol doesn\'t contain a function name');
+
+ if ($fn_is_encoded) {
+  $sym =~ s/Z(.)/
+   my $c = $z_escapes{$1};
+   $self->_croak('Invalid escape sequence') unless defined $c;
+   $c;
+  /ge;
+ }
+
+ $self->_croak('Empty symbol') unless length $sym;
+
+ return $sym;
+}
+
 =head1 SEE ALSO
 
 L<Test::Valgrind>, L<Test::Valgrind::Command>, L<Test::Valgrind::Tool>, L<Test::Valgrind::Action::Suppressions>.
diff --git a/t/81-suppressions-demangle.t b/t/81-suppressions-demangle.t
new file mode 100644 (file)
index 0000000..232306b
--- /dev/null
@@ -0,0 +1,32 @@
+#!perl -T
+
+use strict;
+use warnings;
+
+use Test::More tests => 2 * 7;
+
+use Test::Valgrind::Suppressions;
+
+my @Z_tests = (
+ [ 'malloc'            => 'malloc', 'not encoded' ],
+ [ '_vgrZU_VG_Z_dongs' => qr/Symbol with a "VG_Z_" prefix is invalid/, 'VG_Z' ],
+ [ '_vgrZU_dongs'      => qr/Symbol doesn't contain a function name/,
+                                                           'no function name' ],
+ [ '_vgrZU_libcZdsoZa_malloc'   => 'malloc',   'soname encoded' ],
+ [ '_vgrZU_libcZdsoZa_arZZZAel' => 'arZZZAel', 'soname encoded 2' ],
+ [ '_vgrZZ_libcZdsoZa_arZZZAel' => 'arZ@el',   'function name encoded' ],
+ [ '_vgrZZ_libcZdsoZa_arZdZXZa' => qr/Invalid escape sequence/,
+                                         'function name with invalid escapes' ],
+);
+
+for (@Z_tests) {
+ my ($sym, $exp, $desc) = @$_;
+ my $res = eval { Test::Valgrind::Suppressions->maybe_z_demangle($sym) };
+ if (ref $exp) {
+  like $@,   $exp,  "$desc croaks as expected";
+  is   $res, undef, $desc;
+ } else {
+  is $@,   '',   "$desc does not croak as expected";
+  is $res, $exp, $desc;
+ }
+}