Forum Programmation.c Supprimer tous les appels d'une fonction dans l'ensemble du code source

Posté par .
Tags : aucun
1
27
jan.
2011
Bonjour,

Sur un code source donné (en l’occurrence le code source du driver realtek r8192), je souhaite retirer tous les appels à la fonction printk().

J'ai d'abord pensé à utiliser sed & co pour supprimer les lignes, l'ennuis, c'est que parfois les appels à la fonction s'étendent sur plusieurs lignes, ce qui complique pas mal les choses.

Je précise que je veux vraiment supprimer les appels, pas juste augmenter la verbosité du message et configurer le gestionnaire de log pour qu'il n'affiche pas au delà d'un certain niveau par défaut.

Je pourrai faire à la main, mais je veux rendre le truc automatisé car c'est pour un PKGBUILD (donc en bash).

J'avais pensé aussi redéfinir la fonction printk à l'aide d'une macro, mais je vois pas trop comment faire ça de manière scriptable.
Ou alors une option à passer au compilateur ? (comme ça il suffirait juste de patcher le Makefile)

Des idées ?

Merci
  • # plusieurs lignes reelles ou visuelles

    Posté par . Évalué à 1.

    c'est que parfois les appels à la fonction s'étendent sur plusieurs lignes, ce qui complique pas mal les choses.

    sur plusieurs lignes :
    - visuelles (vi saute à la ligne suivante quand tu fait fleche du bas, ou la ligne se rallonge si tu agrandis ta fenetre)
    exemple :
    void unefonction ( fonction1(), fonction2(arguement1, arguement 2), argumentA, arguementB, arguement C, variableD)
    {
    le code de ma fonction;
    };


    - reelles (avec des retours à la ligne dans une seule ligne) : comme par exemple :
    void unefonction ( fonction1(),
    \ fonction2(arguement1, arguement 2),
    \ argumentA,
    \ arguementB,
    \ arguementC,
    \ variableD
    )
    {
    le code de ma fonction;
    };


    dans le cas 1, tu peux utiliser sed/awk pour trouver et remplacer les printk(xxxxx).
    dans le cas 2, il faut juste que le printk(xxxxx) ne soit pas sur plusieurs lignes lui meme
    • [^] # Re: plusieurs lignes reelles ou visuelles

      Posté par . Évalué à 1.

      Là tu parles de la déclaration de la fonction et non de l'appel en lui même.
      Et je dirai que c'est le cas 2 que j'ai (vrai retour à la ligne).
      Exemple :


      printk(KERN_DEBUG "%s: Encryption failed: len=%d.\n",
      ieee->dev->name, frag->len);


      et sous vi, c'est bien 3 lignes différentes.
  • # pourquoi ?

    Posté par (page perso) . Évalué à 2.

    déjà, j'aimerais bien savoir pourquoi tu veux faire ça ? le driver est si pénible qu'il te pourrit tes logs ?

    bin oui pourquoi une macro que tu insères avec sed; c'est pas bien ?
    ou même tu peux faire un patch ?

    sed -i '/WHERE/a\#define printk ... \' r812.c

    non ?
    • [^] # Re: pourquoi ?

      Posté par . Évalué à 1.

      Le problème c'est qu'il y a plein de fichiers .c et donc que l'endroit d'insertion n'est donc pas le même partout.
      Ou alors il faudrait trouver un moyen d'insérer juste avant la déclaration de la première déclaration de fonction...
  • # And ze winner iz:

    Posté par (page perso) . Évalué à 6.

    • [^] # Re: And ze winner iz:

      Posté par . Évalué à 2.

      Merci. J'ai testé mais c'est pas parfait, certains appels passent à la trappe... avec cette règle :


      @@ expression E; @@
      -printk(E);


      Il n'a matché que le code ressemblant à :

      printk("====> we can not show so many peers\n");


      mais pas :

      printk(KERN_WARNING "%s: could not initialize WEP: "
      "load module rtllib_crypt_wep\n",
      dev->name);


      Peut être que expression ne peut pas contenir des retour à la ligne (grammaire http://www.emn.fr/z-info/coccinelle/docs/main_grammar009.htm(...) ?
      • [^] # Re: And ze winner iz:

        Posté par . Évalué à 1.

        Bon j'essaye avec
        -printk(...)

        apparemment le patch est plus grand...
        • [^] # Re: And ze winner iz:

          Posté par . Évalué à 1.

          Bon ca ne marche complètement, il reste toujours des printk non supprimées et bizarrement ce sont ceux qui tenaient que sur une ligne...
          Du coup j'ai rajouté un coup de sed après pour vraiment tout supprimer...mais je ne comprend pas pourquoi le spatch ne fonctionne pas...
          • [^] # Re: And ze winner iz:

            Posté par . Évalué à 2.

            Pour supprimer une ligne séparée par des ; il te suffit d'utiliser sed ou awk en initialisant la variable FS (ou IFS je ne me rappelle pllus) à ";".
            • [^] # Re: And ze winner iz:

              Posté par . Évalué à 2.

              IFS=';'

              ca dire à ton shell de faire les separations au ; au lieu de le faire aux espaces.
            • [^] # Re: And ze winner iz:

              Posté par . Évalué à 1.

              Ah pas bête merci, si j'ai bien compris, ca veut dire qu'une "ligne" est redéfini par ce qu'il y a entre 2 ";" et donc dans ce cas, si on trouve une "ligne" contenant printk, on est sûr qu'elle ne contient qu'une seule instruction ?
              Mais est-ce que ça "résiste" au retour à la ligne ?
              • [^] # Re: And ze winner iz:

                Posté par (page perso) . Évalué à 2.

                Ca résiste sans problème au retour à la ligne. Mais pas aux commentaires contenant ce caractère:

                printk(KERN_DEBUG "%s: Encryption failed: len=%d.\n", /* ugly hack ; must be rewritten*/
                ieee->dev->name, frag->len);


                Pour ce genre de besoin, il faut une sorte de parser C simplifié. Le faire en awk est je pense possible. Sinon flex/bison est vraiment fait pour (bonjour la doc si tu débutes).

                Quelle que soit la solution utilisée, il ne faut pas que le code soit compliqué.
                Exemple avec erreur à la compilation une fois que c'est passé à la moulinette:

                if ( truc() && printk(KERN_DEBUG "%s: Encryption failed: len=%d.\n", ieee->dev->name, frag->len) ) {
                blah;
                }
                /* oui, c'est crade. Mais c'est valide */


                Exemple avec bug:

                result = printk(KERN_DEBUG "%s: Encryption failed: len=%d.\n", ieee->dev->name, frag->len);
                if (result<=0 && errorstop=true) {
                blah;
                }
              • [^] # Re: And ze winner iz:

                Posté par (page perso) . Évalué à 2.

                Euh... Si tu as un patch coccinelle qui supprime les printk sur plusieurs lignes, et un autre pour ceux sur une ligne, pourquoi tu n'appliques pas tout simplement les deux ?
                • [^] # Re: And ze winner iz:

                  Posté par . Évalué à 1.

                  Voici un fichier ( http://pastebin.toile-libre.org/?show=608376 ) sur lequel je n'arrive pas à trouver de règle spatch qui matche tous les printk, et je ne comprend pas pourquoi ca fait ça, car parfois il matche une ligne et pas une autre et rien ne diffère....
                  Au mieux (avec les règles citées au dessus) il ne trouve que 5 printk sur 20...
  • # Quick and dirty

    Posté par (page perso) . Évalué à 4.

    gcc -D'printk(a, b, c)=' etc

    Ca ajoute une macro printk vide. J'ai testé sur un petit exemple ca semble marcher.

    Autre solution : Créer un fichier qui contient la macro et utiliser l'option -include de gcc.
    • [^] # Re: Quick and dirty

      Posté par . Évalué à 1.

      La fonction printk appelé n'a pas toujours le même nombre d'arguments, est-ce que ca marchera quand même ?
      • [^] # Re: Quick and dirty

        Posté par (page perso) . Évalué à 1.

        J'ai repris mon petit exemple et apparemment ca ne fonctionne pas. Par contre, après avoir lu un commentaire plus haut sur coccinelle, j'ai testé gcc -D'printk(...)=' etc et ça semble fonctionner.
        • [^] # Re: Quick and dirty

          Posté par . Évalué à 1.

          Ne marche pas sur le code complexe du driver malheureusement...
          Peut être pour les mêmes raisons qui fait que spatch ne marche pas non plus.
          • [^] # Re: Quick and dirty

            Posté par . Évalué à 2.

            Ce problème m'a intrigué : j'ai essayé spatch, qui galère apparemment sur les directives de préprocesseur un peu ardues.

            Par contre, que gcc n'y arrive pas, ce n'est pas normal : comment il pourrait le compiler sinon ?… J'ai essayé avec le code que tu fournis plus haut, la solution de Grégory marche nickel. Tu as un exemple qui ne passe pas ?
            • [^] # Re: Quick and dirty

              Posté par . Évalué à 1.

              Essaye peut être sur l'ensemble du code du driver http://www.nd.edu/~pbui/scratch/aur/rtl8192se_linux_2.6.0019(...) Mais pour voir si ca marche ou pas, il faut avoir une carte wifi compatible et regarder les messages de /var/log/kernel.log
              • [^] # Re: Quick and dirty

                Posté par . Évalué à 2.

                Heu, merci, je veux bien aider, mais je vais pas faire le boulot à ta place non plus. Si tu as un exemple concret de printk qui n'est pas supprimé par la directive de préprocesseur de gcc, montre-le, ça m'intéresse, et ça intéresse aussi sûrement des devs de gcc, car c'est sûrement un bug.

                Et pour le tester, je grep simplement "printk" sur le fichier généré ; je ne vois pas en quoi j'ai besoin de le tester en live pour voir si les printk sont bien partis…
                • [^] # Re: Quick and dirty

                  Posté par . Évalué à 1.

                  Attend, je n'ai pas très bien saisi là.

                  Mon exemple concret justement c'était qu'au niveau de l'exécution, les printk s'affichaient toujours après avoir rajouté CFLAGS=`echo $CFLAGS`" -D'printk(...)='" dans mon PKGBUILD juste avant le make.

                  Mais là tu m'expliques tu as un fichier source généré ?
                  C'est à dire que ta commande
                  gcc -D'printk(...)='
                  tu l'exécutes sur du code source et tu obtiens un autre fichier source sur lequel tu fais un grep et qui n'affiche plus les printk ?

                  Comment utilises-tu ta commande sur le fichier exemple que j'avais donné ?
                  • [^] # Re: Quick and dirty

                    Posté par . Évalué à 2.

                    Mais là tu m'expliques tu as un fichier source généré ?

                    Je ne lance que le préprocesseur :

                    gcc -E -D'printk(...)='

                    Et je ne vois aucun printk en sortie.
                    Ça se trouve, ton problème est plutôt du genre l'option est pas bien passée, ou alors les fichiers sont générés autrement, ou… ?
                    • [^] # Re: Quick and dirty

                      Posté par . Évalué à 1.

                      Oui ça doit être ça, car je viens de voir qu'il y a plusieurs Makefile et que des flags sont définis aussi ailleurs dans les Makefile, du coup le la variable CFLAGS n'est peut être pas prise en compte. J'essaye de tout comprendre là pour essayer de voir où je pourrais modifier...
                      • [^] # Re: Quick and dirty

                        Posté par . Évalué à 1.

                        Ok c'est bon ca marche, en fait le Makefile utilisait sa propre variable pour gcc, EXTRA_CFLAGS. Du coup, j'ai cherché l'initialisation de cette variable, elle apparaît dans le Makefile principal (qui appelle ensuite les autres en cascade, donc la variable est bien transmise), un coup de sed pour rajouter le -D'printk(...)=' et plus aucun printk n'apparaît dans les binaires .o (et donc je suppose à l'exécution que ca n'apparaîtra pas non plus, je testerai ça plus tard).
                        Merci
                • [^] # Re: Quick and dirty

                  Posté par . Évalué à 1.

                  Tu veux peut être parler de faire un grep sur les binaires intermédiaires .o ?
            • [^] # Re: Quick and dirty

              Posté par . Évalué à 1.

              Essaye sur le code du driver complet : http://www.nd.edu/~pbui/scratch/aur/rtl8192se_linux_2.6.0019(...)

              Mais il faut une carte wifi compatible pour voir si ca marche ou pas (en regardant la sortie /var/log/kernel.log)

Suivre le flux des commentaires

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