[LINUX] Qu'est-ce qu'une bibliothèque en langage C? Quelles informations sont ouvertes au public?

** Introduction **

Le sujet de cet article est le suivant.

  1. Quelles sont les informations sur la bibliothèque ouverte sur l'extérieur? Commentaire grossier
  2. Comment vérifier les informations publiques
  3. Comment limiter les informations publiques

Le contenu est une plongée approfondie dans cet article. Je vais résumer à nouveau à partir de l'endroit où qu'est-ce qu'une bibliothèque et qu'est-ce qu'une API publique

** Quelles sont les informations sur la bibliothèque publiées à l'extérieur? ** **

** Tout d'abord, qu'est-ce qu'une bibliothèque? ** **

Le programme démarre avec la fonction main et réalise les fonctions du programme en utilisant les fonctions appelées par main et les données utilisées. Cela ne fonctionnera pas sans les fonctions à appeler depuis la fonction principale et les données utilisées, il y aura donc toujours une entité quelque part dans le programme.

program.png

Lorsque vous créez un programme de cette manière, il y a des cas où vous voulez soudainement couper les coins ronds. Vous devez utiliser exactement la même fonction à chaque fois. La bibliothèque ** est un mécanisme pour rassembler ces ** exactement les mêmes fonctions.

ライブラリ.png

** Pour utiliser la bibliothèque **

La bibliothèque s'associe à une bibliothèque appelée ** lien de bibliothèque ** ou ** lien ** lorsque le programme est compilé.

Afin de lier la bibliothèque, la bibliothèque doit effectuer les opérations suivantes.

Vous devez divulguer des informations sur ʻapllo () `et les coupes utilisées dans la figure. Tel est le thème principal de cette fois, ** L'information ouverte au public **. Si les informations de fonction sont résolues par cette liaison, le programme peut utiliser la bibliothèque. À ce stade, la méthode d'utilisation diffère selon le type de bibliothèque.

** Bibliothèque statique (.a) **

Il s'agit d'une bibliothèque dans un format que le programme importe tel quel au moment de la compilation. Puisqu'elle est incluse dans le programme au moment de la construction, la fonction existe déjà lorsque le programme est exécuté, vous pouvez donc utiliser le programme sans réfléchir **. Étant donné que toute la bibliothèque recto-verso est importée, ** la taille augmentera **.

static_lib.png

** Bibliothèque partagée (.so) **

Le programme se souvient uniquement des informations de la bibliothèque au moment de la compilation et les associe au fichier cible au moment de l'exécution. (Cela s'appelle ** bibliothèques de liaison **)

shared_lib.png

Dans le cas d'une bibliothèque partagée, le programme ne dispose que des informations de la bibliothèque, il est donc nécessaire de ** rendre la bibliothèque cible liable ** lorsque le programme s'exécute.

Ce mécanisme est [comme celui-ci](https://qiita.com/developer-kikikaikai/items/f6f87b2d1d7c3e14fb52#%E5%9F%BA%E6%9C%AC%E7%9A%84%E3% 81% AAlinux% E3% 81% AE% E5% 8B% 95% E7% 9A% 84% E3% 83% A9% E3% 82% A4% E3% 83% 96% E3% 83% A9% E3% 83% AA% E3% 83% AA% E3% 83% B3% E3% 82% AF% E3% 81% AB% E9% 96% A2% E3% 81% 99% E3% 82% 8B% E4% BB% 95% E7% B5% 84% E3% 81% BF).

En termes simples, c'est OK si le chemin de la bibliothèque cible est généré par la commande ldd. Sinon, vous devez transmettre le chemin dans la variable de construction ou d'environnement de la bibliothèque. C'est OK si le côté droit de => est lié quelque part comme indiqué ci-dessous.

$ ldd /usr/bin/curl
        linux-vdso.so.1 (0x00007ffe307ac000)
        libcurl.so.4 => /usr/lib/x86_64-linux-gnu/libcurl.so.4 (0x00007f85cce4e000)
...
        libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f85cbb4b000)
        libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f85cb6d3000)
...
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f85c6c95000)

** Supplément **

2018/05/16 postscript

~~ J'ai utilisé l'article par erreur, et ~~ le nom officiel de la bibliothèque. Je voudrais profiter de cette occasion pour résumer.

Nom Exemple Aperçu
Bibliothèque statique Linux xx.a, Windows xxx.lib Bibliothèque au format intégré au programme
Bibliothèque partagée Linux xx.so, Windows xxx.dll Bibliothèque liée au démarrage du programme
Bibliothèque dynamique Linux dlopen(), Windows LoadLibrary() Bibliothèque à lier pendant l'exécution du programme

xx.a, Cela ressemble à une bibliothèque dynamique car elle est intégrée de manière fluide dans divers programmes. Je fais souvent une erreur si je n'organise pas mon cerveau comme "Dynamique ... Oh, c'est un nom qui vient d'une manière différente d'être pris en compte." ... peut-être juste moi. Oui

** Informations sur les bibliothèques exposées à l'extérieur Lien externe **

J'ai fait un long mouvement. De là, c'est la production. J'ai dit quelque chose, mais quelles sont les informations qui sont divulguées à l'extérieur? En termes de programme, c'est ** avec lien externe **. (Osez utiliser l'expression ** information publique dans cet article **)

Pour le dire très grossièrement en langage C, ** les bases sont des fonctions et des variables ** qui ne sont pas définies statiquement. Notez que la façon de penser est légèrement différente entre C et C ++. ** Si la classe n'est pas statique, C ++ peut ne pas être en mesure de bien gérer les variables internes même si la méthode est statique **. C'est vrai. Autres ** Il est nécessaire de comprendre la différence entre statique et statique, qui n'est pas une information publique en C ++ **. Pour plus d'informations sur C ++, veuillez consulter ici. Cet article se concentrera sur C.

Le problème avec cette seule condition est que ** Toutes les fonctions utilisées dans les fichiers de la bibliothèque seront des informations publiques! **. Donc, après cela, nous vous montrerons comment vérifier les informations publiques et comment les limiter. Il chevauche partiellement cet article.

** Comment vérifier les informations publiques (lien externe) **

** commande nm **

Vous pouvez vérifier les informations publiques avec la commande nm.

Par exemple:

Tout d'abord, vérifiez le programme lui-même.

$nm -D test
                 w __cxa_finalize
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U __libc_start_main
                 U memcmp
                 U __printf_chk
                 U publisher_free
                 U publisher_new
                 U publisher_publish
                 U publisher_subscribe
                 U publisher_unsubscribe
                 U puts
                 U __stack_chk_fail

Les minuscules sont une fonction locale, les détails sont omis. Le problème est capital. ** U n'est pas résolu **, c'est-à-dire une fonction qui doit être liée à l'exécution en tant que bibliothèque partagée. Étant donné que publisher_XXX etc. sont des fonctions créées par vous-même, elles ne peuvent être utilisées que si elles sont publiées.

D'un autre côté, la bibliothèque liée ressemble à ceci

nm  .libs/libpublisher.so
...
0000000000000f90 t dputil_list_pop
0000000000000f50 t dputil_list_pull
0000000000000f20 t dputil_list_push
0000000000000ee0 t dputil_lock
0000000000000f00 t dputil_unlock
...
                 U pthread_mutex_init@@GLIBC_2.2.5
                 U pthread_mutex_lock@@GLIBC_2.2.5
                 U pthread_mutex_unlock@@GLIBC_2.2.5
                 U __pthread_register_cancel@@GLIBC_2.3.3
                 U __pthread_unregister_cancel@@GLIBC_2.3.3
                 w __pthread_unwind_next@@GLIBC_2.3.3
...
00000000000009b0 T publisher_free
0000000000202090 b publisher_g
0000000000000a00 T publisher_new
0000000000000b20 T publisher_publish
0000000000000a90 T publisher_subscribe
0000000000000ae0 T publisher_unsubscribe
0000000000000910 t register_tm_clones
                 U __sigsetjmp@@GLIBC_2.2.5
                 U __stack_chk_fail@@GLIBC_2.4
0000000000202078 d __TMC_END__

** T est une information publique **. Il existe un publisher_xxx correctement. En d'autres termes, il n'y a pas de problème si libpublisher.so.0.0.0 est prêt à être lié à l'exécution. pthread_mutex_init etc. est ** U **, mais comme il s'agit d'une fonction standard, elle est liée normalement.

À propos, il est inclus dans dputil_xxx et libpublisher.so dans la fonction locale ci-dessus, mais il s'agit en fait d'une fonction de bibliothèque statique.

$ nm .libs/libdputil.a

dp_util.o:
00000000000000b0 T dputil_list_pop
0000000000000070 T dputil_list_pull
0000000000000040 T dputil_list_push
0000000000000000 T dputil_lock
0000000000000020 T dputil_unlock
                 U _GLOBAL_OFFSET_TABLE_
                 U pthread_mutex_lock
                 U pthread_mutex_unlock

Le fait que ce ne soit pas ** U ** signifie également que libpublisher.so l'a pris en compte au moment de la compilation.

** commande objdump **

Vous pouvez également vider les informations détenues par le programme avec la commande ʻobjdump`. Puisque vous pouvez vérifier diverses informations autres que des liens, cela semble utile pour l'analyse si vous pouvez la maîtriser (= je pense que c'est proche de la lecture de l'assembleur)

objdump -t libpublisher.so.0.0.0

libpublisher.so.0.0.0:     file format elf64-x86-64

SYMBOL TABLE:
...
0000000000000ee0 l     F .text  0000000000000012              dputil_lock
...
0000000000000000       F *UND*  0000000000000000              free@@GLIBC_2.2.5
...
0000000000000ae0 g     F .text  0000000000000032              publisher_unsubscribe
...

Si ** g est joint comme ceci, information publique **, ** l est local **, ** UND n'est pas résolu **. Veuillez utiliser le sens travers pour la signification des mots détaillés.

** Comment limiter l'information publique (lien externe) **

** - Restrictions d'API par version-script **

Identique à l'article précédent. ** Spécifiez la fonction à publier dans XXX.map et ajoutez -Wl, --version-script, libtimelog.map aux options de construction **.

LDFLAGS+=-Wl,--version-script,libtimelog.map

libtimelog.map


{
  global:
    timetestlog_init;
    timetestlog_store_printf;
    timetestlog_exit;
  local: *;
};

C'est simple et facile à comprendre, mais il est difficile de créer un fichier de paramètres.

-fvisibility=hidden

Si vous spécifiez -fvisibility = hidden, toutes les fonctions sont d'abord rendues privées. Ensuite, ajoutez __attribute __ ((visibilité (" default "))) uniquement à ce dont vous avez besoin et publiez-le! C'est une technique appelée. C'est un moyen idéal pour ceux qui aiment contrôler avec des règles de codage.

Dans libpublisher.so utilisé lors de l'introduction de nm, -fvisibility = hidden spécifié, ʻint __attribute __ ((visibilité (" default "))) publisher_new (size_t contents_num)pour chaque fonction publique Je l'ai spécifié et construit comme ça.

En conséquence, je suis curieux que l'API de libdputil.a soit T, mais je peux le limiter à une sensation agréable.

nm -D .libs/libpublisher.so.0.0.0
0000000000202098 B __bss_start
                 U calloc
                 w __cxa_finalize
0000000000001210 T dputil_list_pop
00000000000011d0 T dputil_list_pull
00000000000011a0 T dputil_list_push
0000000000001160 T dputil_lock
0000000000001180 T dputil_unlock
0000000000202098 D _edata
00000000002020c0 B _end
0000000000001224 T _fini
                 U free
                 w __gmon_start__
0000000000000a00 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U pthread_mutex_init
                 U pthread_mutex_lock
                 U pthread_mutex_unlock
                 U __pthread_register_cancel
                 U __pthread_unregister_cancel
                 w __pthread_unwind_next
0000000000000c10 T publisher_free
0000000000000c80 T publisher_new
0000000000000da0 T publisher_publish
0000000000000d10 T publisher_subscribe
0000000000000d60 T publisher_unsubscribe
                 U __sigsetjmp
                 U __stack_chk_fail

** Mon gout **

Je préfère ** - version-script ** car je n'ai pas besoin d'être public / privé lors de l'écriture de code. C'est facile pour moi de les écrire tous ensemble en conf.

20/05/2018 postscript J'aime aussi le fait que cela puisse être automatisé avec un script. J'ai créé un exemple de script qui recherche le répertoire d'inclusion et crée un script de version. La réponse à la macro n'est pas bonne, mais je pense qu'elle peut être utilisée telle quelle.

#!/bin/sh

output_conf_map() {
        #{
        #  global:
        #    function_name;
        # ...
        #  local: *;
        #}

        #only get function list from header file
        HEADER_FUNC_LIST=`grep "[a-zA-Z](" -r $1 | grep -v "@brief" | grep -v "#define" | awk -F"(" '{print $1}' | awk -F " " '{print $NF}'`
        #template
        echo "{"
        echo "  global:"

        #show all function
        for data in $HEADER_FUNC_LIST
        do
                echo "    $data;"
        done

        #template end
        echo "  local: *;"
        echo "};"
}

INCLUDE_LIST=`find . -name include`
for inc_dir in $INCLUDE_LIST
do
        echo $inc_dir
        output_conf_map  $inc_dir
done

** Impression **

D'abord des excuses. La raison de la compilation de cet article est Article sur les restrictions de publication de la bibliothèque A été postée et commentée, une question et une réponse Zen telles que "Pourquoi existe-t-il différentes formes de moyens de restriction des API publiques pour les bibliothèques partagées? Qu'est-ce que public en premier lieu? Pourquoi les gens vivent-ils?" C'était le début. Par conséquent, dans un premier temps, j'ai voulu répondre à la question avec précision dans la langue de la zone de programme.

Cependant, il était impossible de parler de ce domaine sans creuser profondément, et comme la question et la réponse Zen ont vraiment commencé, j'ai pensé à nouveau: "Quelle était la bibliothèque que je voulais organiser?" Grâce à cela, je sens que la partie moelleuse a été effacée, qu'elle soit comprise ou non en tant que développeur middleware supérieur.

Après cela, j'ai beaucoup de mal à la bibliothèque, mais si je sais comment le vérifier, mon anxiété diminuera. Surtout autour d'OSS. ldd, nm super pratique

référence

Un site qui explique comment gérer la mémoire avec beaucoup de soin. Kane: "Oh, c'est celui auquel je suis accro si je creuse plus profondément" Lorsqu'on lui a demandé la taille du code|Des choses que tu ne peux pas dire à l'école| [Collection de colonnes techniques]Portail intégré|Uquest Co., Ltd.

Gestion des fonctions vues de l'assembleur Une histoire d'être facilement vaincu avant la technologie récente en essayant de montrer d'anciennes techniques | Possible Eria

Définition du lien externe https://msdn.microsoft.com/ja-jp/library/k8w8btzz.aspx

Comment limiter le partage de bibliothèque en C ++ Comment écrire une bibliothèque partagée au format C ++ (édition gcc) --Qiita

Comment lire nm Afficher la liste des symboles de l'objet avec la commande nm --Qiita

Nom de la bibliothèque [Bibliothèque - Connaissance de base des termes de communication](http://www.wdic.org/w/TECH/ Library)

Recommended Posts

Qu'est-ce qu'une bibliothèque en langage C? Quelles informations sont ouvertes au public?
[Introduction à Python] Qu'est-ce que Python, le langage de programmation le plus puissant actuellement?
[Introduction à Python] Quelle est la différence entre une liste et un taple?
Comment utiliser la bibliothèque C en Python
C'est un Mac. Qu'est-ce que la commande Linux Linux?
Comment afficher la date de modification d'un fichier en langage C jusqu'à nanosecondes
Comment utiliser une bibliothèque qui n'est pas initialement incluse dans Google App Engine
Qu'est-ce qu'une décision rationnelle qui maximise les chances de rencontrer une «maison idéale»?
[Introduction à Python] Quelle est la méthode d'installation recommandée du système de gestion de paquets pip?
Comment limiter la publication de l'API dans la bibliothèque partagée en langage C de Linux
Essayez de créer un module Python en langage C
Une introduction approximative à la bibliothèque de traduction automatique neuronale
Langage de programmation qui protège les gens de NHK
[Python] Une bibliothèque pratique qui convertit les kanji en hiragana
J'ai senti que j'avais porté le code Python en C ++ 98.
Qu'est-ce qu'un moteur de recommandation? Résumé des types
Pour moi en tant que débutant Django (2) - Qu'est-ce que MTV?
Qu'est-ce qu'une distribution?
Qu'est-ce qu'un terminal?
Qu'est-ce qu'un hacker?
Qu'est-ce qu'un pointeur?
La ventilation est importante. Ce que j'ai fait pour garder une trace de la concentration de C02 dans la pièce
Que faire lorsqu'un artefact manquant se produit dans un fichier jar qui n'est pas défini dans pom.xml
Quelle est la différence entre les liens symboliques et les liens durs?
Un mémorandum pour enregistrer la bibliothèque écrit en Hy dans PyPI
Générez un mot de passe facile à retenir avec apg
J'ai essayé d'illustrer le temps et le temps du langage C
Y a-t-il un biais dans les nombres qui apparaissent dans les nombres de Fibonacci?
[Langage C] Close () Il est dangereux de réessayer en cas d'échec
L'histoire de la définition de la clé privée à 600 avec chmod
[Pyro] Modélisation statistique par le langage de programmation probabiliste Pyro ① ~ Qu'est-ce que Pyro ~
Utilisez un langage de script pour une vie C ++ confortable-OpenCV-Port Python vers C ++ -
Transmettez les données OpenCV de la bibliothèque C ++ d'origine à Python
Y a-t-il un secret dans la fréquence des nombres de rapport de circonférence?
Que faire si vous chattez ou suivez un fichier binaire et que le terminal est brouillé
J'ai essayé de créer un site qui permet de voir facilement les informations mises à jour d'Azure
Hypothèse / Vérification (176) Comment créer un manuel plus simple que "Le manuel le plus simple pour les ordinateurs quantiques"
Que faire lorsqu'une partie de l'image d'arrière-plan devient transparente lorsque l'image transparente est combinée avec Oreiller
Une petite histoire addictive avec les permissions du répertoire spécifié par expdp (pour les débutants)
Comment tromper et utiliser une terrible bibliothèque qui est censée être conservée globalement dans flask
Utilisez un langage de script pour une vie C ++ confortable 5 - Utilisez l'environnement intégré de Spyder pour vérifier les données numériques -
Que faire si le nom d'utilisateur est modifié et que le chemin de la bibliothèque pyenv ne passe pas
Quelle est la fonction d'activation?
Qu'est-ce qu'un arbre de décision?
Qu'est-ce qu'un changement de contexte?
Qu'est-ce qu'un super utilisateur?
Qu'est-ce qu'un appel système
[Définition] Qu'est-ce qu'un cadre?
A quoi sert l'interface ...
Essayez de sélectionner une langue
Qu'est-ce qu'une fonction de rappel?
Qu'est-ce que la fonction de rappel?
L'image est Namekuji
La 2ème bibliothèque SmartHR kiji est utilisée pour exécuter e-Gov (matériel public e-Gov)
[AWS] Que faire lorsque la commande ping provoque un "délai d'expiration"
[Langage C] [Linux] Essayez de créer une simple commande Linux * Ajoutez simplement! !!