Date post: | 19-Jan-2016 |
Category: |
Documents |
Upload: | joleen-webster |
View: | 219 times |
Download: | 0 times |
Model-checking Concurrent Java Software Model-checking Concurrent Java Software Using the Bandera Tool SetUsing the Bandera Tool Set
Matthew Dwyer
John Hatcliff
Radu Iosif
Yu Chen
Georg Jung
Todd Wallentine
Faculty Students and Post-docs
Robby
Roby Joehanes
Venkatesh Ranganath
Oksana Tkachuk
(http://www.cis.ksu.edu/santos/bandera)
FundingUS National Science Foundation (NSF)US National Aeronautics and Space Agency (NASA)US Department of Defense Advanced Research Projects Agency (DARPA) US Army Research Office (ARO)
Rockwell-Collins ATCHoneywell Technology Center and NASA Langley Sun Microsystems
SAnToS Laboratory, Kansas State University, USA
Goals of the ProjectGoals of the Project
II. Integration with commonly used design notations, methods, and processes… UML artifacts, JML
e.g., checking, specification
… automatic generation of synchronization code with dedicated checking
I. Provide platform for construction of and experimentation with technologies for model-checking concurrent Java software
… property specification languagese.g., temp logic, state machines
… model-reduction techniquese.g., abstraction, slicing, compiler-based optimizations
… model-checking enginese.g., explicit-state, symbolic
III. Evaluation using safety-critical military and civilian applications as well as non-critical popular open-source software
… integration with developmentand certification of safety-criticalsystems.
Model CheckingModel Checking
OK
orFinite-state model
Temporal logic formula
Model Checker
Error trace
Line 5: …Line 12: …Line 15:…Line 21:…Line 25:…Line 27:… …Line 41:…Line 47:…
What makes model-checking What makes model-checking software difficult?software difficult?
Model construction
OK
Error trace
orFinite-state model
Temporal logic formula
Model Checker
State explosion
Problems using existing checkers:
Property specification Output interpretation
Line 5: …Line 12: …Line 15:…Line 21:…
Model Construction ProblemModel Construction Problem
Semantic gap:
Model Description
Model CheckerProgram
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
Object take() { … tail=(tail+1)%size; return buffer[tail];}
Gap
Programming Languages
Model Description Languages
methods, inheritance, dynamic creation, exceptions, etc.
automata
What makes model-checking What makes model-checking software difficult?software difficult?
Model construction
OK
Error trace
orFinite-state model
Temporal logic formula
Model Checker
State explosion
Problems using existing checkers:
Property specification Output interpretation
Line 5: …Line 12: …Line 15:…Line 21:…
Property Specification ProblemProperty Specification Problem
Difficult to formalize a requirement in temporal logic
“Between the window open and the window close, button X can be pushed at most twice.”
[]((open /\ <>close) -> ((!pushX /\ !close) U (close \/ ((pushX /\ !close) U (close \/ ((!pushX /\ !close) U (close \/ ((pushX /\ !close) U (close \/ (!pushX U close))))))))))
…is rendered in LTL as...
Property Specification ProblemProperty Specification Problem
We want to write source level specifications...
(((_collect(heap_b) == 1)\ && (BoundedBuffer_col.instance[_index(heap _b)].head == BoundedBuffer_col.instance[_index(heap _b)].tail) )\|| ((_collect(heap _b) == 3)\ && (BoundedBuffer_col_0.instance[_index(heap _b)].head == BoundedBuffer_col_0.instance[_index(heap _b)].tail) )\|| ((_collect(heap _b) == 0) && TRAP))
Heap.b.head == Heap.b.tail
We are forced to write model level specifications...
Forced to state property in terms of model rather than source:
Requirement:
If a buffer instance becomes full,it will eventually become non-full.
Consider multiple instances of a bounded buffer class...
In general, a heap object has no program-level name that persists throughout the lifetime of the object.
b1 b2 b3 Variables
Heap object
Property Specification ProblemProperty Specification Problem
Complications due to the dynamic nature of OO software…
What makes model-checking What makes model-checking software difficult?software difficult?
Model construction
OK
Error trace
orFinite-state model
Temporal logic formula
Model Checker
State explosion
Problems using existing checkers:
Property specification Output interpretation
Line 5: …Line 12: …Line 15:…Line 21:…
State Explosion ProblemState Explosion Problem
Moore’s law and algorithm advances can help– Holzmann: 7 days (1980) ==> 7 seconds (2000)
Explosive state growth in software limits scalability
Bit x1,…,xN 2^N states
Cost is exponential in the number of components
What makes model-checking What makes model-checking software difficult?software difficult?
Model construction
OK
Error trace
orFinite-state model
Temporal logic formula
Model Checker
State explosion
Problems using existing checkers:
Property specification Output interpretation
Line 5: …Line 12: …Line 15:…Line 21:…
Output Interpretation ProblemOutput Interpretation Problem
Raw error trace may be 1000’s of steps long
Model DescriptionProgram
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
Object take() { … tail=(tail+1)%size; return buffer[tail];}
Gap
Error trace
Line 5: …Line 12: …Line 15:…Line 21:…Line 25:…Line 27:… …Line 41:…Line 47:…
Must map line listing onto model description Mapping to source is made difficult by
– Semantic gap & clever encodings of complex features– multiple optimizations and transformations
Bandera:Bandera:An open tool set for model-checking Java source codeAn open tool set for model-checking Java source code
Checker Inputs
CheckerOutputs
Optimization Control
Transformation &Abstraction Tools
ModelCheckers
Java Source
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
Object take() { … tail=(tail+1)%size; return buffer[tail];}
Bandera Temporal Specification
Graphical User Interface
Error Trace Mapping
Bandera
Addressing theAddressing the Model Construction ProblemModel Construction Problem
Numerous analyses, optimizations,two intermediate languages, multiple back-ends
Slicing, abstract interpretation, specialization Variety of usage modes: simple...highly tuned
Model extraction: compiling to model checker inputs:
Java Source
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
Object take() { … tail=(tail+1)%size; return buffer[tail];}
Model DescriptionModel Compiler
Static Analyses
Abstract Interpretation
Slicing Optimizations
Addressing theAddressing the Property Specification ProblemProperty Specification Problem
An extensible language based on field-tested temporal property specification patterns
[]((open /\ <>close) -> ((!pushX /\ !close) U (close \/ ((pushX /\ !close) U (close \/ ((!pushX /\ !close) U (close \/ ((pushX /\ !close) U (close \/ (!pushX U close))))))))))
Using the pattern system: 2-bounded existence
Between {open} and {close} {pushX} exists atMost {2} times;
Addressing theAddressing the State Explosion ProblemState Explosion Problem
Aggressive customization via slicing, abstract interpretation, program specialization
Java Source
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
…
Model DescriptionsModel Compiler
Property
Generate models customized wrt property!
Result: multiple models --- even as many as one per property
Addressing theAddressing the Output Interpretation ProblemOutput Interpretation Problem
Run error traces forwards and backwards Program state queried Heap structures navigated Locks, wait sets, blocked sets displayed
Like a debugger: error traces mapped back to source
Java Source
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
Object take() { … tail=(tail+1)%size; return buffer[tail];}
Model Compiler
ModelChecker
Intermediate Representations
Error traceLine 5: …Line 12: …Line 15:…Line 21:…
ModelDescription
+ simulator
Bandera ArchitectureBandera Architecture
BIRC BIR
Simulator
AbstractionEngine
Slicer
Analyses
Translators
SPIN
dSPIN
SMV
JPF
Property Tool
JavaJimple
Parser
Error Trace Display
Bounded Buffer Bounded Buffer class BoundedBuffer { Object [] buffer; int head; /* next available slot */ int tail; /* last available slot */ int bound; /* max # of elements */
public BoundedBuffer(int b) {…}
public synchronized boolean isEmpty() {…}
public synchronized void add(Object o) {…}
public synchronized Object take () {…}}
Initialization
head tail
Add,Add
head tail
Add,Take,Take
headtail
Property SpecificationProperty Specification
class BoundedBuffer { Object [] buffer; int head, tail, bound;
public synchronized void add(Object o) {…}
public synchronized Object take () {…}}
Requirement:
If a buffer becomes full,it will eventually becomenon-full.
Bandera Specification:
FullToNonFull: {Full(b)} leads to {!Full(b)} globally;
/** * @observable * EXP Full: (head == tail); */
forall[b:BoundedBuffer].
Property SpecificationProperty Specification
Requirement:
Empty buffers must added to before being taken from
Bandera Specification:
NoTakeWhileEmpty: {take.Return(b)} is absent after {Empty(b)} until {add.Call(b)};
forall[b:BoundedBuffer].
/** * @observable * EXP Empty: * head == ((tail+1) % bound);*/class BoundedBuffer { int head, tail, bound;
public synchronized void add(Object o) {…}
public synchronized Object take () {…}}
/** * @observable INVOKE Call; */
/** * @observable RETURN Return; */
Property-directed SlicingProperty-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
mentionedin property
indirectlyrelevant
Property-directed SlicingProperty-directed Slicing/** * @observable EXP Full: (head == tail) */
class BoundedBuffer { Object [] buffer_; int bound; int head, tail; public synchronized void add(Object o) { while ( tail == head ) try { wait(); } catch ( InterruptedException ex) {}
buffer_[head] = o; head = (head+1) % bound; notifyAll(); }...}
Included inslicingcritirion
Slicing Criterion
All statementsthat assign tohead, tail.
indirectlyrelevant
removed byslicing
Abstraction EngineAbstraction Engine
int x = 0;if (x == 0) x = x + 1;
Data domains
(n<0) : neg(n==0): zero(n>0) : pos
Signs
neg poszero
int
Code
Signs x = zero;if (x == zero) x = pos;
Collapses data domains via abstract interpretation:
Abstraction Component Abstraction Component FunctionalityFunctionality
VariableConcrete Type
Abstract Type
Inferred Type
AbstractionLibrary
BanderaAbstractionSpecificationLanguage
BASLCompiler
PVS
JimpleJimple AbstractionEngine
AbstractedJimple
xydonecount
ob
intintbool
ObjectBuffer
int….
SignsSignsSigns
intAbsBool
….PointBuffer
Abstraction SpecificationAbstraction Specificationabstraction Signs abstracts intbegin TOKENS = { NEG, ZERO, POS };
abstract(n) begin n < 0 -> {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
Specification Creation ToolsSpecification Creation Toolsabstraction Signs abstracts intbegin TOKENS = { NEG, ZERO, POS };
abstract(n) begin n < 0 -> {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
AutomaticGeneration
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}
Bounded Buffer BIRBounded Buffer BIR
process BoundedB() 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;
BoundedBuffer_ref = ref { BoundedBuffer_col, BoundedBuffer_col_0 };
State Declarations
static identification of threads
object state as record
qualified lock representation
Reference type indicates mini-heaps that can be pointed to.
Easily express results of “points-to” analysis
bounded integer values
“mini-heaps” – one per allocator site
Bounded Buffer BIRBounded Buffer BIR
loc s34: live { b2, b1, T_0, T_6, T_8 } when true do invisible { T_8 := (T_6 % T_8); } goto s35; … loc s36: live { b2, b1, T_0 } when true do { notifyAll(T_0.BIRLock); } goto s37; … loc s37: live { b2, b1, T_0 } when true do { unlock(T_0.BIRLock); } goto s38;
Guarded Transitions
control point labellive variable information
used to optimize back-end code
annotation denotinginvisible transition which canbe merged with followingtransition
built-in operations on lock representations
Case Study: DEOS Kernel (with NASA Ames)Case Study: DEOS Kernel (with NASA Ames)
A real-time operating system for integrated modular avionics systems
Some interesting history…Non-trivial concurrent Java program: 1443 lines of code, 20 classes, 6 threads
With a known bug
Honeywell Dynamic Enforcement Operating System (DEOS)
Application processes are guaranteed to be scheduled for their budgeted time during a scheduling unit
Requirement:
DEOS ArchitectureDEOS Architecture
Requirement Monitor
Environment
System Clock & Timer
User Process 1
User Process 2
...
DEOS Kernel
...if(...) assert(false);...
class Thread
class StartofPeriodEvent
class ListofThreads
class Scheduler
Verification of DEOSVerification of DEOS
We used Bandera and Java PathFinder (JPF)
Verification of the system exhausted 4 Gigabytes
of memory without completing
– no information about satisfaction of requirement
To verify property or produce a counter-example
– to reduce the state space to a tractable size
– some form of abstraction is needed
Variable SelectionVariable Selection
Requirement Monitor
Environment
System Clock & Timer
User Process 1
User Process 2
...
Control dependencies:
29 conditionals
16 methods
32 variables
DEOS Kernel
int itsPeriodId = 0; ...public int currentPeriod() { return itsPeriodId; }public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=itsPeriodId + 1; ... }
class StartofPeriodEvent
int itsLastExecution; ...public void startChargingCPUTime(){ int cp=itsEvent.currentPeriod(); if(cp == itsLastExecution) { ... }
class Thread
...if(...) assert(false);...
Variable SelectionVariable Selection
Requirement Monitor
Environment
System Clock & Timer
User Process 1
User Process 2
...
Control dependencies:
29 conditionals
16 methods
32 variables
DEOS Kernel
int itsPeriodId = 0; ...public int currentPeriod() { return itsPeriodId; }public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=itsPeriodId + 1; ... }
class StartofPeriodEvent
int itsLastExecution; ...public void startChargingCPUTime(){ int cp=itsEvent.currentPeriod(); if(cp == itsLastExecution) { ... }
class Thread
...if(...) assert(false);...
Unbounded!
Variable SelectionVariable Selection
Requirement Monitor
Environment
System Clock & Timer
User Process 1
User Process 2
...
DEOS Kernel
int itsPeriodId = 0; ...public int currentPeriod() { return itsPeriodId; }public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=itsPeriodId + 1; ... }
class StartofPeriodEvent
int itsLastExecution; ...public void startChargingCPUTime(){ int cp=itsEvent.currentPeriod(); if(cp == itsLastExecution) { ... }
class Thread
...if(...) assert(false);...
Data dependencies
Attaching Abstract TypesAttaching Abstract Types
Requirement Monitor
Environment
System Clock & Timer
User Process 1
User Process 2
...
DEOS Kernel
int itsPeriodId = 0; ...public int currentPeriod() { return itsPeriodId; }public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=itsPeriodId + 1; ... }
class StartofPeriodEvent
int itsLastExecution; ...public void startChargingCPUTime(){ int cp=itsEvent.currentPeriod(); if(cp == itsLastExecution) { ... }
class Thread
...if(...) assert(false);...
SIGNS
SIGNS
SIGNS
Code TransformationCode Transformation
Requirement Monitor
Environment
System Clock & Timer
User Process 1
User Process 2
...
DEOS Kernel
Signs itsPeriodId = ZERO; ...public Signs currentPeriod() { return itsPeriodId; }public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=Signs.add(itsPeriodId ,POS);... }
class StartofPeriodEvent
Signs itsLastExecution; ...public void startChargingCPUTime(){ Signs cp=itsEvent.currentPeriod(); if(Signs.eq(cp,itsLastExecution)){ ... }
class Thread
...if(...) assert(false);...
Verification of Abstracted DEOS Verification of Abstracted DEOS
JPF completed the check– produced a 464 step counter-example
Does the counter-example correspond to a feasible execution?– difficult to determine– because of abstraction, we may get spurious errors
We re-ran JPF to perform a customized search– found a guaranteed feasible 318 step counter-example
After fixing the bug– the requirement was verified
SummarySummary A collection of tools for reasoning about concurrent systems. Has been applied to find bugs in safety-critical systems.
– Can it be used effectively by others – people familiar with quality assurance issues?
Still a research prototype, but the implementation is maturing. Is it possible to integrate tools like this into the develop process for
certified systems?– As a simple debugging utitlity?
– As an officially sanctioned (certified) tool?
– Can it complement existing tools used in certification – especially when concurrency is considered?
The JPF back-end has been modified to produce coverage information.
– Can this complement existing coverage tools?
We would be happy to have challenge problems/case studies.
Primary ChallengesPrimary Challenges
Will there be so much technical knowledge and effort required that it will only be used by research teams or quality assurance in highly safety-critical applications?
Can it be integrated well enough with standard development processes so it can be used not only with designs but also mesh well with rigorous testing?
Can software engineers be trained in the concepts of abstraction and temporal logic, e.g., in a one semester course, so with little further training they can use tools effectively, in concurrent software development?
Can effective “canned” solutions be provided for particular application domains – thus enabling developers with less training?
Unclear how far model-checking can be pushed down the hierarchy of software developers