Presentation is loading. Please wait.

Presentation is loading. Please wait.

The Bandera Model Reduction Tools James Corbett Matthew Dwyer John Hatcliff Shawn Laubach Corina Pasareanu Robby Hongjun Zheng Faculty Students and Post-docs.

Similar presentations


Presentation on theme: "The Bandera Model Reduction Tools James Corbett Matthew Dwyer John Hatcliff Shawn Laubach Corina Pasareanu Robby Hongjun Zheng Faculty Students and Post-docs."— Presentation transcript:

1 The Bandera Model Reduction Tools James Corbett Matthew Dwyer John Hatcliff Shawn Laubach Corina Pasareanu Robby Hongjun Zheng Faculty Students and Post-docs Roby Joehanes Ritesh Desai Venkatesh Ranganath Oksana Tkachuk

2 Bandera Architecture BIRC BIR Simulator Abstraction Engine Slicer Analyses Translators SPIN dSPIN SMV JPF Property Tool Java Jimple Parser Error Trace Display

3 Property-directed Slicing slicing criterion generated automatically from observables mentioned in the property backwards slicing automatically finds all components that might influence the observables. Source program Resulting slice Slice mentioned in property indirectly relevant

4 Slicing: A Simple Example Raise m to the power of n: init: m := 5; [init.1] n := 2; [init.2] result := 1; [init.3] goto test; test: if (n<1) [test.1] then end else loop; loop: result := result*m; [loop.1] n := n-1; [loop.2] goto test; [loop.3] end: return; [end.1] Slicing Criterion: C = { [loop.2] } init: n := 2; [init.2] goto test; test: if (n<1) [test.1] then end else loop; loop: n := n-1; [loop.2] goto test; [loop.3] end: return; [end.1] data dependence control dependence

5 Computing Slices: The Program Dependence Graph Approach init: m := 5; [init.1] n := 2; [init.2] result := 1; [init.3] goto test; test: if (n<1) [test.1] then end else loop; loop: result := result*m; [loop.1] n := n-1; [loop.2] goto test; [loop.3] end: return; [end.1] Source Program [init.1] [init.2] [init.3] [test.1] [loop.1] [loop.2] [loop.3] [end.1] CFG [init.1] [init.2] [init.3] [test.1] [loop.1] [loop.2] [loop.3] [end.1] PDG

6 Computing Slices: The Program Dependence Graph Approach init: m := 5; [init.1] n := 2; [init.2] result := 1; [init.3] goto test; test: if (n<1) [test.1] then end else loop; loop: result := result*m; [loop.1] n := n-1; [loop.2] goto test; [loop.3] end: return; [end.1] Source Program [init.1] [init.2] [init.3] [test.1] [loop.1] [loop.2] [loop.3] [end.1] CFG [init.1] [init.2] [init.3] [test.1] [loop.1] [loop.2] [loop.3] [end.1] PDG Slice set wrt Criterion C: {m | m * n where n in C}

7 Correction: notion of Projection Slicing Criterion: C = { [loop.2] } ([init.1], [m=0,n=0,result=0]) ([init.2], [m=5,n=0,result=0]) ([init.3], [m=5,n=2,result=0]) ([init.4], [m=5,n=2,result=1]) ([test.1], [m=5,n=2,result=1]) ([loop.1], [m=5,n=2,result=1]) ([loop.2], [m=5,n=2,result=5]) ([loop.3], [m=5,n=1,result=5]) ([test.1], [m=5,n=1,result=5]) ([loop.1], [m=5,n=1,result=5]) ([loop.2], [m=5,n=1,result=25]) ([loop.3], [m=5,n=0,result=25]) ([test.1], [m=5,n=0,result=25]) ([end.1], [m=5,n=0,result=25]) (halt, [m=5,n=0,result=25]) Source Program TraceResidual Program (Slice) Trace ([init.2], [n=0]) ([init.4], [n=2]) ([test.1], [n=2]) ([loop.2], [n=2]) ([loop.3], [n=1]) ([test.1], [n=1]) ([loop.2], [n=1]) ([loop.3], [n=0]) ([test.1], [n=0]) ([end.1], [n=0]) (halt, [n=0])

8 Scaling to Concurrency Features of Java What are the relevant notions of dependence? –Besides data and control dependence, we have… dependences due to indefinite delays (divergence, indefinite block) dependences due to defs/refs of shared variables dependences due to synchronization primitives What is the appropriate notion of correctness? –must consider reactive programs designed to run indefinitely –must handle non-determinism (from linear to branching traces)

9 A Simple Language with JVM Concurrency Primitives P Run Blocked Waiting Holds: Buffer Lock Data T1 p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; Producer: count /* shared variable */ buffer /* lock variable */

10 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data T1

11 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data P

12 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data P

13 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data P

14 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data Tk

15 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data Tk

16 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data P

17 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data P

18 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; P Run Blocked Waiting Holds: Buffer Lock Data P

19 A Simple Language with JVM Concurrency Primitives p_obtain_lock: enter-monitor buffer; goto p_check; p_check: if (count=2) then p_wait else p_put; p_wait: wait buffer; goto p_check; p_put: /* put item */ count := count + 1; if (count=1) then p_wakeup else p_release_lock; p_wakeup: notify buffer; goto p_release_lock; p_release_lock: exit-monitor buffer; if 1 then p_obtain_lock else exit_p; exit_p: return; Run Blocked Waiting Holds: Buffer Lock Data P

20 Semantics The program counter pc assigns to each thread t the node of t to be executed. The store S maps each variable to a value The run state table R maps each thread to to either true or false The blocked table B assigns to each pair (k,t) the number of times thread t needs to acquire lock k once it is unblocked The lock waiting table W assigns to each pair (k,t) the number of times thread t needs to acquire lock k once it is awakened The lock table L maps each held lock k to a pair (t,n) where t is the thread that currently holds k, and n is the number of times that t has acquired the lock Transitions on configurations of the form... (pc,S,R,B,W,L)

21 Now…. …on to the notions of dependence needed for Java concurrency

22 Divergence: Infinite Delay Conventional slicing algorithms can turn terminating (diverging) programs into terminating programs Conventional Slice

23 Divergence Dependence Divergence Preserving Slice Node n is divergence dependent on node m if (a) m is a pre-divergence point (the test of a loop), and (b) there exists a non-trivial path p from m to n such that no node along the path (excluding m, n) is a predivergence point. Divergence Dependence Divergence dependence

24 Interference Dependence Node n is interference-dependent on node m if (a) n and m are in different threads, and (b) there is a variable x such that x is assigned to at m and x is read by n. Interference Dependence Thread 1 (fragment)Thread 2 (fragment) M: x=y+3;N: y=x+3; Q: x=3; Consider slice criterion Implied Schedule X=3; y=3+x; x=y+3;

25 Synchronization Dependence Node n is synchronization-dependent on node m if m1 and m2 mark the enclosing monitor for n and m=m1 or m=m2. Synchronization Dependence n m2 m1 q2 q1 enter-monitor k2; exit-monitor k2; enter-monitor k1; exit-monitor k1;

26 Ready Dependence Node n is ready-dependent on node m if m’s failure to complete, e.g., because it is never reached, or because n is wait and the corresponding notify never occurs, or because n’s thread is blocked forever (trying to obtain a lock) can make the thread of n block before reaching or completing n --- thus delaying n’s execution indefinitely. Ready Dependence (intuition) m: enter-monitor k; … exit-monitor k; … n: x=e; Case 1: Thead(n) = Thread(m) and n is reachable from m in the CFG of Thread(n) and Code(m) = enter-monitor k.

27 Ready Dependence n: enter-monitor k; … exit-monitor k; … y=e1; Case 2: Thead(n) != Thread(m) and Code(n) = enter-monitor k and Code(m) = exit-monitor k. enter-monitor k; … m: exit-monitor k; … x=e2; Thread 1:Thread 2:

28 Ready Dependence Case 3: Thead(n) = Thread(m) and n is reachable from m in the CFG of Thread(n) and Code(m) = wait k. enter-monitor k; … m: wait k; … exit-monitor k; … n: x=e;

29 Ready Dependence Case 4: Thead(n) != Thread(m) and Code(n) = wait k and Code(m) = notify k. enter-monitor k; … n: wait k … exit-monitor k; … y=e1; enter-monitor k; … m: notify k; … exit-monitor k; … x=e2; Thread 1:Thread 2:

30 Assessment Most notions of dependence presented here can be optimized by further static analysis –redundant lock analysis –may/must happen in order/parallel –guaranteed-released lock analysis How do we know we have all the dependences?

31 Correctness Issues Generalization of conventional notion of projection based on weak-bisimulation! ([init.1], [m=0,n=0,result=0]) ([init.2], [m=5,n=0,result=0]) ([init.3], [m=5,n=2,result=0]) ([init.4], [m=5,n=2,result=1]) ([test.1], [m=5,n=2,result=1]) ([loop.1], [m=5,n=2,result=1]) ([loop.2], [m=5,n=2,result=5]) ([loop.3], [m=5,n=1,result=5]) ([test.1], [m=5,n=1,result=5]) ([loop.1], [m=5,n=1,result=5]) ([loop.2], [m=5,n=1,result=25]) ([loop.3], [m=5,n=0,result=25]) ([test.1], [m=5,n=0,result=25]) ([end.1], [m=5,n=0,result=25]) (halt, [m=5,n=0,result=25]) Source Program TraceResidual Program (Slice) Trace ([init.2], [n=0]) ([init.4], [n=2]) ([test.1], [n=2]) ([loop.2], [n=2]) ([loop.3], [n=1]) ([test.1], [n=1]) ([loop.2], [n=1]) ([loop.3], [n=0]) ([test.1], [n=0]) ([end.1], [n=0]) (halt, [n=0])

32 Abstraction Component Functionality Variable Concrete Type Abstract Type Inferred Type Abstraction Library Bandera Abstraction Specification Language BASL Compiler PVS Jimple Abstraction Engine Abstracted Jimple x y done count o b int bool Object Buffer int …. Signs intAbs Bool …. Point Buffer

33 Abstraction Specification abstraction Signs abstracts int begin TOKENS = { NEG, ZERO, POS }; abstract(n) begin n {NEG}; n == 0 -> {ZERO}; n > 0 -> {POS}; end operator + add begin (NEG, NEG) -> {NEG} ; (NEG, ZERO) -> {NEG} ; (ZERO, NEG) -> {NEG} ; (ZERO, ZERO) -> {ZERO} ; (ZERO, POS) -> {POS} ; (POS, ZERO) -> {POS} ; (POS, POS) -> {POS} ; (_,_)-> {NEG, ZERO, POS}; /* case (POS,NEG), (NEG,POS) */ end public class Signs { public static final int NEG = 0; // mask 1 public static final int ZERO = 1; // mask 2 public static final int POS = 2; // mask 4 public static int abstract(int n) { if (n < 0) return NEG; if (n == 0) return ZERO; if (n > 0) return POS; } public static int add(int arg1, int arg2) { if (arg1==NEG && arg2==NEG) return NEG; if (arg1==NEG && arg2==ZERO) return NEG; if (arg1==ZERO && arg2==NEG) return NEG; if (arg1==ZERO && arg2==ZERO) return ZERO; if (arg1==ZERO && arg2==POS) return POS; if (arg1==POS && arg2==ZERO) return POS; if (arg1==POS && arg2==POS) return POS; return Bandera.choose(7); /* case (POS,NEG), (NEG,POS) */ } Compiled

34 Specification Creation Tools abstraction Signs abstracts int begin TOKENS = { NEG, ZERO, POS }; abstract(n) begin n {NEG}; n == 0 -> {ZERO}; n > 0 -> {POS}; end operator + add begin (NEG, NEG) -> {NEG} ; (NEG, ZERO) -> {NEG} ; (ZERO, NEG) -> {NEG} ; (ZERO, ZERO) -> {ZERO} ; (ZERO, POS) -> {POS} ; (POS, ZERO) -> {POS} ; (POS, POS) -> {POS} ; (_,_)-> {NEG, ZERO, POS}; end Automatic Generation Forall n1,n2: neg?(n1) and neg?(n2) implies not pos?(n1+n2) Forall n1,n2: neg?(n1) and neg?(n2) implies not zero?(n1+n2) Forall n1,n2: neg?(n1) and neg?(n2) implies not neg?(n1+n2) Proof obligations submitted to PVS... Example: Start safe, then refine: +(NEG,NEG)={NEG,ZERO,POS}

35 Back End Bandera Intermediate Representation (BIR) –guarded command language –includes: locks, threads, references, heap –info to help translators (live vars, invisible) entermonitor r0 r1.count = 0; … loc s5: live { r0, r1 } when lockAvail(r0.lock) do { lock(r0.lock); } goto s6; loc s6: live { r1 } when true do invisible { r1.count = 0;} goto s7; Jimple BIR

36 Bounded Buffer BIR process BoundedB() BoundedBuffer_ref = ref { BoundedBuffer_col, BoundedBuffer_col_0 }; BoundedBuffer_rec = record { bound_ : range -1..4; head_ : range -1..4; tail_ : range -1..4; BIRLock : lock wait reentrant; }; BoundedBuffer_col : collection [3] of BoundedBuffer_rec; BoundedBuffer_col_0 : collection [3] of BoundedBuffer_rec; ……. ………. loc s34: live { b2, b1, add_JJJCTEMP_0, add_JJJCTEMP_6, add_JJJCTEMP_8 } when true do invisible { add_JJJCTEMP_8 := (add_JJJCTEMP_6 % add_JJJCTEMP_8); } goto s35; loc s35: live { b2, b1, add_JJJCTEMP_0, add_JJJCTEMP_8 } when true do { add_JJJCTEMP_0.head_ := add_JJJCTEMP_8; } goto s36; loc s36: live { b2, b1, add_JJJCTEMP_0 } when true do { notifyAll(add_JJJCTEMP_0.BIRLock); } goto s37; loc s37: live { b2, b1, add_JJJCTEMP_0 } when true do { unlock(add_JJJCTEMP_0.BIRLock); } goto s38;

37 Bounded Buffer Promela typedef BoundedBuffer_rec { type_8 bound_; type_8 head_; type_8 tail_; type_18 BIRLock; } … loc_25: atomic { printf("BIR: 25 0 1 OK\n"); if :: (_collect(add_JJJCTEMP_0) == 1) -> add_JJJCTEMP_8 = BoundedBuffer_col. instance[_index(add_JJJCTEMP_0)].tail_; :: (_collect(add_JJJCTEMP_0) == 2) -> add_JJJCTEMP_8 = BoundedBuffer_col_0. instance[_index(add_JJJCTEMP_0)].tail_; :: else -> printf("BIR: 25 0 1 NullPointerException\n"); assert(0); fi; goto loc_26; }

38 Bandera: When to Use It? When you want to check for event-sequencing properties in Java When you want to check simple invariants –Note: model-checking isn’t targeted to, e.g., proving the correctness of a sorting algorithm When you want to use slicing in automated/non-automated analysis of Java code When you want to use abstraction of source code for other purposes (e.g., testing) When you want to model-check Java using another model- checker not in Bandera (define a BIR backend) When you want to model-check code in an input language besides Java (write a translation to Jimple or BIR).

39 Bandera: Why are Others Interested? Funding from Honeywell, interest from Rockwell-Collins –possibly use as part of FAA certification Funding from NASA –interest in using model-checking to catch subtle bugs before deployment Funding from US NSF –interest in applied work on abstraction, support for formal methods in software engineering

40 Mars Pathfinder Mission Mission critical software: - Lander & rover-lander UHF communications - Data acquistion, image processing - Rover commands

41 Extensive Testing but… In first 15 (out of 92) days –there were 5 system resets –loss of data/time Bugs very difficult to diagnose –timing related defect –took days of simulation to reproduce

42 Current Status A reasonable subset of concurrent Java –not handled: recursive methods, exceptions, inner classes, native methods, libraries(*) Public release: November 2000 http://www.cis.ksu.edu/santos/bandera


Download ppt "The Bandera Model Reduction Tools James Corbett Matthew Dwyer John Hatcliff Shawn Laubach Corina Pasareanu Robby Hongjun Zheng Faculty Students and Post-docs."

Similar presentations


Ads by Google