7. Vorlesung Compilerbau,Wintersemester 2008/09
Definition„Zeigeranalyse“
Einfach? Man schaue sich die letzte Zuweisung an …
7
➀ Zeigeranalyse: Nutzen, Einsatzgebiete, Beispiele
❛❛Worauf zeigt ein Zeiger/Objektvariable?
p = q;
r = p.val;
p = q;
r = p.f();
... f(){return this.val}
p = q;
r = p.f(p);
... f(){if p.equals(“Caesar”)
return p
else
return this.val}
Alias Inter-Prozedural Kontext-sensitiv
Unentscheidbar (im allgemeinen)
nicht approximierbar mit beschränktem Qualitätsverlust
lange keine skalierbaren Algorithmen für (kontext-sensitive) Zeigeranalyse
8. Vorlesung Compilerbau,Wintersemester 2008/09
Definition„Zeigeranalyse“
Zeigeranalyse: worauf zeigen die Zeiger eines Programs
kontext-sensitiv – berücksichtigt unterschiedliche Aufrufkontexte
Unifikations-basiert vs. Inklusions-basiert
8
➀ Zeigeranalyse: Nutzen, Einsatzgebiete, Beispiele
n = f(o);
m = f(p);
... f(i){return i};
!" #"
$" %"
!" #"
$" %"
kontext-insensitiv kontext-sensitiv
n = o;
m = p;
m = q;
n = m;
!" #"
$" %"
%"
!" #"
$" %"
%"
Unifikations-basiert Inklusions-basiert
9. Vorlesung Compilerbau,Wintersemester 2008/09
Einsatz: Methodenaufruf
Methodenaufruf in OO-Programmen: Java, C++ (nur virtual)
Zeigeranalyse: liefert präzisen Typ des Objekts
hier: o Typ T, sein präziser Typ ist T2
falls Typ eindeutig: unbedingter Sprung zur Methode
hier: Sprung zum Code von m in T2
Ersparnis: Analyse des Typs von o zur Laufzeit & Verwendung der Methodentabelle
wichtiger Bestandteil in Compilern für C++, Java (insbes. auch JIT)
9
➀ Zeigeranalyse: Nutzen, Einsatzgebiete, Beispiele
T o = new T1();
o = l.transform(o);
o.m();
T l(T o){return new T2()}
10. Vorlesung Compilerbau,Wintersemester 2008/09
Einsatz: Alias-Analyse
Zeigeralias verbreitet in C, C++, Java
Zeiger verweisen auf das gleiche (Heap-) Objekt
Änderungen an dem Objekt betreffen Wert alle beteiligten Zeiger
Erkennung von Zeigeralias nötig, z.B., für
Propagation von Konstantenwerten (u.U. sogar Einsparen von Variablen) über Zeiger
statische Berechnung von Sprungadressen (bei Verwendung von Funktionszeigern)
10
➀ Zeigeranalyse: Nutzen, Einsatzgebiete, Beispiele
p.val = 1;
q.val = 2;
x = p.val;
q = new Value();
p = q;
q = new Value();
p = new Value();
x = 2
x = 1
p Alias von q
11. Vorlesung Compilerbau,Wintersemester 2008/09
Einsatz: Fehlererkennung
Ziel: Auffinden von„verdächtigen“ Codefragmenten
Zugriff auf bereits freigegebenen Speicher → Aliasanalyse
„schmutzige“ Verwendung von Eingaben → z.B. SQL Injection
Pufferüberlauf beim Zugriff auf Arrays → dynamische Bereichstests
aber: verhältnismäßig teuer → statische Analyse zur Minimierung der Bereichstests
11
➀ Zeigeranalyse: Nutzen, Einsatzgebiete, Beispiele
q = new Value();
p = q;
delete p;
delete q;
12. Vorlesung Compilerbau,Wintersemester 2008/09
Einsatz: SQL Injection
„Schmutzige“ (tainted) Verwendung von Eingaben in SQL Anfragen
Benutzereingabe (z.B. aus Webformular) wird direkt verwendet zur
Konstruktion von eingebetteten Datenbankanfragen (z.B. über JDBC)
z.B. Variablen $n und $p für Benutzername und Passwort
12
➀ Zeigeranalyse: Nutzen, Einsatzgebiete, Beispiele
SELECT balance FROM Account
WHERE name = ‘$n’ and password = ‘$p’
SELECT balance FROM Account
WHERE name = ‘Julius Caesar’ ‐‐’ and password = ‘...’
Angreifer: als Benutzername einen Ausdruck
mit Symbolen oder Wörtern, die in SQL spezielle Bedeutung haben
z.B. Kommentarzeichen‘‐‐’
13. Vorlesung Compilerbau,Wintersemester 2008/09
Einsatz: Pufferüberlauf
Problem: Eingaben (oder Ergebnisse), die Pufferplatz überschreiten
typisch: String als Zeichen-Array mit fixer Größe k, Eingabe > k
Lösung: dynamische Überprüfung der Puffer/Array Grenzen
in Java automatisch durch Compiler garantiert
Problem: naives Einfügen bei allen Arrayzugriffen sehr teuer
Lösung: Zeigeranalyse, um festzustellen, wo Überlauf möglich
z.B. bei Benutzereingaben, nicht begrenzten Schleifen, etc.
13
➀ Zeigeranalyse: Nutzen, Einsatzgebiete, Beispiele
16. Vorlesung Compilerbau,Wintersemester 2008/09
Intra-Prozedurale Analyse
Intra-Prozedural: innerhalb einer Prozedur
keine Aufrufe anderer Prozeduren / Methoden / etc.
Pointer- bzw. Objektvariablen zeigen auf Heap-Objekte; liegen auf Stack
Heap-Zeiger zeigen auf andere Heap-Objekte
16
o1: p = new A();
o2: q = new A();
p.f = q;
r = p.f;
s = r;
!" #$"
%" #&"
'"
("
)"
➁ Interprozedurale, kontext-sensitive Zeigeranalyse
Heap-Objekt
Objektvariable
17. Vorlesung Compilerbau,Wintersemester 2008/09
Aufrufgraphen
Inter-Prozedural: auch Datenfluß zwischen mehreren Prozeduren
Technik: Aufrufgraph aufstellen
Aufrufgraph := Graph (N, E) für ein Programm P, so dass
es für jede Prozedur p in P einen Knoten np ∈ N gibt
es für jeden Aufrufpunkt c in P einen Knoten nc ∈ N gibt
falls ein Aufrufpunkt c eine Prozedur p aufrufen kann
gibt es eine Kante von nc nach np
17
➁ Interprozedurale, kontext-sensitive Zeigeranalyse
18. Vorlesung Compilerbau,Wintersemester 2008/09
Beispiel Aufrufgraph
18
Name + Signatur class A {
A val;
int f(A a){return 1}
A f(A a) {
c1: return a.f(val);
}
static void main() {
val = new B();
val.val = this;
c2: val.f(new A());
}
}
class B extends A {
A f(A a){
c3: return val.f(a);
}
}
➁ Interprozedurale, kontext-sensitive Zeigeranalyse
!"#$%
!"#$
!"#$
%"#$
&'$
&($
&)$
!
*+,
+ Intra + Inter
19. Vorlesung Compilerbau,Wintersemester 2008/09
Kontext-Sensitive Analyse
mehrere Aufrufe der gleichen Funktion
unterschiedliche Parameter (u.a. Kontexte)
kontext-insensitive Analyse
kann Parameter nicht propagieren bei
mehreren Aufrufen der gleichen Funktion
einfach & billig zu realisieren (Aufrufgraph)
kontext-sensitive Analyse
präziser, hier z.B. Eliminierung der Aufrufe
durch Parameterpropag.: X[i] = 16;
bis 2004: kein„präziser“, sklalierbarer Alg.
19
➁ Interprozedurale, kontext-sensitive Zeigeranalyse
for(i=0; i<1012; i++) {
c1: t1 = g(0);
c2: t2 = g(4);
c3: t3 = g(9);
X[i] = t1+t2+t3;
}
int g(int v) {
c4: return f(v);
}
int f(int v) {
return (v + 1);
}
20. Vorlesung Compilerbau,Wintersemester 2008/09
Kontext-Sensitive Analyse
Idee:„Klonen“
20
➁ Interprozedurale, kontext-sensitive Zeigeranalyse
for(i=0; i<1012; i++) {
c1: t1 = g(0);
c2: t2 = g(4);
c3: t3 = g(9);
X[i] = t1+t2+t3;
}
int g(int v) {
c4: return f(v);
}
int f(int v) {
return (v + 1);
}
for(i=0; i<1012; i++) {
c1: t1 = g1(0);
c2: t2 = g2(4);
c3: t3 = g3(9);
X[i] = t1+t2+t3;
}
int g1(int v) {
c4.1: return f1(v); }
int g2(int v) {
c4.2: return f2(v); }
int g3(int v) {
c4.3: return f3(v); }
int f1(int v) {
return (v + 1);}
int f2(int v) {
return (v + 1);}
int f3(int v) {
return (v + 1);}
24. Vorlesung Compilerbau,Wintersemester 2008/09
Kontext-Sensitive Analyse durch Klonen
Hoffnungslos? – typisches Program ~1014 Pfade, nur 1 Byte pro Klon
256 TBi Speicher > 12fache der Größe der“Library of Congress”
so viel Speicher verbraucht so viel Energie wie ~120 Haushalte
Sequentielles Lesen von Festplatte: ~70 Tage
Trotzdem: Es geht mit folgender Beobachtung:
Viele der Pfade sind weitgehend identisch, Kontexte sehr ähnlich
Datenstruktur, die die hoch-redundante Aufrufgraph Relation kompakt
kompakt (“exponentially more succinct”) darstellen kann
Lösung: Binary Decision Diagram (Binäre Entscheidungsdiagramm)
24
➁ Interprozedurale, kontext-sensitive Zeigeranalyse
34. Vorlesung Compilerbau,Wintersemester 2008/09
Geordnete, reduzierte BDDs (ROBDDs)
Binary Decision Diagram (BDD) :=
gerichteter, azyklischer Graph mit Wurzel bestehend aus
einer oder zwei Blättern (keine ausgehenden Kanten), die mit 0 bzw. 1 gelabelt sind;
jeder andere Knoten ist ein Variablenknoten u mit genau 2 ausgehenden
Kanten low(u) und high(u) und einer Variablen var(u) als Label
Geordnetes BDD :=
auf allen Pfaden von der Wurzel kommen Variablen in gleicher Ordnung vor
Reduziertes BDD :=
unique – var(u) = var(v) ∧ low(u) = low(v) ∧ high(u) = high(v) u = v
non-redundant – ∀ u: low(u) ≠ high(u)
34
➂ Skalierung durch Binary Decision Diagrams (BDDs)
35. Vorlesung Compilerbau,Wintersemester 2008/09
Variablenordnung in BDDs
Problem: Größe & Form hängt von Reihenfolge der Variablen ab
35
➂ Skalierung durch Binary Decision Diagrams (BDDs)
!"#
!$#
!%#
&# "#
!'#
!"#
!$#
!%#
&# "#
!'#
!$#
!'#
x1 ∧ x2 ∨ x3 ∧ x4
x1 < x2 < x3 < x4
x1 < x3 < x2 < x4
37. Vorlesung Compilerbau,Wintersemester 2008/09
Variablenordnung in BDDs
Schlimmer:
Bestimmen der optimalen Variablenordnung für eine gegebene boolesche
Funktion ist NP-vollständig
Bestimmen selbst einer um einen konstanten Faktor c > 1 schlechteren
Ordnung ist noch NP-vollständig (also APX-hart)
In der Praxis: Zahlreiche, effiziente Heuristiken
große Zahl von BDD-Libraries → http://en.wikipedia.org/wiki/Binary_decision_diagram
Kanonisches ROBDD zu jeder booleschen Funktion f(x1, …, xn)
gibt es genau ein ROBDD mit Variablenordnung x1 < … < xn
daher: effizienter Equivalenztest
37
➂ Skalierung durch Binary Decision Diagrams (BDDs)
40. Vorlesung Compilerbau,Wintersemester 2008/09
Manuelle Zeigeranalyse mit BDDs
Implementierung komplex, fehleranfällig, schwer zu optimieren
daher: deklarative Spezifikation, automatische Transformation in BDDs
40
➃ Deklarative Spezifikation mit Datalog
>50
Seiten,
SAS 2002 ~ 15 Zeilen, PLDI 2004
41. Vorlesung Compilerbau,Wintersemester 2008/09
Spezifikationssprache: Datalog
Datalog: (rekursive) Logik über Relationen mit endlicher Domain
siehe zweiter Teil der Vorlesung, hier nur intuitive Behandlung
Semantik: wenn Konjunktion der Atome im Rumpf war ist, dann auch Kopf
Variablen entsprechend instantiiert, jede Var. im Kopf auch im Rumpf
41
➃ Deklarative Spezifikation mit Datalog
vPointsTo(q, o).
Assignment(p, q).
vPointsTo(V1, O) :‐ Assignment(V1, V2),
vPointsTo(V2, O).
Prädikat- (Relations-) Symbol
Fact
Regel (Kopf :- Rumpf)
keine Funktionssymbole;
nur stratifizierte Negation
42. Vorlesung Compilerbau,Wintersemester 2008/09
Extraktion von Fakten
Zurück zum Beispielprogram (intra-prozedural):
42
o1: p = new A();
o2: q = new A();
p.f = q;
r = p.f;
s = r;
!" #$"
%" #&"
'"
("
)"
vPointsTo(p, o1).
vPointsTo(q, o2).
Store(p, f, q).
Load(p, f, r).
Assign(s, r).
➃ Deklarative Spezifikation mit Datalog
Ziel:
44. Vorlesung Compilerbau,Wintersemester 2008/09
Zugriff auf Heapzeiger
Ableitbar aus Belegung von Objektvariablen (vPointsTo) &
Heapzeigern (hPointsTo) sowie Heapzugriffen (Load)
44
➃ Deklarative Spezifikation mit Datalog
vPointsTo(Var2, Obj2) :‐ Load(Var1, Att, Var2),
vPointsTo(Var1, Obj1),
hPointsTo(Obj1, Att, Obj2).
Load(p, f, r).
vPointsTo(p, o1).
hPointsTo(o1, f, o2). ∧
→
vPointsTo(r, o2).!" #$"
#%"
&"
!"
wegen
r = p.f;
45. Vorlesung Compilerbau,Wintersemester 2008/09
Alias-Auflösung
Ableitbar aus Belegung von Objektvariablen (vPointsTo) &
Heapzuweisungen (Store)
45
➃ Deklarative Spezifikation mit Datalog
vPointsTo(Var1, Obj) :‐ Assign(Var1, Var2),
vPointsTo(Var2, Obj).
Assign(s,r).vPointsTo(r, o2).
∧
→
vPointsTo(s, o2).
wegen
s = r;
!" #$"
%" #&"
'"
("
!"
46. Vorlesung Compilerbau,Wintersemester 2008/09
Vollständiger Analysalgorithmus
Das wars … damit haben wir einen Zeigeranalysalgorithmus
der schneller oder gleich-schnell wie manuelle Ansätze ist
46
➃ Deklarative Spezifikation mit Datalog
hPointsTo(Obj1, Att, Obj2) :‐ Store(Var1, Att, Var2),
vPointsTo(Var1, Obj1),
vPointsTo(Var2, Obj2).
vPointsTo(Var2, Obj2) :‐ Load(Var1, Att, Var2),
vPointsTo(Var1, Obj1),
hPointsTo(Obj1, Att, Obj2).
vPointsTo(Var1, Obj) :‐ Assign(Var1, Var2),
vPointsTo(Var2, Obj).
47. Vorlesung Compilerbau,Wintersemester 2008/09
Gleich schnell?
Übersetzung der Datalog Spezifikation in BDDs
Datalog → relationale Algebra → BDDs → Domain-optimierte BDDs
Details siehe:
J. Whaley and M. S. Lam. Cloning-based context-sensitive pointer alias analysis using
binary decision diagrams. In Proc. ACM Conf. on Programming Language Design and
Implementation (PLDI), 2004. ACM.
Implementiert in bddbddb
Datalog Engine basierend auf BDDs
http://bddbddb.sourceforge.net/
47
➃ Deklarative Spezifikation mit Datalog
53. Vorlesung Compilerbau,Wintersemester 2008/09
Literatur zur Interprozeduralen Zeigeranalyse
Basiswissen:
Aho, Lam, Sethi, Ullman: “Compilers”, 2nd Edition, Kapitel 12
M. S. Lam, J. Whaley, V. B. Livshits, M. C. Martin, D. Avots, M. Carbin, and
C. Unkel. Context-sensitive program analysis as database queries. In Proc. ACM
Symp. on Principles of Database Systems (PODS), 2005. ACM.
Weiterführende Literatur:
V. T. Chakaravarthy and S. Horwitz. On the non-approximability of points-to
analysis. Acta Inf., 38(8):587–598, 2002.
J. Whaley and M. S. Lam. Cloning-based context-sensitive pointer alias analysis
using binary decision diagrams. In Proc. ACM Conf. on Programming
Language Design and Implementation (PLDI), 2004. ACM.
53
Fragen