9
votes

Est-il possible de remplacer les fonctions statiques dans un module d'objet (GCC, LD, X86, Objcopy)?

Y a-t-il un moyen de remplacer les fonctions avec une portée statique dans un module d'objet?

Si je commence par quelque chose comme ça, un module avec symbole global "foo" est une fonction qui appelle Symbole local "bar," qui appelle le symbole local "baz" p> xxx pré>

Il possède un global "FOO" et deux locaux "Bar" et "Baz" P. >

Supposons que je souhaite écrire des tests de l'unité qui exercent une barre d'exercice et Baz, Je peux faire: p> xxx pré>

et maintenant bar et baz sont des symboles globaux et accessibles de en dehors du module. Jusqu'à présent, si bon. P>

Mais si je veux interposer ma propre fonction sur le dessus de "Baz", et ont "bar" appeler mon interposé "Baz"? P>

Y a-t-il un moyen de faire cela? P>

- L'option Wrap ne semble pas le faire ... p>

[scameron@localhost ~]$ cat ibaz.c
#include <stdio.h>
extern void foo();
extern void bar();

void __wrap_baz()
{
    printf("wrapped baz\n");
}
int main(int argc, char *argv[])
{
    foo();
    baz();
}

[scameron@localhost ~]$ gcc -o ibaz ibaz.c foo2.o -Xlinker --wrap -Xlinker baz
[scameron@localhost ~]$ ./ibaz
foo
bar
baz
wrapped baz
[scameron@localhost ~]$


6 commentaires

Je n'ai pas encore utilisé les symboles faibles, mais ils semblent affaiblir Baz de votre module d'origine vous permettront de le remplacer par un nouveau.


J'imagine que s'il essaie de faire de telles choses, il n'a pas accès au code source


J'ai accès au code source, mais je préférerais ne pas modifier la source de la manière habituelle des tests unitaires. En réalité, cela est pour tester un module de noyau Linux. En amont, ils n'aiment généralement pas que vous mettez des changements dans la source juste pour accueillir des choses qui ne sont pas le noyau et pour la compatibilité des correctifs, je ne veux pas gâcher inutilement la source.


Affaiblir ne fonctionne pas: [Scameron @ localhost ~] $ objcopy --weaken-symbole = baz foo2.o foo3.o [Scameron @ localhost ~] $ GCC -O ibaz ibaz.c foo3.xlinker - XLinker Baz [Scameron @ localhost ~] $ ./ibaz foo bar Baz enveloppé Baz [Scameron @ localhost ~] $ (Ugh. Stackoverflow Mise en forme de commentaire suce.)


Cela semble intéressant bien que: CS .virginia.edu / kim / Publicité / PIN / DOCS / 45467 / PIN / HTML / ...


Cela semble également intéressant: dynamorio.org


3 Réponses :


4
votes

Etant donné que statique est une promesse au compilateur C que la fonction ou la variable est locale dans le fichier, le compilateur est libre de supprimer ce code s'il peut obtenir le même résultat sans elle.

Ceci pourrait enfiler l'appel de la fonction. Cela pourrait signifier remplacer une variable avec des constantes. Si le code est à l'intérieur d'un si est toujours faux, la fonction peut ne pas exister même dans le résultat compilé.

Tout cela signifie que vous ne pouvez pas rediriger de manière fiable des appels vers cette fonction.

Si vous compilez avec le nouveau -Lto options est encore pire, car le compilateur est libre de réorganiser, supprimer ou en ligne tout le code de l'ensemble du projet.


1 commentaires

Je mets autour de l'inlinçon en compilant avec -fno-inline. Il n'y a pas de fonctions qui m'intéressent entièrement par le compilateur (sinon je les aurais déjà supprimé moi-même.) Il peut y avoir des cas d'angle que je ne peux pas traiter, mais c'est bon. Je suis plus intéressé par le cas typique. Je ne suis pas opposé à la modification mécanique du code de la machine sur les sites d'appels pour atteindre cette fin, il suffit de déterminer comment le faire.



2
votes

J'ai reçu un email de Ian Lance Taylor (Auteur d'or, un lien alternatif à LD):

Y a-t-il un moyen de remplacer les fonctions avec une portée statique dans un module d'objet? (Je suis sur X86_64 et I386 Linux)

Non, il n'y a pas. En particulier, le compilateur peut appeller des appels en ligne vers statique fonctions, et il peut également réécrire les fonctions d'utiliser une autre Convention sur appel (GCC fait toutes ces deux optimisations). il y a donc Aucun moyen fiable de remplacer une fonction statique après que le code ait été compilé.

L'inlinisation peut être traitée, je pense, par -fno-inline, mais changer les conventions appelantes est probablement trop.

Cela étant dit, les gars de Dynamorio prétendent pouvoir le faire, mais je ne l'ai pas vérifié:


1 commentaires

Bien sûr, l'inlinfing ne peut également être traitée que par la recompilation du code.



0
votes

Si vous êtes d'accord avec la modification du code de la machine, vous ne devez avoir aucun problème de modification de code source.

Écrire des scripts pour produire mécaniquement des sources de test d'unité à partir des sources réelles. Perl fait-il très bien.


0 commentaires