• Aucun résultat trouvé

5.2 Détection et expression de chemins infaisables

5.2.3 Expression de chemins infaisables dans FFX

Nous avons brièvement présenté le langage d’annotation portable FFX en sec- tion 2.4.3. Les chemins infaisables détectés par l’analyse présentée dans cette thèse sont exprimées au format FFX, permettant leur exploitation par des outils externes capables de lire ce format et d’utiliser des propriétés parmi celles qu’il exprime. Nous al- lons maintenant présenter le sous-ensemble de ce langage qui sera utilisé pour exprimer des chemins infaisables, sous la forme de conflits entre arcs des CFG du programme.

5.2.3.1 Les conflits dans FFX

La syntaxe du sous-ensemble de FFX utilisé est définie par la grammaire partielle de la Figure 5.4. FLOWFACTS := <flowfacts> CONFLICT+ </flowfacts> CONFLICT :=

<conflict seq="true"> FUNCTION

</conflict> FUNCTION :=

<function address=ADDR> ITEM* </function> ITEM := EDGE CALL LOOP EDGE :=

<edge source=ADDR target=ADDR />

CALL :=

<call ADDRESS> FUNCTION </call> LOOP :=

<loop address=ADDR> ITERATION_ALL ITERATION_LAST </loop> ITERATION_ANY := <iteration number="*"> ITEM+ </iteration> ITERATION_LAST := <iteration number="n"> ITEM+ </iteration> ADDR := "INT"

Figure 5.4 – Grammaire FFX partielle

Essentiellement, un chemin infaisable est un conflit entre un ensemble d’arcs dans un contexte donné (boucles, points d’appel). Ainsi, dans FFX, chaque chemin infaisable est représenté par un conflit (CONFLICT) entre une liste d’éléments (ITEM) dans le contexte

d’une fonction (FUNCTION). Chacun de ces éléments peut être

• un arc (EDGE), représenté par l’adresse de la dernière instruction du bloc de départ

et l’adresse de la première instruction du bloc d’arrivée ;

• un ensemble d’éléments dans le contexte d’un appel (CALL) à une fonction (FUNCTION)

identifié par l’adresse du point d’appel ;

• un ensemble d’éléments dans le contexte d’une boucle (LOOP) identifiée par l’adresse

de la tête de boucle, considérés valides

soit pour la dernière itération (ITERATION_LAST)

de la boucle en question.

Il est important de noter que les arcs en conflit seront listés en séquence, dans l’ordre dans lequel ils ont été lus par l’analyse. Cela garantit que, dans un contexte donné (boucle ou fonction), les arcs listés (EDGE) appartiennent à un chemin du contexte en

question9. Cette propriété sera essentielle par la suite (section 5.2.3.3), elle est exprimée

dans le langage FFX par l’attribut seq de la balise <conflict>, systématiquement positionné à “true” dans notre cas.

5.2.3.2 Écriture mathématique des conflits FFX

Remarque. Les chemins issus de l’analyse de programme définie dans le chapitre

précédent sont un peu particuliers : leurs arcs peuvent provenir de multiples CFG (ap- pelant et appelés). Ceux-ci sont représentés dans notre outil par les adresses des blocs source et destination dans le programme binaire ; il est donc immédiat de déterminer le CFG de la fonction de laquelle chaque arc provient. La génération et la sémantique des balises de contexte de fonction (<function>) et d’appels (<call>) ne pose ainsi pas de difficulté. Nous nous concentrons donc seulement sur les contextes de boucle (<loop> et <iteration>).

Le format XML de FFX étant très verbeux, nous ferons usage dans la suite d’une notation mathématique équivalente, plus concise. Nous noterons ainsi un conflit entre trois arcs e1, e2, e3 par

e1, e2, e3

Si ce conflit est valable, pour toute itération d’une boucle h, nous le noterons loop∗

h[e1, e2, e3]

l’étoile∗ désignant toute itération, à l’instar du langage FFX. De même, si seul e 1 est

dans la boucle h et que le conflit porte sur la dernière itération de celle-ci, nous le noterons

loopn

h[e1], e2, e3

9. Du fait que ces contextes définissent en réalité des régions sans boucles, c’est même le seul ordonnancement vérifiant cette propriété d’appartenance à un chemin du contexte.

Bien entendu, ces contextes loop∗ et loopn peuvent s’emboîter :

loop∗

h0[loopnh[e1], e2,loop

h00[e3]]

Nous notons l’ensemble des conflits ainsi descriptibles Cffx.

5.2.3.3 Sémantique des conflits FFX

Nous pouvons définir la sémantique des chemins infaisables exprimés sous la forme de conflits entre arcs dans FFX, en les traduisant en un chemin abstrait de Π∗, incluant

des arcs de multiples CFG. Cette traduction s’opèrera par une fonction τ : Cffx→Π∗

La fonction τ utilise la propriété de séquentialité des arcs exprimés (attributseq=

"true"). Elle relie systématiquement les listes d’arcs en intercalant entre chaque couple d’arc un connecteur représentant l’ensemble des chemins entre la cible de l’arc précédent et la source de l’arc suivant. Lorsque la liste d’arcs est dans le contexte d’une boucle – pour toutes itérations ou pour la dernière – la tête de boucle est exclue. Les connecteurs reliant un arc en dehors d’une boucle et un arc à l’intérieur de cette boucle n’excluent pas la tête de boucle (on a le droit de boucler jusqu’à s’“installer” dans le contexte d’une itération). La contrainte “dernière itération” exprimée par loopn est traduite en

ne permettant pas de boucler en sortie de boucle : ainsi, sur le deuxième exemple, le connecteur entre e1 et e2 ne permet pas de repasser sur la tête de boucle h.

Exemple. Ainsi, pour tout e1 = (s1 → t1), e2 = (s2 → t2), e3 = (s3 → t3) arcs du

programme, et pour toutes têtes de boucle h, h0,

• Les conflits hors boucles sont traduits par un chemin constitué des arcs du conflit (dans l’ordre énoncé) reliés par des connecteurs :

τ(e1, e2, e3) = e1.t1χs2. e2 .t2χs3 . e3

• Les conflits vrais pour toute itération d’une boucle sont traduits par des chemins ne pouvant passer par la tête de boucle (cela en ferait un chemin inter-itération) :

τ(loop∗h[e1, e2]) = e1 .s1χ

{h}

• L’entrée dans un contexte de boucle est traduite par deux connecteurs, le pre- mier nous permettant d’itérer à loisir sur la boucle en question jusqu’à atteindre l’itération désirée : τ(e3,loop∗h[e1, e2]) = e3.t3χh.hχ {h} s1 . e1.s1χ {h} t2 . e2

• La sortie de contexte de dernière itération d’une boucle est traduite par une interdiction de reboucler (de repasser par la tête de boucle) :

τ(e3,loopnh[e1], e2) = e3.t3χs1e1.t1χ

{h}

s2 . e2

• Le même raisonnement s’applique pour des boucles imbriquées : τ(loop∗h0[e3,loop ∗ h[e1, e2]]) = h0χ{h 0} s3 . e3.t3χ {h0} h .hχ {h,h0} s1 . e1.s1χ {h,h0} t2 . e2 = e3.t3χ {h0} h .hχ {h,h0} s1 . e1.s1χ {h,h0} t2 . e2