Ce fichier est un petit memo de tout les choix concernant l'implementation de disc2. L'objectif de ce programme est assez ambitieux: retrouver le source original d'un programme a partir de l'executable. Le fichier source produit est en C. Ce programme part d'une idee toute simple: quand on connait bien l'assembleur d'une machine et comment le C y est code (conventions d'appel...), on peut manuellement reconstitue des parties du fichier source original. L'idee est de rendre ce travail automatique, ainsi qu'independant de l'assembleur utilise, du format du binaire, de la machine sur laquelle on execute disc2. Quelque chose d'assez general en somme. A l'heure actuelle, pour que le traitement soit "independant", on utilise des "modules". Cad des structures contenant des fonctions propres a tel ou tel assembleur, tel ou tel format de fichier. Le traitement se fait en trois phases: 1) Traitement du format du binaire: convertir le fichier executable en representation en memoire, definit le point d'entree (ie l'adresse de la premiere instruction executee), ainsi que les diverses table de symboles [et de relocation, mais ce n'est pas pris en compte dans la version actuelle] 2) Desassemblage: a partir du point d'entree, on desassemble tout le code en suivant les fonctions appellees. Chaque fonction est egalement decomposee en bloc de base. 3) Reconstitution du code C. Pour l'instant, seul les appels de fonction sont retranscrits. Les formats de binaires acceptes sont: - elf (utilises sous Linux et Solaris) - dos (les .exe seulement) - win32 (concerne Windows 95 et Windows NT) Les architectures supportes sont: (et de maniere incomplete) - i86 (Intel 80x86 en mode reel 16 bits) - i386 (Intel 80x86 en mode protege 32 bits) - sparc (Sun Sparc) Il existe egalement un module pour le systeme d'exploitation qui permet de decoder la signification des appels systemes. Pour l'instant, ceci n'est pas operationnel. L'interet de ces modules est qu'une grosse partie du travail peut etre faite de maniere independantes (et donc etre utile pour tout les modules). L'autre interet est le cas du format elf, on peut faire un combinaison elf+i386 ou elf+sparc. (meme si ceci m'a oblige a reecrire toutes les routines pour gere correctement l'ordre des octets, par exemple pour que la combinaison elf+i386 marche en l'executant sur un Sun). On pourrait meme traiter des combinaisons qui n'existe pas aujourd'hui: win32+sparc. Seulement voila, ca ne genere pas de code C. Pour ce faire, il serait interessant de transformer chaque instruction assembleur en qqch de general. Un code intermediaire pour reprendre ce qui est utilise dans le cas des compilateurs. (puisque l'on fait le travail inverse, on peut utiliser les memes techniques). Chaque instruction pourrait etre vue (de maniere theorique) comme un fonction (simple) avec parametres d'entrees, des parametres de sorties ... et des effets de bords. Ces parametres d'entrees/sorties peuvent etre toutes les ressources qu'un processeur mets a la disposition des instructions: - constantes - registres (divers) - contenu memoire (et les modes d'adressage associes) - code-condition (flags) - pile. Comment representer les instructions de branchements ? Surtout dans le cas du sparc ou chaque instruction (ou presque) a pour effet de bord une addition. Le 07/01/1998. Finallement, la representation des instructions utilise un code a 3 adresses represente sous forme de quadruplet. Cette representation permet de representer tout le programme sous une forme intermediaire. On utilise les structures suivantes: - un programme est une liste de fonction (on neglige pour l'instant les declarations de variables globales). - une fonction est une liste de bloc de base (BB). On neglige ici aussi les declarations de variables locales. - un bloc de base est une liste d'instruction. - une instruction est representer par une expression qui est une liste de quadruplet, chaque quadruplet representant une operation elementaire. De cette maniere, disc2 se decompose en plusieurs etapes: - analyse du format du binaire (pour avoir la corespondance adresse memoire/emplacement dans le fichier+la table des symboles et de relocation). - desassemblage: on obtient les instructions elementaires et une representation (independantes de l'asm!) de tout le programme - diverses operations sur la representation intermediaire pour obtenir des structures de plus haut niveau. Optimisation en particulier. - affichage de la representation intermediaire en C. (backend en anglais). A la limite ceci pourrait se traduire en Pascal, ou en autre chose, mais comme la structure de disc2 est assez influencee pour reconnaitre des constructions en language C et que le language C est tres largment repandue. Ce choix est definitif. Il faudrait aussi disposer d'une structure contenant TOUTES les informations relatives a l'executable: - descripteur du fichier (il serait preferable que ce soit un FILE * car les fonctions fread() sont bufferisees et presentes dans toutes les bibliotheques du C) - representation intermediaire (liste de fonctions) - plan memoire (table des sections) - signatureS - table de symboles Cette structure permettrait d'eviter les variables globales et devrait meme permettre la decompilation de plusieurs executables en meme temps. A faire: - remplacer int fd par FILE *fp. - gerer le delay slot sur Sparc. Hop, erreur dans le calcul des adresses pour Intel. En effet, le couple (seg16,off16) etait traduit en addr32=seg16*16+off16 le tout restreint a 20 bits. Maintenant, on calcul l'addresse de destination d'un call par la formule dst32=addr_courante32+count+off16(signe), le tout restreint a 20 bits Et bien, ca ne donne pas le bon resultat dans tout les cas, car en realite l'adresse resultante provient de (seg16,off16+count+off16 restreint a 16 bits). Exemple: On est en [0010:C000], on rencontre l'instruction E8 00 D0, soit call +D000, l'adresse de destination est donc: [0010:C000+3+D000], soit [0010:9003] (C000+3+D000=19003) et non [0011:9003] !!! Conclusion: le probleme n'a pas de solution. Le 11/01/1998. Les vieilles structures bloc_de_base et liste_de_bloc_de_base sont completement eliminees. Un debut d'algorithme de structuration des graphes fonctionne (dans ~/c/divers/traducteur_3.c). Il est base sur le principe suivant: on regarde un certain nombre de noeuds et on essaye de voir s'ils correspondent a une certaine structure (if_then, do_while, ...) . Si oui, on remplace la construction par un noeud representant cette construction. On essaye alors de reduire le graphe initial a un seul noeud. Ajout des programmes/dll au format Windows 3.X dit win16. Fonctionne egalement pour les .drv. Les dlls sont localisees dans le repertoire donne par la variable d'environnement DISC_WINDOWS_SYSTEM. Le 04/02/1998. Derniere mise au point sur entcsun3.tamu.edu (en particulier prise en compte de la variable afficher_asm). Le 03/07/1998.