Symboles publics et privés
Lorsqu’un fichier de symboles .pdb ou .dbg de taille réelle est créé par un éditeur de liens, il contient deux collections distinctes d’informations : les données de symboles privés et une table de symboles publics. Ces collections diffèrent par la liste des éléments qu’elles contiennent et les informations qu’elles stockent sur chaque élément.
Les données de symbole privé incluent les éléments suivants :
Fonctions
Variables globales
Variables locales
Informations sur les structures, classes et types de données définis par l’utilisateur
Nom du fichier source et numéro de ligne dans ce fichier correspondant à chaque instruction binaire
La table de symboles publics contient moins d’éléments :
Fonctions (à l’exception des fonctions déclarées statiques)
Variables globales spécifiées en tant qu’extern (et toutes les autres variables globales visibles dans plusieurs fichiers objet)
En règle générale, la table de symboles publics contient exactement les éléments accessibles d’un fichier source à un autre. Les éléments visibles dans un seul fichier objet, tels que les fonctions statiques , les variables globales uniquement dans un seul fichier source et les variables locales, ne sont pas inclus dans la table de symboles publics.
Ces deux collections de données diffèrent également par les informations qu’elles incluent pour chaque élément. Les informations suivantes sont généralement incluses pour chaque élément contenu dans les données de symboles privés :
Nom de l’élément
Adresse de l’élément dans la mémoire virtuelle
Type de données de chaque variable, structure et fonction
Types et noms des paramètres de chaque fonction
Étendue de chaque variable locale
Symboles associés à chaque ligne de chaque fichier source
Enregistrements d’omission de pointeur de trame (FPO) pour chaque fonction utilisée pour accéder à la pile
D’autre part, la table de symboles publics stocke uniquement les informations suivantes sur chaque élément qu’elle contient :
Nom de l'élément.
Adresse de l’élément dans l’espace de mémoire virtuel de son module. Pour une fonction, il s’agit de l’adresse de son point d’entrée.
Enregistrements d’omission de pointeur de trame (FPO) pour chaque fonction.
Peut inclure des préfixes/suffixes de symbole appelés décorations.
Les données de symboles publics peuvent être considérées comme un sous-ensemble des données de symboles privés de deux manières : elles contiennent une liste plus courte d’éléments et elles contiennent également moins d’informations sur chaque élément. Par exemple, les données de symbole public n’incluent pas du tout les variables locales.
Chaque variable locale est incluse uniquement dans les données de symbole privé, avec son adresse, son type de données et son étendue. Les fonctions, en revanche, sont incluses à la fois dans les données de symboles privés et dans la table de symboles publics, mais alors que les données de symboles privés incluent le nom de la fonction, l’adresse, les enregistrements FPO, les noms et types de paramètres d’entrée et le type de sortie, la table de symboles publics inclut uniquement le nom de la fonction, l’adresse et l’enregistrement FPO.
Il existe une autre différence entre les données de symboles privés et la table de symboles publics. La plupart des éléments de la table de symboles publics ont des noms décorés d’un préfixe, d’un suffixe ou des deux. Ces décorations sont ajoutées par le compilateur C, le compilateur C++ et l’assembleur MASM. Les préfixes classiques incluent une série de traits de soulignement ou la chaîne __imp_ (désignant une fonction importée). Les suffixes classiques incluent un ou plusieurs signes ( @ ) suivis d’adresses ou d’autres chaînes d’identification. Ces décorations sont utilisées par l’éditeur de liens pour lever l’ambiguïté du symbole, car il est possible que des noms de fonction ou des noms de variables globales puissent être répétés dans différents modules. Ces décorations constituent une exception à la règle générale selon laquelle la table de symboles publics est un sous-ensemble des données de symboles privés.
Fichiers de symboles complets et fichiers de symboles supprimés
Un fichier de symboles complet contient à la fois les données de symboles privés et la table de symboles publics. Ce type de fichier est parfois appelé fichier de symboles privé, mais ce nom est trompeur, car un tel fichier contient des symboles privés et publics.
Un fichier de symboles supprimé est un fichier plus petit qui contient uniquement la table de symboles publics ou, dans certains cas, uniquement un sous-ensemble de la table de symboles publics. Ce fichier est parfois appelé fichier de symboles publics.
Création de fichiers de symboles complets et supprimés
Si vous générez vos fichiers binaires avec Visual Studio, vous pouvez créer des fichiers de symboles complets ou supprimés. Pour plus d’informations sur la création de symboles supprimés, consultez /PDBSTRIPPED (Symboles privés de bande) .
À l’aide de l’outil BinPlace, vous pouvez créer un fichier de symboles supprimé à partir d’un fichier de symboles complet. Lorsque les options BinPlace les plus courantes sont utilisées (-a -x -s -n), les fichiers de symboles supprimés sont placés dans le répertoire répertorié après le commutateur -s , et les fichiers de symboles complets sont placés dans le répertoire répertorié après le commutateur -n . Lorsque BinPlace supprime un fichier de symboles, les versions supprimées et complètes du fichier reçoivent des signatures identiques et d’autres informations d’identification. Cela vous permet d’utiliser l’une ou l’autre version pour le débogage. Pour plus d’informations sur BinPlace, consultez BinPlace.
À l’aide de l’outil PDBCopy, vous pouvez créer un fichier de symboles supprimé à partir d’un fichier de symboles complet en supprimant les données de symboles privés. PDBCopy peut également supprimer un sous-ensemble spécifié de la table de symboles publics. Pour plus d’informations, consultez PDBCopy.
À l’aide de l’outil SymChk, vous pouvez déterminer si un fichier de symboles contient des symboles privés. Pour plus d’informations, consultez SymChk.
Affichage des symboles publics et privés dans le débogueur
Vous pouvez utiliser WinDbg, KD ou CDB pour afficher les symboles. Quand l’un de ces débogueurs a accès à un fichier de symboles complet, il a à la fois les informations répertoriées dans les données de symboles privés et les informations répertoriées dans la table de symboles publics. Les données de symbole public contiennent des décorations de symboles.
Lors de l’accès aux symboles privés, les données de symboles privés sont toujours utilisées, car ces symboles ne sont pas inclus dans la table de symboles publics. Ces symboles ne sont jamais décorés.
La commande .symopt (Définir les options de symbole) peut être utilisée pour contrôler les options de symbole qui déterminent la façon dont les symboles publics et privés sont utilisés par le débogueur. Par exemple, cette commande active les informations de débogage des symboles.
.symopt+ 0x80000000
Les options suivantes modifient la façon dont les symboles publics et privés sont utilisés dans le débogueur.
Lorsque l’option SYMOPT_UNDNAME est activée, les décorations ne sont pas incluses lorsque le nom d’un symbole public est affiché. De plus, lors de la recherche de symboles, les décorations sont ignorées. Lorsque cette option est désactivée, les décorations sont affichées lors de l’affichage de symboles publics, et les décorations sont utilisées dans les recherches. Les symboles privés ne sont jamais décorés en aucune circonstance. Cette option est activée par défaut dans tous les débogueurs.
Lorsque l’option SYMOPT_PUBLICS_ONLY est activée, les données de symbole privé sont ignorées et seule la table de symboles publics est utilisée. Cette option est désactivée par défaut dans tous les débogueurs.
Lorsque l’option SYMOPT_NO_PUBLICS est activée, la table de symboles publics est ignorée et les recherches et les informations sur les symboles utilisent uniquement les données de symbole privé. Cette option est désactivée par défaut dans tous les débogueurs.
Lorsque l’option SYMOPT_AUTO_PUBLICS est activée (et que SYMOPT_PUBLICS_ONLY et SYMOPT_NO_PUBLICS sont désactivés), la première recherche de symboles est effectuée dans les données de symboles privés. Si le symbole souhaité y est trouvé, la recherche se termine. Si ce n’est pas le cas, la table de symboles publics fait l’objet d’une recherche. Étant donné que la table de symboles publics contient un sous-ensemble des symboles dans les données privées, la table de symboles publics est généralement ignorée.
Lorsque les options SYMOPT_PUBLICS_ONLY, SYMOPT_NO_PUBLICS et SYMOPT_AUTO_PUBLICS sont toutes désactivées, les données de symboles privés et la table de symboles publics sont recherchées chaque fois qu’un symbole est nécessaire. Toutefois, lorsque des correspondances sont trouvées dans les deux emplacements, la correspondance dans les données de symbole privé est utilisée. Par conséquent, le comportement dans cette instance est le même que lorsque SYMOPT_AUTO_PUBLICS est activé, sauf que l’utilisation de SYMOPT_AUTO_PUBLICS peut entraîner une légère accélération des recherches de symboles.
Voici un exemple dans lequel la commande x (Examiner les symboles) est utilisée trois fois. La première fois, les options de symbole par défaut sont utilisées, de sorte que les informations sont extraites des données de symbole privé. Notez que cela inclut des informations sur l’adresse, la taille et le type de données du tableau typingString. Ensuite, la commande .symopt+ 4000 est utilisée, ce qui fait que le débogueur ignore les données de symboles privés. Lorsque la commande x est réexécuter, la table de symboles publics est utilisée ; cette fois, il n’y a pas d’informations sur la taille et le type de données pour typingString. Enfin, la commande .symopt- 2 est utilisée, ce qui permet au débogueur d’inclure des décorations. Lorsque la commande x est exécutée cette dernière fois, la version décorée du nom de la fonction, _typingString, s’affiche.
0:000> x /t /d *!*typingstring*
00434420 char [128] TimeTest!typingString = char [128] ""
0:000> .symopt+ 4000
0:000> x /t /d *!*typingstring*
00434420 <NoType> TimeTest!typingString = <no type information>
0:000> .symopt- 2
0:000> x /t /d *!*typingstring*
00434420 <NoType> TimeTest!_typingString = <no type information>
Affichage des symboles publics et privés avec l’outil DBH
Une autre façon d’afficher les symboles consiste à utiliser l’outil DBH . Affichez les options d’aide à l’aide de l’option /?
.
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh /?
dbh dbghelp shell
usage: dbh [-n] [-c] [-d] [-?] [-??] [-p] [targetmodule] [command]
[-n] display noisy symbol spew
[-d] use decorated publics
[-p:XXXX] attaches to process ID XXXX
[-s:SSSS] set symbol path to SSSS
[-c] callbacks return false
[targetmodule] load symbols for specified module
[command] execute command and exit
[-?] display these usage instructions
[-??] display detailed usage instructions
Utilisez un outil tel que Tlist pour répertorier les ID de processus et l’option -p pour l’attacher à un processus existant.
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh -p:4308
DBH utilise les mêmes options de symbole que le débogueur. Comme le débogueur, DBH laisse SYMOPT_PUBLICS_ONLY et SYMOPT_NO_PUBLICS désactivés par défaut, puis active SYMOPT_UNDNAME et SYMOPT_AUTO_PUBLICS activés par défaut. Ces valeurs par défaut peuvent être remplacées par une option de ligne de commande ou par une commande DBH.
Voici un exemple dans lequel le addr de commande DBH 414fe0 est utilisé trois fois. La première fois, les options de symbole par défaut sont utilisées et les informations sont donc extraites des données de symboles privés. Notez que cela inclut des informations sur l’adresse, la taille et le type de données de la fonction fgets. Ensuite, la commande symopt +4000 est utilisée, ce qui fait que DBH ignore les données de symboles privés. Lorsque l’addr 414fe0 est réexécuté, la table de symboles publics est utilisée ; cette fois, il n’existe aucune information de taille et de type de données pour la fonction fgets. Enfin, la commande symopt -2 est utilisée, ce qui amène DBH à inclure des décorations. Lorsque le module complémentaire 414fe0 est exécuté cette dernière fois, la version décorée du nom de la fonction, _fgets, s’affiche.
pid:4308 mod:TimeTest[400000]: addr 414fe0
fgets
name : fgets
addr : 414fe0
size : 113
flags : 0
type : 7e
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagFunction (5)
index : 7d
pid:4308 mod:TimeTest[400000]: symopt +4000
Symbol Options: 0x10c13
Symbol Options: 0x14c13
pid:4308 mod:TimeTest[400000]: addr 414fe0
fgets
name : fgets
addr : 414fe0
size : 0
flags : 0
type : 0
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagPublicSymbol (a)
index : 7f
pid:4308 mod:TimeTest[400000]: symopt -2
Symbol Options: 0x14c13
Symbol Options: 0x14c11
pid:4308 mod:TimeTest[400000]: addr 414fe0
_fgets
name : _fgets
addr : 414fe0
size : 0
flags : 0
type : 0
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagPublicSymbol (a)
index : 7f
Informations supplémentaires
Pour plus d’informations sur les symboles, consultez Syntaxe des symboles et correspondance de symboles, Options de symbole, Abréviations d’état des symboles et Chargement différé de symboles.