270 likes | 275 Views
This webpage provides an overview of shape analysis using 3-valued logic TVLA and its applications. It covers the basic ideas behind TVLA, TVLA for singly linked lists, reachability, and implementation hints. It also includes code examples and textual error messages.
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