1 / 25

Regression Verification for Multi-Threaded Programs

Regression Verification for Multi-Threaded Programs. Sagar Chaki, SEI-Pittsburgh Arie Gurfinkel, SEI-Pittsburgh Ofer Strichman , Technion-Haifa Originally presented at VMCAI 2012. VSSE 2012. Regression Verification. Formal equivalence checking of two similar programs

justus
Télécharger la présentation

Regression Verification for Multi-Threaded Programs

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Regression Verification for Multi-Threaded Programs Sagar Chaki, SEI-Pittsburgh Arie Gurfinkel, SEI-Pittsburgh Ofer Strichman, Technion-Haifa Originally presented at VMCAI 2012 VSSE 2012

  2. Regression Verification • Formal equivalence checking of two similar programs • Three selling points: • Specification: • not needed • Complexity: • dominated by the change, not by the size of the programs. • Invariants: • Easy to derive automatically high-quality loop/recursion invariants • Tool support: • RVT (Technion) • SymDiff (MSR)

  3. Possible applications of regression verification • Understand how changes propagate through the API • Validate refactoring • Semantic Impact Analysis • GenericTranslation Validation • Proving Determinism • P is equivalent to itself ,P is deterministic • many more…

  4. Definition: Partial Equivalence Let f1 and f2 be functions with equivalent I/O signature f1 and f2are partially equivalent, executions of f1 and f2 on equal inputs …which terminate, result in equal outputs. Undecidable

  5. Multi-Threaded Programs (MTPs) Finite set of root functions : P = f1 || … || fn Each executed in a separate thread Communicate via shared variables is P partially equivalent to itself? …no! shared variable int base = 1; void f1(int n, int *r) { if (n < 1) *r = base; else { int t; f1(n-1, &t); *r = n * t; } } void f2() { base = 2; } thread thread P Computes n! or 2*n!

  6. Towards partial equivalence of MTPs P is a multi-threaded program (P): the set of terminating computations of P R(P) = { (in, out) | ∃ ∈ (P).  begins in in and ends in out} Example: R (P) = {(n, n!), (n, 2n!) | n∈Z} int base = 1; void f1(int n, int *r) { if (n < 1) *r = base; else { int t; f1(n-1, &t); *r = n * t; } } void f2() { base = 2; } P

  7. Partial equivalence of MTPs MTPs P1, P2 arepartially equivalent if R(P1) = R(P2). Denoted p.e.n. (P1, P2) Partial Equivalence of Nondeterministic programs Claim: 8P.²p.e.n.(P,P)

  8. Towards a sound proof rulefor partial equivalence of MTPs • The sequential case • Challenges in extending it to p.e.n. • A proof rule

  9. First: The sequential case [GS’08] Loops/recursion are not a big problem in practice: Recursive calls are replaced with calls to the same uninterpreted function: Abstracts the callees By construction assumes the callees are partially equivalent Sound by induction f1 f2 isolation = UF UF f1 f2 = 9

  10. First: The sequential case [GS’08] • Now we have two isolated functions f1, f2 • Checking partial equivalence is decidable: in1 = in2 = *; o1 = f1(in); o2 = f2(in); assert (o1==o2) • The algorithm traverses up the call graphs while abstracting equal callees. • How can this method be extended to proving p.e.n(f1,f2) ?

  11. What affects partial equivalence of MTPs? Before: in= 1 o1= 1, o2 = 0; (1, h1, 0i) 2 R(p) x1 = x2 = 0 f1() { o1 = x1; o2 = x2; } f2(int in) { x1 = in; x2 = in; } x2 = in; x1 = in; || Swap write order After: in= 1 o1= 1)o2= 1 (1, h1, 0i) R(p) 11

  12. After: in1= 1, in2 = 2 o2 = 1) x1 = 1 < t2 = x1) t1 = 0 ) o1 = 0 (h1,2i, h2,1i)  R(p) What affects partial equivalence of MTPs? x1 = x2 = 0 f1(int in1) { x1 = in1; t1 = x2; o1 = t1; } f2(int in2) { t2 = x1; x2 = in2; o2 = t2; } t1 = x2; x1 = in1; || Swap R/W order Before: in1 = 1, in2 = 2 x1 = 1; t2 = x1 = 1; x2 = in2 = 2; t1 = x2 = 2; o1 = t1 = 2; o2 = t2 = 1; (h1,2i, h2,1i) 2R(p) 12

  13. Before: in= 1 o1= 0, o2 = 1; (1, h0, 1i) 2 R(p) What affects partial equivalence of MTPs? x1 = x2 = 0 f1() { o1 = x1; o2 = x2; } f2(int in) { x1 = in; x2 = in; } o2 = x2; o1 = x1; || Swap read order After: in = 1 o1 = 0)o2 = 0 (1, h0, 1i) R(p) 13

  14. Preprocessing Loops) recursive functions Mutual recursion) simple recursion Non-recursive functions) inlined Function’s return value) parameter Each shared variable x only appears in t = xorx = exp (add auxiliaries) Each auxiliary variable is read once int base = 1; void f1(int n, int *r) { if (n < 1) *r = base; else { int t; f1(n-1, &t); *r = n * t; } } void f2() { base = 2; } P

  15. Mapping • Assume each function is used in a single thread. • Otherwise, duplicate it • Find a mapping between the non-basic types • Find a bijective map between: • threads • shared variables • functions (same proto-type), • in mapped functions: read globals, written-to globals • Without such a mapping: goto end-of-talk.

  16. The Observable Stream • Consider a function f and input in • The observable stream of f(in)’s run is its sequence of • function calls • read/write of shared variables • Example: let x be a shared variable: x x x x

  17. Observable Equivalence of Functions f, f’are observably equivalent,8in. f(in), f’(in)have equal sets of finite observable streams Denote by observe-equiv(f,f’) • Assume: outputs are defined via shared variables • Hence: observable equivalence ) partial equivalence

  18. Observable Equivalence of Functions • We prove observe-equiv(f,f’) by • isolating f,f’. • proving observ. equivalence of all (isolated) pairs • Given f, we build an isolated version [f], in which: • Function calls are replaced with calls to uninterpreted functions • Shared variables are read from an “input” stream • The observable stream is recorded

  19. Reading from an input stream… • For each shared variable x: R(x) ÃR(*) // read R(x) W(x) g(…) W(x) R(x) R(x) R(*) R(*) R(*)

  20. Reading from an input stream… R(x) local W(x) g(…) W(x) R(x) R(x) • Enforce: equal locations)same ‘*’ value • … if their streams up to that point were equal. R(*1) R(*1) R(x) W(x) W(x) local g(…) R(x) local R(x) R(*2) R(*2) R(*3) R(*3)

  21. Summary: from f to [f] Transform function f and f’ to [f] and [f’] by: Function calls are replaced with calls to UFs t = g() ) t = UFg() For (g,g’) 2 map, UFg = UFg’ Shared variables are read from an “input” stream: t = x ) t = UFx(loc) // loc is the location in the stream For (x,x’)2 map, Ufx = Ufx’ The Observable Stream is recorded.

  22. Example: from f to [f] Observable stream Output treated as shared list out; void [f] (int n, int *r) { int t, loc = 0; if (n < 1) { t = UFbase(loc); out += (R,”base”); loc++; out += (W,”r”,t); loc++;} else { t = UFf,t(n-1); out += (C,f,n-1); out += (W,”r”, n * t); loc++; } } int base = 1; void f (int n, int *r) { int t; if (n < 1) { t = base; *r = t;} else { f(n-1,&t); *r = n * t; } } read write function call write f [f]

  23. Checking observable equivalence of [f],[f’] Generate sequential program S: in1 = in2 = *; [f(in1)];[f’(in2)]; rename ([f’].out); // according to map assert([f].out == [f’].out); Validity of S is decidable f [f] S CBMC f’ [f’]

  24. AProof Rule Compositional: check one function pair at a time Sequential: no thread composition General: supports loops/recursion + arbitrary # of threads 8f, f’ 2map. observe-equiv([f], [f’]) p.e.n. (P1, P2)

  25. Summary and Future Thoughts • We suggested foundations of regression verification for MTPs • Notion of partial equivalence of multi-threaded programs • A proof rule • Challenges ahead: • Synchronization primitives: Locks, semaphores, atomic blocks • Dynamic thread creation • Make more complete

More Related