• Aucun résultat trouvé

4.4 Discussion et conclusion

4.4.1 Discussion

Étant donné que les algorithmes de parcours de CFG présentés dans ce chapitre énumèrent tous les chemins du programme – au moins pour les régions séquentielles analysées – l’analyse se heurte à un problème de complexité, en particulier en la pré-sence de nombreuses conditions en séquence, chaque condition dédoublant le nombre de chemins à analyser. Ce nombre croît exponentiellement, tout comme la complexité de l’analyse : chaque chemin nécessite une analyse séparée, et génère un problème de satisfiabilité propre à tester.

Nous proposons une solution à ce problème par l’introduction d’un seuil ajustable, noté η, du nombre de chemins analysables en tout point du programme2, pour des programmes de grande et moyenne taille. Ainsi, dans l’Algorithme 7 au lieu de collecter

2. Nous utilisons η = 250 ou η = +∞ pour la quasi-totalité de nos expérimentations (à l’exception d’un programme pour lequel nous avons dû abaisser le seuil à 80).

Algorithme 7 : Interprétation abstraite d’un CFG par accélération d’état Données : G= (V, E, , ω), le CFG ; et {sGk | ∃b ∈ V, GkC (b)} Résultat : {se| e ∈ E}; et sG pour e ∈ E faire se ← nil pour h ∈ HG faire qh ← enter s~← {(1Sˇ,~)} wl ← {sink(~)}

tant que wl 6= ∅ faire b ← pop(wl) pred ← ins(b) si b /∈ HG ins(b) \ BG si b ∈ HG∧ qb = enter ins(b) ∩ BG si b ∈ HG∧ qb 6= enter

si ∀e ∈ pred, se 6= nil alors s ←S

e∈predse

pour e ∈ pred faire

se ← nil succ ← outs(b) si b ∈ HG alors s ←F si∈ssi si qb = enter alors qb ← iter sb ← s

sinon si qb = iter alors qb ← leave

s ← sb xb s

sinon si qb = leave alors qb ← enter

si ∃e ∈ ins(b), se 6= nil alors wl ← wl ∪ {b} succ ← ∅ siC (b) = ∅ alors s ← I[b](s) sinon si ∃G0,C (b) = {G0} alors s ← s ◦ sG0

pour e ∈ succ \ {exits(h) | L(h) 3 b ∧ qh 6= leave} faire se ← I[e](s)

Ξ(se, {(h, qh) | L(h) 3 b}) wl ← wl ∪ {sink(e)} sG ← ∪e∈ins(ω)se

les états des arcs en entrée avec

s ← [

e∈pred se

nous utilisons plutôt

s ← S e∈pred se si P e∈pred|se| ≤ η b F e∈pred se sinon

en fusionnant par union abstraite (ˆt) l’ensemble des états en entrée dans le cas où le seuil η est dépassé. Ce seuil pousse l’analyse à travailler sur des fenêtres du programme de taille modeste, et améliore la complexité, évitant des temps d’analyse déraisonnables. Cela se fait au prix de ne plus pouvoir différencier les chemins en entrée de chacun de ces points de fusion, et donc d’être incapable de détecter des chemins infaisables entre des arcs avant et après un tel point.

Une autre piste d’amélioration de la complexité est la simplification du graphe de contrôle et de ses blocs par slicing (cf section 3.1.2.6). Après avoir implanté cette tech-nique dans notre outil, nous avons constaté des gains de performance, mais avons perdu un nombre significatif de chemins infaisables, du fait que le slicing peut supprimer du code dynamiquement mort, et restructurer le graphe de manière à le faire disparaître.

Par ailleurs, il est possible de chercher à détecter des formes de chemins infaisables particulières selon les applications : des comportements plus complexes pourraient être reconnus par la fonction d’accélération (Définition 4.11) pour supporter des schémas adaptés à l’application considérée ; par défaut, seuls les progressions arithmétiques sont traitées. On pourrait par exemple chercher à généraliser des suites arithmético-géométriques (du type un+1 = aun+b, et dont la forme générale est un= (u0b

1−a)an+ b

1−a) ou d’autres problèmes, qui peuvent nécessiter une extension des expressions de E

b

Λ. D’autres domaines abstraits permettent et facilitent le développement de méthodes d’accélération plus performantes, comme par exemple les travaux de Ancourt et al. [8] dans PIPS, qui utilisent la différentiation discrète sur des contraintes affines entières, représentées par des polyèdres. Le processus d’accélération gagne ainsi en généralité par rapport aux méthodes de reconnaissance de formes que nous utilisons. L’outil FAST inclut également des techniques d’accélération [11] pour des systèmes linéaires représentés par des formules de Presburger sur des entiers positifs. Enfin, Gonnord et Halbwachs [41] cherchent également à calculer l’effet exact des boucles lorsque

pos-sible. Une forme d’accélération abstraite raisonnant sur des approximations polyédrales est définie, généralisant efficacement des fonctions f ainsi représentées à des fonctions vraies après k itérations. Cette méthode est utilisée en complément à des techniques classiques d’élargissement, moins précises mais capables de traiter les cas où l’accélé-ration est impossible.

Enfin, remarquons que les méthodes d’analyse présentées dans la section 4.2 sont applicables pour des abstractions non paramétriques comme Se, à condition d’utiliser une vue aplatie des graphes de flot de contrôle.

4.4.2 Conclusion générale

En se basant sur les développements du Chapitre 3, traitant de l’intérieur des blocs de bases, le Chapitre 4 achève notre analyse de programme. Nous avons raffiné un algorithme de parcours de graphe de flot de contrôle pour l’analyse par interprétation abstraite de programme.

Utilisant un système de rendez-vous, le parcours d’un CFG résulte en un état abs-trait présent sur chaque arc et sur chaque bloc, représentant une approximation des états possibles de la machine en ces points du programme.

Grâce à la composabilité de l’abstraction utilisée, chaque CFG n’est analysé qu’une fois, donnant des résultats indépendants du contexte d’appel. Les états obtenus sont ensuite spécialisés à chaque contexte d’appel, permettant de bénéficier des avantages d’une vue aplatie des CFG (découverte de propriétés spécifiques à un contexte d’appel, factorisation des propriétés indépendantes du contexte d’appel) sans les inconvénients (duplication de l’analyse, complexité élevée, absence de propriétés générales).

Cette même composabilité nous a permis de définir une opération d’accélération d’état, qui vient remplacer un algorithme de parcours de boucle par point fixe moins précis. Des schémas sont reconnus et des propriétés arithmétiques sont utilisées pour permettre la détermination de propriétés vraies pour toute itération. Ces propriétés sont exprimées en fonction des indices d’itérations, variables de I dorénavant acceptées dans la syntaxe des expressions utilisées la table des variables et dans les prédicats.

L’algorithme final (Algorithme 7) est complet, à la seule exception de la définition de la fonction Ξ, dernière pièce du puzzle, qui doit en un point du programme utiliser les propriétés découvertes sur l’état de la machine en ce point pour identifier de potentiels

chemins infaisables. C’est de l’exploitation de ces propriétés de flot de données pour la détection de propriétés de flot de contrôle que traitera donc le prochain chapitre.

5

Chemins infaisables

Sommaire

5.1 Introduction : un problème SMT . . . 126

5.2 Détection et expression de chemins infaisables . . . 131

5.3 Applications . . . 150

5.4 Conclusion générale . . . 158

Ce chapitre se base sur l’analyse de flot de données complète précédemment définie (Chapitres 3, 4) pour détecter des chemins infaisables, sous la forme d’ensembles d’arcs du CFG en conflit sémantique. Nous ferons appel à un solveur externe pour résoudre un problème de décision que nous extrairons des informations de flot de données du programme analysé, et qui représentera la satisfiabilité de l’exécution d’un chemin. Afin d’éviter toute perte de généralité, l’implantation n’est pas dépendante d’un outil en particulier, et les informations de flot de contrôle ainsi obtenues sont représentées dans le format portable FFX [21].

5.1 Introduction : un problème SMT

Documents relatifs