CSE507 Computer-Aided Reasoning for Software Model Checking II - - PowerPoint PPT Presentation

cse507
SMART_READER_LITE
LIVE PREVIEW

CSE507 Computer-Aided Reasoning for Software Model Checking II - - PowerPoint PPT Presentation

CSE507 Computer-Aided Reasoning for Software Model Checking II courses.cs.washington.edu/courses/cse507/14au/ Emina Torlak emina@cs.washington.edu Today 2 Today Last lecture Model checking basics 2 Today Last lecture Model


slide-1
SLIDE 1

CSE507

Emina Torlak

emina@cs.washington.edu

courses.cs.washington.edu/courses/cse507/14au/

Computer-Aided Reasoning for Software

Model Checking II

slide-2
SLIDE 2

Today

2
slide-3
SLIDE 3

Today

2

Last lecture

  • Model checking basics
slide-4
SLIDE 4

Today

2

Last lecture

  • Model checking basics

Today

  • Software model checking with SLAM

Based on lectures by Tom Ball and Sriram K. Rajamani. See the SLAM project webpage for details.

slide-5
SLIDE 5

Today

2

Last lecture

  • Model checking basics

Today

  • Software model checking with SLAM

Reminders

  • Homework 3 is due on today at 11pm
  • Project demos will be held on Dec 08, 10:30-12:20, in MGH 254

Based on lectures by Tom Ball and Sriram K. Rajamani. See the SLAM project webpage for details.

slide-6
SLIDE 6

Overview of SLAM

3

Program P Safety property S A trace of P that violates S

SLAM

Software, programming Languages, Abstraction, and Model checking

slide-7
SLIDE 7

Overview of SLAM

3

Program P Safety property S A trace of P that violates S

SLAM

Software, programming Languages, Abstraction, and Model checking A sequential program (device driver) implemented in C.

slide-8
SLIDE 8

Overview of SLAM

3

Program P Safety property S A trace of P that violates S

SLAM

Software, programming Languages, Abstraction, and Model checking A sequential program (device driver) implemented in C. Temporal property (an API usage rule) written in SLIC, such as “a lock should be alternatively acquired and released.”

slide-9
SLIDE 9

Overview of SLAM

3

Program P Safety property S A trace of P that violates S

SLAM

Software, programming Languages, Abstraction, and Model checking Ships in Microsoft’s Static Driver Verifier (SDV) tool. Most influential PLDI paper award and the 2011 CAV award.

slide-10
SLIDE 10

The SLAM process

4

Instrumentation Program P Safety property S P’

slide-11
SLIDE 11

The SLAM process

4

Instrumentation Program P Safety property S Abstraction P’ boolean program B

slide-12
SLIDE 12

The SLAM process

4

Instrumentation Program P Safety property S Abstraction Model checking P’ boolean program B

slide-13
SLIDE 13

The SLAM process

4

Instrumentation Program P Safety property S Abstraction Model checking P’ boolean program B

slide-14
SLIDE 14

The SLAM process

4

Instrumentation Program P Safety property S Abstraction Model checking Trace validation P’ boolean program B error trace for B

slide-15
SLIDE 15

The SLAM process

4

Instrumentation Program P Safety property S Abstraction Model checking Trace validation P’ boolean program B error trace for B A trace of P that violates S

slide-16
SLIDE 16

The SLAM process

4

Instrumentation Program P Safety property S Abstraction Model checking Trace validation P’ boolean program B error trace for B A trace of P that violates S

new predicates

slide-17
SLIDE 17

The SLAM process

4

Instrumentation Program P Safety property S Abstraction Model checking Trace validation P’ boolean program B error trace for B A trace of P that violates S

new predicates C2BP Bebop Newton

slide-18
SLIDE 18

The SLAM process: specifying safety properties

5

Instrumentation Program P Safety property S C2BP Bebop Newton P’ boolean program B error trace for B A trace of P that violates S

new predicates

slide-19
SLIDE 19

Specification Language for Interface Checking

6
slide-20
SLIDE 20

Specification Language for Interface Checking

6

A finite state language for stating rules for API usage

  • Temporal safety properties expressed as safety

automata that monitor program’s execution behavior at the level of function calls and returns.

  • Familiar C syntax.
slide-21
SLIDE 21

Specification Language for Interface Checking

6

A finite state language for stating rules for API usage

  • Temporal safety properties expressed as safety

automata that monitor program’s execution behavior at the level of function calls and returns.

  • Familiar C syntax.

Suitable for control-dominated properties

  • E.g., ordering of function calls with associated

constraints on data values at the API boundary.

slide-22
SLIDE 22

A locking protocol in SLIC

7

Locked Error Unlocked release acquire release acquire

slide-23
SLIDE 23 state { enum {Locked, Unlocked} state = Unlocked; } KeAcquireSpinLock.return { if (state == Locked) abort; else state = Locked; } KeReleaseSpinLock.return { if (state == Unlocked) abort; else state = Unlocked; }

The global state structure defines a static set of state variables.

A locking protocol in SLIC

7

Locked Error Unlocked release acquire release acquire

slide-24
SLIDE 24 state { enum {Locked, Unlocked} state = Unlocked; } KeAcquireSpinLock.return { if (state == Locked) abort; else state = Locked; } KeReleaseSpinLock.return { if (state == Unlocked) abort; else state = Unlocked; }

A locking protocol in SLIC

7

Locked Error Unlocked release acquire release acquire Transfer functions define events and event handlers that describe state transitions on events.

slide-25
SLIDE 25

The SLAM process: instrumentation

8

Instrumentation Program P Safety property S C2BP Bebop Newton P’ boolean program B error trace for B A trace of P that violates S

new predicates

slide-26
SLIDE 26

Instrumentation by example: 2 steps

9 state { enum {Locked, Unlocked} state = Unlocked; } KeAcquireSpinLock.return { if (state == Locked) abort; else state = Locked; } KeReleaseSpinLock.return { if (state == Unlocked) abort; else state = Unlocked; } void example() { do { KeAcquireSpinLock(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); }

Program P Safety property S Simplified code for a PCI device driver.

slide-27
SLIDE 27

Step 1: translate the SLIC spec S to C

10 state { enum {Locked, Unlocked} state = Unlocked; } KeAcquireSpinLock.return { if (state == Locked) abort; else state = Locked; } KeReleaseSpinLock.return { if (state == Unlocked) abort; else state = Unlocked; } enum {Locked=0, Unlocked=1} state = Unlocked; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if (state == Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if (state == Unlocked) slic_abort(); else state = Unlocked; }

Distinguished error label. Safety property S

slide-28
SLIDE 28

Step 2: insert calls to SLIC functions into P

11 void example() { do { KeAcquireSpinLock(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); }

Program P

void example() { do { KeAcquireSpinLock(); KeAcquireSpinLock_return(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); KeReleaseSpinLock_return(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); KeReleaseSpinLock_return(); }

Program P’

slide-29
SLIDE 29

P satisfies S iff SLIC_ERROR is unreachable in P’

12 void example() { do { KeAcquireSpinLock(); KeAcquireSpinLock_return(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); KeReleaseSpinLock_return(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); KeReleaseSpinLock_return(); }

Program P’

enum {Locked=0, Unlocked=1} state = Unlocked; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if (state == Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if (state == Unlocked) slic_abort(); else state = Unlocked; }
slide-30
SLIDE 30

The SLAM process: predicate abstraction

13

Instrumentation Program P Safety property S C2BP Bebop Newton P’ boolean program B error trace for B A trace of P that violates S

new predicates

slide-31
SLIDE 31

Predicate abstraction of C Programs

14
slide-32
SLIDE 32

Predicate abstraction of C Programs

14

Given a program P and a finite set E of predicates, C2BP creates a boolean program B that is a sound

  • ver-approximation of P.
  • B has the same control-flow structure as P

, but only |E| boolean variables.

  • For any path p feasible in P

, there is a corresponding feasible path in B.

slide-33
SLIDE 33

Predicate abstraction of C Programs

14

Given a program P and a finite set E of predicates, C2BP creates a boolean program B that is a sound

  • ver-approximation of P.
  • B has the same control-flow structure as P

, but only |E| boolean variables.

  • For any path p feasible in P

, there is a corresponding feasible path in B. Suitable abstraction for checking control- dominated properties (such as SLIC rules).

  • Models control flow in P precisely.
  • Models only a few predicates about data relevant to each

rule being checked (so limits state explosion).

slide-34
SLIDE 34

Predicate abstraction by example: 5+ steps

15 void example() { do { KeAcquireSpinLock(); KeAcquireSpinLock_return(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); KeReleaseSpinLock_return(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); KeReleaseSpinLock_return(); } enum {Locked=0, Unlocked=1} state = Unlocked; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if (state == Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if (state == Unlocked) slic_abort(); else state = Unlocked; }

Program P’

(state == Locked) (state == Unlocked)
slide-35
SLIDE 35

Step 1: extract initial predicates from SLIC rules

16 void example() { do { KeAcquireSpinLock(); KeAcquireSpinLock_return(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); KeReleaseSpinLock_return(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); KeReleaseSpinLock_return(); }

Program P’

(state == Unlocked) (state == Locked) enum {Locked=0, Unlocked=1} state = Unlocked; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if (state == Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if (state == Unlocked) slic_abort(); else state = Unlocked; }
slide-36
SLIDE 36 b(state==Locked), b(state==Unlocked) := F, T; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if b(state==Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if b(state==Unlocked) slic_abort(); else state = Unlocked; }

Step 2: introduce boolean variables for E

17 void example() { do { KeAcquireSpinLock(); KeAcquireSpinLock_return(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); KeReleaseSpinLock_return(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); KeReleaseSpinLock_return(); } (state == Unlocked) (state == Locked)
slide-37
SLIDE 37

Step 3: skip statements with no effect on E

18 void example() { do { skip; KeAcquireSpinLock_return(); skip; if (request) { skip; skip; KeReleaseSpinLock_return(); skip; } } while (nPackets != nOld); skip; KeReleaseSpinLock_return(); } b(state==Locked), b(state==Unlocked) := F, T; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if b(state==Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if b(state==Unlocked) slic_abort(); else state = Unlocked; } (state == Unlocked) (state == Locked)
slide-38
SLIDE 38 void example() { do { skip; KeAcquireSpinLock_return(); skip; if (request) { skip; skip; KeReleaseSpinLock_return(); skip; } } while (nPackets != nOld); skip; KeReleaseSpinLock_return(); }

Step 4: encode the effects of assignments on E

19 b(state==Locked), b(state==Unlocked) := F, T; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if b(state==Locked) slic_abort(); else b(state==Locked), b(state==Unlocked) := T, F; } void KeReleaseSpinLock_return { if b(state==Unlocked) slic_abort(); else b(state==Locked), b(state==Unlocked) := F, T; } (state == Unlocked) (state == Locked)
slide-39
SLIDE 39 void example() { do { skip; KeAcquireSpinLock_return(); skip; if (*) { skip; skip; KeReleaseSpinLock_return(); skip; } } while (*); skip; KeReleaseSpinLock_return(); }

Step 5: use non-determinism for conditions

20 b(state==Locked), b(state==Unlocked) := F, T; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if b(state==Locked) slic_abort(); else b(state==Locked), b(state==Unlocked) := T, F; } void KeReleaseSpinLock_return { if b(state==Unlocked) slic_abort(); else b(state==Locked), b(state==Unlocked) := F, T; } (state == Unlocked) (state == Locked)
slide-40
SLIDE 40 void example() { do { skip; KeAcquireSpinLock_return(); skip; if (*) { skip; skip; KeReleaseSpinLock_return(); skip; } } while (*); skip; KeReleaseSpinLock_return(); }

Step 5: use non-determinism for conditions

20 b(state==Locked) void SLIC_ERROR: ; } void slic_abort(); b b void slic_abort(); b b (state == Unlocked) (state == Locked)

This is a highly simplified example of predicate abstraction. The process is much more complex in reality. For details, see Automatic predicate abstraction of C programs.

slide-41
SLIDE 41

The SLAM process: model checking

21

Instrumentation Program P Safety property S C2BP Bebop Newton P’ boolean program B error trace for B A trace of P that violates S

new predicates

slide-42
SLIDE 42

Model checking of boolean programs

22
slide-43
SLIDE 43

Model checking of boolean programs

22

Given a boolean program B and a statement s in B, Bebop determines if s is reachable in B.

  • Produces a shortest trace in B (if any) leading to S.
slide-44
SLIDE 44

Model checking of boolean programs

22

Given a boolean program B and a statement s in B, Bebop determines if s is reachable in B.

  • Produces a shortest trace in B (if any) leading to S.

Performs symbolic reachability analysis using BDDs.

  • Adapts the interprocedural dataflow analysis of Reps,

Horwitz and Sagiv (RHS) to decide the reachability of s in B.

  • Uses BDDs to represent the procedure summaries in RHS,

which are binary relations between sets of states.

slide-45
SLIDE 45

Model checking of boolean programs

22

Given a boolean program B and a statement s in B, Bebop determines if s is reachable in B.

  • Produces a shortest trace in B (if any) leading to S.

Performs symbolic reachability analysis using BDDs.

  • Adapts the interprocedural dataflow analysis of Reps,

Horwitz and Sagiv (RHS) to decide the reachability of s in B.

  • Uses BDDs to represent the procedure summaries in RHS,

which are binary relations between sets of states. For details, see Bebop: A Symbolic Model Checker for Boolean Programs.

slide-46
SLIDE 46

Model checking of the example program

23 void example() { do { skip; KeAcquireSpinLock_return(); skip; if (*) { skip; skip; KeReleaseSpinLock_return(); skip; } } while (*); skip; KeReleaseSpinLock_return(); } b(state==Locked), b(state==Unlocked) := F, T; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if b(state==Locked) slic_abort(); else b(state==Locked), b(state==Unlocked) := T, F; } void KeReleaseSpinLock_return { if b(state==Unlocked) slic_abort(); else b(state==Locked), b(state==Unlocked) := F, T; }
slide-47
SLIDE 47

The SLAM process: trace validation

24

Instrumentation Program P Safety property S C2BP Bebop Newton P’ boolean program B error trace for B A trace of P that violates S

new predicates

slide-48
SLIDE 48

Error trace validation & abstraction refinement

25
slide-49
SLIDE 49

Error trace validation & abstraction refinement

25

Given a program P’ and a candidate error trace, Newton determines if the trace is feasible.

  • Uses verification condition generation for feasibility checking.
  • If feasible, the error trace corresponds to a real bug.
  • If not, returns a small set of predicates that explain why the

path is infeasible. Based on greedy minimal unsatisfiable core computation.

slide-50
SLIDE 50

Error trace validation & abstraction refinement

25

Given a program P’ and a candidate error trace, Newton determines if the trace is feasible.

  • Uses verification condition generation for feasibility checking.
  • If feasible, the error trace corresponds to a real bug.
  • If not, returns a small set of predicates that explain why the

path is infeasible. Based on greedy minimal unsatisfiable core computation. For details, see Generating Abstract Explanations of Spurious Counterexamples in C Programs.

slide-51
SLIDE 51 void example() { do { KeAcquireSpinLock(); KeAcquireSpinLock_return(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); KeReleaseSpinLock_return(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); KeReleaseSpinLock_return(); }

Validation & refinement for the example

26 enum {Locked=0, Unlocked=1} state = Unlocked; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if (state == Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if (state == Unlocked) slic_abort(); else state = Unlocked; } (state == Unlocked) (state == Locked)
slide-52
SLIDE 52 void example() { do { KeAcquireSpinLock(); KeAcquireSpinLock_return(); nOld = nPackets; if (request) { request = request->next; KeReleaseSpinLock(); KeReleaseSpinLock_return(); nPackets++; } } while (nPackets != nOld); KeReleaseSpinLock(); KeReleaseSpinLock_return(); }

Validation & refinement for the example

26 enum {Locked=0, Unlocked=1} state = Unlocked; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if (state == Locked) slic_abort(); else state = Locked; } void KeReleaseSpinLock_return { if (state == Unlocked) slic_abort(); else state = Unlocked; } (state == Unlocked) (state == Locked) (nPackets == nOld)

✗✗✗✗✗

slide-53
SLIDE 53 void example() { do { skip; KeAcquireSpinLock_return(); b(nOld==nPackets) := T; if (*) { skip; skip; KeReleaseSpinLock_return(); b(nOld==nPackets) := b(nOld==nPackets) ? F : *; } } while (!b(nOld==nPackets)); skip; KeReleaseSpinLock_return(); }

Back to C2BP and Bebop …

27 (state == Unlocked) (state == Locked) (nPackets == nOld) b(state==Locked), b(state==Unlocked) := F, T; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if b(state==Locked) slic_abort(); else b(state==Locked), b(state==Unlocked) := T, F; } void KeReleaseSpinLock_return { if b(state==Unlocked) slic_abort(); else b(state==Locked), b(state==Unlocked) := F, T; }
slide-54
SLIDE 54 void example() { do { skip; KeAcquireSpinLock_return(); b(nOld==nPackets) := T; if (*) { skip; skip; KeReleaseSpinLock_return(); b(nOld==nPackets) := b(nOld==nPackets) ? F : *; } } while (!b(nOld==nPackets)); skip; KeReleaseSpinLock_return(); }

Back to C2BP and Bebop …

27 b(state==Locked), b(state==Unlocked) := F, T; void slic_abort() { SLIC_ERROR: ; } void KeAcquireSpinLock_return { if b(state==Locked) slic_abort(); else b(state==Locked), b(state==Unlocked) := T, F; } void KeReleaseSpinLock_return { if b(state==Unlocked) slic_abort(); else b(state==Locked), b(state==Unlocked) := F, T; }

slide-55
SLIDE 55

Summary

28

Today

  • Software model checking with SLAM
  • Predicate abstraction of C programs
  • Model checking of boolean programs
  • Trace validation and abstraction refinement

Next lecture

  • Guest lecture by Zach Tatlock!
  • Verifying compiler optimizations with SMT solvers