X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=misc%2Ftools%2Fprogs-analyzer.pl;h=d0df1c420676ef6b57ed32e65b061847a3d3c83d;hb=857c997721671a1e81ffce0b51473bd95e916f09;hp=b4ffbca5e226cfe549fd15e914c210ac16461c90;hpb=2661560c0a9ed6b70c66687c7d75e769447d6cbb;p=xonotic%2Fxonotic.git diff --git a/misc/tools/progs-analyzer.pl b/misc/tools/progs-analyzer.pl old mode 100644 new mode 100755 index b4ffbca5..d0df1c42 --- a/misc/tools/progs-analyzer.pl +++ b/misc/tools/progs-analyzer.pl @@ -1,3 +1,5 @@ +#!/usr/bin/perl + use strict; use warnings; use Digest::SHA; @@ -125,6 +127,10 @@ sub checkop($) { return { a => 'inglobal', b => 'inglobalfunc' }; } + if($op =~ /^INVALID#/) + { + return { isinvalid => 1 }; + } return { a => 'inglobal', b => 'inglobal', c => 'outglobal' }; } @@ -673,6 +679,10 @@ sub find_uninitialized_locals($$) } } + if($c->{isinvalid}) + { + ++$warned{$ip}{''}{"Invalid opcode"}; + } for(qw(a b c)) { my $type = $c->{$_}; @@ -897,7 +907,8 @@ sub detect_constants($) use constant GLOBALFLAG_Q => 32; # unique to function use constant GLOBALFLAG_U => 64; # unused use constant GLOBALFLAG_P => 128; # possibly parameter passing - my @globalflags = (GLOBALFLAG_Q | GLOBALFLAG_U) x @{$progs->{globals}}; + use constant GLOBALFLAG_D => 256; # has a def + my @globalflags = (GLOBALFLAG_Q | GLOBALFLAG_U) x (@{$progs->{globals}} + 2); for(@{$progs->{functions}}) { @@ -979,21 +990,42 @@ sub detect_constants($) if $name eq 'IMMEDIATE' or $name =~ /^\./; $_->{debugname} = $name if $name ne ''; + $globalflags[$_->{ofs}] |= GLOBALFLAG_D; if($type->{save}) { - for my $i(0..(typesize($_->{type}{type})-1)) - { - $globalflags[$_->{ofs}] |= GLOBALFLAG_S; - } + $globalflags[$_->{ofs}] |= GLOBALFLAG_S; } - if($name ne '') + if(defined $_->{debugname}) { - for my $i(0..(typesize($_->{type}{type})-1)) + $globalflags[$_->{ofs}] |= GLOBALFLAG_N; + } + } + # fix up vectors + my @extradefs = (); + for(@{$progs->{globaldefs}}) + { + my $type = $_->{type}; + for my $i(1..(typesize($type->{type})-1)) + { + # add missing def + if(!($globalflags[$_->{ofs}+$i] & GLOBALFLAG_D)) { - $globalflags[$_->{ofs}] |= GLOBALFLAG_N; + print "Missing globaldef for a component@{[defined $_->{debugname} ? ' of ' . $_->{debugname} : '']} at $_->{ofs}+$i\n"; + push @extradefs, { + type => { + saved => 0, + type => 'float' + }, + ofs => $_->{ofs} + $i, + debugname => defined $_->{debugname} ? $_->{debugname} . "[$i]" : undef + }; } + # "saved" and "named" states hit adjacent globals too + $globalflags[$_->{ofs}+$i] |= $globalflags[$_->{ofs}] & (GLOBALFLAG_S | GLOBALFLAG_N | GLOBALFLAG_D); } } + push @{$progs->{globaldefs}}, @extradefs; + my %offsets_initialized = (); for(0..(@{$progs->{globals}}-1)) { @@ -1086,7 +1118,8 @@ sub detect_constants($) $globaldefs[$_] //= { ofs => $_, s_name => undef, - debugname => undef + debugname => undef, + type => undef }; } for(0..(@{(DEFAULTGLOBALS)}-1)) @@ -1158,7 +1191,7 @@ sub parse_progs($) die "Out of range name in globaldef $_" if $g->{s_name} < 0 || $g->{s_name} >= length $p{strings}; my $name = $p{getstring}->($g->{s_name}); - die "Out of range ofs in globaldef $_ (name: \"$name\")" + die "Out of range ofs $g->{ofs} in globaldef $_ (name: \"$name\")" if $g->{ofs} >= $p{globals}; } @@ -1172,7 +1205,7 @@ sub parse_progs($) die "Out of range name in fielddef $_" if $g->{s_name} < 0 || $g->{s_name} >= length $p{strings}; my $name = $p{getstring}->($g->{s_name}); - die "Out of range ofs in globaldef $_ (name: \"$name\")" + die "Out of range ofs $g->{ofs} in fielddef $_ (name: \"$name\")" if $g->{ofs} >= $p{header}{entityfields}; } @@ -1194,12 +1227,12 @@ sub parse_progs($) my $file = $p{getstring}->($f->{s_file}); die "Out of range first_statement in function $_ (name: \"$name\", file: \"$file\", first statement: $f->{first_statement})" if $f->{first_statement} >= @{$p{statements}}; - die "Out of range parm_start in function $_ (name: \"$name\", file: \"$file\", first statement: $f->{first_statement})" - if $f->{parm_start} < 0 || $f->{parm_start} >= @{$p{globals}}; - die "Out of range locals in function $_ (name: \"$name\", file: \"$file\", first statement: $f->{first_statement})" - if $f->{locals} < 0 || $f->{parm_start} + $f->{locals} >= @{$p{globals}}; if($f->{first_statement} >= 0) { + die "Out of range parm_start in function $_ (name: \"$name\", file: \"$file\", first statement: $f->{first_statement})" + if $f->{parm_start} < 0 || $f->{parm_start} >= @{$p{globals}}; + die "Out of range locals in function $_ (name: \"$name\", file: \"$file\", first statement: $f->{first_statement})" + if $f->{locals} < 0 || $f->{parm_start} + $f->{locals} > @{$p{globals}}; die "Out of range numparms $f->{numparms} in function $_ (name: \"$name\", file: \"$file\", first statement: $f->{first_statement})" if $f->{numparms} < 0 || $f->{numparms} > 8; my $totalparms = 0; @@ -1210,7 +1243,9 @@ sub parse_progs($) $totalparms += $f->{parm_size}[$_]; } die "Out of range parms in function $_ (name: \"$name\", file: \"$file\", first statement: $f->{first_statement})" - if $f->{locals} < 0 || $f->{parm_start} + $totalparms >= @{$p{globals}}; + if $f->{parm_start} + $totalparms > @{$p{globals}}; + die "More parms than locals in function $_ (name: \"$name\", file: \"$file\", first statement: $f->{first_statement})" + if $totalparms > $f->{locals}; } } @@ -1235,8 +1270,18 @@ sub parse_progs($) elsif($type eq 'inglobalvec') { $s->{$_} &= 0xFFFF; - die "Out of range global offset in statement $ip - cannot continue" - if $s->{$_} >= @{$p{globals}}-2; + if($c->{isreturn}) + { + die "Out of range global offset in statement $ip - cannot continue" + if $s->{$_} >= @{$p{globals}}; + print "Potentially out of range global offset in statement $ip - may crash engines" + if $s->{$_} >= @{$p{globals}}-2; + } + else + { + die "Out of range global offset in statement $ip - cannot continue" + if $s->{$_} >= @{$p{globals}}-2; + } } elsif($type eq 'outglobal') {