$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";
+ }
}
}
$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>.
--- /dev/null
+#!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;
+ }
+}