IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

exécution de "blocs" d'instruction créés dynamiquement


Sujet :

C

  1. #41
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Ces hypotheses peuvent sembler raisonnables, mais le fait qu'il y a des problemes meme avec gcc -O0 montre qu'il n'en est rien.
    justement, il n'y a plus de problèmes en -O0



    perso, cela constitue un projet de master... donc le fait que mon code puisse être réutilisé ensuite n'est pas l'objectif prioritaire

    d'un autre côté, je suis en train d'envisager une version très édulcorée de JIT (en gros, j'oublie toutes optimisations, et trucs à calculer trop gourmands en mémoire), pour passer par des méthodes existantes portables et éprouvées... mais le but de la technique que j'étudiais était justement d'éviter la JIT pour des contraintes matérielles (surtout dans l'embarqué). en plus, un prototype fonctionnait à l'époque de gcc 2.95 (mais il ne marche plus non plus )

    de toute façon, il est trop tard pour changer de sujet, et trop tôt pour décider de me consacrer exclusivement au rapport de stage... donc j'explore les possibilités restantes (méthode shadock)
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  2. #42
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par gorgonite
    justement, il n'y a plus de problèmes en -O0
    Tu oublies un mot: apparents.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  3. #43
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Tu oublies un mot: apparents.

    pas faux...

    mais de toute façon, faut que j'avance. j'ai bien étudié le JIT d'openjdk aujourd'hui ; et il semble utiliser exactement la même manipulation pour allouer des blocs exécutables... la différence c'est qu'il génère son asm via une "vraie" compilation, et non en juxtaposant des blocs prédéfinies (mais le traitement est plus couteux... mais évites de se mélanger les pinceaux dans les labels)

    en gros, c'est pas la joie...
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  4. #44
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par gorgonite
    pas faux...

    mais de toute façon, faut que j'avance. j'ai bien étudié le JIT d'openjdk aujourd'hui ; et il semble utiliser exactement la même manipulation pour allouer des blocs exécutables... la différence c'est qu'il génère son asm via une "vraie" compilation, et non en juxtaposant des blocs prédéfinies (mais le traitement est plus couteux... mais évites de se mélanger les pinceaux dans les labels)

    en gros, c'est pas la joie...
    Ta manip ne me gènerait pas avec du code que tu as écrit toi-même en assembleur. Une technique possible:tu écris le C, tu fais générer de l'assembleur que tu édites comme tu veux.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  5. #45
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Ta manip ne me gènerait pas avec du code que tu as écrit toi-même en assembleur. Une technique possible:tu écris le C, tu fais générer de l'assembleur que tu édites comme tu veux.

    j'ai essayé en construisant moi-même mes "blocs"


    EDIT petite erreur dans le code...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    unsigned char* end = NULL;
    static int i=0;
     
    void containsBloc() {
    	__asm__ __volatile__ (
    		";\n"
    		".block_begin: \n"
    		"movl  i, %%eax"
    		: "=a"(i) : 
    	);
    	__asm__ __volatile__ (
    		"addl  $4, %%eax"
    		: "=a"(i) : "a"(i)
    	);
    	__asm__ __volatile__ (
    		"jmp *%0\n"
    		".block_end: " 
    		: : "m"(end)
    	);
    }
     
    int main(int argc, char** argv) {
       unsigned char* beginBlock;
       unsigned char* endBlock;
       unsigned char *buf;
       unsigned char *beginBuf;
       size_t size;
     
       end = &&end;
       __asm__ __volatile__("movl  $.block_begin, %%ebx" :"=b"(beginBlock) );
       __asm__ __volatile__("movl  $.block_end, %%ecx" :"=c"(endBlock) );
       size = endBlock - beginBlock;
       buf = mmap(NULL, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
       if (buf == MAP_FAILED) {
          perror("mmap");
          exit(EXIT_FAILURE);
       }
       beginBuf = buf;
       memcpy(buf, beginBlock, size);
       buf += size;
       if (msync(beginBuf, size, MS_INVALIDATE) != 0) {
          perror("msync");
          exit(EXIT_FAILURE);
       }
     
       __asm__ __volatile__ ("jmp *%0" : : "m" (beginBuf));
     
    end:
       printf("%d\n",i);
       return 0;
    }


    ça marche en -O0 et -O1 ; mais ça foire toujours en -Os
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  6. #46
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    enfin une version qui marche en -O0, -O1, -Os et -O2

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    unsigned char* end = NULL;
    static int i=0;
     
    void containsBloc() {
    	__asm__ __volatile__ (
    		";\n"
    		".block_begin: \n"
    		"\tmovl  i, %%eax"
    		: "=a"(i) : 
    	);
    	__asm__ __volatile__ (
    		"addl  $4, %%eax"
    		: "=a"(i) : "a"(i)
    	);
    	__asm__ __volatile__ (
    		"jmp *%0\n"
    		".block_end: " 
    		: : "m"(end)
    	);
    }
     
    int main(int argc, char** argv) {
    	unsigned char* beginBlock;
    	unsigned char* endBlock;
    	unsigned char *buf;
    	unsigned char *beginBuf;
    	size_t size;
     
    	__asm__ __volatile__("movl  $.end, %%edx" :"=d"(end) );
    	__asm__ __volatile__("movl  $.block_begin, %%ebx" :"=b"(beginBlock) );
    	__asm__ __volatile__("movl  $.block_end, %%ecx" :"=c"(endBlock) );
    	size = endBlock - beginBlock;
    	buf = mmap(NULL, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    	if (buf == MAP_FAILED) {
    		perror("mmap");
    		exit(EXIT_FAILURE);
    	}
    	beginBuf = buf;
    	memcpy(buf, beginBlock, size);
    	buf += size;
    	if (msync(beginBuf, size, MS_INVALIDATE) != 0) {
    		perror("msync");
    		exit(EXIT_FAILURE);
    	}
     
    	__asm__ __volatile__ (
    		"jmp *%0\n" 
    		".end:\n"
    		: : "m" (beginBuf)
    	);
     
    	printf("%d\n",i);
    	return 0;
    }
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  7. #47
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    voici une version qui marche avec toutes les optimisations (enfin celles que j'ai testées )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    unsigned char* end = NULL;
    static int i=0;
    static int (*pputs)(const char*);
    static char hello[17] = "hello world asm";
     
    void containsBloc() {
    	__asm__ __volatile__ (
    		";\n"
    		".block_begin: "
    	);
    	pputs(hello);
    	__asm__ __volatile__ (
    		"addl  $4, %%eax"
    		: "=a"(i) : "a"(i)
    	);
    	__asm__ __volatile__ (
    		"jmp *%0\n"
    		".block_end: " 
    		: : "m"(end)
    	);
    }
     
    int main(int argc, char** argv) {
    	unsigned char* beginBlock;
    	unsigned char* endBlock;
    	unsigned char *buf;
    	unsigned char *beginBuf;
    	size_t size;
    	pputs = &puts;
     
    	__asm__ __volatile__("movl  $.end, %%edx" :"=d"(end) );
    	__asm__ __volatile__("movl  $.block_begin, %%ebx" :"=b"(beginBlock) );
    	__asm__ __volatile__("movl  $.block_end, %%ecx" :"=c"(endBlock) );
    	size = endBlock - beginBlock;
    	buf = mmap(NULL, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    	if (buf == MAP_FAILED) {
    		perror("mmap");
    		exit(EXIT_FAILURE);
    	}
    	beginBuf = buf;
    	memcpy(buf, beginBlock, size);
    	buf += size;
    	if (msync(beginBuf, size, MS_INVALIDATE) != 0) {
    		perror("msync");
    		exit(EXIT_FAILURE);
    	}
     
    	__asm__ __volatile__ (
    		"jmp *%0\n" 
    		".end:\n"
    		: : "m" (beginBuf)
    	);
     
    	printf("%d\n",i);
    	return 0;
    }
    j'aimerais bien vos avis quant au code, et à sa maintenabilité... je ne parlerais pas de sa portabilité, elle est devenue x86-minded (pas vraiment réaliste pour de l'embarqué )
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  8. #48
    Membre averti

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Points : 422
    Points
    422
    Par défaut
    salut j'ai une proposition

    #include <stdio.h>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    const char * chaine = "coucou";
    asm("debut:");
    asm("pushl _chaine");
    asm("movl $_puts, %eax");
    asm("call %eax");
    asm("addl $4, %esp");
    asm("ret");
    asm("fin:");
    asm("nop");
    int size;
    void *debut;
    void* buf;
    void blockExecute() {
        asm("movl $fin , %eax");
        asm("subl $debut, %eax");
        asm("movl %eax, _size");
        printf(" %d ",size);
        buf = malloc(size);
        asm("movl $debut, _debut");
        memcpy(buf,debut,size);
        puts("début de l'exécution");
        asm("movl _buf, %eax");
        asm("call %eax");
        printf("fin de l'execution");
        free(buf);
        return ;
    }
     
    int main(int argc, char** argv) {
    	blockExecute();
    	return 0;
    }

  9. #49
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    j'ai enfin quelque chose qui semble fonctionner (avec toutes les optimisations), et sans trop d'assembleur...


    mais il me reste un problème de taille... les performances ne sont pas forcemment au rendez-vous

    j'ai surtout comparé avec l'option -02 qui est celle couramment utilisée

    sur un processeur centrino 1.6Ghz, les temps d'exécution sont
    'BASIC' 44s
    'RICARDI' 22s
    'BLOCK' 36s

    ce qui est moins bon que prévu... (passer deux mois pour faire une optimisation moins performante que celle de base, c'est un peu déprimant)

    sur un processeur amd64 3200+, je suis plutôt content des performances
    'BASIC' 36s
    'RICARDI' 14,9s
    'BLOCK' 14s

    même si j'espérais gagner plus...


    si quelqu'un pouvait m'éclairer à ce sujet, ça m'arrangerait



    mon code est en pièce jointe
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  10. #50
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    quelqu'un a-t-il eu le temps de regarder mon usine à gaz, juste pour avoir un avis extérieur sur la maintenabilité d'une telle solution ?
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  11. #51
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par gorgonite
    quelqu'un a-t-il eu le temps de regarder mon usine à gaz, juste pour avoir un avis extérieur sur la maintenabilité d'une telle solution ?
    Si tu ne connais pas encore mon avis, c'est inutile que je le repete
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #52
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Si tu ne connais pas encore mon avis, c'est inutile que je le repete


    Si si, j'ai bien compris le votre...


    je souhaitais juste le confirmer ou le nuancer avec l'opinion d'autres experts, c'est juste pour "conclure" par un avis purement technique à la fin de mon rapport
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  13. #53
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    bah une opinion c'est juste qu'à moins de quelque chose de vraiment vraiment vraiment spécial, il est inutile, dangereux, et non portable de faire quelque chose comme ça....

    A la limite, faire un prog en assembleur et l'appeler depuis un prog en C oui.

    Si vraiment tu es sur une plateforme spéciale et pour un besoin très très particulier, oui sans doute. Quoique, je ne vois pas ce qu'on gagne à le faire en assembleur plutôt qu'en C.

    Et en tous cas, une horreur du point de vue de la maintenance.... Et je ne pense pas que du point de vue optimisation on y gagne.....

    Mais ça n'est qu'un avis
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  14. #54
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 27
    Points
    27
    Par défaut
    [HS]
    salut,
    je laisse ce message juste pour remercier (meme si il ne l'a pas fait expres ^^), Gorgonite d'avoir posté son source que j'ai telechargé juste par curiositée, j'ai enfin decouvert le moyen de jumper sur un label (pourtant je ne suis pas un codeur de la derniere heure).

    c'est marran parcque tout seul j'etais pratiquement arrivé au meme code sauf que je doublai pas les && dans la table donc en desespoir de cause j'ai abandonné cette optimisation pour faire des jump sur fonction (avec les arguments a passer et tout c'etais pas rapide du tout j'avai aussi abandonné cette solution) :'(
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    const void *tab[2] = {&&lbl1, &&lbl2} ;
    goto *tab[1] ;
    lbl1:
    lbl2:
    merci encore et a+

  15. #55
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par orand
    j'ai enfin decouvert le moyen de jumper sur un label
    A noter que c'est une extension de gcc.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  16. #56
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    A noter que c'est une extension de gcc.
    cela veut dire qu'aucun autre compillateur n'autorisera cette manip ? :/
    pourtant ca me semble logique qu'on puisse de cette maniere acceder a un label.

  17. #57
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par orand
    cela veut dire qu'aucun autre compillateur n'autorisera cette manip ? :/
    Aucun, le mot est fort. gcc a une présence suffisemment forte pour que lea compatibilité avec lui soit une raison qui incite à ajouter des extensions. Ca ne m'étonnerait pas que les compilateurs d'Intel ou de Sun destinés à Linux l'ait aussi.

    pourtant ca me semble logique qu'on puisse de cette maniere acceder a un label.
    Il n'est garanti nulle part qu'un void* soit assez grand pour représenter une adresse d'instruction (exemple historique: les modèles avec plus de 64K de code et moins de 64K de données sur 8086).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

+ Répondre à la discussion
Cette discussion est résolue.
Page 3 sur 3 PremièrePremière 123

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo