#! /usr/bin/perl # perl -i -p -e 's/^(Breakpoint )(?:\d+ )?(?:at 0x[0-9a-f]+ )?/$1/' use strict; use warnings; use Data::Dumper; use List::Util qw(&shuffle); my $BATCH=500; my $die; @ARGV>=5 or die "$0 ..."; my $limit=shift; my $gdb=shift; my $nm=shift; my $nm_retdrop=shift; $limit=~/^\d+$/ or die "limit is not numeric: $limit"; $limit or undef $limit; -x $gdb or die "-x $gdb"; -x $nm or die "-x $nm"; -x $nm_retdrop or die "-x $nm_retdrop"; #system "cgclassify -g '*':hammock $$ &>/dev/null"; system "renice +19 -p $$ &>/dev/null"; system "ionice -c3 -p $$ &>/dev/null"; srand 0; while (@ARGV) { my $file=shift; my $debug="${file}.debug"; warn "$file\n"; -r $file or die "-r $file"; -r $debug or die "-r $debug"; my %break; sub nm($) { my($nm_kind)=@_; my $f="$nm_kind -C $debug|"; local *F; open F,$f or die $f; my @retval; while () { chomp; next if !(my $break=(/^.{16} [tT] (.*)$/)[0]); # $break=~s/@.*//; next if $break=~/[.]clone[.]\d+$/; push @retval,$break; die "' in: $break" if $break=~/'/; $break{$break}++; } close F or die $f; return @retval; } my @nm=nm $nm; my @nm_retdrop=nm $nm_retdrop; @nm==@nm_retdrop or die '@nm!=@nm_retdrop'; @nm>0 or die '@nm==0'; warn "minsyms ".scalar(@nm)."\n"; my @break=shuffle(sort(keys(%break))); warn "breaks ".scalar(@break)."\n"; my %h; for my $i (0..$#nm) { my $a=$nm[$i]; my $b=$nm_retdrop[$i]; next if $a eq $b; length($a) > length ($b) or die "$a length $b"; $h{$b}{$a}=1; } warn "function templates ".scalar(keys(%h))."\n"; for my $b (keys(%h)) { my @a=keys(%{$h{$b}}); next if @a==1; print Dumper([$b,\@a]); $die++; } my $break_done=0; while (@break) { local *GDB; my $GDB="|$gdb -nx $file 2>&1"; open GDB,$GDB or die "open $GDB"; print GDB <<"EOH" or die "print $GDB"; set prompt set breakpoint pending off set confirm no set width 0 set height 0 set pagination off set language c++ EOH my $batch_done=0; while (@break && $batch_done < $BATCH) { my $break=shift @break; print GDB <<"EOH" or die "print $GDB"; echo BREAK @{[ sprintf "%6d",$break_done ]} $break\\n b '$break' delete EOH $batch_done++; $break_done++; last if defined $limit && --$limit<=0; } print GDB <<"EOH" or die "print $GDB"; quit EOH close GDB or die "close $GDB"; $? and die "error $? on close $GDB"; last if defined $limit && $limit<=0; } # while (@break); } # while (@ARGV); die $die if $die;