2008-12-26 6 views
20

Je cherche des façons de restreindre le nombre de symboles C exportés vers une bibliothèque statique Linux (archive). J'aimerais les limiter aux seuls symboles faisant partie de l'API officielle de la bibliothèque. J'utilise déjà 'static' pour déclarer la plupart des fonctions comme statiques, mais cela les limite à la portée du fichier. Je cherche un moyen de restreindre à la portée de la bibliothèque.Restriction des symboles dans une bibliothèque statique Linux

Je peux le faire pour les bibliothèques partagées en utilisant les techniques de How to Write Shared Libraries d'Ulrich Drepper, mais je ne peux pas appliquer ces techniques aux archives statiques. Dans son article Good Practices in Library Design plus tôt, il écrit:

La seule possibilité est de combiner tous les fichiers objets qui ont besoin certaines ressources internes en une seule en utilisant « ld -r » et limiter les symboles qui sont exportés par ce combiné fichier objet. L'éditeur de liens GNU propose des options pour .

Quelqu'un pourrait-il m'aider à découvrir ce que ces options pourraient être? J'ai eu un certain succès avec 'strip -w -K prefix_ *', mais cela semble brutal. Idéalement, je voudrais une solution qui fonctionne aussi bien avec GCC 3 et 4.

Merci!

Répondre

0

Ma façon de le faire est de marquer tout ce qui est de ne pas être exporté INTERNE, comprennent tous les fichiers .h garde, compilez dev construit avec -DINTERNAL = et compiler construit avec un communiqué unique fichier .c qui comprend tous autres fichiers de bibliothèque .c avec -DINTERNAL = static.

+0

Cela fonctionnerait si vous avez tout dans un fichier ou vous pouvez le compiler. Souvent, vous ne le faites pas. Parfois, vous devez avoir de petits fichiers à combiner avec d'autres langues (par exemple Haskell - c'est la raison pour laquelle j'ai trouvé cette page). –

+0

@Maciej: Eh bien OP a demandé à propos de gcc ... – Joshua

10

bibliothèques statiques ne peuvent pas faire ce que vous voulez pour le code compilé avec GCC soit 3.x ou 4.x.

Si vous pouvez utiliser des objets partagés (bibliothèques), l'éditeur de liens GNU fait ce que vous avez besoin avec une fonctionnalité appelée un script de version. Ceci est généralement utilisé pour fournir des points d'entrée spécifiques à la version, mais le cas dégénéré distingue simplement les symboles publics et privés sans aucun contrôle de version. Un script de version est spécifié avec l'option --version-script = en ligne de commande de ld.

Le contenu d'un script de version qui fait l'entrée pointe foo et bar ouvert au public et se cache toutes les autres interfaces:

{ global: foo; bar; local: *; }; 

Voir la ld doc à: http://sourceware.org/binutils/docs/ld/VERSION.html#VERSION

Je suis un grand défenseur de la bibliothèques partagées, et cette capacité à limiter la visibilité des globals est l'une de leurs grandes vertus.

Un document qui fournit plus des avantages des objets partagés, mais écrit pour Solaris (par Greg Nakhimovsky de vénérée mémoire), est à http://developers.sun.com/solaris/articles/linker_mapfiles.html

J'espère que cela aide.

9

Je ne crois pas GNU ld a de telles options; Ulrich doit avoir signifié objcopy, qui a beaucoup de ces options: --localize-hidden, --localize-symbol=symbolname, --localize-symbols=filename.

Le --localize-hidden en particulier permet d'avoir un contrôle très fin sur lequel les symboles sont exposés.Considérez:

int foo() { return 42; } 
int __attribute__((visibility("hidden"))) bar() { return 24; } 

gcc -c foo.c 
nm foo.o 
000000000000000b T bar 
0000000000000000 T foo 

objcopy --localize-hidden foo.o bar.o 
nm bar.o 
000000000000000b t bar 
0000000000000000 T foo 

Alors bar() est plus exporté de l'objet (même si elle est toujours présente et utilisable pour le débogage). Vous pouvez également supprimer bar() tous avec objcopy --strip-unneeded.

+0

Un problème que je vois avec cela, c'est que vous devez le faire sur tous les fichiers objets. Un autre problème est le cas de l'OP, quand vous voulez avoir des fonctions internes dans une bibliothèque statique réparties sur plusieurs fichiers objets, si vous "cachez" un symbole dans un fichier objet, comment peut-on y accéder depuis un autre fichier objet dans le même bibliothèque statique? –

+0

Merci. Je n'avais aucune idée d'objcopy existé et il a juste résolu un mal de tête majeur pour moi. –

6

Les mérites de cette réponse dépendra de la raison pour laquelle vous utilisez les bibliothèques statiques. Si c'est pour permettre à l'éditeur de liens de déposer des objets inutilisés plus tard, j'ai peu à ajouter. Si c'est pour l'organisation - en minimisant le nombre d'objets qui doivent être transmis pour lier les applications - cette extension de la réponse de Employed Russian peut être utile.

Au moment de la compilation, la visibilité de tous les symboles au sein d'une unité de compilation peut être définie à l'aide:

-fvisibility=hidden 
-fvisibility=default 

Cela implique, on peut compiler un seul fichier « de interface.c » avec une visibilité par défaut et un plus grand nombre de fichiers d'implémentation avec visibilité cachée, sans annotation de la source. Un lien repositionnable produira alors un seul fichier d'objet où les fonctions non-api sont « cachées »:

ld -r interface.o implementation0.o implementation1.o -o relocatable.o 

Le fichier objet combiné peut maintenant être soumis à objcopy:

objcopy --localize-hidden relocatable.o mylibrary.o 

Ainsi, nous avons une fichier objet unique "bibliothèque" ou "module" qui expose uniquement l'API prévue.


La stratégie ci-dessus interagit modérément bien avec l'optimisation du temps de liaison. Compiler avec -flto et effectuer la liaison relogeable par passage -r au lieur via le compilateur:

gcc -fuse-linker-plugin -flto -nostdlib -Wl,-r {objects} -o relocatable.o 

Utilisation objcopy pour localiser les symboles cachés comme précédemment, puis appeler le lieur une dernière fois pour dépouiller les symboles locaux et quel que soit l'autre code mort qu'il peut trouver dans l'objet post-lto. Malheureusement, il est peu probable relocatable.o avoir conservé toute information relative LPour:

gcc -nostdlib -Wl,-r,--discard-all relocatable.o mylibrary.o 

Les implémentations actuelles de lto semblent être actifs pendant la phase de liaison repositionnable. Avec lto activé, les symboles cachés => locaux ont été supprimés par le dernier lien relogeable. Sans lto, les symboles cachés => locaux ont survécu au lien final relocatable.

Les futures implémentations de lt semblent susceptibles de conserver les métadonnées requises à travers l'étape de liaison relocalisable, mais à l'heure actuelle, le résultat du lien relocalisable semble être un simple fichier objet ancien.

Questions connexes