Journal Auto-génération de code à la volée

Posté par  .
Étiquettes : aucune
0
22
juin
2007
Salut à toi Journal !

Je t'écris pour te poser une question "technique", limite philosophique.

Suite à ce journal : http://linuxfr.org/~Montaigne/24628.html, je me suis demandé comment pourrait faire une application sous linux en user-space, pour auto-générer son code. Je cherchais une solution efficace et performante (en c par exemple).

La première solution à laquelle j'ai pensé est relativement sale : j'écris du code dans un .c (fwrite...), je le compile avec un appel à gcc (system...) sous forme de .so que j'ouvre avec dlopen.

En deuxième solution, je voyais "smasher" la stack de mon propre programme, mais là je trouve ça... inqualifiablement affreux.

Cher lecteur, connais-tu une solution à cet épineux problème ? A noter que je n'y vois pas d'intérêt pratique, c'est juste pour la culture.

Merci !
  • # en Java

    Posté par  (site web personnel) . Évalué à 4.

    Ok, tu cherches une solution en C. Mais si jamais tu es intéressé, c'est possible en java.
    Au delà des solutions de script, tu peux compiler une classe à partir d'une chaîne de caractère et la charger par la suite. Un exemple :
    http://www.javaworld.com/javatips/jw-javatip131.html

    Bon courage pour la suite :-)
  • # Les gouts et les couleurs

    Posté par  . Évalué à 4.

    Tu trouves sale la solution qui consiste à écrire du code C dans un fichier et à le faire compiler.

    Nous n'avons pas les mêmes gouts.

    Le développement en C est maitrisé et connu; maintenable, on trouve des compilateurs pour pratiquement toutes les architectures.

    Je trouve particulièrement sale un mécanisme qui génèrerait directement du code binaire en mémoire; qui devrait être exécuter. Ca oblige à jouer avec les segments de données et de code; à contourner le résolveur de lien; a mettre tout un tas d'artifice qui vont être propre à l'architecture et à l'OS, sans garantie même d'une version à l'autre.

    En plus de cela, ça oblige à intégrer au minimum un assembleur et un résolveur de liens directement dans ton programme, tache qui sera mal fait par rapport à un assembleur maintenu.

    Bref, une vrai usine à gaz.
  • # a la volé...

    Posté par  . Évalué à 2.

    ben, ca depends un peu de ce que tu veux faire...
    si tu veux faire des choses assez simple et determiné, tu peu imaginer ton propre language et ta propre pile; ton programme ne serait qu'un interpreteur.
    exemple typique : un emulateur de calculatrice (je pense a une hp par exemple).

    imagine ton programme (un interpreteur d'un language simple tel que le RPN), il attends des evenements ou il interagit avec je ne sais quoi...
    et quand il recoit certains evenement, il ponds dans la pile des instructions...
    quand je parle de pile, je ne parle pas de la pile systeme, je parle d'une pile emulé par une classe en C par exemple avec des pop() drop() et companie.
    et ensuite, il interprete les instructions de la pile (là c'est important d'avoir un language simple et determiné, voir specifique)

    voilà, ca peut être un peu lourds, mais ce qui est bien c'est que l'execution du code à la volé se fait à l'interieur de l'interpreteur et sans bidouiller la stack "systeme"...
    mais tout depends des actions que tu souhaite faire faire à to ncode generé à la volé (par exemple si c'est un truc hyper generaliste, il faudra definir sans doute pas mal d'instruction). c'est pas utilisable dans toutes sorte de situation, et demande pas mal de boulot.
  • # Si j'étais un vrai homme ...

    Posté par  . Évalué à 5.

    Si j'étais un vrai homme, voilà ce que je ferais a ta place :

    Je bidouillerais gcc pour qu'il puisse avoir ses entrées sorties directement en mémoire, c'est a dire par exemple, de lui passez une chaine de caratère et qu'il te retourne un pointeur sur le code compilé écrit sur le tas (pas la peine d'aller péter ta pile :) ).

    Le top du top serait d'avoir le code compilé en flux continu, avec une callback appelée a chaque fois qu'un sous arbre de l'arbre de compilation est terminé (par exemple, pour chaque fonction, lorsque tout est défini bien sûr). La blague c'est le link, qui sera ultra funky mais y'a vraiment moyen de se marrer.

    Bon le truc c'est que les segments de code sont en lecture seule, et qu'à l'avenir en se verra de plus en plus souvent interdire l'exécution sur la pile (tant mieux) et sur le tas (un peu plus balot, mais c'est bien quand même). L'avantage de dlopen() et consorts, c'est que ca passe par des privilèges noyaux pour rajouter des segments de code.

    (bon j'espère que j'ai pas dit de bêtises, mais je crois que non)

    Pour ma part, entre un appel a gcc ou de l'écriture de code en mémoire, et même en général en informatique, la philosophie qui convient est "tu peux faire ce que tu veux, a partir du moment que tu le maîtrise et que tu peux le justifier, honnêtement"
    • [^] # Commentaire supprimé

      Posté par  . Évalué à 2.

      Ce commentaire a été supprimé par l’équipe de modération.

      • [^] # Re: Si j'étais un vrai homme ...

        Posté par  (site web personnel) . Évalué à 2.

        Mouais, sauf que ce qu'il y a sur le disque, c'est quand même pas tout à fait la même chose que ce que tu trouves en mémoire. Il y a toute la partie relogement et édition de lien qui manque. Et un binaire déjà relogé, sur un RAMdisk, ça serait quand même une bête étrange ...
  • # Mouais

    Posté par  . Évalué à 2.

    Générer du code dynamiquement est crade et dangereux, un programme utilisant ceci subira un kill sauvage et bien mérité sur un kernel PaX[1]/Grsecurity[2] configuré correctement. Après on peut bien autoriser l'exécution de tels programmes avec paxctl, mais bon...

    Sinon il reste la possibilité de t'interfacer avec un interpréteur de script, comme dit plus haut.

    [1] : http://pax.grsecurity.net/
    [2] : http://www.grsecurity.net/
  • # dynamique

    Posté par  (site web personnel) . Évalué à 3.

    Je suis pas sûr d'avoir tout compris mais j'ai l'intuition que libffi peut aider.
    http://sourceware.org/libffi/

    pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

  • # Scheme

    Posté par  (site web personnel) . Évalué à 7.

    Tu codes en Scheme, ou Perl, tu utilises une quasiquotation (ou une chaine de caracteres), quelques macros, et un eval.

    Bon, c'est pas très hype car ca marche depuis avant ta naissance. Néanmoins, si tu remplaces les S-expressions par du XML, ca fait tout de suite vachement plus cool, et ca marche aussi bien.
  • # tcc

    Posté par  (site web personnel) . Évalué à 2.

    As tu pensé à tcc qui est capable je crois de compiler à la volée du code C ? Par contre je crois qu'il reste des bugs...

    Il y a un module pour le langage lua qui l'utilise

    désolée, pas le temps de développer
  • # Gnu Lightning

    Posté par  . Évalué à 3.

    Suivant ce que tu veut faire, il y a gnu lightning qui existe depuis pas mal de temps et réponds à une moitié du problème (pseudo asm -> binaire -> exec).
    Reste à faire un parser pour produire du code dans leur format.

    http://www.gnu.org/software/lightning/lightning.html

    Cela dit, pourquoi tu veut compiler le code à la volée? Ce serait plus simple de prendre un truc comme lua, que tu peut binder assez facilement avec du c.
    • [^] # Re: Gnu Lightning

      Posté par  . Évalué à 1.

      Merci PenPen. Je ne connaissais pas cette librairie. C'est exactement le genre de choses que je recherchais. :)

      J'ai un mauvais à priori concernant les performances d'une solution qui embarque du lua, du python ou du script en règle générale. Ca reste qu'un à priori. Un jour, je prendrais le temps de faire des benchs pour me faire une idée plus précise.
      • [^] # Re: Gnu Lightning

        Posté par  . Évalué à 2.

        ben le script ca permet de gagner du temps ... sur les parties non critiques (exemple pour python : parser une conf puis l'injecter dans du C ;))
        (temps de code).

        Ensuite si ta fonction est appelé 15 millions de fois en une seconde, oui il est preferable de bien l'optimiser celle la;)
  • # lex et yacc

    Posté par  (site web personnel) . Évalué à 3.

    C'est pas comme ça qu'on fait normalement ?

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.