2017-07-04 2 views
7

Ich schrieb ein Dienstprogramm, um ein CFG (Control Flow Graph) für eine Java-Methode zu erstellen, deren Knoten Grundbausteine ​​anstelle von Anweisungen sind.Wie berücksichtigen wir Exception-Würfe in der statischen Code-Analyse?

Ich konnte Ausnahmewürfe nicht als Kanten in CFG betrachten. Die Gründe dafür sind:

  1. Jeder Befehl im try-Block kann möglicherweise Exceptions/Fehler auslösen, die von einem der verschachtelten try-catch-Blöcke behandelt werden können. Wenn wir Exception-Throws als Kanten betrachten, erhöht sich die Anzahl der zu verarbeitenden Pfade drastisch, ebenso wie die Anzahl der Knoten in CFG.
  2. Wir müssen die Vererbungshierarchie für Ausnahmen kennen, bevor wir entscheiden können, welche Sprünge möglich sind.

Wie lösen statische Analysatoren dieses Problem?

Ich bin an diesem Punkt fest. Wenn ich weitermachen soll, wie soll ich dann vorgehen?

Edit: In meinem Fall kann ich die Unterstützung auf diese Anwendungsfälle beschränken, die angeben können, wo und welche Ausnahmen ausgelöst werden. Das hat mein zweites Problem gelöst. Ich würde trotzdem gerne wissen, wie generische statische Codeanalysatoren das handhaben.

+1

Ich bin zu faul, um nachzuschlagen - wofür steht CFG? – GhostCat

+1

@GhostCat https://en.wikipedia.org/wiki/Control_flow_graph; "eine Darstellung aller Pfade, die während ihrer Ausführung durch ein Programm durchlaufen werden könnten, unter Verwendung der Graph-Notation." – Aaron

Antwort

6

Hier ist, wie ich mit dem Thema in den Krakatau decompiler behandelt:

Wir brauchen die Vererbungshierarchie für Ausnahmen wissen, bevor wir entscheiden, was möglich Sprünge.

Krakatau benötigt die Klassendefinitionen aller referenzierten Klassen, um die Vererbungshierarchie zu kennen. Wenn ich es aber trotzdem tun würde, würde ich das nicht tun. Das Anfordern von Klassendefinitionen macht es für Benutzer schwierig, den Decompiler zu betreiben, weil das Finden und Hinzufügen der Abhängigkeiten ein großer Schmerz ist. Sie brauchen das eigentlich nicht, wenn die Analyse etwas ungenau ist. Sie können stattdessen einfach davon ausgehen, dass alle Ausnahmen alle Handler erreichen können. In der Praxis erwarte ich, dass es zu fast den gleichen Ergebnissen führen würde.

Jeder Befehl im try-Block kann möglicherweise Exceptions/ Fehler auslösen, die von einem der verschachtelten try-catch-Blöcke behandelt werden können. Wenn Exception-throws als Kanten betrachtet werden, erhöht sich die Anzahl der zu verarbeitenden Pfade drastisch, und dies gilt auch für die Anzahl der Knoten in CFG.

Krakatau enthält Ausnahmen als Kanten in der CFG, was zu den von Ihnen identifizierten Problemen führt. Um die Anzahl der Kanten zu reduzieren, gab ich vor, dass nur bestimmte Anweisungen auslösen können (Methodenaufrufe, Array-Zugriffe, Division, etc.). Das ist technisch nicht korrekt, aber es ist das Richtige für den echten Code. Ich habe noch nie etwas gesehen, das sich wirklich für die Exceptions interessiert, die von einem Linkfehler, Thread.Stop oder ähnlichem ausgelöst werden. Ich habe später eine Option hinzugefügt, um dieses Verhalten zu deaktivieren.

Wie auch immer, dies funktionierte gut genug für den meisten Code, aber es verursachte manchmal Leistungsprobleme. Besonders große Methoden mit vielen Feldzugängen oder Methodenaufrufen würden zu riesigen CFGs führen, die die Dekompilierung sehr verlangsamen. Ich habe einige Tricks versucht, um dies zu optimieren, aber letztendlich bestand die Lösung darin, von Basisblöcken zu erweiterten Basisblöcken zu wechseln.

Erweiterte Basisblöcke ähneln Basic Blocks, mit der Ausnahme, dass Ausnahmekanten halbimplizit dargestellt werden, was zu einer viel kleineren CFG führt. Ein EBB besteht aus einem geraden Liniencode mit keinen Eintrittspunkten oder Austrittspunkten in der Mitte, abgesehen von Ausnahmekanten, und wobei jeder Befehl in dem Block von demselben Satz von Ausnahmebehandlern abgedeckt ist. Auf diese Weise haben Sie, anstatt eine Ausnahmekante pro Anweisung zu haben, eine pro Block, was die Dinge viel effizienter macht.

Sogar Java-Methoden mit Tausenden von Methodenaufrufen haben normalerweise nur ein paar Versuche/Fänge und daher nur ein paar EBBs.

+0

danke noch einmal! Ich habe Krakatau einige Zeit später für meine Testsuite benutzt und es war ziemlich umfangreich. – user3911119

Verwandte Themen