10
votes

Pourquoi le linker modifie-t-il une "adresse absolue" a --defsym

Objectif: une bibliothèque partagée à utiliser une fonction d'un exécutable (qui n'exporte pas de symboles).

signifie: gcc -wl, - défensym, fonction = 0x432238

La page de l'homme indique que: xxx

à ma consternation, dlopen () est ajouté 0x7ffff676f000 , le L'adresse de base de la bibliothèque partagée (ceci est du code 64 bits) à l'adresse exportée "Adresse de symboles absolue": xxx

objdump montre l'adresse de symbole correcte ( 0x432238 ) Dans la bibliothèque, mais une fois chargé avec dlopen () , le symbole a l'adresse 0x7ffff6ba1238

Si, une fois chargé, je corrigai manuellement le Symbole de la bibliothèque à l'adresse correcte puis tous fonctionne bien (sinon, la bibliothèque Segfault).

  • pourquoi l'adresse "absolue" est modifiée?
  • Comment l'éviter?

    mise à jour:

    Je contestez la pertinence technique de la réponse ci-dessous, et encore plus sa "mise à jour": < / p>

    ayant --defsym pour définir un symbole déployé dans une bibliothèque de photos / exécutable est inutile (il ne sert à aucun but autre que de polluer le binaire sans aucune fonctionnalité utilisable).

    Par conséquent, La seule utilisation pertinente de --defsym dans une bibliothèque partagée PIC partagée ou une exécutable PIC devrait être de définir un ( non relocalisé ) "adresse absolue".

    Incidemment, c'est le fonctionnaire But de --defsym Si vous vous souciez de lire la page d'homme:

    "Créez un symbole global dans le fichier de sortie, contenant l'adresse absolue donnée par expression."

    Au mieux, il s'agit d'un lieur Linux Deffect qui serait trivial à réparer. Et pour ceux qui ne peuvent pas attendre que les personnes-in-déniaires se rendent compte (et corrigez) leur erreur, la solution consiste à corriger la table de relocalisation une fois que l'image binaire a été chargée par la liaison défectueuse.

    Ensuite, --Defsym devient utile dans les bibliothèques / exécutables de pic, ce qui me semble être une progression bienvenue.


3 commentaires

- Defsym est très utile tel que mis en œuvre et vos revendications selon lesquelles le comportement actuel est inutile ou qu'un bogue est difficile à comprendre. Par exemple, dans Intel SGX A - DEFSYM __IMAGEBASE = 0 est utilisé de sorte que le code exécuté dans une enclave puisse trouver l'adresse à laquelle une enclave est chargée. Cela permet de prendre des stacktraces, calculez décalée de __ imagebase et symbolisant en dehors de l'enclave. Ceci est juste un exemple. Changer le comportement Comme vous le suggérez "Patch La table de relocalisation une fois que l'image binaire a été chargée" enfreindrait d'innombrables projets.


télécharger.01.org/intel-sgx/linux- 2.2 / Docs / ...


@Chris Beck, je suis émerveillé par la "conformité stérile" soumise des réponses et le manque de leur capacité à répondre à la question technique pour apporter une solution. De plus, je suis abasourdi de voir que personne ne semble se rendre compte de la manière dont le comportement actuel (dysfonctionnel) a été choisi à dessein de générer des problèmes de sécurité sans fin.


3 Réponses :


9
votes

Vous semblez avoir fondamentalement mal compris ce que - defsym code> ne

// code in library
int fn()
{
    // exe_fn not exported from the executable, but we know where it is.
    int (*exe_fn)(void) = (int (*)(void)) 0x432238;
    return (*exe_fn)();
}


7 commentaires

Merci pour la réponse, mais cela ne résout pas mon problème car une définition ne sera pas définie comme un symbole dans la bibliothèque partagée. Comment créer réellement un symbole que GDB sera en mesure de répertorier?


Je sais comment faire des hacks laids qui fonctionneront, mais y a-t-il un moyen «propre» de le faire? C'était ma question.


En ce qui concerne la page «homme», ce que le «contenant l'adresse absolue donnée par expression» signifie?


"Définir ne sera pas défini comme un symbole dans la bibliothèque partagée". Vous NE PAS voulez un symbole défini dans la bibliothèque partagée. Vous en voulez un dans l'exécutable. Puisque vous ne pouvez pas (ou ne voulez pas) reconstruire l'exécutable afin qu'il exporte le symbole, vous êtes alors laissé avec des hacks.


Je fais vraiment un symbole dans la bibliothèque partagée, et il existe différentes façons de faire de ce travail comme prévu, allant des wrappers simples pour corriger ce que le manuel de la liaison insiste pour appeler une "adresse absolue" avant de relocaliser ce. Merci quand même pour votre réponse, ce qui pourrait aider les autres.


"Je veux vraiment un symbole dans la bibliothèque partagée". Non, tu ne le fais pas. Votre question pose "... Utilisez une fonction d'un exécutable". Vous décidez-vous: si le code de fonction est dans l'exécutable principal, il est pas (et ne doit pas être défini) dans la bibliothèque partagée.


Ignorer catégoriquement Mes contraintes exprimées ne vous donnera aucun point. J'ai dit que je voulais un symbole dans la bibliothèque de débogage / de traçage, car l'exécutable n'exportera aucun symbole. Aussi, laissez-moi juger de ce que je veux ou non. Je préférerais apprécier de vous voir répondre à mes questions (laissé sans adresse).



2
votes

Ajout d'un contrepoint: Oui, il y a une utilisation réelle à cela, mais je pense que c'est bien cassé, non seulement avec des bibliothèques dynamiques, mais également avec des exécutables indépendants de la position.

ld utilisera des symboles Lorsqu'il est utilisé pour incorporer des fichiers binaires dans des exécutables:

ld -r -b binaire binaire hello_world.txt -o hello_world.o

Ceci produira un fichier d'objet Avec, entre autres, les symboles suivants: xxx

de sorte qu'un exécutable qui puisse s'agisse d'utiliser des variables extern pour y accéder. (... comme dans: Notre texte "Hello World" de Hello_World.txt est la seule chose dans la section .Data , avec longueur 0xc ).

lier ce fichier d'objet dans un fichier exécutable (et non des symboles de dénudage) entraîne xxx

et nous pouvons faire des choses comme xxx

(Oui, il a l'air assez étrange que nous recherchons une adresse de quelque chose (quels symboles sont habituellement utilisés pour), puis nous le traitons comme un entier ... mais cela fonctionne réellement.) < / p>

Notez également comment la liaison sait ce qu'elle devrait déménager et ce qu'elle ne devrait pas; Les pointeurs de données sont par rapport à .data , tandis que la taille est * ABS * , qui, car gil décrit, n'est pas censé être déplacé (... puisque ce n'est pas 't calculé relativement à quoi que ce soit).

Cependant, cela ne fonctionne que dans des exécutables indépendants non de position . Une fois que vous allez de -fpie (qui est par défaut de GCC récemment dans des distributions de Linux modernes, comme il ressemble à) à -NO-Pie , la liaison dynamique déménage tout, y compris < Code> * ABS * symboles. Cela se passe à l'heure d'exécution de la liaison: les tables de symboles ressemblent à la même chose, peu importe la manière dont l'exécutable a été compilé.

Le fait que la même chose arrive pour les bibliothèques partagées semble être une conséquence de la même chose: La délocalisation des binaires placés dynamiquement (une bibliothèque exécutable indépendante de la position ou une bibliothèque partagée) entraîne des relocations similaires, ce qui a du sens pour les fonctions incluses dans le binaire lui-même, mais pas pour * ABS * .

Malheureusement, je n'ai pas de réponse à l'une des questions: je pense aussi que cela n'a pas mal fait, et je ne sais pas comment le réparer (voir Obtenir la valeur des symboles * ABS * de C pour un autre problème Concentant dans le même problème).

Cependant, étant donné comment même GNU LD hélicit d'intégrer une taille comme un symbole de cette façon ... Je pense que cette application / question est entièrement valide, de manière à répondre à la réponse:

  • ... c'est fait parce que la mise en œuvre n'est pas réellement correcte
  • en tant que solution de contournement ", générer un fichier d'en-tête avec des adresses absolues en ligne" vous vient à l'esprit, après la réponse de Russe employée

    ... Mais je serais réellement intéressé par la manière de corriger la table de relocalisation de la manière dont Gil mentionné dans la question!


0 commentaires

1
votes

Le comportement de --defsym a changé entre GCC 5.4.0 (en utilisant Ubuntu 16.04.4) et 7.3.0 (Ubuntu 18.04). Aux 5,40, --Defsym a créé un symbole représentant une adresse absolue et non relocatable. À 7.3.0, Lookelf -s montre le symbole comme "ABS", mais le symbole est en fait déplacé lorsque le programme exécute. (Cela a également causé des problèmes pour ma demande.)

Une adresse absolue peut représenter quelque chose comme un registre de périphérique mappé de mémoire ou un vecteur d'interruption, quelque chose qui reste au même endroit, quel que soit l'endroit où l'application est chargée. Le comportement plus ancien est correct - les adresses absolues ne doivent pas être déplacées. Si la relocalisation se produit lorsque l'image exécutable est chargée en mémoire, elle pourrait ne pas être un problème de GCC, mais c'est un problème.


0 commentaires