IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Discussion :

DLL, prefered base address, rebasing et autres joyeuseries


Sujet :

Windows

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    413
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 413
    Par défaut DLL, prefered base address, rebasing et autres joyeuseries
    Bonjour à tous,

    Je viens de découvrir avec étonnement qu'il fallait définir autant que possible la "prefered base address" des DLLs que l'on va mapper de façon à ce que le loader n'ait pas à les "rebaser".
    Ceci afin d'éviter de devoir modifier toutes les adresses absolues existantes mais également pour garder la possibilité que le code de la DLL soit partagé entre plusieurs process.
    (source ICI et ICI)

    Sous réserve d'avoir mal compris, j'ai deux questions qui me viennent à l'esprit :
    1) Est-ce correct ce que j'ai résumé plus haut? Parce qu'avec le nombre actuel de DLLs, il devient assez complexe d'estimer un endroit "libre" en mémoire, sans compter la taille que font chaque dll une fois mappées en mémoire.
    2) S'il y a rebasing car l'adresse "préférée" n'est pas disponible lors du mapping, comment le loader peut-il modifier chaque adresse absolue qui se trouve dans le code? Ca me semble presque impossible.

    Merci d'avance,
    Nicolas

  2. #2
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Par défaut
    Tiens, bonne question !

    Pour ma part, je pense avoir compris ça comme toi.

    1/ ça je sais pas...

    2/ Si, il n'y a pas de raison que ce soit impossible. Par exemple, on prefere l'adresse A, mais on est chargé à l'adresse B. Il y a donc un ecart de B-A octet entre les deux adresses.

    Ben au chargement du code de la DLL, il suffit d'ajouter B-A à toutes les adresses mémoires. Sur du code ASM ça me parait un poil complexe mais pas impossible du tout, et il me semble que les DLL intègrent des informations symboliques (nom des fonctions, signatures, types de retours...)

    Il suffirait donc, au moment de compiler la DLL, de remplacer l'adresse de base par un symbole. Toutes les adresses sont exprimées en offset par rapport à ce symbole (un peu comme pour du code Position-Independant-Code) et au moment de la charger en mémoire, emplacer ce symbole par l'adresse de chargement.

    N'empeche que tout ça attise ma curiosté, alors si quelqu'un a des infos...

  3. #3
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Par défaut
    Ah, en lisant un peu mieux tes liens, il y a ceci :

    http://www.ddj.com/showArticle.jhtml...dj0012b&pgno=8

    Il preconise de choisir l'adresse de départ d'une DLL en fonction de la premiere lettre de son nom (dans une plage mémoire qu'il a d'abord soigneusement identifiée comme étant la plage mémoire de chargement des DLL).

    Ca ne me parait pas complement idiot, le but étant de répartir au mieux les DLL en mémoire.

    Mais bon, comme le dit l'auteur,
    "Base address conflicts are not the only cause of slow DLL load times, or even the most important one."
    Donc bon, je ne suis pas sûr que ça vaille le coup de s'embeter avec ça.

    Surtout que :
    - pour que la repartition en fonction du nom fonctionne bien, il faut que toutes les DLLs jouent le jeu
    - la probabilité d'avoir une DLL qui commence par "a" n'est surement pas la meme que de commencer par "w" il faudrait donc des tailles de plage pour chaque lettre adaptées à la probabilité
    - un algo bien foutu dans une DLL bien foutu remplacera toutes les bonnes adresses du monde (sauf les bonnes adresses de bistrots)

    Enfin, à mon avis !

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    413
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 413
    Par défaut
    Salut buzzkaido,

    Un petit exemple où la "relocation" des adresses par le loader ne peut pas fonctionner : un contrôle CRC sur la partie de code de la DLL, par exemple pour une protection anti-crack ou anti-virale (on peut remettre en doute l'utilité d'une telle méthode mais soit, elle n'est pas impossible) : un simple changement des adresses absolues hardcodées dans la partie code ferait échouer ce test CRC, et je doute que le loader modifie la valeur de ce CRC .

    Autre situation :
    Imaginons que le loader de Windows analyse entièrement le code de chaque DLL qui doit être "relocatée". En terme de perfs, je n'ose même pas imaginer ce que ça peut donner : "revenez dans une heure les gars, je suis en train d'analyser le code de toutes vos DLLs". Mais soit "imaginons"
    Imaginons qu'un codeur en assembleur ait pondu un code comme ça :
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    mov eax, 0400000h
    lea eax, DWORD PTR [eax * 3]
    (Désolé pour la syntaxe, l'asm ça date un peu pour moi)
    Non pas qu'il veuille récupérer une adresse mais simplement multiplier eax par 3 sans utiliser l'instruction mul.
    Ca semble quand même être un loader vachement bien pensé s'il arrive à comprendre que cette instruction ne fait pas référence à une adresse mémoire mais est simplement un calcul.


    Et on pourrait encore trouver une quirielle d'autres exemples, peut-être mieux choisis qui tendent à prouver que le loader ne modifie certainement pas les adresses absolues dans le code.


    A mon sens, pour qu'une DLL (ou même un exécutable) soit "relocatable", il faut que le compilateur l'ait permis, et que tous les sauts, appel de fonctions, références de variables, soient calculés en fonction de la "base address" réelle. Mais ça me semble aussi un énorme travail...


    Citation Envoyé par buzzkaido
    Ah, en lisant un peu mieux tes liens, il y a ceci :

    http://www.ddj.com/showArticle.jhtml...dj0012b&pgno=8

    Il preconise de choisir l'adresse de départ d'une DLL en fonction de la premiere lettre de son nom (dans une plage mémoire qu'il a d'abord soigneusement identifiée comme étant la plage mémoire de chargement des DLL).

    Ca ne me parait pas complement idiot, le but étant de répartir au mieux les DLL en mémoire.

    Mais bon, comme le dit l'auteur,

    Donc bon, je ne suis pas sûr que ça vaille le coup de s'embeter avec ça.

    Surtout que :
    - pour que la repartition en fonction du nom fonctionne bien, il faut que toutes les DLLs jouent le jeu
    - la probabilité d'avoir une DLL qui commence par "a" n'est surement pas la meme que de commencer par "w" il faudrait donc des tailles de plage pour chaque lettre adaptées à la probabilité
    - un algo bien foutu dans une DLL bien foutu remplacera toutes les bonnes adresses du monde (sauf les bonnes adresses de bistrots)

    Enfin, à mon avis !
    Je suis d'accord, il n'est sans doute pas vraiment important d'en prendre compte lorsque l'on code. Mais j'aimerai quand même comprendre comment cette relocation est possible...

  5. #5
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Par défaut
    Effectivement, bien vu pour les exemple en asm....

    A mon sens, pour qu'une DLL (ou même un exécutable) soit "relocatable", il faut que le compilateur l'ait permis, et que tous les sauts, appel de fonctions, références de variables, soient calculés en fonction de la "base address" réelle. Mais ça me semble aussi un énorme travail...
    Non, pas sûr du tout, il existe pour les instruction de saut (jmp, jea...) la possibilité de donner une adresse "relative" à la position courante.

    Donc pour le compilateur, ça ne complique un peu les choses, mais c'est pas impossible.

    Comme expliqué dans tes liens, un code en adresse relative est un peu plus lent, meme si sur les processeurs d'aujourd'hui, je ne pense pas que ça change grand chose...

    Par contre, l'article precise que les DLL windows ne fonctionnenent pas sur ce principe, mais avec une adresse de base. C'est pour ça qu'à mon avis il s'agit d'un symbole remplacé par sa valeur au moment du chargement.

    Par contre, pour le coup des anti-virus, je sais pas trop comment il se debrouillent...

    Tout ça n'étant que des suppositions, si quelqu'un a des infos, je suis preneur !

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    413
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 413
    Par défaut
    Non, pas sûr du tout, il existe pour les instruction de saut (jmp, jea...) la possibilité de donner une adresse "relative" à la position courante.
    Si je me souviens bien, cela dépend de la taille du saut : un saut de plus de 127 bytes sera automatiquement un saut long, donc avec une adresse absolue.
    127 bytes, c'est tout de même assez court que pour n'utiliser que des sauts de ce type.

    Par contre, l'article precise que les DLL windows ne fonctionnenent pas sur ce principe, mais avec une adresse de base. C'est pour ça qu'à mon avis il s'agit d'un symbole remplacé par sa valeur au moment du chargement.
    Pour avoir désassemblé une DLL écrite en C++ hier, je peux te dire que l'adresse est bien hardcodée dans le code asm et quelle dépend de la "prefered address base".
    Prenons comme exemple une DLL avec une pab à 0x10000000, une section data qui commence à 3000. Tu verras dans le code, lorsque tu fais références à des variables, des adresses hardcodées comme 0x10003004, 0x1000300F, ...
    Et pour peu que tu changes à la main la pab dans le header du fichier, ça plante royalement dès que le code commence à utiliser des adresses (logique vu que les adresses sont hardcodées et que la zone mémoire sur laquelle elles pointent n'est pas initialisée ou ne contient pas les bonnes valeurs)...

    Enfin bref, il faut attendre de plus amples informations

  7. #7
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Par défaut
    Si je me souviens bien, cela dépend de la taille du saut : un saut de plus de 127 bytes sera automatiquement un saut long, donc avec une adresse absolue.
    Oui, sur un 386...

    Depuis j'ai un peu laissé tombé l'assembleur, et je sais pas trop pour les nouveaux processeurs, mais ça m'étonnerait que ce soit le cas. Cette limitation était principalement dû au fait que les instructions devaient tenir sur 16 bit, donc 8 bit pour l'instruction de saut + 8 bits pour l'adresse, en signé car relatif.

    Depuis, on a des proc 64 bits...

    Par contre, le fait que l'adresse de base soit hardcodée m'étonnes... du coup, effectivement, la relocation c'est un truc bien balèze !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. La base addresse du Kernel32.dll avec un code inconnu !
    Par The Hidden Ghost dans le forum x86 32-bits / 64-bits
    Réponses: 5
    Dernier message: 13/07/2014, 00h15
  2. [SGBD] Copie d'une base mysql à une autre
    Par nicoaix dans le forum Outils
    Réponses: 1
    Dernier message: 23/06/2006, 17h57
  3. [VB6] création dll win32 et appel par un autre programme
    Par Tankian85 dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 10/03/2006, 08h21
  4. Réponses: 17
    Dernier message: 13/02/2006, 14h43
  5. Réponses: 1
    Dernier message: 17/12/2005, 00h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo