X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=lib%2FTest%2FValgrind%2FSuppressions.pm;h=62d43e88cd9d3b4e35ad3eff4a91893ce2454271;hb=f2071d95aaaa4817e91cc33530deedc8d701d44d;hp=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391;hpb=8e236cf7f5ac06829edb65527fcdf12716ecd159;p=perl%2Fmodules%2FTest-Valgrind.git diff --git a/lib/Test/Valgrind/Suppressions.pm b/lib/Test/Valgrind/Suppressions.pm index e69de29..62d43e8 100644 --- a/lib/Test/Valgrind/Suppressions.pm +++ b/lib/Test/Valgrind/Suppressions.pm @@ -0,0 +1,226 @@ +package Test::Valgrind::Suppressions; + +use strict; +use warnings; + +=head1 NAME + +Test::Valgrind::Suppressions - Generate suppressions for given tool and command. + +=head1 VERSION + +Version 1.19 + +=cut + +our $VERSION = '1.19'; + +=head1 DESCRIPTION + +This module is an helper for generating suppressions. + +=cut + +use base qw; + +=head1 METHODS + +=head2 C + + Test::Valgrind::Suppressions->generate( + tool => $tool, + command => $command, + target => $target, + ); + +Generates suppressions for the command C<< $command->new_trainer >> and the tool C<< $tool->new_trainer >>, and writes them in the file specified by C<$target>. +The action used behind the scenes is L. + +Returns the status code. + +=cut + +sub generate { + my $self = shift; + + my %args = @_; + + my $cmd = delete $args{command}; + unless (ref $cmd) { + require Test::Valgrind::Command; + $cmd = Test::Valgrind::Command->new( + command => $cmd, + args => [ ], + ); + } + $cmd = $cmd->new_trainer; + return unless defined $cmd; + + my $tool = delete $args{tool}; + unless (ref $tool) { + require Test::Valgrind::Tool; + $tool = Test::Valgrind::Tool->new(tool => $tool); + } + $tool = $tool->new_trainer; + return unless defined $tool; + + my $target = delete $args{target}; + $self->_croak('Invalid target') unless $target and not ref $target; + + require Test::Valgrind::Action; + my $action = Test::Valgrind::Action->new( + action => 'Suppressions', + target => $target, + name => 'PerlSuppression', + ); + + require Test::Valgrind::Session; + my $sess = Test::Valgrind::Session->new( + min_version => $tool->requires_version, + ); + + eval { + $sess->run( + command => $cmd, + tool => $tool, + action => $action, + ); + }; + $self->_croak($@) if $@; + + my $status = $sess->status; + $status = 255 unless defined $status; + + return $status; +} + +=head2 C + + my $mangled_suppression = Test::Valgrind::Suppressions->maybe_generalize( + $session, + $suppression, + ); + +Removes all wildcard frames at the end of the suppression. +It also replaces sequences of wildcard frames by C<'...'> when C C<3.4.0> or higher is used. +Returns the mangled suppression. + +=cut + +sub maybe_generalize { + shift; + + my ($sess, $supp) = @_; + + 1 while $supp =~ s/[^\r\n]*:\s*\*\s*$//; + + # With valgrind 3.4.0, we can replace unknown series of frames by '...' + my $can_ellipsis = $sess->version >= '3.4.0'; + + my $did_length_check; + + ELLIPSIS: { + if ($can_ellipsis) { + $supp .= "...\n"; + $supp =~ s/(?:^\s*(?:\.{3}|\*:\S*|obj:\*)\s*(?:\n|\z))+/...\n/mg; + } + + last if $did_length_check++; + + my $frames_count =()= $supp =~ m/^(?:(?:obj|fun|\*):|\.{3}\s*$)/mg; + if ($frames_count > 24) { + # Keep only 24 frames, and even sacrifice one more if we can do ellipsis. + my $last = $can_ellipsis ? 23 : 24; + my $len = length $supp; + $supp =~ m/^(?:(?:obj|fun|\*):\S*|\.{3})\s*\n/mg for 1 .. $last; + my $p = pos $supp; + substr $supp, $p, $len - $p, ''; + redo ELLIPSIS if $can_ellipsis; + } + } + + $supp; +} + +=head2 C + + my $demangled_symbol = Test::Valgrind::Suppressions->maybe_z_demangle( + $symbol, + ); + +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. + +=head1 AUTHOR + +Vincent Pit, C<< >>, L. + +You can contact me by mail or on C (vincent). + +=head1 BUGS + +Please report any bugs or feature requests to C, or through the web interface at L. +I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Test::Valgrind::Suppressions + +=head1 COPYRIGHT & LICENSE + +Copyright 2008,2009,2010,2011,2013,2015,2016 Vincent Pit, all rights reserved. + +This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. + +=cut + +1; # End of Test::Valgrind::Suppressions