Post on 19-Dec-2015
transcript
Levels of Reasoning
• propositionalp1 = q1 p2 = q2 . . . pn = qn p = q
• schematic (1st order uninterpreted)x := s ; x := t = x := t[x/s]
• 1st order interpretedi j j k i k
Schematic KAT (SKAT)
x := s ; y := t = y := t[x/s] ; x := s y FV(s)
x := s ; y := t = x := s ; y := t[x/s] x FV(s)
x := s ; x := t = x := t[x/s]
b[x/t] ; x := t = x := t ; b
x := x = 1
Relation to Hoare Assignment Rule
b[x/t] ; x := t x := t ; b
is equivalent to
{b[x/t]} x := t {b}
b[x/t] ; x := t = x := t ; b
is equivalent to the conjunction of
{b[x/t]} x := t {b} {~b[x/t]} x := t {~b}
• universal Horn logic
p1 = q1 p2 = q2 . . . pn = qn p = q
• premises pi = qi
− self-evident assumptions about local behavior
− typically involve atomic instructions and tests
• conclusion p = q
− equivalence of original program and optimized or
annotated program
• use schematic and interpreted reasoning only to
establish validity of premises – most reasoning done
at the propositional level
Reasoning with KAT
Compiler Optimizations[Kozen & Patron 00]
• dead code elimination
• common subexpression elimination
• copy propagation
• loop hoisting
• loop unrolling
• reducing nesting depth
• induction variable elimination
• instruction scheduling
• algebraic simplification
• elimination of redundant instructions
• array bounds check elimination
• introduction of sentinels
Typical Premises
“two instructions that do not affect each other can be
done in either order”
load r1,x ; load r2,y = load r2,y ; load r1,x
“after loading a value in a register, that register
contains that value”
load r1,x = load r1,x ; r1=x p = pb
“no need to load a value if the register already
contains that value”
r1=x ; load r1,x = r1=x bp = b
Loop Hoisting
for (i = 0; i < n; i++) {
b[i] = x;
}
i := 0
: test i < n
jump if false
load r,x
store r,b[i]
i := i + 1
jump
:
Loop Hoisting
for (i = 0; i < n; i++) {
b[i] = x;
}
i := 0
: test i < n
jump if false
load r,x
store r,b[i]
i := i + 1
jump
:
This is of the form w(cupv)*c
p = load r,x b = r=x
load r,x = load r,x ; r=x p = pb
bpp
r=x ; load r,x = r=x bp = b
b p b
ub = bu
vb = bv
p = pb bp = b ub = bu vb = bv
w(cupv)*c = w(cupv(cubv)*c + c)
Suffices to show
p = pb bp = b ub = bu vb = bv
(cupv)* = cupv(cubv)* + 1
Loop Unrolling
while b do { while b do { p; p;} if b then p;
}
(bp)*b = (bp(bp + b))*b
Key lemma q* = (qn)*(1 + q)n-1
Array Bounds Check Elimination
for (i = 0; i < x.length; i++) { x[i] := e(i);
}
i := 0: test i < n
jump if falsecompute e(i) if i out of bounds then errorx[i] := e(i) i := i + 1jump
:
Array Bounds Check Elimination
for (i = 0; i < x.length; i++) { x[i] := e(i);
}
i := 0: test i < n
jump if falsecompute e(i) if i out of bounds then errorx[i] := e(i) i := i + 1jump
:
Array Bounds Check Elimination
a = 0 i b = i < x.length c = ab i is in bounds
We have to prove
u(bp(cq + cs)v)*b = u(bpqv)*b
Introduce a using u = ua, show a and b (and therefore c) hold where needed to eliminate the array bounds check
LU Decomposition with Pivoting[Mateev, Menon, Pingali 01]
• Restructuring of matrix operations to take advantage of locality
• Def/use analysis fails: transformations break def/use dependencies
• MMP develop a new technique, fractal symbolic analysis
y = x; x = 2*x;y = 2*y; y = 2*y;x = 2*x; y = x;
y = 2*x; x = 2*x;x = 2*x; y = x;
x := s ; x := t = x := t[x/s]
y = x; x = 2*x;y = 2*y; y = 2*y;x = 2*x; y = x;
y = 2*x; x = 2*x;x = 2*x; y = x;
x := s ; y := t = y := t[x/s] ; x := s
y FV(s)
for (j = 0; j < n-1; j++) {tmp = a[j]; //swapa[j] = a[j+1];a[j+1] = tmp;for (i = j+1; i < n; i++) {
a[i] = a[i]/a[j]; //update}
}
for (j = 0; j < n-1; j++) {tmp = a[j]; //swapa[j] = a[j+1];a[j+1] = tmp;
}for (j = 0; j < n-1; j++) {
for (i = j+1; i < n; i++) {a[i] = a[i]/a[j]; //update
}}
for (j = 0; j < n-1; j++) {swap(j,j+1);
for (i = j+1; i < n; i++) {update(i,j);
}}
for (j = 0; j < n-1; j++) {swap(j,j+1);
}for (j = 0; j < n-1; j++) {
for (i = j+1; i < n; i++) {update(i,j);
}}
k > j
swap(k,k+1);for (i = j+1; i < n; i++) {
update(i,j);}
=
for (i = j+1; i < n; i++) {update(i,j);
}swap(k,k+1);
Key Lemma pq = qp pq* = q*p
for (j = 0; j < n-1; j++) {swap(j,j+1);for (i = j+1; i < n; i++) {
update(i,j);}
}
for (j = 0; j < n-1; j++) {swap(j,j+1);
}for (j = 0; j < n-1; j++) {
for (i = j+1; i < n; i++) {update(i,j);
}}
Key Lemma pq = qp p*q* = (pq)*(p* + q*)
start
y1 := x
y4 := f(y1)
y1 := f(y1)
y2 := g(y1,y4)
y3 := g(y1,y1)
P(y1)
y1 := f(y3)
P(y4)
P(y2)
y2 := f(y2) P(y3)
z := y2
halt
T
T
T
TF
F
F
F
start
y := f(x)
loop
P(y)
y := g(y,y)
P(y)
y2 := f(f(y)) z := y
halt
T
T
F
F
SchemeEquivalence
Example of Paterson
from [Manna 74]
x1p41p11q214q311(a1p11q214q311)*a1p13
((a4+a4(a2p22)*a2a3p41p11) q214q311(a1p11q214q311)*a1p13)*
a4(a2p22)*a2a3z2z
saq(araq)*az
x1 p41 p11 q214 q311 a1 p13 a4 a2 a3 z2
p22
a1
a4
a2
a3
s q a
r
z
a
a
Kleene’s Theorem
Static Analysis
• Derivation of information about the execution state at various points in a program at compile time or load time, prior to execution
• Approaches– type inference– dataflow analysis– abstract interpretation– set constraints
• Applications– code optimization– verification
Software Model Checking withSLAM
Thomas BallTesting, Verification and Measurement
Sriram K. RajamaniSoftware Productivity Tools
Microsoft Research
http://research.microsoft.com/slam/
State Machine for Locking
Unlocked Locked
Error
Rel Acq
Acq
Rel
state {
enum {Locked,Unlocked}
s = Unlocked;
}
KeAcquireSpinLock.entry {
if (s==Locked) abort;
else s = Locked;
}
KeReleaseSpinLock.entry {
if (s==Unlocked) abort;
else s = Unlocked;
}
Locking Rule in SLIC
do {KeAcquireSpinLock();
nPacketsOld = nPackets;
if(request){request = request->Next;KeReleaseSpinLock();nPackets++;
}} while (nPackets != nPacketsOld);
KeReleaseSpinLock();
ExampleDoes this code
obey the locking rule?
do {KeAcquireSpinLock();
if(*){
KeReleaseSpinLock();
}} while (*);
KeReleaseSpinLock();
ExampleModel checking boolean program
(bebop)
U
L
L
L
L
U
L
U
U
U
E
do {KeAcquireSpinLock();
nPacketsOld = nPackets;
if(request){request = request->Next;KeReleaseSpinLock();nPackets++;
}} while (nPackets != nPacketsOld);
KeReleaseSpinLock();
ExampleIs error path feasible
in C program?(newton)
U
L
L
L
L
U
L
U
U
U
E
do {KeAcquireSpinLock();
nPacketsOld = nPackets; b = true;
if(request){request = request->Next;KeReleaseSpinLock();nPackets++; b = b ? false : *;
}} while (nPackets != nPacketsOld); !b
KeReleaseSpinLock();
ExampleAdd new predicateto boolean program
(c2bp)b : (nPacketsOld == nPackets)
U
L
L
L
L
U
L
U
U
U
E
do {KeAcquireSpinLock();
b = true;
if(*){
KeReleaseSpinLock();b = b ? false : *;
}} while ( !b );
KeReleaseSpinLock();
b
b
b
b
ExampleModel checking
refined boolean program
(bebop)
b : (nPacketsOld == nPackets)
U
L
L
L
L
U
L
U
U
U
E
b
b
!b
Example
do {KeAcquireSpinLock();
b = true;
if(*){
KeReleaseSpinLock();b = b ? false : *;
}} while ( !b );
KeReleaseSpinLock();
b : (nPacketsOld == nPackets)
b
b
b
b
U
L
L
L
L
U
L
U
U
b
b
!b
Model checking refined
boolean program(bebop)
do { KeAcquireSpinLock(); nPacketsOld = nPackets; if (request) { request = request->Next; KeReleaseSpinLock(); nPackets++; } } while (nPackets != nPacketsOld); KeReleaseSpinLock();
do { kA; n; if (R) { do p while C u; = p;(C;p)*;~C kR; m; if C then p } = C;p + ~C } while (~B); kR;
do { kA; n; if (R) { do p while C u; = p;(C;p)*;~C kR; m; if C then p } = C;p + ~C } while (~B); kR;
kA;n;(R;u;kR;m + ~R); (~B;kA;n;(R;u;kR;m + ~R))*;B;kR
Preconditions for safe execution
operation preconditionkA (acquire) ~A (unlocked)kR (release) A (locked)Global precondition: initially unlocked
Original program
~A;kA;n;(R;u;kR;m + ~R);(~B;kA;n;(R;u;kR;m + ~R))*;B;kR
Annotated program
~A;~A;kA;n;(R;u;A;kR;m + ~R);(~B;~A;kA;n;(R;u;A;kR;m + ~R))*;B;A;kR
kA = kA;A - acquiring the lock acquires itkR = kR;~A - releasing the lock releases itB;m = B;m;~B - if two integer variables are
equal and we increment one, then they are no longer equal
n = n;B - setting one variable equal to another makes them equal
A;n = n;A - commutativity conditionsA;u = u;AA;m = m;AB;u = u;BB;kR = kR;B
kA = kA;A kR = kR;~A B;m = B;m;~B n = n;B A;n = n;A A;u = u;A A;m = m;A B;u = u;B B;kR = kR;B
~A;kA;n;(R;u;kR;m + ~R);(~B;kA;n;(R;u;kR;m + ~R))*;B;kR
=~A;~A;kA;n;(R;u;A;kR;m + ~R);(~B;~A;kA;n;(R;u;A;kR;m + ~R))*;B;A;kR
Security Automata [Schneider 98]
• general mechanism for specification and runtime enforcement of safety policies
• policy is specified by a finite automaton M• code is instrumented to call M before all
critical operations (ones that could change state of M )
• M aborts the computation if the operation causes a transition to an error state
• can handle all safety properties
read
send
send
read
errorstart
Example
no sendafter read
read
send
send
read
error
• code is instrumented to call M before each read and send instruction
• purely a runtime mechanism
start
Security Automata and KATUse KAT to do static analysis to eliminate unnecessary calls to M
• assertion U for each state of M
• premises AM :
• UV = 0 for U ≠ V
• Up pV for each atomic transition U V
• Up pU if p is noncritical
• start state S, error states E
p
Prefixes
Pre(r) = an expression representing prefixes of computations of r. Defined inductively:
Pre(p) = 1 + p p an atomic actionPre(b) = 1 b a testPre(pq) = Pre(p) + p;Pre(q)Pre(p + q) = Pre(p) + Pre(q)Pre(p*) = p*;Pre(p)
This is a closure operator in the sense thatPre(Pre(p)) = Pre(p) is a theorem of KAT
Eliminating Runtime Checks
Soundness Theorem Let D be any set of premises over P,B, and let r be any program over P,B. If
D AM S·Pre(r) (~E·ΣP)*·~E
is a theorem of KAT, then r is safe with respect to M in any Kripke frame whose trace algebra satisfies D.
Completeness Theorem The converse holds as well, provided D is finite and all elements of D are of the form p = 0.
2nd-Order Abstract Interpretation
Let L be an upper semilattice such that all ascending chains are finite (ACC). Elements are called types or abstract values.
Associated with each atomic action p is a strict, partial, finitely additive map fp : L L called its transfer function.
Take premises Xp p fp(X) and propagate information as before (ACC needed for *).
Types or Abstract Values
• Represent sets of values– statically derivable– conservative approximation
• Form a partial semilattice– higher = less specific– join does not exist = type error
Example: Java Bytecode
Object
Array [ ]
Integer Continuations
Array [ ][ ] …Interface
implements
Useless
Null
Java class
hierarchy
int, short, byte,
boolean, char
Example: Java Bytecode
local variable array
operand stack
this p0 p1 p2
parameters other locals
maxLocals
maxS
tack
= reference type= integer= continuation
StringHash-
tableObject
String-
Buffer
User-
Classint[ ]
= useless
Example of a Transfer Function
0 1 2 3 4 5 6 7
loca
lsst
ack
0 1 2 3 4 5 6 7
loca
lsst
ack
iload 3
Preconditions for safe execution:
• local 3 is an integer• stack is not full
Effect:• push integer in local 3 on stack