Empêcher le link de certaines fonctions dans un .so

3 réponses
Avatar
sthanizlas
Bonjour,

Je me demandais s'il =E9tait possible d'emp=EAcher le link de fonctions dan=
s un .so. Je m'explique:

j'ai un fichier test.c qui contient ceci:

int f1 (int a)
{
return a;
}

un fichier test2.c qui contient ceci:

int f1 (int);
int f2 (int a, int b)
{
return f1 (a + b);
}

Je compile les 2 avec -fPIC et avec les objets, je produis 2 libraires, une=
static, et une dynamique.
ar cr libtest.a test.o test2.o
ranlib libtest.a

gcc -fPIC -shared -o libtest.so test.o test2.o

Je fais un fichier principal main.c qui utilise cette librairie:
#include <stdio.h>
int f1 (int);
int f2 (int, int);
int main (int argc, char *argv)
{
printf ("f1: %d\n", f1 (3));
printf ("f2: %d\n", f2 (3, 4));
return 0;
}

Tout va bien, que je fasse du link static ou dynamique, le programme m'affi=
che bien
f1: 3
f2: 7

Maintenant, sans modifier le code existant, j'ai envie de wrapper la foncti=
on f1 dans une fonction =E0 moi qui ex=E9cuterait =E9galement le code de f1=
. Je cherche un peu sur le net, je trouve, je fais un fichier wrapped.c com=
me ceci:
int __real_f1 (int);
int __wrap_f1 (int a)
{
a =3D a + 42;
return __real_f1 (a);
}

et je link mon main.c avec wrapped.c, la libtest, et l'option -Wl,-wrap,f1
au link static, j'obtiens
f1: 45
f2: 49

au link dynamique, j'obtiens
f1: 45
f2: 7

Que s'est-il pass=E9 ? Tout simplement, dans la lib static libtest.a on n'a=
pas effectu=E9 d'=E9dition de lien du tout (c'est juste une collection de =
.o). Tout se fait =E0 la fin et la fonction f1 est wrapp=E9e partout. Lors =
de la cr=E9ation de la lib dynamique, une =E9dition partielle de lien a =E9=
t=E9 effectu=E9e, en particulier, l'appel =E0 f1 dans la fonction f2 a =E9t=
=E9 mapp=E9 au code de f1 contenu dans la librairie libtest.so, ce qui expl=
ique le r=E9sultat.

Question:
Est-il possible d'emp=EAcher ce comportement ? (au moins pour les fonctions=
export=E9es)

J'ai essay=E9 diverses options de linker en vain. J'ai parcouru le web en v=
ain aussi.

J'esp=E8re que =E7a =E9veillera votre curiosit=E9 :)

3 réponses

Avatar
espie
In article ,
sthanizlas wrote:
Bonjour,

Je me demandais s'il était possible d'empêcher le link de fonctions dans
un .so. Je m'explique:



Manque des gros bouts d'explication.
Faudrait au moins dire de quel OS tu parles, et de quelles versions de
linker (bon, ca ressemble fort a du binutils recent sur linux ceci-dit).
Je compile les 2 avec -fPIC et avec les objets, je produis 2 libraires,
une static, et une dynamique.
ar cr libtest.a test.o test2.o
ranlib libtest.a



Bon, deux points:
1/ on parle de bibliotheques en francais. "library" est un faux ami.
2/ plus important: le terme de "bibliotheque partagee" est abusif. En
elf, on parle de "shared object". Ca veut dire que ce ne sont pas des
bibliotheques, mais des trucs plus simples (en particulier, on s'attend
a ce que tu charges tout d'un coup).

Lors de la création de la lib dynamique, une édition partielle de lien a
été effectuée, en particulier, l'appel à f1 dans la fonction f2 a été
mappé au code de f1 contenu dans la librairie libtest.so, ce qui
explique le résultat.


Oui, c'est normal. ton ld est cense te pondre un objet complet.

Question:
Est-il possible d'empêcher ce comportement ? (au moins pour les
fonctions exportées)

J'ai essayé diverses options de linker en vain. J'ai parcouru le web en
vain aussi.

J'espère que ça éveillera votre curiosité :)



Bof. Pas trop de curiosite. Mais histoire que tu aies quelques reponses,
faut vraiment que tu apprennes a poser plus precisement tes problemes.
C'est ta methodologie qui pose souci. Ce que tu decris ici n'a rien
de portable... donc au minimum, voir dans quel cadre tu vas en avoir
besoin... et si ce souci de portabilite en est un pour toi.

le fait de preciser le besoin devrait aussi t'amener a revoir les endroits
ou poser ta question... t'auras plus de chance dans les groupes systeme
que dans fr.comp.lang.c.

Enfin, je soupconne que ce que tu veux n'est pas possible tel quel, mais
possible en rusant (la-encore ca sera fortement dependant de l'OS, mais
on n'en est plus a ca pres, hein): tu n'arriveras pas a tes fins avec
un seul shared object. Par contre, tu dois pouvoir garder tes deux fichiers
objets separes (sous forme d'un test1.so et d'un test2.so) et utiliser un
linker-script pour fabriquer une libtest.so qui ne sera PAS un shared object,
mais bien un truc qui charge test1.so et test2.so (si tu es comme je le
soupconne sous linux, tu peux regarder a quoi ressemble reellement ta libc.
Il y a de fortes chances que le fichier qui s'appelle "libc.so" ne soit pas
un binaire, mais bien une composition de plusieurs sous-machins).

Ou alors, alternativement, avoir libtest.so qui soit un seul de test1/test2,
et qui depende de l'autre bibliotheque. Caveat: dans tous les cas, ca va
etre un peu folklorique cote gestion du path si tu veux que ca soit
transparent.
Avatar
Luk Bettale
Merci pour ta réponse. Effectivement, je suis sous linux, et effectivemen t, je ne cherche absolument pas la portabilité. Je suis également d'acc ord après réflexion que cette question aurait eu sa place plutôt dans un autre groupe (celui de gcc par exemple).

J'avais déjà la solution d'utiliser 2 .so séparées, mais je voulais n'en garder qu'une seule. Par contre, je ne connaissais pas le coup du lin ker-script, je pense que c'est la solution vers laquelle je vais me tourner .
Avatar
Antoine Leca
sthanizlas écrivit :
Je me demandais s'il était possible d'empêcher le link
de fonctions dans un .so.



Non. Tout au plus avec le système d'objets partagés habituellement
utilisé avec *nix, on peut masquer des fonctions en interposant un autre
.so devant celui qui contient la fonction que tu veux empêcher: l'effet
sur le code exécuté est le même, mais pas la méthode, et donc le
résultat n'est pas identique car le simple fait de charger ou pas un .so
a un effet non-nul.
Et tout ceci ne fonctionne pas dans la logique Windows, et en ce qui
concerne Mac OSX je ne sais pas.

Que s'est-il passé ? Tout simplement, dans la lib static libtest.a
on n'a pas effectué d'édition de lien du tout



Techniquement c'est le contraire... Quand tu utilises des bibliothèques
dynamiques, la compilation ne réalise pas totalement l'édition des
liens, celle-ci est terminée au moment du chargement juste avant
l'exécution du programme.


Antoine