Syntaxe de plage d’adresses et d’adresses
Il existe plusieurs façons de spécifier des adresses dans le débogueur.
Les adresses sont normalement des adresses virtuelles, sauf si la documentation indique spécifiquement un autre type d’adresse. En mode utilisateur, le débogueur interprète les adresses virtuelles en fonction du répertoire de page du processus actuel. En mode noyau, le débogueur interprète les adresses virtuelles en fonction du répertoire de page du processus spécifié par le contexte du processus. Vous pouvez également définir directement le contexte d’adresse en mode utilisateur. Pour plus d’informations sur le contexte d’adresse en mode utilisateur, consultez .context (Définir le contexte d’adresse en mode utilisateur).
Dans les expressions MASM, vous pouvez utiliser l’opérateur poi pour déréférencer n’importe quel pointeur. Par exemple, si le pointeur à l’adresse 0x0000008e’ed57b108 pointe vers l’emplacement d’adresse 0x805287637256, les deux commandes suivantes sont équivalentes.
0:000> dd 805287637256
0:000> dd poi(000000bb`7ee23108)
Exemple d’adresse mémoire d’affichage
Pour voir un exemple d’utilisation de poi, déterminez le décalage pour CurrentLocale du bloc d’environnement de thread (TEB). Utilisez la commande dx pour afficher @$teb, qui est un exemple de pseudo-registres, qui contiennent des adresses courantes, telles que l’emplacement du compteur de programme actuel.
0:000> dx @$teb
@$teb : 0x1483181000 [Type: _TEB *]
...
[+0x108] CurrentLocale : 0x409 [Type: unsigned long]
CurrentLocale est +0x108 à partir du début de l’TEB. Ensuite, déterminez l’adresse mémoire de cet emplacement.
0:000> ? @$teb + 0x108
Evaluate expression: 613867303176 = 0000008e`ed57b108
Utilisez poi pour déréférencer cette adresse pour voir qu’elle contient la valeur CurrentLocale de 0x409.
0:000> ? poi(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409
Dans les expressions du débogueur C++, les pointeurs se comportent comme des pointeurs en C++. Toutefois, les nombres sont interprétés comme des entiers. Si vous devez déduire un nombre réel, vous devrez peut-être le caster en premier, comme l’illustre l’exemple suivant.
Pour essayer cela, utilisez .expr pour définir l’évaluateur d’expression sur C++.
0:000> .expr /s C++
Current expression evaluator: C++ - C++ source expressions
Avec l’évaluateur d’expression défini sur C++, nous pouvons effectuer un cast à l’aide de longs.
0:000> d *((long*)0x00000014`83181108 )
00000000`00000409 ???????? ???????? ???????? ????????
Pour plus d’informations sur la conversion de valeurs numériques, consultez Nombres et opérateurs C++.
Si l’évaluateur d’expression est défini sur c++, nous pouvons encapsuler le pointeur poi avec @@masm(), pour avoir uniquement cette partie de l’expression évaluée par l’évaluateur d’expression MASM.
0:000> .expr /s c++
Current expression evaluator: C++ - C++ source expressions
0:000> ? @@masm(poi(00000078`267d7108))
Evaluate expression: 1033 = 00000000`00000409
Pour plus d’informations sur les deux évaluateurs d’expression, consultez Évaluation des expressions.
Vous pouvez également indiquer une adresse dans une application en spécifiant le nom du fichier source d’origine et le numéro de ligne. Pour plus d’informations sur la façon de spécifier ces informations, consultez La syntaxe de ligne source.
Plages d’adresses
Vous pouvez spécifier une plage d’adresses par paire d’adresses ou par une adresse et un nombre d’objets.
Pour spécifier une plage par une paire d’adresses, spécifiez l’adresse de départ et l’adresse de fin. Par exemple, l’exemple suivant est une plage de 8 octets, commençant à l’adresse 0x00001000.
0x00001000 0x00001007
Pour spécifier une plage d’adresses par adresse et nombre d’objets, spécifiez un argument d’adresse, la lettre L (majuscules ou minuscules) et un argument valeur. L’adresse spécifie l’adresse de départ. La valeur spécifie le nombre d’objets à examiner ou à afficher. La taille de l’objet dépend de la commande. Par exemple, si la taille de l’objet est de 1 octet, l’exemple suivant est une plage de 8 octets, commençant à l’adresse 0x00001000.
0x00001000 L8
Toutefois, si la taille de l’objet est un double mot (32 bits ou 4 octets), les deux plages suivantes donnent chacune une plage de 8 octets.
0x00001000 0x00001007
0x00001000 L2
Spécificateur de plage de tailles L
Il existe deux autres façons de spécifier la valeur (spécificateur de plage de tailles L) :
L ? La taille (avec un point d’interrogation) signifie la même chose que la taille L, sauf que L ? La taille supprime la limite de plage automatique du débogueur. En règle générale, il existe une limite de plage de 256 Mo, car les plages plus grandes sont des erreurs typographiques. Si vous souhaitez spécifier une plage supérieure à 256 Mo, vous devez utiliser le L ? Syntaxe de taille .
L- Taille (avec un trait d’union) spécifie une plage de longueur taille qui se termine à l’adresse donnée. Par exemple, 80000000 L20 spécifie la plage comprise entre 0x80000000 et 0x8000001F, et 80000000 L-20 spécifie la plage comprise entre 0x7FFFFFE0 et 0x7FFFFFFF.
Certaines commandes qui demandent des plages d’adresses acceptent une adresse unique comme argument. Dans ce cas, la commande utilise un nombre d’objets par défaut pour calculer la taille de la plage. En règle générale, les commandes pour lesquelles la plage d’adresses est le paramètre final autorisent cette syntaxe. Pour connaître la syntaxe exacte et la taille de plage par défaut pour chaque commande, consultez les rubriques de référence pour chaque commande.
Exemple de plage de mémoire de recherche
Tout d’abord, nous allons déterminer l’adresse du registre du pointeur d’instruction d’extraction à l’aide de l’évaluateur d’expression MASM.
0:000> ? @rip
Evaluate expression: 140720561719153 = 00007ffc`0f180771
Ensuite, nous allons rechercher à partir de 00007ffc'0f180771, pour 100000 à l’aide de la commande s (Rechercher la mémoire). Nous spécifions la plage à rechercher à l’aide de L100000.
0:000> s -a 00007ffc`0f180771 L100000 "ntdll"
00007ffc`0f1d48fa 6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00 ntdll\ldrinit.c.
00007ffc`0f1d49c2 6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00 ntdll\ldrmap.c..
00007ffc`0f1d4ab2 6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63 ntdll\ldrredirec
00007ffc`0f1d4ad2 6e 74 64 6c 6c 5c 6c 64-72 73 6e 61 70 2e 63 00 ntdll\ldrsnap.c.
...
Nous pouvons également spécifier la même plage que celle-ci à l’aide de deux adresses mémoire.
0:000> s -a 0x00007ffc`0f180771 0x00007ffc`0f280771 "ntdll"
00007ffc`0f1d48fa 6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00 ntdll\ldrinit.c.
00007ffc`0f1d49c2 6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00 ntdll\ldrmap.c..
00007ffc`0f1d4ab2 6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63 ntdll\ldrredirec
00007ffc`0f1d4ad2 6e 74 64 6c 6c 5c 6c 64-72 73 6e 61 70 2e 63 00 ntdll\ldrsnap.c.
...
Enfin, nous pouvons effectuer une recherche vers l’arrière dans la plage de mémoire à l’aide du paramètre de longueur L.
0:000> s -a 00007ffc`0f1d4ad2 L-100000 "ntdll"
00007ffc`0f1d48fa 6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00 ntdll\ldrinit.c.
00007ffc`0f1d49c2 6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00 ntdll\ldrmap.c..
00007ffc`0f1d4ab2 6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63 ntdll\ldrredirec
Exemple de mémoire unassemble
Cet exemple utilise la commande u (unassemble) et le paramètre L pour désassembler trois octets de code.
0:000> u 00007ffc`0f1d48fa L3
ntdll!`string'+0xa:
00007ffc`0f1d48fa 6e outs dx,byte ptr [rsi]
00007ffc`0f1d48fb 7464 je ntdll!`string'+0x21 (00007ffc`0f1d4961)
00007ffc`0f1d48fd 6c ins byte ptr [rdi],dx
Vous pouvez également spécifier une plage de mémoire de trois octets pour annuler l’assemblage comme suit.
0:000> u 00007ffc`0f1d48fa 00007ffc`0f1d48fd
ntdll!`string'+0xa:
00007ffc`0f1d48fa 6e outs dx,byte ptr [rsi]
00007ffc`0f1d48fb 7464 je ntdll!`string'+0x21 (00007ffc`0f1d4961)
00007ffc`0f1d48fd 6c ins byte ptr [rdi],dx
Modes d’adressage et prise en charge des segments
Sur les plateformes x86, CDB et KD prennent en charge les modes d’adressage suivants. Ces modes sont distingués par leurs préfixes.
Préfixe | Nom | Types d’adresse |
---|---|---|
% | flat | Adresses 32 bits (également des sélecteurs 16 bits qui pointent vers des segments 32 bits) et des adresses 64 bits sur des systèmes 64 bits. |
& | virtual 86 | Adresses en mode réel. x86 uniquement. |
# | plain | Adresses en mode réel. x86 uniquement. |
La différence entre les modes 86 bruts et virtuels est qu’une adresse 16 bits simple utilise la valeur de segment comme sélecteur et recherche le descripteur de segment. Mais une adresse virtuelle 86 n’utilise pas de sélecteurs et est mappée directement dans les 1 Mo inférieurs.
Si vous accédez à la mémoire via un mode d’adressage qui n’est pas le mode par défaut actuel, vous pouvez utiliser les préfixes du mode d’adresse pour remplacer le mode d’adresse actuel.
Arguments d’adresse
Les arguments d’adresse spécifient l’emplacement des variables et des fonctions. Le tableau suivant explique la syntaxe et la signification des différentes adresses que vous pouvez utiliser dans CDB et KD.
Syntaxe | Signification |
---|---|
offset |
Adresse absolue dans l’espace mémoire virtuelle, avec un type qui correspond au mode d’exécution actuel. Par exemple, si le mode d’exécution actuel est 16 bits, le décalage est de 16 bits. Si le mode d’exécution est segmenté 32 bits, le décalage est segmenté 32 bits. |
&[[ segment :]] offset |
L’adresse réelle. x86 et x64. |
%segment :[[ offset]] |
Adresse 32 bits ou 64 bits segmentée. x86 et x64. |
%[[ offset]] |
Adresse absolue (32 bits ou 64 bits) dans l’espace mémoire virtuelle. x86 et x64. |
name[[ +|− ]] offset |
Adresse 32 bits ou 64 bits plate. nom peut être n’importe quel symbole. offset spécifie le décalage. Ce décalage peut être le mode d’adresse indiqué par son préfixe. Aucun préfixe ne spécifie une adresse de mode par défaut. Vous pouvez spécifier le décalage en tant que valeur positive (+) ou négative (−). |
Utilisez la commande dg (Sélecteur d’affichage) pour afficher les informations de descripteur de segment.
Voir aussi
Pour afficher des informations sur la mémoire, utilisez la commande !address .
Pour rechercher de la mémoire, utilisez la commande s (Rechercher la mémoire).
Pour afficher le contenu de la mémoire, utilisez la commande d, da, db, dc, dd, dD, df, dp, dq, du, dw (Display Memory).
Pour plus d’informations sur la façon dont vous pouvez afficher et modifier la mémoire à l’aide d’une fenêtre Mémoire, consultez Utilisation d’une fenêtre mémoire.