From: Vincent Pit Date: Thu, 5 Nov 2009 18:13:43 +0000 (+0100) Subject: Z-demangle symbol names in suppressions X-Git-Tag: v1.12~2 X-Git-Url: http://git.vpit.fr/?a=commitdiff_plain;h=f81011346e3e0eb98b78830bcdb9b547a09ad3e8;p=perl%2Fmodules%2FTest-Valgrind.git Z-demangle symbol names in suppressions --- diff --git a/lib/Test/Valgrind/Parser/Suppressions/Text.pm b/lib/Test/Valgrind/Parser/Suppressions/Text.pm index b738ea0..c8e6e9f 100644 --- a/lib/Test/Valgrind/Parser/Suppressions/Text.pm +++ b/lib/Test/Valgrind/Parser/Suppressions/Text.pm @@ -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"; + } } } diff --git a/lib/Test/Valgrind/Suppressions.pm b/lib/Test/Valgrind/Suppressions.pm index 3af3a98..dc18782 100644 --- a/lib/Test/Valgrind/Suppressions.pm +++ b/lib/Test/Valgrind/Suppressions.pm @@ -111,6 +111,54 @@ sub strip_tail { $supp; } +=head2 C + +If C<$symbol> is Z-encoded as described in C's F, extract and decode its function name part. +Otherwise, C<$symbol> is returned as is. + +This routine follows C's F. + +=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, L, L, L. diff --git a/t/81-suppressions-demangle.t b/t/81-suppressions-demangle.t new file mode 100644 index 0000000..232306b --- /dev/null +++ b/t/81-suppressions-demangle.t @@ -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; + } +}