Table des symboles - Symbol table

En informatique , une table de symboles est une structure de données utilisée par un traducteur de langage tel qu'un compilateur ou un interpréteur , où chaque identifiant (ou symbole) dans le code source d' un programme est associé à des informations relatives à sa déclaration ou à son apparition dans la source. En d'autres termes, les entrées d'une table de symboles stockent les informations relatives au symbole correspondant de l'entrée.

Fond

Une table de symboles peut n'exister qu'en mémoire pendant le processus de traduction, ou elle peut être intégrée dans la sortie de la traduction, comme dans un fichier objet ABI pour une utilisation ultérieure. Par exemple, il peut être utilisé lors d'une session de débogage interactive ou comme ressource pour formater un rapport de diagnostic pendant ou après l' exécution d'un programme.

La description

L'information minimale contenue dans une table de symboles utilisée par un traducteur comprend le nom du symbole et son emplacement ou son adresse. Pour un compilateur ciblant une plate-forme avec un concept de relocalisation, il contiendra également des attributs de relocalisation (absolus, relocalisables, etc.) et les informations de relocalisation nécessaires pour les symboles relocalisables. Les tables de symboles pour les langages de programmation de haut niveau peuvent stocker le type du symbole : chaîne, entier, virgule flottante, etc., sa taille, ses dimensions et ses limites. Toutes ces informations ne sont pas incluses dans le fichier de sortie, mais peuvent être fournies pour une utilisation dans le débogage . Dans de nombreux cas, les informations de référence croisée du symbole sont stockées avec ou liées à la table des symboles. La plupart des compilateurs impriment tout ou partie de ces informations dans la table des symboles et les listes de références croisées à la fin de la traduction.

Mise en œuvre

De nombreuses structures de données sont disponibles pour la mise en œuvre des tables. Les arbres, les listes linéaires et les listes auto-organisées peuvent tous être utilisés pour implémenter une table de symboles. La table des symboles est accessible par la plupart des phases d'un compilateur, en commençant par l'analyse lexicale et en continuant par l'optimisation.

Un compilateur peut utiliser une grande table de symboles pour tous les symboles ou utiliser des tables de symboles hiérarchiques séparées pour différentes portées . Par exemple, dans un langage étendu tel qu'Algol ou PL/I, un symbole "p" peut être déclaré séparément dans plusieurs procédures, peut-être avec des attributs différents. La portée de chaque déclaration est la section du programme dans laquelle les références à "p" résolvent cette déclaration. Chaque déclaration représente un identifiant unique "p". La table des symboles doit avoir un moyen de différencier les références aux différents "p".

Une structure de données courante utilisée pour implémenter les tables de symboles est la table de hachage . Le temps de recherche dans les tables de hachage est indépendant du nombre d'éléments stockés dans la table, il est donc efficace pour un grand nombre d'éléments. Il simplifie également la classification des littéraux sous forme de tableau en incluant la classification dans le calcul de la clé de hachage.

Comme l'analyseur lexical passe une grande partie de son temps à rechercher la table des symboles, cette activité a un effet crucial sur la vitesse globale du compilateur. Une table des mnémoniques doit être organisée de telle sorte que les entrées puissent être trouvées le plus rapidement possible. Les tables de hachage sont généralement utilisées pour organiser une table de symboles, où le mot-clé ou l'identifiant est « haché » pour produire un indice de tableau. Les collisions sont inévitables dans une table de hachage, et une façon courante de les gérer consiste à stocker le synonyme dans le prochain espace libre disponible dans la table.

Applications

Un fichier objet contiendra une table des symboles des identifiants qu'il contient et visibles de l'extérieur. Lors de la liaison de différents fichiers objets, un éditeur de liens identifiera et résoudra ces références de symboles. Habituellement, tous les symboles externes non définis seront recherchés dans une ou plusieurs bibliothèques d'objets . Si un module est trouvé qui définit ce symbole, il est lié avec le premier fichier objet, et tous les identifiants externes non définis sont ajoutés à la liste des identifiants à rechercher. Ce processus se poursuit jusqu'à ce que toutes les références externes aient été résolues. C'est une erreur si une ou plusieurs restent non résolues à la fin du processus.

Lors de la rétro-ingénierie d' un exécutable, de nombreux outils se réfèrent à la table des symboles pour vérifier quelles adresses ont été attribuées aux variables globales et aux fonctions connues. Si la table des symboles a été supprimée ou nettoyée avant d'être convertie en un exécutable, les outils auront plus de mal à déterminer les adresses ou à comprendre quoi que ce soit sur le programme.

Exemple

Considérons le programme suivant écrit en C :

// Declare an external function
extern double bar(double x);

// Define a public function
double foo(int count)
{
    double sum = 0.0;

    // Sum all the values bar(1) to bar(count)
    for (int i = 1; i <= count; i++)
        sum += bar((double) i);
    return sum;
}

Le compilateur AC qui analyse ce code contiendra au moins les entrées de table de symboles suivantes :

Nom du symbole Taper Portée
bar fonction, double externe
x double paramètre de fonction
foo fonction, double global
count entier paramètre de fonction
sum double bloquer local
i entier instruction de boucle for

De plus, la table des symboles contiendra également des entrées générées par le compilateur pour les valeurs d'expression intermédiaires (par exemple, l'expression qui iconvertit la variable de boucle en a doubleet la valeur de retour de l'appel à la fonction bar()), les étiquettes d'instruction, etc.

Exemple : SysV ABI

Exemple de tableau : SysV ABI
Adresse Taper Nom
00000020 une T_BIT
00000040 une F_BIT
00000080 une JE MORD
20000004 t irqvec
20000008 t fiqvec
2000000c t InitReset
20000018 T _principale
20000024 t Finir
20000030 T AT91F_US3_CfgPIO_useB
2000005c t AT91F_PIO_CfgPeriph
200000b0 T principale
20000120 T AT91F_DBGU_Printk
20000190 t AT91F_US_TxReady
200001c0 t AT91F_US_PutChar
200001f8 T AT91F_SpuriousHandler
20000214 T AT91F_DataAbort
20000230 T AT91F_FetchAbort
2000024c T AT91F_Undef
20000268 T AT91F_UndefHandler
20000284 T AT91F_LowLevelInit
200002e0 t AT91F_DBGU_CfgPIO
20000030c t AT91F_PIO_CfgPeriph
20000360 t AT91F_US_Configure
200003dc t AT91F_US_SetBaudrate
2000041c t AT91F_US_Baudrate
200004ec t AT91F_US_SetTimeguard
2000051c t AT91F_PDC_Open
2000059c t AT91F_PDC_DisableRx
200005c8 t AT91F_PDC_DisableTx
200005f4 t AT91F_PDC_SetNextTx
20000638 t AT91F_PDC_SetNextRx
2000067c t AT91F_PDC_SetTx
200006c0 t AT91F_PDC_SetRx
20000704 t AT91F_PDC_EnableRx
20000730 t AT91F_PDC_EnableTx
2000075c t AT91F_US_EnableTx
20000788 T __aeabi_uidiv
20000788 T __udivsi3
20000884 T __aeabi_uidivmod
2000089c T __aeabi_idiv0
2000089c T __aeabi_ldiv0
2000089c T __div0
200009a0 _Les données
200009a0 UNE _etext
200009a0 holaamigosh
200009a4 UNE __bss_end__
200009a4 UNE __bss_start
200009a4 UNE __bss_start__
200009a4 UNE _data
200009a4 UNE _finir

Un exemple de table de symboles peut être trouvé dans la spécification SysV Application Binary Interface (ABI), qui prescrit comment les symboles doivent être disposés dans un fichier binaire, afin que différents compilateurs, éditeurs de liens et chargeurs puissent tous trouver et travailler de manière cohérente avec le symboles dans un objet compilé.

L'ABI SysV est implémentée dans l' utilitaire nm de GNU binutils . Ce format utilise un champ d' adresse mémoire trié , un champ "type de symbole" et un identifiant de symbole (appelé "Nom").

Les types de symboles dans l'ABI SysV (et la sortie de nm) indiquent la nature de chaque entrée dans la table des symboles. Chaque type de symbole est représenté par un seul caractère. Par exemple, les entrées de table de symboles représentant des données initialisées sont désignées par le caractère "d" et les entrées de table de symboles pour les fonctions ont le type de symbole "t" (car le code exécutable est situé dans la section texte d'un fichier objet). De plus, la majuscule du type de symbole indique le type de lien : les lettres minuscules indiquent que le symbole est local et les majuscules indiquent un lien externe (global).

Exemple : la table des symboles Python

Le langage de programmation Python comprend une prise en charge étendue de la création et de la manipulation de tables de symboles. Les propriétés qui peuvent être interrogées incluent si un symbole donné est une variable libre ou une variable liée , s'il s'agit d'une portée de bloc ou d' une portée globale , s'il est importé et à quel espace de noms il appartient.

Exemple : tables de symboles dynamiques

Certains langages de programmation permettent de manipuler la table des symboles au moment de l'exécution, de sorte que des symboles peuvent être ajoutés à tout moment. Racket est un exemple d'un tel langage.

Les langages de programmation LISP et Scheme permettent tous deux d'associer des propriétés génériques arbitraires à chaque symbole.

Le langage de programmation Prolog est essentiellement un langage de manipulation de tables de symboles ; les symboles sont appelés atomes , et les relations entre les symboles peuvent être raisonnées. De même, OpenCog fournit une table de symboles dynamique, appelée espace atomique , qui est utilisée pour la représentation des connaissances .

Voir également

Les références