examine-relay 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #!/usr/bin/perl -w
  2. # -----------------------------------------------------------------------------
  3. #
  4. # Relay-checker.
  5. #
  6. # This program will inspect a log file with relay information and tell you
  7. # whether calls and returns match. If not, this suggests that the parameter
  8. # list might be incorrect. (It could be something else also.)
  9. #
  10. # This program now accepts a second command line parameter, which will enable
  11. # a "full" listing format; otherwise a trimmed down simplified listing is
  12. # generated. It does not matter what the second command line parameter is;
  13. # anything will enable the full listing.
  14. #
  15. # Copyright 1997-1998 Morten Welinder (terra@diku.dk)
  16. # 2001 Eric Pouech
  17. #
  18. # This library is free software; you can redistribute it and/or
  19. # modify it under the terms of the GNU Lesser General Public
  20. # License as published by the Free Software Foundation; either
  21. # version 2.1 of the License, or (at your option) any later version.
  22. #
  23. # This library is distributed in the hope that it will be useful,
  24. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  26. # Lesser General Public License for more details.
  27. #
  28. # You should have received a copy of the GNU Lesser General Public
  29. # License along with this library; if not, write to the Free Software
  30. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  31. # -----------------------------------------------------------------------------
  32. use strict;
  33. my $srcfile = $ARGV[0];
  34. my $fullformat = $ARGV[1];
  35. my %tid_callstack = ();
  36. my $newlineerror = 0;
  37. my $indentp = 1;
  38. my $lasttid = 0;
  39. open (IN, "<$srcfile") || die "Cannot open $srcfile for reading: $!\n";
  40. LINE:
  41. while (<IN>) {
  42. if (/^([0-9a-f]+):Call ([A-Za-z0-9]+\.[A-Za-z0-9_.]+)\((.*\)) .*/) {
  43. my $tid = $1;
  44. my $func = $2;
  45. if (defined $fullformat) {
  46. if ($lasttid ne $tid) {
  47. print "******** thread change\n"
  48. }
  49. $lasttid = $tid;
  50. print ($indentp ? (' ' x 2 x (1 + $#{$tid_callstack{$tid}})) : '');
  51. print "$_";
  52. }
  53. # print "have call func=$func $_";
  54. if (/ ret=(........)$/ ||
  55. / ret=(....:....) (ds=....)$/ ||
  56. / ret=(........) fs=....$/) {
  57. my $retaddr = $1;
  58. my $segreg = $2;
  59. $segreg = "none" unless defined $segreg;
  60. push @{$tid_callstack{$tid}}, [$func, $retaddr, $segreg];
  61. next;
  62. } elsif (not eof IN) {
  63. # Assume a line got cut by a line feed in a string.
  64. $_ .= scalar (<IN>);
  65. if (!$newlineerror) {
  66. print "Err[$tid] string probably cut by newline at line $. .\n";
  67. $newlineerror = 1;
  68. }
  69. # print "[$_]";
  70. redo;
  71. }
  72. }
  73. elsif (/^([0-9a-f]+):Call (window proc) ([0-9a-fx]+) .*/) {
  74. my $tid = $1;
  75. my $func = $2;
  76. my $retaddr = $3;
  77. my $segreg = "none";
  78. if (defined $fullformat) {
  79. if ($lasttid ne $tid) {
  80. print "******** thread change\n"
  81. }
  82. $lasttid = $tid;
  83. print ($indentp ? (' ' x 2 x (1 + $#{$tid_callstack{$tid}})) : '');
  84. print "$_";
  85. }
  86. push @{$tid_callstack{$tid}}, [$func, $retaddr, $segreg];
  87. }
  88. elsif (/^([0-9a-f]+):Ret ([A-Za-z0-9]+\.[A-Za-z0-9_.]+)\(.*\) .* ret=(........)$/ ||
  89. /^([0-9a-f]+):Ret ([A-Za-z0-9]+\.[A-Za-z0-9_.]+)\(.*\) .* ret=(....:....) (ds=....)$/ ||
  90. /^([0-9a-f]+):Ret ([A-Za-z0-9]+\.[A-Za-z0-9_.]+)\(.*\) .* ret=(........) fs=....$/ ||
  91. /^([0-9a-f]+):RET ([A-Za-z0-9]+\.[A-Za-z0-9_.]+: [A-Za-z0-9]+)\(.*\) .* ret=(........)$/ ||
  92. /^([0-9a-f]+):Ret (window proc) ([0-9a-fx]+) .*/) {
  93. my $tid = $1;
  94. my $func = $2;
  95. my $retaddr = $3;
  96. my $segreg = $4;
  97. my ($topfunc,$topaddr,$topseg);
  98. if (defined $fullformat) {
  99. if ($lasttid ne $tid) {
  100. print "******** thread change\n"
  101. }
  102. $lasttid = $tid;
  103. }
  104. # print "have ret func=$func <$_>\n";
  105. if (!defined($tid_callstack{$tid}))
  106. {
  107. print "Err[$tid]: unknown tid\n";
  108. next;
  109. }
  110. $segreg = "none" unless defined $segreg;
  111. POP:
  112. while (1) {
  113. if ($#{$tid_callstack{$tid}} == -1) {
  114. print "Err[$tid]: Return from $func to $retaddr with empty stack.\n";
  115. next LINE;
  116. }
  117. ($topfunc,$topaddr,$topseg) = @{pop @{$tid_callstack{$tid}}};
  118. if ($topfunc ne $func) {
  119. print "Err[$tid]: Return from $topfunc, but call from $func.\n";
  120. next POP;
  121. }
  122. last POP;
  123. }
  124. my $addrok = ($topaddr eq $retaddr);
  125. my $segok = ($topseg eq $segreg);
  126. if ($addrok && $segok) {
  127. if (defined $fullformat) {
  128. print ($indentp ? (' ' x 2 x (1 + $#{$tid_callstack{$tid}})) : '');
  129. print "$_";
  130. } else {
  131. print "Ok [$tid]: ", ($indentp ? (' ' x (1 + $#{$tid_callstack{$tid}})) : '');
  132. print "$func from $retaddr with $segreg.\n";
  133. }
  134. } else {
  135. print "Err[$tid]: Return from $func is to $retaddr, not $topaddr.\n"
  136. if !$addrok;
  137. print "Err[$tid]: Return from $func with segreg $segreg, not $topseg.\n"
  138. if !$segok;
  139. }
  140. }
  141. else {
  142. print "$_";
  143. }
  144. }
  145. foreach my $tid (keys %tid_callstack) {
  146. while ($#{$tid_callstack{$tid}} != -1) {
  147. my ($topfunc,$topaddr,$topseg) = @{pop @{$tid_callstack{$tid}}};
  148. print "Err[$tid]: leftover call to $topfunc from $topaddr.\n";
  149. }
  150. }
  151. close (IN);