Comment extraire les informations de variable locale (adresse et type) d'un programme Delphi ou des informations de débogage générées par le compilateur?

105

Mon but est:

  • Étant donné un thread suspendu dans un programme Windows 32 ou 64 bits compilé en Delphi, parcourir la pile (faisable)
  • Compte tenu des entrées de pile, pour énumérer les variables locales dans chaque méthode et leurs valeurs. C'est-à-dire à tout le moins trouver leur adresse et leur type (entier32 / 64 / signé / non signé, chaîne, flottant, enregistrement, classe ...) dont la combinaison peut être utilisée pour trouver leur valeur.

Le premier est très bien et c'est le second sur lequel porte cette question. À un niveau élevé, comment énumérer les variables locales étant donné une entrée de pile dans Delphi?


À un niveau bas, voici ce que j'ai étudié:

RTTI: ne répertorie pas ce type d'informations sur les méthodes. Ce n'était pas quelque chose que je pensais vraiment être une option réaliste, mais je l'ai quand même répertorié ici.

Informations de débogage: chargement des informations de débogage produites pour une génération de débogage.

  • Fichiers cartographiques: même un fichier cartographique détaillé (un fichier au format texte! Ouvrez-en un et jetez un œil) ne contient pas d'informations sur les variables locales. Il s'agit essentiellement d'une liste d'adresses et de numéros de ligne de fichier source. Idéal pour la corrélation d'adresse à fichier et de ligne, par exemple les points bleus dans la gouttière; pas génial pour des informations plus détaillées
  • Informations de débogage à distance (fichier RSM) - aucune information connue sur son contenu ou son format.
  • Fichiers TD32 / TDS: ma ligne de recherche actuelle. Ils contiennent des symboles globaux et locaux parmi de nombreuses autres informations.

Les problèmes que je rencontre ici sont:

  • Il n'y a pas de documentation sur le format de fichier TD32 (que je peux trouver.)
  • La plupart de mes connaissances à leur sujet proviennent du code Jedi JCL qui les utilise (JclTD32.pas) et je ne sais pas comment utiliser ce code, ni si les structures sont suffisamment étendues pour afficher les variables locales. Je suis à peu près certain qu'il gérera les symboles mondiaux, mais je suis très incertain à propos du local. Il existe une grande variété de constantes définies et sans documentation pour le format, pour lire ce qu'elles signifient, je me laisse deviner. Cependant, ces constantes et leurs noms doivent venir de quelque part.
  • La source que je peux trouver à l'aide des informations TDS ne charge ni ne gère les symboles locaux.

Si c'est la bonne approche, alors cette question devient "Existe-t-il une documentation pour le format de fichier TDS / TD32, et y a-t-il des exemples de code qui chargent des variables locales?"

Un exemple de code n'est pas essentiel mais pourrait être très utile, même s'il est très minime.

David
la source
2
Je n'ai pas réellement utilisé les unités Jedi JCL pour accéder aux informations TD32 - j'ai ma propre bibliothèque propriétaire pour cela, mais il semble que toute la plomberie de base dont vous aurez besoin se trouve dans JclTD32.pas. Il n'y a pas de code de démonstration que je puisse trouver pour accéder aux informations de variable, cependant, mais l'exemple qui s'y trouve (dans .. \ jcl \ examples \ windows \ debug \ sourceloc) montre comment obtenir des informations de numéro de ligne à partir des données TD32, donc vous devriez pouvoir vous appuyer sur cela pour obtenir ce dont vous avez besoin. Veuillez rapporter ici ce que vous avez découvert :)
500 - Erreur de serveur interne
2
@ 500-InternalServerError Merci. Les informations sur les numéros de ligne sont faciles (même dans les fichiers cartographiques) - mais pouvez-vous fournir des informations sur ce que vous voyez dans le code JCL qui se rapporte spécifiquement aux symboles locaux? Aussi, par curiosité, quelle est votre bibliothèque propriétaire TD32, et est-elle publiée / utilisable publiquement ou uniquement en interne?
David
3
Chaque symbole de procédure / fonction / méthode en dessous contient à son tour une liste de symboles qui lui sont locaux. La plupart des définitions semblent être présentes dans l'unité Jedi, mais certaines sont des commentaires. Ma suggestion serait de créer de minuscules applications de test et de regarder ce que renvoie une énumération de symboles. Le code que j'ai est propriétaire et je ne peux pas le publier. Il ne couvre de toute façon pas le sujet des variables locales. Mais les informations sur lesquelles il est basé sont semi-publiques, donc je pourrai peut-être vous aider si vous rencontrez des murs spécifiques.
500 - Erreur de serveur interne
4
tds2pdb ( code.google.com/p/map2dbg ) semble avoir un analyseur pour les fichiers tds. C'est du code C # cependant.
Graymatter
4
Il y avait un document informel, oui, mais Borland (à l'époque) a décidé de publier une DLL à la place pour accéder aux informations de débogage afin qu'ils puissent changer le format interne et ne pas avoir à mettre à jour la documentation. Malheureusement, je ne peux localiser ni le document original ni la DLL pour le moment. Je vous suggère de contacter le support technique d'Embarcadero et de vous renseigner à ce sujet.
500 - Erreur de serveur interne

Réponses:

2

Vérifiez si des symboles de débogage n'étaient pas en binaire. Il est également possible d'utiliser GDB (sur Windows un port de celui-ci). Ce serait formidable si vous trouviez un fichier .dbg ou .dSYM. Ils contiennent du code source, par exemple.

gdb> list foo
56 void foo()
57 {
58  bar();
59  sighandler_t fnc = signal(SIGHUP, SIG_IGN);
60  raise(SIGHUP);
61  signal(SIGHUP, fnc);
62  baz(fnc);
63 }

Si vous n'avez aucun fichier de débogage, vous pouvez essayer d'obtenir MinGW ou Cygwin et utiliser nm (1) ( page de manuel ). Il lira les noms de symboles à partir du binaire. Ils peuvent contenir certains types, comme ceux en C ++:

int abc::def::Ghi::jkl(const std::string, int, const void*)

N'oubliez pas d'ajouter l' --demangleoption alors ou vous obtiendrez quelque chose comme:

__ZN11MRasterFont21getRasterForCharacterEh

au lieu de:

MRasterFont::getRasterForCharacter(unsigned char)
Haut Sekret
la source
2
Jakub, merci pour la réponse. Malheureusement, j'ai probablement besoin de lire un format de débogage spécifique - TDS. Les applications Delphi ne sont pas compilées avec des informations de débogage compatibles GDB sous Windows. Je ne sais pas non plus comment nm aidera, car il reposera sur un format de fichier de débogage spécifique qui n'est probablement pas celui que Delphi génère. Ou ai-je mal compris votre réponse - GDB peut-il lire les symboles de Delphi, par exemple?
David
@DavidM, votre commentaire est très important. Essayez de trouver le port de GNU Binutils ou GNU Debugger sur Windows (je ne connais que le port Binutils). Il existe une bibliothèque BFD pour GDB. Il est également utilisé dans Binutils. Il permet de lire plusieurs formats de fichiers et de les reconnaître par leurs nombres magiques. Si tout échoue, utilisez l'outil appelé strings. Il extraira les chaînes de n'importe quel fichier binaire. Voir la page de manuel . Cela imprimera des chaînes qui peuvent mais ne doivent pas être utiles
Top Sekret
0

Jetez un œil à http://download.xskernel.org/docs/file%20formats/omf/borland.txt Open Architecture Handbook. Il est ancien, mais vous trouverez peut-être des informations pertinentes sur le format de fichier.

Muetze1
la source
Pouvez-vous s'il vous plaît ajouter un peu de contexte, le lien peut être rompu à l'avenir.
Hintham le
Le lien contient le document officiel de borland sur le format de fichier OMF utilisé par le compilateur Borland et d'autres formats de fichiers binaires utilisés par Borland. Il y a quelques années, j'ai jeté un coup d'œil au format de fichier TDS et il semblait que certaines parties étaient compatibles avec les formats de fichier documentés. Lorsque vous essayez de rassembler des informations sur les variables locales à partir du fichier TDS, la documentation liée doit être utilisée ou référencée. Si le lien est rompu, ma réponse sera inutile et les informations nécessaires seront perdues. Le "Open Architecture Handbook" lié faisait partie des anciennes versions de Turbo Pascal et C.
Muetze1