zing: a systematic state explorer for concurrent software tony andrews shaz qadeer sriram k....
TRANSCRIPT
Zing: A Systematic State Explorer for Concurrent Software
Tony AndrewsShaz Qadeer
Sriram K. RajamaniJakob Rehof
Microsoft Research
Model Checking
Finding bugs by systematically exploring all possible states of a model
Works for control-dominated hardware and protocols
Model is written manually by someone who understands the system
Typical models are FSMs
Model Checking at MSR
Check source code in common programming languages
Model can be extracted automatically from the code
Good models are not necessarily FSMs
Characteristics of Software
Primitive values are more complicated– Pointers– Objects
Control flow (transition relation) is more complicated– Functions– Function pointers– Exceptions
States are more complicated – Unbounded graphs over values
Variables are scoped– Locals– Shared scopes
Much richer modularity constructs– Functions– Classes
What is Zing?
• Zing is a framework for software model-checking– Language, compiler, runtime, tools
• Supports key programming language constructs– Objects, functions, threads, channels, dynamic allocation
• Enables easier extraction of models from code• Supports research in exploring large state spaces
– New techniques implemented• compositional model checking• summarizing procedures with concurrency
• Supports conformance checking
Applications of Zing
• Check for errors in sets of web services whose behavior is described by BPEL4WS
• Check web services for conformance with behavioral contracts
• Check behavior of Windows device drivers under concurrent execution
• Find errors in complex application protocols
What can we check for?• Assertion violations
– Zing has assert(…) statement – Assertion violations are flagged as errors
• Stuck states – Deadlock: a process is waiting for message
that is never sent or condition that is never satisfied
• Conformance– Does a communicating process conform to a
specification (“contract”) ?
Outline• Overview
• Zing “show and tell”
• Architecture
• State-space reduction algorithms
• Conformance Checker
Bluetooth driver
BPEL4WS checking
Zing Model
Zing State
Explorer
BuyerBuyer SellerSeller
AuctionAuctionHouseHouse
RegRegServiceService
BPEL ProcessesBPEL Processes
Zing features
– processes– simple data types– structures– arrays– enums– communication
• message queues• shared memory
– blocking– non-determinism– atomic blocks
– objects– functions (methods)– dynamic memory
allocation– exceptions– range type– sets– variable-size arrays
Outline• Overview
• Zing “show and tell”
• Architecture
• State-space reduction algorithms
• Conformance Checker
Zing’s eco-system
Visual Studio.NET
visualization(UML activity)
visualization(call graph)
…
eventtrace
modelextraction
user“source”
Zing runtimelibrary
User
ProductGroups
MSR
Legend
ZingCompiler
ZingSourceCode
Zing objectcode (MSIL)
Domain-specific tools
Model-checker
State browser
Debugger
ConformanceChecker
Zing Object Model
State
Zing Application
StateImplCheckers,Simulators,etc.
State: contains state of the entire model
Can query how many processes are in the state
Can “execute” a particular process in the state for one atomic step and return the resulting state
Can compare if two states are equal
State
Heap: complex types
…
ProcessProcess
Process
…Processes
Zing State Internals
Globals: simple types & refs
Stack
IPLocalsParams
IPLocalsParams
…
State explosion
• 5 components, 100 states/component5 components, 100 states/component• Worst case: 10 billion statesWorst case: 10 billion states
Outline• Overview
• Zing “show and tell”
• Architecture
• State-space reduction algorithms
• Conformance Checker
Saving storage• Only states on the
checkers stack are stored
• For states not on the stack only a fingerprint is stored
• In progress:– Store only “deltas” from
previous states
State reduction• Abstract notion of
equality between states• Avoid exploring “similar”
states several times• Exploit structure and do
this fully automatically while computing the fingerprint:
s1 s2 f(s1) = f(s2)
Heap1
a
100
b 0
200
Heap2
b 0
150
a
300
ptr
ptr
Interleaving reduction
• Do not explore all interleavings between threads– Interleave only at transaction boundaries
• Combine atomicity with summarization– Two level model checking algorithm
Transactions
• In a well synchronized concurrent program– A thread’s computation can be viewed as a
sequence of transactions– While analyzing a transaction, interleavings
with other threads need not be considered– Furthermore: summarize transactions, leading
to reuse and efficiency
How do you identify transactions?
Lipton’s theory of reduction
B: both right + left movers– variable access holding lock
N: non-movers – access unprotected variable
Four atomicities
•R: right movers– lock acquire
S0 S1 S2
acq(this) x
S0 T1 S2
x acq(this)
S7T6S5
rel(this) z
S7S6S5
rel(this)z
L: left movers– lock release
S2 S3 S4
r=bal y
S2 T3 S4
r=baly
S2 T3 S4
r=bal x
S2 S3 S4
r=balx
Transaction
Any sequence of actions whose atomicities are in R*(N+)L* is a transaction
S0 S1 S2
R R
S5 S6
LS3 S4
R N LS7
R
Precommit
Transaction
Postcommit
Transactions and summaries
Corollary of Lipton’s theorem:
No need to schedule other threads in the middle of a transaction
If a procedure body occurs in a transaction, we can summarize it!
Resource allocator (1) bool available[N]; mutex m;
int getResource() { int i = 0; L0: acquire(m); L1: while (i < N) { L2: if (available[i]) { L3: available[i] = false; L4: release(m); L5: return i; } L6: i++; } L7: release(m); L8: return i; }
Choose N = 2
Summaries:<pc, i, m, (a[0],a[1])> <pc’, i’, m’, (a[0]’,a[1]’)>
<L0, 0, 0, (0, 0)> <L8, 2, 0, (0,0)><L0, 0, 0, (0, 1)> <L5, 1, 0, (0,0)><L0, 0, 0, (1, 0)> <L5, 0, 0, (0,0)><L0, 0, 0, (1, 1)> <L5, 0, 0, (0,1)>
Resource allocator (2) bool available[N]; mutex m[N];
int getResource() { int i = 0; L0: while (i < N) { L1: acquire(m[i]); L2: if (available[i]) { L3: available[i] = false; L4: release(m[i]); L5: return i; } else { L6: release(m[i]); } L7: i++; } L8: return i; }
Choose N = 2
Summaries:<pc,i,(m[0],m[1]),(a[0],a[1]> <pc’,i’,(m[0]’,m[1]’),(a[0]’,a[1]’)>
<L0, 0, (0,0), (0,0)> <L1, 1, (0,0), (0,0)>
<L0, 0, (0,0), (0,1)> <L1, 1, (0,0), (0,1)>
<L0, 0, (0,0), (1,0)> <L5, 0, (0,0), (0,0)>
<L0, 0, (0,0), (1,1)> <L5, 0, (0,0), (0,1)>
<L1, 1, (0,0), (0,0)> <L8, 2, (0,0), (0,0)>
<L1, 1, (0,0), (0,1)> <L5, 1, (0,0), (0,0)>
<L1, 1, (0,0), (1,0)> <L8, 2, (0,0), (1,0)>
<L1, 1, (0,0), (1,1)> <L5, 1, (0,0), (1,0)>
Abstraction
• Represent only aspects of the program relevant to property being checked
• Automatic iterative refinement of abstractions
• Use “regions” to construct conservative abstractions of the heap
Composition
• Divide and conquer• Check one component of the model at a time• Requires behavioral contracts
Outline• Overview
• Zing “show and tell”
• Architecture
• State-space reduction algorithms
• Conformance Checker
Contract checking
A
CA
CB CC
Does each implementation conform to its contract?
Example:Does A conform to CA?
Use only CB and CC (and not B and C during this check)
Contract checking
A
CA
CB CC
Spec (Zing)
Impl (Zing)
Zing Conformance
Checker
Conformance and Zing
• Conformance was originally defined syntactically for CCS
• Tony Hoare helped us generalize definition to make it purely semantic– makes no assumptions about the syntactic structure
of the processes– can work for any system where we can observe
externally visible behavior for processes– we have implemented exactly this on top of Zing!
Conformance Checkervoid doDfs(State initImpl, State initSpec) { addState(initImpl, initSpec);
while(dfsStack.Count > 0) { StatePair pair = dfsStack.Peek(); State I = pair.first(); State S = pair.second(); State newI = I.GetNextSuccessor(); // lookup the events on the transition from I to newI if (newI == null) { if (isStable(I)){ // first get all the events we executed from I Event[][] IEvents = I.AccumulateEvents; if (!checkRefusals(S, IEvents)) {
Console.WriteLine(“Contract over-promises”); generateError(I, S);
return; } } dfsStack.Pop(); continue; }
Event[] events = newI.Events; State newS = executeWithTrace (S, events); if (newS == null){
Console.WriteLine(“Implementation has unspecified behavior”);
continue; }
addState (newI, newS); } }
Stack dfsStack;Hashtable stateHash;
void addState(State i, State s) { StatePair combinedState = new StatePair(i,s); if(!stateHash.contains(combinedState)){ stateHash.add(combinedState); dfsStack.push(combinedState); }}
State executeWithTrace(State s, Event[] l ) { S’: S l S’, if such S’ exists null: otherwise }
Bool checkRefusals(State s, Event[][] L){
true: exists stable S’ such that S * S’, and for all l, if S’ l then l L
false: otherwise}