1 | #!/usr/bin/perl -w
|
---|
2 |
|
---|
3 | use DB_File;
|
---|
4 | use Fcntl ':flock';
|
---|
5 |
|
---|
6 | if (!defined($ARGV[0])) {
|
---|
7 | print "usage: requires .class dump as parameter!\n";
|
---|
8 | exit;
|
---|
9 | }
|
---|
10 |
|
---|
11 | sub bailout
|
---|
12 | {
|
---|
13 | untie %bcheckdb if(defined(%bcheckdb));
|
---|
14 |
|
---|
15 | if(defined(MYLOCK)) {
|
---|
16 | flock MYLOCK, LOCK_UN;
|
---|
17 | close(MYLOCK);
|
---|
18 | }
|
---|
19 |
|
---|
20 | print @_;
|
---|
21 | exit 5;
|
---|
22 | }
|
---|
23 |
|
---|
24 | sub ask_user
|
---|
25 | {
|
---|
26 | my ($dbkey, $dbchunk) = @_;
|
---|
27 |
|
---|
28 | if (defined($ENV{"BCHECK_UPDATE"})) {
|
---|
29 | $bcheckdb{$dbkey} = $dbchunk;
|
---|
30 | return;
|
---|
31 | }
|
---|
32 |
|
---|
33 | &bailout("BC problem detected") if (! -t STDIN);
|
---|
34 |
|
---|
35 | print "(I)gnore / (Q)uit / (U)pdate: ";
|
---|
36 |
|
---|
37 | my $key;
|
---|
38 | while(defined(read STDIN, $key, 1)) {
|
---|
39 | $key = lc($key);
|
---|
40 |
|
---|
41 | print "got: >$key<\n";
|
---|
42 |
|
---|
43 | return if ($key eq 'i');
|
---|
44 |
|
---|
45 | &bailout("BC problem. aborted") if ($key eq 'q');
|
---|
46 |
|
---|
47 | if ($key eq 'u') {
|
---|
48 | $bcheckdb{$dbkey} = $dbchunk;
|
---|
49 | return;
|
---|
50 | }
|
---|
51 | print "\n(I)gnore / (Q)uit / (U)pdate: ";
|
---|
52 | }
|
---|
53 | }
|
---|
54 |
|
---|
55 | sub diff_chunk($$)
|
---|
56 | {
|
---|
57 | my ($oldl, $newl) = @_;
|
---|
58 | my @old = split /^/m, $oldl;
|
---|
59 | my @new = split /^/m, $newl;
|
---|
60 | my $haschanges = 0;
|
---|
61 | my $max = $#old > $#new ? $#old : $#new;
|
---|
62 |
|
---|
63 | die "whoops. key different" if ($old[0] ne $new[0]);
|
---|
64 |
|
---|
65 | if ($#old != $#new) {
|
---|
66 | warn ("Structural difference.\n");
|
---|
67 | print @old;
|
---|
68 | print "-----------------------------------------------\n";
|
---|
69 | print @new;
|
---|
70 | $haschanges = 1;
|
---|
71 | return $haschanges;
|
---|
72 | }
|
---|
73 |
|
---|
74 | print $old[0];
|
---|
75 |
|
---|
76 | my ($class) = ($old[0] =~ /^(?:Class |Vtable for )(\S+)/);
|
---|
77 |
|
---|
78 | my $c = 1;
|
---|
79 | while ($c < $max) {
|
---|
80 | my ($o, $n) = ($old[$c], $new[$c]);
|
---|
81 | chomp $o;
|
---|
82 | chomp $n;
|
---|
83 | $c++;
|
---|
84 | next if ($o eq $n);
|
---|
85 |
|
---|
86 | if(defined($class) and $n =~ /^(\d+\s+)\w+(::\S+\s*.*)$/) {
|
---|
87 | next if ($n eq "$1$class$2");
|
---|
88 | }
|
---|
89 |
|
---|
90 | $haschanges = 1;
|
---|
91 |
|
---|
92 | print "-$o\n+$n\n\n";
|
---|
93 | }
|
---|
94 |
|
---|
95 | return $haschanges;
|
---|
96 | }
|
---|
97 |
|
---|
98 | local $dblock = $ENV{"HOME"} . "/bcheck.lock";
|
---|
99 | my $dbfile = $ENV{"HOME"} . "/bcheck.db";
|
---|
100 | my $cdump = $ARGV[0];
|
---|
101 |
|
---|
102 | die "file $cdump is not readable: $!" if (! -f $cdump);
|
---|
103 |
|
---|
104 | # make sure the advisory lock exists
|
---|
105 | open(MYLOCK, ">$dblock");
|
---|
106 | print MYLOCK "";
|
---|
107 |
|
---|
108 | flock MYLOCK, LOCK_EX;
|
---|
109 |
|
---|
110 | tie %bcheckdb, 'DB_File', $dbfile;
|
---|
111 |
|
---|
112 | my $chunk = "";
|
---|
113 |
|
---|
114 | open (IN, "<$cdump") or die "cannot open $cdump: $!";
|
---|
115 | while (<IN>) {
|
---|
116 |
|
---|
117 | chop;
|
---|
118 |
|
---|
119 | s/0x[0-9a-fA-F]+/0x......../g;
|
---|
120 | s/base size=/size=/g;
|
---|
121 | s/base align=/align=/g;
|
---|
122 |
|
---|
123 | $chunk .= $_ . "\n";
|
---|
124 |
|
---|
125 | if(/^\s*$/) {
|
---|
126 | my @lines = split /^/m, $chunk;
|
---|
127 | my $key = $lines[0];
|
---|
128 | chomp $key;
|
---|
129 |
|
---|
130 | if($key !~ /<anonymous struct>/ &&
|
---|
131 | $key !~ /<anonymous union>/) {
|
---|
132 | if(defined($bcheckdb{$key})) {
|
---|
133 | my $dbversion = $bcheckdb{$key};
|
---|
134 |
|
---|
135 | if($dbversion ne $chunk) {
|
---|
136 | &ask_user($key, $chunk) if(&diff_chunk($dbversion, $chunk));
|
---|
137 | }
|
---|
138 | }
|
---|
139 | else {
|
---|
140 | $bcheckdb{$key} = $chunk;
|
---|
141 | print "NEW: $key\n";
|
---|
142 | }
|
---|
143 | }
|
---|
144 |
|
---|
145 | $chunk = "";
|
---|
146 | next;
|
---|
147 | }
|
---|
148 |
|
---|
149 | }
|
---|
150 | close(IN);
|
---|
151 |
|
---|
152 | untie %bcheckdb;
|
---|
153 | flock MYLOCK, LOCK_UN;
|
---|
154 | close(MYLOCK);
|
---|
155 |
|
---|
156 | exit 0;
|
---|