Sous-sections
Nous décrivons dans cette partie les contributions du
projet qui sont de nature linguistique. Dans chaque cas, il
s'agit de proposer un formalisme ou un langage spécialisé
adapté à un type de problème et conduisant à des traitements
automatiques (vérification, analyse, transformation, etc.).
Nous abordons successivement nos travaux sur les
architectures de logiciels (module 6.1.1), les agents
mobiles (module 6.1.2), la programmation
par aspects (module 6.1.3), un langage dédié
pour le parallélisme (module 6.1.4), et un cadre pour
la définition de systèmes d'information logiques (module
6.1.5).
Participants : Pascal Fradet,
Michaël Périn, Lakshminarayanan Renganarayanan.
Mots clés : architectures de
logiciels, vues, relations inter-vues, cohérence,
vérification, UML, graphe .
Résumé :
Nous avons proposé un cadre permettant de décrire des
familles d'architectures de logiciels sous forme d'ensemble
de vues. Ces vues sont définies formellement comme des
classes de graphes. Des algorithmes de vérification ont été
proposés pour détecter les incohérences de spécification
(aussi bien intra-vues qu'inter-vues).
L'intérêt d'une définition précise de l'architecture d'un
logiciel est reconnu de longue date mais les architectures de
logiciels étaient jusqu'à présent utilisées de manière
informelle par les développeurs (souvent sous la forme de
dessins décrivant des visions d'ensemble du logiciel). Une
définition formelle est un premier pas vers un traitement
rigoureux et systématique des architectures ; elle peut aussi
servir à améliorer la communication entre les différents
acteurs impliqués dans un développement (en fournissant des
définitions précises et sans ambiguïté).
Par ailleurs, il s'avère que les propriétés que l'on
souhaite vérifier dans ce contexte sont de natures très
diverses et que chacune d'elle peut demander une présentation
différente de l'organisation du logiciel. La définition d'une
architecture comme un ensemble de vues
complémentaires s'impose donc mais il est alors nécessaire de
traiter les délicats problèmes de mise en relation des vues
et de la cohérence de ces vues multiples.
Nous avons abordé cette question en décrivant les vues par
des diagrammes avec multiplicités sur les arcs inspirés des
notations UML [32,15]. Les diagrammes répondent à un
besoin de généricité et d'abstraction que l'on retrouve dans
les descriptions informelles utilisées en pratique par les
concepteurs. En particulier, un diagramme permet de spécifier
une famille potentiellement infinie d'architectures. Ce
formalisme permet de représenter des objets sémantiques très
variés et les différents types de vues que nous avons
considérés jusqu'à présent se décrivent naturellement de
cette manière.
Il est rare toutefois que les vues soient complètement
indépendantes ; il est même possible que deux vues
répondent à des exigences conflictuelles. Dans notre
formalisme, les relations entre vues sont représentées par
des arcs supplémentaires (dits de correspondance) entre les
noeuds des différentes vues. Les conditions de cohérence
entre vues sont définies dans un langage de contraintes à la
OCL ( Object Constraint Language de
UML) qui permet d'exprimer des propriétés de
chemins dans les graphes. Un algorithme de vérification
permet d'assurer les conditions de cohérence sur les familles
de graphes décrites par les diagrammes des différentes vues
[32,15].
Le fait de travailler sur des diagrammes spécifiant des
familles d'architectures complexifie la vérification de
cohérence. Pour obtenir un algorithme complet, nous avons dû
nous restreindre à un sous-ensemble de propriétés de
cohérence structurelles (typiquement, l'existence de chemins
entre composants). Nous étudions maintenant les problèmes de
relations inter-vues et de cohérence dans le cas où chaque
vue est spécifiée par un unique graphe. Les descriptions
deviennent certes moins génériques mais devraient nous
permettre de décrire des relations inter-vues plus complexes
et de vérifier des propriétés de cohérence sémantique.
Nos travaux sur les architectures de logiciels se sont
appuyés sur des études de cas (système de contrÔle de trains
proposé par la société néerlandaise Signaal, système de
contrÔle d'accès). Ils se concrétisent dans le cadre d'une
action industrielle conduite en collaboration avec le projet
EP-ATR, Sycomore Aérospatiale Matra,
AQL et TNI. Commandité par le
Celar, ce projet porte sur la conception d'un outil d'aide à
la mise au point d'architectures sécurisées.
Participants : Pascal Fradet,
Siegfried Rouvrais.
Mots clés : architectures de logiciel,
interactions, agent mobile, propriétés non fonctionnelles,
sécurité, performance .
Résumé :
Nous étudions l'analyse de propriétés d'interactions
exprimées comme des compositions d'agents mobiles, de
RPC (Remote Procedure Calls), ou
d'évaluations à distance. Les propriétés analysées sont la
performance (en terme de volume de données échangées) et la
sécurité (confidentialité et intégrité). Ce type
d'information permet de guider le concepteur de systèmes
distribués dans ses choix d'implantation.
Les agents mobiles ont été récemment proposés comme une
nouvelle forme d'interaction des systèmes distribués. Une des
raisons qui rendent les agents difficiles à utiliser est que
leurs avantages ou inconvénients, comparés aux interactions
classiques comme les RPC, portent sur des
aspects non fonctionnels (comme les performances). Les
propriétés non fonctionnelles sont souvent difficiles à
appréhender et choisir la bonne combinaison d'interactions
pour implanter un service complexe est une tâche
délicate.
Nous avons travaillé à cette question en analysant et en
comparant les différents styles d'interaction selon deux
types de propriétés : les performances et la sécurité.
Nous avons proposé un cadre linguistique pour spécifier et
implanter les services complexes. Les agents mobiles, les
RPC, l'évaluation à distance ou toute
combinaison de ces protocoles sont représentés comme des
expressions fonctionnelles. Ces expressions peuvent alors
être analysées et comparées simplement. Pour les
performances, nous avons pris comme critère le volume de
données échangées sur le réseau. Pour la sécurité, nous nous
sommes focalisés sur les propriétés de confidentialité et
d'intégrité. Ces analyses permettent de guider le concepteur
de systèmes distribués dans ses choix de protocoles [25].
Nous poursuivons actuellement ce travail dans deux
directions :
- la prise en compte de propriétés de tolérance aux
fautes,
- l'intégration de ce cadre à un environnement de
développement basé sur un langage de description
d'architectures de logiciels.
Ce travail est effectué en collaboration avec Valérie
Issarny du projet Solidor.
Programmation par aspects
Participants : Thomas Colcombet,
Pascal Fradet.
Mots clés : aspect, analyse et
transformation de programme, politique de sécurité,
construction de programme .
Résumé :
La programmation par aspects propose de décrire un
logiciel comme un ensemble formé d'un composant principal
et d'une collection d'aspects. Un outil, appelé tisseur,
est chargé de produire automatiquement un programme
intégrant les différents aspects au composant principal.
Nous avons appliqué ce paradigme à la sécurité. La
politique de sécurité (l'aspect) est décrite séparément du
programme par une propriété temporelle sur les traces
d'exécution. Le tisseur impose automatiquement cette
propriété au composant par transformation de programme. Une
application particulièrement intéressante de cette
technique est la sécurisation d'applets au moment de leur
réception.
La notion d'«aspect» présente des similarités avec celle
de «vue» présentée dans le module précédent dans le contexte
des architectures logicielles. En programmation par aspects,
un logiciel est formé d'un composant principal et d'une
collection d'aspects décrivant des tâches comme la gestion
mémoire, la synchronisation, les optimisations, etc. Un
outil, appelé tisseur, est chargé de produire automatiquement
un programme intégrant les différents aspects au composant
principal. L'intérêt de cette approche est de localiser (dans
les aspects) des choix de mise en oeuvre qui seraient sinon
dispersés dans le code source.
Nous avons proposé une méthode automatique, inspirée de la
programmation par aspects, pour imposer des propriétés
exprimées sur les traces d'exécution des programmes [20,12]. Le programmeur spécifie la
propriété séparément de son programme comme un aspect et le
tisseur produit un programme « équivalent » respectant la
propriété, c'est-à-dire un programme se comportant comme le
programme original mais s'arrêtant en produisant une erreur
avant toute tentative de violation de la propriété. Le défi
est d'imposer la propriété de la faÇon la moins coûteuse
possible. On minimise à l'aide d'analyses statiques le nombre
de tests dynamiques nécessaires pour prévenir les
violations.
Le domaine d'application évident est celui de la sécurité.
En effet, de nombreuses politiques de sécurité peuvent
s'exprimer comme des propriétés sur les traces d'exécution.
En particulier, une application potentielle est la
sécurisation d'applets au moment de leur réception. Cette
méthode a l'avantage de la flexibilité puisque chaque site
peut imposer à la volée sa propre politique de sécurité aux
applets. La séparation du programme et de la propriété
conduit également à des programmes plus faciles à développer
et à maintenir. Ceci est particulièrement important dans le
domaine de la sécurité. Il est difficile de prévoir toutes
les attaques possibles et les programmes doivent pouvoir être
changés rapidement pour faire face aux nouvelles menaces
identifiées. De plus, considérer les aspects comme des
propriétés permet de décrire et de contrÔler précisément
l'impact sémantique du tissage. C'est une autre
caractéristique importante dans le contexte de la
sécurité.
Le coeur de l'approche a été mis en oeuvre en O'Caml. Des
heuristiques simples ont été utilisées pour les analyses
potentiellement coûteuses et la complexité globale du
processus est linéaire en fonction de la taille du
programme.
La programmation par aspects a clairement d'autres
applications pour la construction de programmes. La
séparation des problèmes offerte par les aspects permet
d'espérer pouvoir concilier programmes de haut niveau et
efficacité. Nous étudions actuellement dans cet esprit un
aspect de représentation de données et, en collaboration avec
Mario Südolht et Rémi Douence de l'école de Mines de Nantes,
un aspect d'assemblage de composants.
Langage dédié pour machines parallèles
Participants : Pascal Fradet,
Julien Mallet.
Mots clés : langage dédié,
parallélisme, schéma de programme, compilation, analyse de
coût, distribution de données .
Résumé :
Nous avons proposé un langage spécialisé pour machines
parallèles. Les restrictions du langage source permettent
de choisir automatiquement la meilleure distribution de
données parmi un ensemble de distributions standards. Ce
choix repose sur une analyse de coût exacte et symbolique
prenant en compte les temps de calcul et les temps de
communication.
Il n'existe pas de langage idéal pour programmer les
machines parallèles : on trouve d'une part des langages
à parallélisme explicite efficaces mais non portables et très
complexes à utiliser ; d'autre part des langages simples
et portables ont été proposés mais leur compilation est
complexe et relativement inefficace. La démarche que nous
avons adoptée est celle d'un langage spécialisé permettant
une estimation exacte et symbolique du coût de
l'implantation parallèle. Notre langage source est un langage
fonctionnel du premier ordre où la récursivité générale et
les conditionnelles sont remplacées par des collections de
schémas de programmes (patrons). Le résultat de l'analyse de
coût, qui prend en compte les temps de calcul et les temps de
communication, permet de choisir la meilleure distribution de
données parmi un ensemble de distributions standards
[17,12,35].
Participants : Sébastien Ferré,
Yoann Padioleau, Olivier Ridoux.
Mots clés : système d'information,
analyse de concept, logique .
Résumé :
Nous étudions la conception de systèmes d'information
non-hiérarchiques offrant à la fois des possibilités de
navigation et d'interrogation. Nous avons développé pour
cela un modèle d'analyse de concepts logiques qui
généralise l'analyse de concepts formels de Wille et
Ganter [GW99].
L'analyse de concepts logiques
(ACL [33,24]) part d'un contexte
logique dans lequel des objets sont étiquetés par des
formules logiques et produit un treillis de concepts dits
logiques. La logique employée à cet effet peut être presque
quelconque mais dans la pratique on exigera qu'elle soit
décidable. Des fragments de logique classique (ou
intuitionniste), les logiques de descriptions, ou même une
logique d'ensembles d'attributs où la relation de contenance
sert de relation de déduction, constituent des exemples de
logiques qu'on peut employer pour étiqueter les objets.
L'instance de l'ACL qui utilise la logique des
attributs est tout simplement l'analyse de concepts formels
(ACF). Les concepts sont des paires
(E, I) (pour
extension-intention) dont les composantes sont mutuellement
maximales. En d'autres termes, E est le plus grand ensemble d'objets
dont les étiquettes (qui sont des formules) impliquent
I, et I est la formule la plus générale qui
implique les étiquettes de E. E et
I sont liés par une
connection de Galois.
Ce modèle est très général et peut être instancié par le
choix d'une logique et d'une mise en oeuvre.
Traditionnellement, l'ACF est mise en oeuvre
dans des systèmes d'analyse a posteriori de faits bruts
constituant le contexte formel. On peut mettre en oeuvre
l'ACL de cette faÇon, mais nous préférons
étudier son emploi dans des systèmes plus dynamiques où
l'ACL est considérée comme un modèle
d'organisation. Par exemple, munie d'une logique permettant
de décrire les différentes vues d'une architecture
logicielle, l'ACL devient un environnement de
développement de logiciels qui intègre la navigation dans
l'architecture. D'où l'idée de la mettre en oeuvre dans un
système de fichiers qu'on appellera «système de fichiers
logique» [34,23].
Nous étudions actuellement l'extension de ce modèle pour
la prise en compte de relations entre objets, une métaphore
de navigation dans le treillis de concepts logiques, et les
algorithmes de consultation, navigation et mise à jour. Sur
ce dernier point, l'enjeu principal est de ne jamais
construire entièrement le treillis de concepts logiques. La
métaphore de navigation envisagée possède les
caractéristiques suivantes : une formule désigne un
endroit où l'on souhaite lire ou écrire,
l'interrogation du contenu d'un endroit retourne entre autres
la désignation d'endroits proches par des formules (combinant
ainsi interrogation et navigation), et la
manipulation des formules se fait aussi bien en prenant en
compte leur intension que leur extension. Ce dernier point
permet de faire des déductions qui sont correctes dans le
contexte courant, mais pas en général.
Comme exemple de mise en oeuvre, nous avons réalisé un
système de fichiers (sous Linux) qui offre les fonctions de
l'analyse de concepts formels sous l'interface standard d'un
système de fichiers virtuel. Dans cette réalisation, seul le
système de fichiers est spécifique, et les couches
supérieures comme le shell restent inchangées. Les
commandes et les applications changent de sémantique de la
faÇon suivante : cd d revient à se focaliser
sur l'attribut d, ls liste les fichiers qui
possèdent les attributs courants avec, le cas échéant, leurs
attributs supplémentaires, ls -r liste les fichiers
qui possèdent au moins les attributs courants, mv d1
d2 remplace l'attribut d1 par l'attribut
d2 dans tous les fichiers accessibles, etc. Nous
recherchons maintenant comment mettre en oeuvre un système de
fichiers basé sur l'analyse de concepts logiques de faÇon la
plus générique possible.
Transformations certifiées de programmes Java Card
Participants : Thomas Jensen,
Bjarke Ebert.
Mots clés : transformation,
optimisation, code intermédiaire, carte à puce, Java Card,
preuve formelle, Coq .
Résumé :
Nous avons conÇu et breveté une méthode qui permet de
prouver la correction des transformations effectuées sur le
code intermédiaire Java Card pour permettre son
installation sur une carte à puce. Cette preuve a été
vérifiée avec l'assistant de preuve Coq. La formalisation
de ces transformations forme la base de travaux qui visent
à construire un transformateur Java Card certifié en
Coq.
Notre effort de formalisation des différents aspects de
Java et de sa mise en oeuvre a entre autre porté sur la
vérification d'optimisations pour Java Card. La définition du
langage Java Card comprend un langage intermédiaire (le «Java
Card byte code») et un format (le format CAP
pour «Converted APplet format») utilisé pour stocker des
applications sur une carte. Le format Cap joue un rÔle
semblable à celui du format des fichiers de classes («class
files») de Java mais regroupe le code des classes de tout un
package de Java contrairement aux fichiers de classes de Java
(qui ne représentent qu'une seule classe par fichier). Ceci
permet de remplacer des références symboliques entre classes
à travers le «constant pool» par des adresses de mémoire, ce
qui est plus rapide et permet de supprimer des entrées dans
le «constant pool». Une autre optimisation, nécessaire
puisqu'il n'y a pas de chaînes de caractères en Java Card,
s'appelle la «tokenization»: elle consiste à remplacer les
noms de méthodes, champs, etc.
par un numéro (un «token»). Ceci permet entre autres
d'utiliser le nom (c'est à dire le «token») pour indexer une
table de méthodes au lieu d'effectuer une recherche à travers
le «constant pool» et la hiérarchie de classes pour
implémenter l'appel de méthodes virtuelles.
Pour prouver la correction de ces optimisations, nous
avons développé un cadre qui permet de décrire la sémantique
des deux formats [21]. La différence entre les deux formats est
encapsulée dans des fonctions auxiliaires, ce qui permet
d'utiliser le même système d'inférence pour spécifier les
deux sémantiques. En utilisant la notion de relation logique,
il a été possible de définir une relation liant une entité
dans un format à l'entité lui correspondant dans l'autre
format. La tâche restant à accomplir pour établir
l'équivalence consiste alors à montrer que lesdites fonctions
auxiliaires respectent ces relations ce qui représente une
simplification majeure de la preuve. Cette technique a permis
d'effectuer la preuve de correction avec l'assistance de
l'outil Coq.
Nous travaillons maintenant sur la construction d'un
transformateur Java Card certifié en Coq. La formalisation de
ces transformations forme la base d'une preuve constructive
que pour chaque programme Java Card il existe un programme
équivalent en format CAP. Notre approche
utilise les techniques d'extraction de programmes de l'outil
Coq pour extraire un transformateur à partir de cette preuve
constructive.