Presentation is loading. Please wait.

Presentation is loading. Please wait.

Lazy Abstraction Lecture 2: Modular Analyses Ranjit Jhala UC San Diego With: Tom Henzinger, Rupak Majumdar, Ken McMillan, Gregoire Sutre.

Similar presentations


Presentation on theme: "Lazy Abstraction Lecture 2: Modular Analyses Ranjit Jhala UC San Diego With: Tom Henzinger, Rupak Majumdar, Ken McMillan, Gregoire Sutre."— Presentation transcript:

1 Lazy Abstraction Lecture 2: Modular Analyses Ranjit Jhala UC San Diego With: Tom Henzinger, Rupak Majumdar, Ken McMillan, Gregoire Sutre

2 Program Verification by Lazy Abstraction Ranjit Jhala UC San Diego Lecture 1 With: Tom Henzinger, Rupak Majumdar, Ken McMillan, Gregoire Sutre

3 Last lecture … Lazy Abstraction for Sequential Programs Predicates: –Abstract infinite program states Counterexample-guided Refinement: –Find predicates tailored to prog, property 1.Abstraction : Expensive Reachability Tree 2.Refinement : Find predicates, use locations Proof of unsat of TF + Interpolation

4 This Lecture: Modular Analyses Procedures - Summaries Concurrency - Thread-Context Reasoning

5 An example main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; }

6 Inline Calls in Reach Tree main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1,2 Initial 2,2 4,2 3,2 4,2 3 3 4 1,4 2,4 4,4 3,4 4,4 5 5

7 Inline Calls in Reach Tree 1 2 1,2 Initial 2,2 4,2 3,2 4,2 3 3 4 1,4 2,4 4,4 3,4 4,4 5 5 Problem -Repeated analysis for “inc” -Exploding call contexts int x; //global f1(){ 1: x = 0; 2: if(*) f2(); 3: else f2(); 4: if (x<0) ERROR; return; } int x; //global f1(){ 1: x = 0; 2: if(*) f2(); 3: else f2(); 4: if (x<0) ERROR; return; } f2(){ 1: if(*) f3(); 2: else f3(); return; } f2(){ 1: if(*) f3(); 2: else f3(); return; } f3(){ 1: if(*) f4(); 2: else f4(); return; } f3(){ 1: if(*) f4(); 2: else f4(); return; } f4(){ 1: if(*) f5(); 2: else f5(); return; } f4(){ 1: if(*) f5(); 2: else f5(); return; } fn(){ 1: x ++; return; } fn(){ 1: x ++; return; } 2 n nodes in Reach Tree

8 Inline Calls in Reach Tree 1 2 1,2 Initial 2,2 4,2 3,2 4,2 3 3 4 1,4 2,4 4,4 3,4 4,4 5 5 Problem -Repeated analysis for “inc” -Exploding call contexts -Cyclic call graph (Recursion) -Infinite Tree!

9 Solution : Procedure Summaries Summaries: Input/Output behavior Plug summaries in at each callsite … instead of inlining entire procedure [Sharir-Pnueli 81, Reps-Horwitz-Sagiv 95] Summary = set of (F  F’) –F : Precondition formula describing input state –F’ : Postcondition formula describing output state

10 Solution : Procedure Summaries Summaries: Input/Output behavior Plug summaries in at each callsite … instead of inlining entire procedure [Sharir-Pnueli 81, Reps-Horwitz-Sagiv 95, Ball-Rajamani 01] Summary = set of (F  F’) –F : Precondition formula describing input state –F’ : Postcondition formula describing output state inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } ( : sign=0  rv > a) (sign = 0  rv < a) Q. How to compute, use summaries ?

11 Lazy Abstraction + Procedure Summaries Abstract Refine C Program Safe Trace Yes No Property Q. How to compute, use summaries ?

12 Abstraction with Summaries main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 main Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a : flag=0 a=x sign=flag : sign=0 [flag!=0]

13 Abstraction with Summaries main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 a=x sign=flag : sign=0 [sign!=0] : sign=0 rv=a+1 rv>a Summary: ( : sign=0  rv>a),

14 Summary Successor main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0  rv>a), 3 a=x sign=flag y>x assume rv>a y=rv

15 Abstraction with Summaries main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0  rv>a), 3 y>x [y<=x] 3 4 flag=0 a=x sign=flag sign=0 [sign=0] [flag==0]

16 Abstraction with Summaries main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0  rv>a), (sign=0  rv<a) 3 y>x 3 4 flag=0 a=x sign=flag sign=0 1 2 3 4 rv<a

17 Summary Successor main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0  rv>a), (sign=0  rv<a) 3 y>x 3 4 flag=0 1 sign=0 2 3 4 rv<a a=x sign=flag assume rv<a y=rv 3 y<z

18 Abstraction with Summaries main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0  rv>a), (sign=0  rv<a) 3 y>x 3 4 flag=0 1 sign=0 2 3 4 rv<a 3 y<z [y>=z]

19 Another Call … main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 inc : flag=0 : sign=0 rv>a Summary: ( : sign=0  rv>a), (sign=0  rv<a) 3 6 y>x 3 4 flag=0 1 sign=0 2 3 4 rv<a 3 y<z a=z1 sign=1 : sign=0 6 Predicates: flag=0,y>x,y z1 sign=0, rv>a, rv<a

20 Another Call … main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0,y>x,y z1 sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0  rv>a), (sign=0  rv<a) 3 6 y>x 3 4 flag=0 1 sign=0 2 3 4 rv<a 3 y<z 7 a=z1 sign=1 assume rv>a y1=rv 6 y1>z1 SAFE Note: Predicates are well-scoped …

21 Lazy Abstraction + Procedure Summaries Abstract Refine C Program Safe Trace Yes No Property Q. How to find scoped predicates ?

22 pc 1 : x 1 = 3 pc 2 : assume (x 1 >0) pc 3 : x 3 = f 1 (x 1 ) pc 4 : y 2 = y 1 pc 5 : y 3 = f 2 (y 2 ) pc 6 : z 2 = z 1 +1 pc 7 : z 3 = 2*z 2 pc 8 : return z 3 pc 9 : return y 3 pc 10 : x 4 = x 3 +1 pc 11 : x 5 = f 3 (x 4 ) pc 12 : assume(w 1 <5) pc 13 : return w 1 pc 14 : assume x 4 >5 pc 15 : assume (x 1 =x 3 +2) Traces with Procedure Calls Trace Formula i Trace i Find predicate needed at point i pc 1 : x 1 = 3 pc 2 : assume (x 1 >0) pc 3 : x 3 = f 1 (x 1 ) pc 4 : y 2 = y 1 pc 5 : y 3 = f 2 (y 2 ) pc 6 : z 2 = z 1 +1 pc 7 : z 3 = 2*z 2 pc 8 : return z 3 pc 9 : return y 3 pc 10 : x 4 = x 3 +1 pc 11 : x 5 = f 3 (x 4 ) pc 12 : assume(w 1 <5) pc 13 : return w 1 pc 14 : assume x 4 >5 pc 15 : assume(x 1 =x 3 +2)

23 Interprocedural Analysis Trace Formula i Trace i Require at each point i : Scoped predicates YES: Variables visible at i NO: Caller’s local variables Find predicate needed at point i YES NO

24 Problems with Cutting Trace Formula i Trace i -- ++ Caller variables common to  - and  + Unsuitable interpolant: not well-scoped

25 Scoped Cuts Trace Formula i Call begins Trace i

26 Scoped Cuts -- ++ Trace Formula i Call begins Trace i Predicate at pc i = Interpolant from cut i

27 Common Variables Formals Current locals Trace Formula Predicate at pc i = Interpolant from i-cut i Trace i -- ++ Common Variables Formals Well-scoped

28 Example Trace m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) ERROR: main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } main(){  1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; }  return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; }

29 Trace Formula Trace SSA Trace m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) m1: assume(flag 0 !=0) m2: a 0 =x 0, sign 0 =flag 0 i1: assume(sign 0 !=0) i2: rv 0 =a 0 +1 i4: y 0 =rv 0 m3: assume(y 0 <= x 0 )

30 Trace Formula TraceTrace Formula m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag 0  0 Æ a 0 =x 0 Æ sign 0 = flag 0 Æ sign 0  0 Æ rv 0 =a 0 +1 Æ y 0 =rv 0 Æ y 0 <= x 0 ii Call begins

31 Trace Formula TraceTrace Formula m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag 0  0 Æ a 0 =x 0 Æ sign 0 = flag 0 Æ sign 0  0 Æ rv 0 =a 0 +1 Æ y 0 =rv 0 Æ y 0 <= x 0 -- ++ ii

32 Trace Formula TraceTrace Formula m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag 0  0 Æ a 0 =x 0 Æ sign 0 = flag 0 Æ sign 0  0 Æ rv 0 =a 0 +1 Æ y 0 =rv 0 Æ y 0 <= x 0 i -- ++ i rv 0 a0a0 a0a0 rv 0 > a 0 Interpolate

33 Lazy Abstraction + Procedure Summaries Abstract Refine C Program Safe Trace Yes No Property Q. How to find scoped predicates ? Solution: Scoped Cuts + Interpolation

34 Review : Procedures Modular Analysis via Summaries –Summary = (In,Out) vertices’ formulas Requires scoped predicates –Scoped cuts + Interpolation

35 This Lecture: Modular Analyses Procedures - Summaries Concurrency - Thread-Context Reasoning

36 This Lecture: Modular Analyses Procedures - Summaries Concurrency - Thread-Context Reasoning

37 Multithreaded Programs OS, WebServers, Databases, Embedded Systems Curse of Interleaving Non-deterministic scheduling Exponentially many behaviors: hard to detect, reproduce errors Testing exercises a fraction of possible behaviors Thread Shared Memory x Thread Thread

38 Data Races  x:= x+1   x:= x+1   x:= x-5   x:= x-5  x A data race on x is a state where: Two threads can access x One of the accesses is a write Unpredictable, undesirable Synchronization: Must hold lock when accessing x lock(l) unlock(l) lock(l) unlock(l)

39 Previous Work : Locks  x:= x+1  x:= x+1  lock(l) unlock(l) 1.Infer some lock(s) that protect x 2.Check lock(s) held when accessing x 3.Report error if lock(s) not held Static LockSet [Sterling 93], [Engler-Ashcraft 03] [Flanagan-Freund 00] [Bacon et al. 00] [Boyapati et al. 02] [Dinning-Schonberg 90] [Savage et al. 97] [Cheng et al. 98] [Choi et al. 02] Type-based Dynamic LockSet Object Usage Graph [von Praun-Gross 03] Scalable Restricted to locking

40 Other Synchronization Idioms Producer-Consumer atomic{ old:= state; if(state==0){ state:=1; }  if(old==0){ x++; state:=0; } atomic{ old:= state; if(state==0){ state:=1; }  if(old==0){ x++; state:=0; } State-basedInterrupt-toggling x

41 Previous Work : Model Checking Producer-Consumer atomic{ old:= state; if(state==0){ state:=1; }  if(old==0){ x++; state:=0; } atomic{ old:= state; if(state==0){ state:=1; }  if(old==0){ x++; state:=0; } State-basedInterrupt-toggling x Model Checking (State Exploration) [Godefroid 97] [Holzmann][Havelund-Visser] [Dwyer-Hatcliff][Avrunin-Clarke] [Musuvathi-Dill-Engler 02] [Yahav 01] Any Synch. Idiom Fixed #threads Manual Abstraction State Explosion

42 Data Race Shared Memory Initial Race Checking by State Exploration Is there a path from Initial to Race ?

43 Problem: State Explosion Shared Memory Data Race Initial Is there a path from Initial to Race ?

44 Problem: State Explosion 2. Control k threads, m locations = m k - k=4,m=100, states = 1 billion Unbounded threads ? 1. Data Infinitely many valuations for program variables Data Race Initial

45 LA for Multithreaded Programs 1.Data Races –Previous Work –State Explosion 2.Abstractions 3.Context Inference

46 1.Data Races –Previous Work –State Explosion 2.Abstractions 3.Context Inference LA for Multithreaded Programs

47 Problem: State Explosion 2. Control k threads, m locations = m k - k=4,m=100, states = 1 billion Unbounded threads ? 1. Data Infinitely many valuations for program variables Data Race Initial

48 Solution: Abstract Irrelevant Detail 1. Data Infinitely many valuations for program variables 2. Control k threads, m locations = m k - k=4,m=100, states = 1 billion Unbounded threads ? Observe - Analyze system as Thread + Context - Context: Summary of all other threads (w.r.t. property) 2. Thread-Context Analysis Observe - Few relevant variables, relationships - Track predicates (relationships) instead of values 1. Predicate Abstraction

49 Example Check for races on x: Initially: s is 0 1 st thread into atomic : - sets old to 0 (value of s ) - sets s to 1 - passes test before access Later threads: - set old to 1 (value set by 1 st thread) - fail test before access (until the 1 st thread is done) 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} }

50 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Verifying Multithreaded Programs LA for Multithreaded Programs

51 Predicate Abstraction 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } Predicates on Variables s=0, old=0 s=0 1 2 3 4 1 Reachability Graph s=0 s=0, old=0 5 6 : s=0, old=0 : s=0 old=0 s=0 old=0 Q: What about other threads ? x++

52 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Contexts Thread-Context Reasoning 3.Context Inference LA for Multithreaded Programs

53 Threads, Contexts Q: What about other threads ? Shared Memory Assume threads run same code Context: Summary of all other threads - Precise enough to check property System = Thread + Context Q: What does a Context look like ? Context

54 Thread, Contexts Context: Summary of all other threads 1. Summarize a single thread 2. Multiple threads by counting Q: What does a Context look like ? Shared Memory Context 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } s=0 s s,x s0s0 s0s0 ThreadSummary Context

55 Many Threads by Counting s=0 s s,x s0s0 s0s0 Context True 1 1 1 0 0 0 s=0 State s 0s 0 s  0 Æ s=0 Initial loc = 1, other = 0 Operations 1. Pick edge w/ source counter > 0, 2. Source counter -1 Target counter +1 Havoc variables on edge, Assume predicate on target Unbounded threads k-Counter Abstraction: Value > k abstracted to 1 for k=1, values: 0,1, 1 Q: What does a Context look like ? 1 Contra! 1 2 1

56 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Contexts Thread-Context Reasoning 3.Context Inference LA for Multithreaded Programs

57 Thread-Context Reasoning Q: How to check race-freedom ? Given an Abstraction: 1. Data:Predicates 2. Control: Summary, k 1 Use Context Build finite Reach Graph Check Race unreachable 2 Verify Context Sound Check Summary Overapproximates single Thread’s behavior k k Shared Memory No Race µ Reach Graph Summarize Computed Summary Given Summary

58 Q: How to check race-freedom ? Given an Abstraction: 1. Data:Predicates 2. Control: Summary, k 1 2 Shared Memory Assume-Guarantee (Use) (Verify) No Race k Shared Memory No Race µ Reach Graph Summarize Thread-Context Reasoning Computed Summary Given Summary

59 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Context Inference LA for Multithreaded Programs

60 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Context Inference LA for Multithreaded Programs

61 Inference: Build Summary 1 Reach Grap h 2 ; µ ; Summarize 1 Reach Grap h No Race Race Trace Abstraction Preds: P 0 Ctr: k 0

62 Inference: Trace Analysis Trace FeasibleInfeasible Refine using Trace Either: 1.Add new predicates 2.Increase k Abstraction Preds: P 0 Ctr: k 0 Report Trace Interleaved sequence of threads’ ops Abstraction Preds: P 1 Ctr: k 1

63 Inference: Build Summary 1 Reach Graph 2 µ ; Summarize Abstraction Preds: P 0 Ctr: k 0 Abstraction Preds: P 1 Ctr: k 1 1 Reach Graph 2 µ Summarize 1 Reach Graph 2 µ Summarize ;

64 Context Inferred 1 Reach Graph 2 µ Summarize Shared Memory Assume-Guarantee No Race

65 NO (trace) Context Inference Init. Abstraction Preds: P 0 Ctr: k 0 Init. Summary Summary: ; 1 Reach Graph YES Summarize Safe? 2 µ ? YES NO Update Summary Refine using Trace Feasible? YES NO Output SAFE No Data Races Output Data Race TRACE ANALYSIS BUILD SUMMARY

66 Plan 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Context Inference –Example

67 Ex: Races on x 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } ; Abstraction Preds = ; k=1 1 2 3 4 5 6 Reach Graph T 7 x++; Summarize 2 µ ; 1 x Build Summary x Control-Flow Graph

68 Ex: Races on x 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } Abstraction Preds = ; k=1 Reach Graph 1 Build Summary x 1 2 3 4 5 6 x++ 6 Race x

69 Thread 1 Ex: Races on x 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } Abstraction Preds = ; k=1 Reach Graph 1 Trace Analysis x 1 2 3 4 5 6 x++ 6 Trace x Thread 0 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } x assume (True) old := s assume (s==0) s:= 1 // do_work() assume (old==0) //write x enabled 1 2 3 4 5 6 T 7 x++; assume (True) old := s assume (s==0) s:= 1 // do_work() assume (old==0) //write x enabled

70 Thread 1 Ex: Races on x Trace Analysis Trace Thread 0 assume (True) old := s assume (s==0) s:= 1 // do_work() assume (old==0) //write x enabled assume (True) old := s assume (s==0) s:= 1 // do_work() assume (old==0) //write x enabled Time s is set to 1 Infeasible branch New Predicate s = 0 Infeasible Trace

71 Ex: Races on x 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } ; Abstraction Preds: s=0 k=1 Reach Graph Summarize 2 µ ; 1 Build Summary, old=0 s=0 1 2 3 4 s=0 old=0 5 6 : s=0 old=0 7 x++ s:=0 : s=0 old=0 Local Pred. old=0 - Prunes infeasible paths - Invisible to other threads - Quantified away s:=1 s=0 x s0s0 s s s0s0 x s0s0 s s s0s0

72 Ex: Races on x 1:while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1:while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } Abstraction Preds: s=0 k=1 Reach Graph Summarize 2 µ 1 Build Summary, old=0 1 2 3 4 s=0 Ç s  0 5 6 s=0 old=0 s  0 old=0 x++ s:=0 s:=1 T T 5 Context changes s s  0 old  0 s=0 s s,x s0s0 s0s0 s=0 x s0s0 s s s0s0 Local Pred. old=0 - Cuts locally infeasible paths - Invisible to other threads - Quantified away s=0 x s0s0 s s s0s0 s s,x s0s0 s0s0 s=0 Ç s  0

73 Ex: Races on x 1:while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } 1:while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work()  5: if(old==0){ 6: x++; 7: s:=0;} } Abstraction Preds: s=0 k=1 Reach Graph Sumz 2 µ 1 Build Summary, old=0 1 2 3 4 5 6 s=0 old=0 s  0 old=0 x++ s:=0 s:=1 T T T 5 s  0 old  0 s=0 s s,x s0s0 s0s0 s=0 s s,x s0s0 s0s0 s=0 s s,x s0s0 s0s0 SAFE No Races on x

74 Plan 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Context Inference –Example 4. Experiments

75 Data Races in NesC Programs PL for Networked Embedded Systems [Gay et al. 03] Interrupts fire events, which fire other events or post tasks which run asynchronously Race-freedom important –Non-trivial synchronization idioms –Flow-based analysis Compiled to C

76 Case Study: sense.nc atomic{ old:= state; if(state==0){ state:=1; }  if(old==0){ x++;  atomic{ old:= state; if(state==0){ state:=1; }  if(old==0){ x++;  Interrupt 1 fires  old := state if (state ==0){ state := 1  assume (old == 0){ about to write x Interrupt 2 fires  state := 0 Interrupt 1 fires  old := state assume (state ==0){ state := 1  If (old == 0){ about to write x Interrupt 1 handler disables interrupt 2 BLAST finds information proves no races

77 Review : Multithreaded 1.Multithreaded Verification is hard –Data, Control Explosion –Abstract Irrelevant details 2.Combine Abstractions 1.Data: Predicates 2.Control: Contexts (Summary + Counter) 3.Iterative Context Inference

78 Next lecture … Partial-program analysis: From verification to interfaces


Download ppt "Lazy Abstraction Lecture 2: Modular Analyses Ranjit Jhala UC San Diego With: Tom Henzinger, Rupak Majumdar, Ken McMillan, Gregoire Sutre."

Similar presentations


Ads by Google