what went wrong?
DESCRIPTION
What Went Wrong?. Alex Groce Carnegie Mellon University Willem Visser NASA Ames Research Center. Java Code. Bytecode. void add(Object o) { buffer[head] = o; head = (head+1)%size; } Object take() { … tail=(tail+1)%size; return buffer[tail]; }. JAVAC. JVM. 0: iconst_0 - PowerPoint PPT PresentationTRANSCRIPT
What Went Wrong?
Alex GroceCarnegie Mellon University
Willem VisserNASA Ames Research Center
Java PathFinder
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
Object take() { … tail=(tail+1)%size; return buffer[tail];}
Java Code
JAVAC JVM
0: iconst_01: istore_22: goto #395: getstatic 8: aload_09: iload_210: aaload
Bytecode
Special JVM
Model Checker
Counterexamples
• When the model checker finds a bug, it reports a counterexample.
• However, even an exact trace of the program failing is not what we really want for most bugs.
Counterexamples
• How can we get more information from a counterexample?
– Perhaps if we had some successful runs to compare to, or other failing runs in which to look for common elements…
• A common way of debugging by hand
• Except we can automate it using the model checker
Counterexamples
The Error
Counterexamples
“The Error”
Real cause
Counterexamples
“The Error”
Real cause
• Idea: generate other traces that can give you more information about what is going wrong.
• How?
Positives and Negatives
Real cause
assert (x < 5);
(and x = 8)
“The Error”
Positives and Negatives
“The Error”
Real cause
Same location, same error:NEGATIVE (-)
Real cause
assert (x < 5);
(and x = 10)
An Error
assert (x < 5);
(and x = 8)
Positives and Negatives
Real cause
Same control flow location,no error condition:
POSITIVE (+)
Same location, same error:NEGATIVE (-)
Real cause
assert (x < 5);
(and x = 3)assert (x < 5);
(and x = 10)
“The Error” An Error
assert (x < 5);
(and x = 8)
No Error
The Basic Search
“The Error”
Real cause
The Basic Search
Real cause
The Basic Search
Real cause
The Basic Search
Real cause
The Basic Search
Real cause
The Basic Search
Real cause
The Basic Search
Real cause
The Basic Search
The Basic Search
The Basic Search
The Basic Search
The Search in Detail
“The Error”
Real cause
Depth limit
Positives Negatives
The Search
“The Error”
Real cause
Depth limit
Alreadyvisited
Positives Negatives
The Search
“The Error”
Real cause
Depth limit
Positives Negatives
The Search
“The Error”
Real cause
Depth limit
Positives Negatives
“push-through”
The Search
“The Error”
Real cause
Depth limit
Alreadyvisited
Positives Negatives
After the Search
“The Error”
Real cause
• Positives that are prefixes of some negative are removed
• While negatives are a true subset of complete negatives, positives are an approximation based on observed behavior
• This can be useful: in some reactive systems, every trace can be extended into an error trace
Analysis of the Traces
Now what do we do with these?
• Report on code that appears – only in positives/negatives– in all positives/negatives– only and all positives/negatives (causal)
• Transform positives into negatives• Find difference in invariants across positives and negatives
Positives Negatives
Analysis by Code Lines
• For our example trace, the line(s) in the real cause will be:– in all negative traces and – only appear in negative traces– thus will be identified as genuine cause
• Includes which thread executed the code and any nondeterministic choices made
• Can custom define equivalences to allow for looser definition of “the same code”
“The Error”
Real cause
Automaticallyidentified
Common Ground
“The Error”
Real cause
(Can set a minimum shared prefixor suffix size)
Shared prefix
Shared suffix(control flow only)
Transformation“How to make it break”
Transformation Analysis
• Sorted so that minimal way to break (transformation from each positive to nearest negative) is identified
• Rerun code line analysis over transformation code only (very useful in some cases)
• Can identify type of error:– If any positive can be transformed into a negative by
only altering thread scheduling, the error is essentially concurrency based
Invariant Differences
• Pick certain control locations at which to observe data values in our traces
• Run a dynamic invariant detection algorithm to compute invariants across these locations for all negatives and then all positives
• Compare the discovered invariants
A Stack Examplepublic IntStack (int s) { stack = new int[s]; top = 0;}
public void push (int i) { stack[top++] = i;}
public int pop () { top--; return stack[top];}
A Stack Examplepublic IntStack (int s) { stack = new int[s]; top = 0;}
public void push (int i) { stack[top++] = i;}
public int pop () { top--; return stack[top];}
A simple stack with an interfacethat initializes the stack to a randommaximum size then randomlypushes and pops data.
A Stack Examplepublic IntStack (int s) { stack = new int[s]; top = 0;}
public void push (int i) { stack[top++] = i;}
public int pop () { top--; return stack[top];}
A simple stack with an interfacethat initializes the stack to a randommaximum size then randomlypushes and pops data.
ORIGINAL COUNTEREXAMPLE:Stack overflow for stack size 1(array out of bounds on stack)
A Stack Examplepublic IntStack (int s) { stack = new int[s]; top = 0;}
public void push (int i) { stack[top++] = i;}
public int pop () { top--; return stack[top];}
A simple stack with an interfacethat initializes the stack to a randommaximum size then randomlypushes and pops data.
ORIGINAL COUNTEREXAMPLE:Stack overflow for stack size 1(array out of bounds on stack)
Run analysis with a search depth of 50 and compute invariants.
A Stack Example
Code line analysis
Code in the push method appears in all negatives.
public IntStack (int s) { stack = new int[s]; top = 0;}
public void push (int i) { stack[top++] = i;}
public int pop () { top--; return stack[top];}
A Stack Example
Invariant analysis
For positives, on entry to the push method, this invariant holds:
stack.length > top
For negatives, however the invariant is:
stack.length >= top
public IntStack (int s) { stack = new int[s]; top = 0;}
public void push (int i) { stack[top++] = i;}
public int pop () { top--; return stack[top];}
A Stack Example
Transformations from positive to negative
Change stack size from 3 to 1
…
Change stack size from 4 to 2
Insert a push
…
Remove a pop
…
public IntStack (int s) { stack = new int[s]; top = 0;}
public void push (int i) { stack[top++] = i;}
public int pop () { top--; return stack[top];}
DEOS Error Analysis
• DEOS– Real time operating system– Allows threads to be created and deleted– Has time budgets for various threads
DEOS Error Analysis
• DEOS– Real time operating system– Allows threads to be created and deleted– Has time budgets for various threads
• Original counterexample– Assertion about the time budget of a thread fails
DEOS Error Analysis
• DEOS– Real time operating system– Allows threads to be created and deleted– Has time budgets for various threads
• Original counterexample– Assertion about the time budget of a thread fails
• Run analysis with size limit of 10
DEOS Error Analysis
Transformations
Change a wait until next period into a thread deletionInsert an interrupt and system clock ticks (before a deletion already in the positive)Change a wait until next period into an interrupt and system clock ticks and afterwards a deletion…
The DEOS error requires deletion (which appears in the set of code found in all negatives) but also relies upon specific timing, as indicated by the transformations.
Related Work
• “Fate and Free Will in Error Traces” (TACAS 02)
• SLAM group independently investigated very similar concepts this summer (submitted to POPL)– Approach quite similar in spirit, lacks invariants and
transformation approaches, but has some niceties with respect to source code analysis
• Andreas Zeller: work on isolating error-causing thread schedules and cause-effect chains
Future Work
• More efficient algorithms for generation of the traces (try bounded model checking)
• Different approaches to analysis:– Generation of automata– Characterization of error classes– Checking of causality…