dlsym – obtenir le symbole ignoré

J’ai une application qui charge dynamicment les bibliothèques qui chargent dynamicment les bibliothèques qui …

Sous Windows, je peux parcourir tous les modules chargés à la recherche du symbole qui m’intéresse. Je ne sais pas comment le faire dans un environnement Unix / Linux. Je sais que je peux utiliser dlsym(dlopen(0, flag)) ou dlsym(RTLD_DEFAULT / RTLD_NEXT) pour les deux premiers symboles et connaître l’ordre des modules à rechercher – comment puis-je approfondir et obtenir toutes les définitions d’un symbole donné ?

Pour trouver un symbole dans un object fragment, ouvrez-le avec dlopen .

  void* foobar = dlopen ("/usr/local/lib/foobar.so", RTLD_NOW); void* mysymbol = dlsym (foobar, "mysymbol"); 

Mettre à jour Voici un programme qui itère sur tous les symboles nommés “foo”. Ce ne sont pas des librairies POSIX mais GNU. Je suis presque certain que POSIX ne fournit pas de telles fonctionnalités.

 #define _GNU_SOURCE #include  #include  #include  void doit (const char* s) { void* obj = dlopen (s, RTLD_LAZY); void* fcn = dlsym (obj, "foo"); if (fcn) printf ("Object %s has 'foo' at addr %p\n", *s ? s : "(exe)", fcn); } int cb (struct dl_phdr_info *info, size_t size, void *data) { doit (info->dlpi_name); return 0; } int main () { dl_iterate_phdr (cb, 0); return 0; } 

Voici la sortie:

 Object (exe) has 'foo' at addr 0xb76f8418 Object (exe) has 'foo' at addr 0xb76f8418 Object /tmp/libfoo.so has 'foo' at addr 0xb76f8418 Object /tmp/libfoo1.so has 'foo' at addr 0xb76f5418 Object /tmp/libfoo2.so has 'foo' at addr 0xb76f2418 

Il y a des doublons mais c’est un problème mineur.

Répondre à sa propre question pour faciliter la vie des personnes à la recherche de la solution. Il n’y a pas de manière unifiée, celui qui veut parcourir les modules chargés devrait rechercher les commandes / types de données suivants (les experts sont invités à commenter):

Les fenêtres:
MODULEENTRY32, CreateToolhelp32Snapshot, Module32First, Module32Suivant

Linux:
comme décrit dans la réponse de nm, retourne non nul à partir du rappel lorsque le module approprié a été trouvé (termine la boucle).

AIX:
loadquery (L_GETINFO, buffer, size), struct ld_info.

HP-UX:
dlget, dlgetname (si vous avez besoin du chemin du module).

Solaris:
ldinfo, Link_map.

De plus, je vous recommande de libérer les modules et d’obtenir le symbole d’un nouveau handle pour que le compte de référence de la bibliothèque soit incrémenté, ce qui l’empêche d’être déchargé. Au moins sous AIX, la bibliothèque peut être chargée et initialisée à nouveau, mais dans la plupart des cas, il est préférable de tenter d’appeler une fonction à partir de la bibliothèque déchargée.