270 likes | 413 Views
Shape Analysis via 3-Valued Logic TVLA + Applications. Mooly Sagiv Tel Aviv University. Shape Analysis with Applications. http://www.cs.tau.ac.il/~rumster/TVLA /. Outline. Basic ideas behind TVLA TVLA for Singly Linked Lists Reachability Applications (next week). TVP. The TVLA System.
E N D
Shape Analysisvia 3-Valued LogicTVLA + Applications Mooly Sagiv Tel Aviv University Shape Analysis with Applications http://www.cs.tau.ac.il/~rumster/TVLA/
Outline • Basic ideas behind TVLA • TVLA for Singly Linked Lists • Reachability • Applications (next week)
TVP The TVLA System • Input: • SOS using Predicate Logic • Control Flow Graph • A set of 3-valued structures at the start node • Implementation hints • Output • The set of 3-valued structures at every control flow node (labeled directed graphs) • Textual error messages TVS
/* create.c */ Elements create() { Elements *f, *x; int i, size; for(i=0; i<size; i++) { f = malloc(sizeof(Elements)); f->n = x; x = f; } return x; } /* list.h */ typedef struct node { struct node *n; int data } *Elements; c2tvp create tvla create include\empty -d tvla create include\empty
Elements * reverse(Elements *x) { Elements *y, *t; y = NULL; while (x != NULL) { t = y; y = x; x = x n; y n = t; } return y; } typedef struct node { struct node *n; int data; } *Elements; c2tvp reverse tvla reverse include\list
/* reverse.tvp */ %s PVar {x, y, t} #include "include\pred.tvp" %% #include "include\cond.tvp" #include "include\stat.tvp" %% // y = NULL n_1 Set_Null_L(y) n_2 // while (x != NULL) { n_2 Is_Null_Var(x) exit n_2 Is_Not_Null_Var(x) n_3 // t = y n_3 Copy_Var_L(t, y) n_4 // y = x n_4 Copy_Var_L(y, x) n_5 // x = x->n n_5 Get_Next_L(x, x) n_6 // y->n = NULL n_6 Set_Next_Null_L(y) n_7 // y->n = t n_7 Set_Next_L(y, t) n_2 // }
/* create.tvp */ %s PVar {x, f} #include "include\pred.tvp" %% #include "include\cond.tvp" #include "include\stat.tvp" %% // for(i=0; i<size; i++) { n_1 uninterpreted() n_2 // f = malloc(sizeof(Elements)); n_2 Malloc_L(f) n_3 // f->n = x; n_3 Set_Next_Null_L(f) n_4 n_4 Set_Next_L(f,x) n_5 // x = f; n_5 Copy_Var_L(x, f) n_1 n_2 uninterpreted() exit // }
/* pred.tvp */ /*************** Core Predicates *************/ foreach (z in PVar) { %p z(v_1) unique box } %p n(v_1, v_2) function /**********************************************/ /*********** Instrumentation Predicates *************/ %i is[n](v) = E(v_1, v_2) ( v_1 != v_2 & n(v_1, v) & n(v_2, v))
/* cond.tvp */ %action uninterpreted() { %t "uninterpreted" } %action Is_Not_Null_Var(x1) { %t x1 + " != NULL" %f { x1(v) } %p E(v) x1(v) } %action Is_Null_Var(x1) { %t x1 + " == NULL" %f { x1(v) } %p !(E(v) x1(v)) } %action Is_Eq_Var(x1, x2) { %t x1 + " == " + x2 %f { x1(v), x2(v) } %p A(v) x1(v) <-> x2(v) } %action Is_Not_Eq_Var(x1, x2) { %t x1 + " != " + x2 %f { x1(v), x2(v) } %p !A(v) x1(v) <-> x2(v) }
stat.tvp %action Set_Null_L(x1) { %t x1 + " = NULL" { x1(v) = 0 } } %action Copy_Var_L(x1, x2) { %t x1 + " = " + x2 %f { x2(v) } { x1(v) = x2(v) } } %action Malloc_L(x1) { %t x1 + " = (L) malloc(sizeof(struct node)) " %new { x1(v) = isNew(v) } }
stat.tvp (2) %action Get_Next_L(x1, x2) { %t x1 + " = " + x2 + "->" + n %f { E(v_1) x2(v_1) & n(v_1, v) } %message (!E(v) x2(v)) -> "an illegal dereference to\n" + n + " component of " + x2 + "\n" { x1(v) = E(v_1) x2(v_1) & n(v_1, v) } }
stat.tvp (3) %action Set_Next_Null_L(x1) { %t x1 + "->" + n + " = null" %f { x1(v) } %message (!E(v) x1(v)) -> "an illegal dereference to\n" + n + " component of " + x1 + "\n" { n(v_1, v_2) = n(v_1, v_2) & !x1(v_1) is[n](v) = is[n](v) & (!(E(v_1) x1(v_1) & n(v_1, v)) | E(v_1, v_2) v_1 != v_2 & (n(v_1, v) & !x1(v_1)) & (n(v_2, v) & !x1(v_2))) } }
stat.tvp (4) %action Set_Next_L(x1, x2) { %t x1 + "->" + n + " = " + x2 %f { x1(v), x2(v) } %message (E(v, v1) x1(v) & n(v, v1)) -> "Internal Error! assume that " + x1 + "->" + n + "==NULL" %message (!E(v) x1(v)) -> "an illegal dereference to\n" + n + " component of " + x1 + "\n" { n(v_1, v_2) = n(v_1, v_2) | x1(v_1) & x2(v_2) is[n](v) = is[n](v) | E(v_1) x2(v) & n(v_1, v) } }
Typical Garbage Collector • Reachability-based Program Variables a b c d e f
Typical Garbage Collector • Reachability-based Program Variables a b c d e f
Typical Garbage Collector • Reachability-based Program Variables a b c d e f
Reachability • Concrete semantics which records reachability from stack (global) variables • Useful for: • Compile-time Garbage Collection • Saving calls to Dynamic Garbage Collection • No memory leaks • Speeding-up static analysis • Instrumentation predicater[n, x](v) = E(v1) x(v1) & n*(v1, v)
/* create.c */ Elements create() { Elements *f, *x; int i, size; for(i=0; i<size; i++) { f = malloc(sizeof(Elements)); f->n = x; x = f; } return x; } /* list.h */ typedef struct node { struct node *n; int data } *Elements; c2tvp create tvla rcreate include\empty
Elements * reverse(Elements *x) { Elements *y, *t; y = NULL; while (x != NULL) { t = y; y = x; x = x n; y n = t; } return y; } typedef struct node { struct node *n; int data; } *Elements; c2tvp reverse tvla rreverse include\rlist
Elements* reverse(Elements *x){ Elements *y,*t; y = NULL;while (x!= NULL) { t = xn; y = x; xn = y; x = t; }return y; typedef struct node { struct node *n; int data; } *Elements; c2tvp fumble tvla rfumble include\rlist
/* rpred.tvp */ /*************** Core Predicates *************/ foreach (z in PVar) { %p z(v_1) unique box } %p n(v_1, v_2) function /**********************************************/ /*********** Instrumentation Predicates *************/ %i is[n](v) = E(v_1, v_2) ( v_1 != v_2 & n(v_1, v) & n(v_2, v)) foreach (z in PVar) { %i r[n,z](v) = E(v_1) (z(v_1) & n*(v_1, v)) } %i c[n](v) = n+(v, v)
rstat.tvp %action Set_Null_L(x1) { %t x1 + " = NULL“ %message … -> { x1(v) = 0 r[n, x](v) = 0 } } %action Copy_Var_L(x1, x2) { %t x1 + " = " + x2 %f { x2(v) } { x1(v) = x2(v) r[n, x](v) = 0 } } %action Malloc_L(x1) { %t x1 + " = (L) malloc(sizeof(struct node)) " %new { x1(v) = isNew(v) r[n, x](v) = isNew(v) } }
x x x u u u1 u1 (1) Focus on v1: x(v1) cdr(v1,v) cdr x x y u u u1 cdr cdr x cdr x cdr y u u1 y u u1 r[cdr] cdr cdr cdr y cdr u1 u.1 u.0
Benefit of Reachability • Predict memory leaks • Separate disjoint data structures • More precise semantic reduction • x = x->n
Optimizations in TVLA • Order of constrains • Eliminate cycles • Lazy evaluation • Functional properties • Exploit sparseness • OBDD representation • Java representation
TVLA Design Mistakes • The operational semantics is written in too low level language • No types • No local updates to specific predicate values • No constants and functions • No means for modularity • No local variables and sequencing • Combines UI with functionality • TVP can be a high level language • TVLA3VLA
TVLA Experience • Quite fast on small programs • But runs on medium programs too • Not a panacea • More instrumentation may lead to faster (and more precise) analysis