find-comptr-leakers.pl 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #!/usr/bin/perl -w
  2. #
  3. # This Source Code Form is subject to the terms of the Mozilla Public
  4. # License, v. 2.0. If a copy of the MPL was not distributed with this
  5. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. # Script loosely based on Chris Waterson's find-leakers.pl and make-tree.pl
  7. use 5.004;
  8. use strict;
  9. use Getopt::Long;
  10. # GetOption will create $opt_object, so ignore the
  11. # warning that gets spit out about those vbls.
  12. GetOptions("object=s", "list", "help");
  13. # use $::opt_help twice to eliminate warning...
  14. ($::opt_help) && ($::opt_help) && die qq{
  15. usage: find-comptr-leakers.pl < logfile
  16. --object <obj> Examine only object <obj>
  17. --list Only list leaked objects
  18. --help This message :-)
  19. };
  20. if ($::opt_object) {
  21. warn "Examining only object $::opt_object (THIS IS BROKEN)\n";
  22. } else {
  23. warn "Examining all objects\n";
  24. }
  25. my %allocs = ( );
  26. my %counter;
  27. my $id = 0;
  28. my $accumulating = 0;
  29. my $savedata = 0;
  30. my $class;
  31. my $obj;
  32. my $sno;
  33. my $op;
  34. my $cnt;
  35. my $ptr;
  36. my $strace;
  37. sub save_data {
  38. # save the data
  39. if ($op eq 'nsCOMPtrAddRef') {
  40. push @{ $allocs{$sno}->{$ptr} }, [ +1, $strace ];
  41. }
  42. elsif ($op eq 'nsCOMPtrRelease') {
  43. push @{ $allocs{$sno}->{$ptr} }, [ -1, $strace ];
  44. my $sum = 0;
  45. my @ptrallocs = @{ $allocs{$sno}->{$ptr} };
  46. foreach my $alloc (@ptrallocs) {
  47. $sum += @$alloc[0];
  48. }
  49. if ( $sum == 0 ) {
  50. delete($allocs{$sno}{$ptr});
  51. }
  52. }
  53. }
  54. LINE: while (<>) {
  55. if (/^</) {
  56. chop; # avoid \n in $ptr
  57. my @fields = split(/ /, $_);
  58. ($class, $obj, $sno, $op, $cnt, $ptr) = @fields;
  59. $strace = "";
  60. if ($::opt_list) {
  61. save_data();
  62. } elsif (!($::opt_object) || ($::opt_object eq $obj)) {
  63. $accumulating = 1;
  64. }
  65. } elsif ( $accumulating == 1 ) {
  66. if ( /^$/ ) {
  67. # if line is empty
  68. $accumulating = 0;
  69. save_data();
  70. } else {
  71. $strace = $strace . $_;
  72. }
  73. }
  74. }
  75. if ( $accumulating == 1) {
  76. save_data();
  77. }
  78. foreach my $serial (keys(%allocs)) {
  79. foreach my $comptr (keys( %{$allocs{$serial}} )) {
  80. my $sum = 0;
  81. my @ptrallocs = @{ $allocs{$serial}->{$comptr} };
  82. foreach my $alloc (@ptrallocs) {
  83. $sum += @$alloc[0];
  84. }
  85. print "Object ", $serial, " held by ", $comptr, " is ", $sum, " out of balance.\n";
  86. unless ($::opt_list) {
  87. print "\n";
  88. foreach my $alloc (@ptrallocs) {
  89. if (@$alloc[0] == +1) {
  90. print "Put into nsCOMPtr at:\n";
  91. } elsif (@$alloc[0] == -1) {
  92. print "Released from nsCOMPtr at:\n";
  93. }
  94. print @$alloc[1]; # the stack trace
  95. print "\n";
  96. }
  97. print "\n\n";
  98. }
  99. }
  100. }